Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
44ae837
Add GFX IP version fallback for GPU family detection
mgajda Apr 14, 2026
f5acf66
Add PCI device IDs for RDNA 3, 3.5, and RDNA 4 GPUs
mgajda Apr 14, 2026
34f7cbc
Use user-friendly names for newer GPU models
mgajda Apr 15, 2026
b33708e
Distinguish Radeon 7000 series chip variants with product model numbers
mgajda Apr 15, 2026
d0e51af
Use product names for GFX1034 (Navi 24)
mgajda Apr 15, 2026
71200a3
Add comprehensive GFX code coverage including Instinct accelerators
mgajda Apr 15, 2026
9e7e469
Remove market segment labels from Radeon RX 7000 series names
mgajda Apr 15, 2026
9a6a703
Add names for gfx1171-1172: Ryzen AI Medusa Point and Medusa Halo
mgajda Apr 15, 2026
82054e6
Note that gfx1170/1171/1172 Medusa variant mapping is yet undetermined
mgajda Apr 15, 2026
f6f8c5a
Make all GPU family strings unique by adding GFX codes where needed
mgajda Apr 15, 2026
b31f81a
Reorder GPU strings: start with unique product name, GFX code in pare…
mgajda Apr 15, 2026
1776944
Include Radeon 880M in Strix Point GPU string
mgajda Apr 15, 2026
b562eb2
Update Strix Halo GPU string with Radeon 8040S/8050S/8060S variants
mgajda Apr 15, 2026
8d1a159
Correct Strix Point/Halo and gfx1170 mappings
mgajda Apr 15, 2026
5ebc983
Add gfx1152: Kraken Point
mgajda Apr 15, 2026
7edc0cf
Add Radeon model numbers for Kraken Point: 820M/840M/860M
mgajda Apr 15, 2026
e42a885
Correct official AMD codename: Krackan Point (with 'a')
mgajda Apr 15, 2026
fa94ca2
Correct gfx1151 mapping: Radeon 880M (Strix Halo), gfx1170-1172 all M…
mgajda Apr 15, 2026
a6bd5a3
Display unknown GPUs with GFX code as 'GFX#### (unknown)'
mgajda Apr 15, 2026
dea888c
Fix enum name references in detect.c and PCI IDs for build
mgajda Apr 15, 2026
f0c9920
Remove stray bits.vcn references that broke the build
mgajda May 12, 2026
ac8cde8
Identify APUs via GFX IP version instead of ambiguous PCI IDs
mgajda May 12, 2026
465672e
Prefer GFX IP version over PCI ID for family detection
mgajda May 12, 2026
bf38988
Use GC number / GFX number terminology consistently
mgajda May 12, 2026
165bfce
Show GC number alongside putative GFX target on unknown cards
mgajda May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions amdgpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,37 @@ void init_amdgpu(int fd) {
if (amdgpu_device_initialize(fd, &drm_major, &drm_minor, &amdgpu_dev))
return;

// Query the GC (Graphics & Compute) block number from amdgpu
// for family detection fallback. The GC number is the
// authoritative chip identifier on modern hardware, more
// reliable than the PCI device ID (which is reused across APU
// SKUs).
{
struct drm_amdgpu_info_hw_ip gfx_ip = {};
if (!amdgpu_query_hw_ip_info(amdgpu_dev, AMDGPU_HW_IP_GFX,
0, &gfx_ip)) {
unsigned int major = gfx_ip.hw_ip_version_major;
unsigned int minor_raw = gfx_ip.hw_ip_version_minor;
unsigned int minor, rev;

/*
* Newer kernels pack (minor << 8 | rev) into the
* minor field. GC 11.x onward only exists on
* these kernels, and for GC 10.x a value >= 256
* is unambiguously the new packing.
*/
if (major >= 11 || minor_raw >= 256) {
minor = (minor_raw >> 8) & 0xff;
rev = minor_raw & 0xff;
} else {
minor = minor_raw;
rev = 0;
}

gfx_version = major * 100 + minor * 10 + rev;
}
}

if (!(ret = getgrbm_amdgpu(&out32))) {
getgrbm = getgrbm_amdgpu;
getsrbm = getsrbm_amdgpu;
Expand Down
70 changes: 69 additions & 1 deletion detect.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
#include <errno.h>

struct bits_t bits;
unsigned int gfx_version;
uint64_t vramsize;
uint64_t gttsize;
unsigned int sclk_max = 0; // kilohertz
unsigned int mclk_max = 0; // kilohertz
unsigned int is_apu = 0; // 1 if APU (unified memory), 0 if discrete GPU
unsigned int has_power_sensor = 0; // 1 if power sensor available, 0 if unavailable
const void *area;
static const void *srbm_area;

Expand All @@ -38,6 +41,8 @@ int (*getvram)(uint64_t *out);
int (*getgtt)(uint64_t *out);
int (*getsclk)(uint32_t *out);
int (*getmclk)(uint32_t *out);
int (*gettemp)(uint32_t *out);
int (*getpower)(uint32_t *out);

static int find_pci(short bus, struct pci_device *pci_dev) {
int ret = pci_system_init();
Expand Down Expand Up @@ -265,7 +270,7 @@ static int getuint64_null(uint64_t *out) { UNUSED(out); return -1; }
void init_pci(const char *path, short *bus, unsigned int *device_id, const unsigned char forcemem) {
short device_bus = -1;
int err = 1;
getgrbm = getsclk = getmclk = getuint32_null;
getgrbm = getsclk = getmclk = gettemp = getpower = getuint32_null;
getsrbm = getsrbm2 = getuint32_null;
getvram = getgtt = getuint64_null;

Expand Down Expand Up @@ -341,6 +346,61 @@ int getfamily(unsigned int id) {
return 0;
}

/*
* Map the GC (Graphics & Compute) block number to chip family.
* The number is encoded as major * 100 + minor * 10 + rev, with
* major/minor/rev coming from amdgpu_query_hw_ip_info(GFX).
*
* Note: for GC 10.x the rev matches the GFX shader target name
* (GC 10.3.0 == gfx1030). For GC 11.0.x they diverge: GC 11.0.1
* is Phoenix (gfx1103), GC 11.0.3 is Navi 32 (gfx1101).
*/
int getfamily_gfx(unsigned int gc_ver) {

switch(gc_ver) {
// RDNA 1 (GC 10.1.x)
case 1010: return NAVI10;
case 1011: return NAVI12;
case 1012: return NAVI14;
// RDNA 2 (GC 10.3.x)
case 1030: return SIENNA_CICHLID;
case 1031: return NAVY_FLOUNDER;
case 1032: return DIMGREY_CAVEFISH;
case 1033: return GFX1033;
case 1034: return GFX1034;
case 1035: return YELLOW_CARP;
case 1036: return MENDOCINO;
case 1037: return MENDOCINO;
// RDNA 3 (GC 11.0.x) - GC rev != GFX shader target
case 1100: return NAVI31; // GC 11.0.0 = gfx1100
case 1101: return RADEON_780M; // GC 11.0.1 = gfx1103 (Phoenix1)
case 1102: return NAVI33; // GC 11.0.2 = gfx1102
case 1103: return NAVI32; // GC 11.0.3 = gfx1101 (Navi 32)
case 1104: return RADEON_780M; // GC 11.0.4 = gfx1103 (Phoenix2)
// RDNA 3.5 (GC 11.5.x)
case 1150: return STRIX_POINT;
case 1151: return RADEON_880M;
case 1152: return KRACKAN_POINT;
// RDNA 4m (GC 11.7.x)
case 1170: return MEDUSA_POINT;
case 1171: return MEDUSA_POINT_2;
case 1172: return MEDUSA_POINT_3;
// RDNA 4 (GC 12.0.x)
case 1200: return RADEON_9000;
case 1201: return GFX1201;
// RDNA 5 (GC 13.x)
case 1300: return GFX1300;
case 1310: return GFX1310;
}

// No major.minor catch-all: revisions within a GC family report
// genuinely different SKUs (GC 11.0.0 = NAVI31 vs GC 11.0.1 =
// Phoenix iGPU), so rounding by major.minor mislabels cards.
// Unknown GC numbers return 0 and radeontop.c prints
// "GFX#### (unknown)" instead.
return 0;
}

void initbits(int fam) {

// The majority of these is the same from R600 to Southern Islands.
Expand Down Expand Up @@ -377,4 +437,12 @@ void initbits(int fam) {
bits.vce0 = (1U << 7);
}
}

// RDNA (GFX10+): VGT replaced by Geometry Engine at bit 21,
// Event Engine and Sequencer Instruction Cache bits undefined.
if (fam >= NAVI10) {
bits.ee = 0;
bits.vgt = (1U << 21);
bits.sh = 0;
}
}
35 changes: 35 additions & 0 deletions family_str.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,39 @@ const char * const family_str[] = {
str(ALDEBARAN),
str(CYAN_SKILLFISH),
str(BEIGE_GOBY),
// RDNA 2 (gfx10.x)
"Radeon RX 6800/6900 XT (gfx1030)",
"Radeon RX 6700/6750/6800M/6850M (gfx1031)",
"Radeon RX 6600 (gfx1032)",
"Radeon RX 6500/W6300 (gfx1034)",
// RDNA 3 APUs (gfx1103-1151)
"Radeon 660M/680M (gfx1035)",
"Radeon Graphics 128SP (gfx1036)",
"Steam Deck GPU (gfx1033)",
"Radeon 740M/760M/780M (gfx1103)",
"Radeon 890M (Strix Point)",
"Radeon 880M (Strix Halo)",
// RDNA 4 APUs (gfx115x - Kraken)
"Radeon 820M/840M/860M (Krackan Point)",
// RDNA 4 APUs (gfx117x - Medusa Point variants)
"Medusa Point (gfx1170)",
"Medusa Point (gfx1171)",
"Medusa Point (gfx1172)",
// RDNA 4 dGPU (gfx12xx)
"Radeon 9000 (gfx1200)",
"Radeon 9000 XT (gfx1201)",
// RDNA 5 (gfx13xx)
"Radeon (gfx1300)",
"Radeon (gfx1310)",
// Instinct MI (gfx90x)
"Instinct MI8/MI6 (gfx803)",
"Instinct MI25 (gfx900)",
"Instinct MI50/MI60 (gfx906)",
"Instinct MI100 (gfx908)",
"Instinct MI210/MI250/MI250X (gfx90a)",
"Instinct MI300/MI300X/MI325X (gfx940)",
// RDNA 3 dGPU (gfx110x)
"Radeon RX 7900 (gfx1100)",
"Radeon RX 7800/7700 (gfx1101)",
"Radeon RX 7600/7500 (gfx1102)",
};
26 changes: 26 additions & 0 deletions include/r600_pci_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,29 @@ CHIPSET(0x7422, 0x7422, BEIGE_GOBY)
CHIPSET(0x7423, 0x7423, BEIGE_GOBY)
CHIPSET(0x7424, 0x7424, BEIGE_GOBY)
CHIPSET(0x743F, 0x743F, BEIGE_GOBY)
CHIPSET(0x7446, 0x7446, NAVI31)
CHIPSET(0x7448, 0x7448, NAVI31)
CHIPSET(0x744A, 0x744A, NAVI31)
CHIPSET(0x744B, 0x744B, NAVI31)
CHIPSET(0x744C, 0x744C, NAVI31)
CHIPSET(0x745E, 0x745E, NAVI31)
CHIPSET(0x7460, 0x7460, NAVI32)
CHIPSET(0x7461, 0x7461, NAVI32)
CHIPSET(0x7470, 0x7470, NAVI32)
CHIPSET(0x747E, 0x747E, NAVI32)
CHIPSET(0x73F0, 0x73F0, NAVI33)
CHIPSET(0x7480, 0x7480, NAVI33)
CHIPSET(0x7481, 0x7481, NAVI33)
CHIPSET(0x7483, 0x7483, NAVI33)
CHIPSET(0x7487, 0x7487, NAVI33)
CHIPSET(0x7489, 0x7489, NAVI33)
CHIPSET(0x748B, 0x748B, NAVI33)
CHIPSET(0x7499, 0x7499, NAVI33)
CHIPSET(0x749F, 0x749F, NAVI33)
// APU PCI device IDs are ambiguous (same ID across SKUs / pci.ids
// versions). Identification is done via the GC (Graphics &
// Compute) block number in getfamily_gfx() when amdgpu reports it.
// See PR #180 discussion.
CHIPSET(0x7550, 0x7550, GFX1201)
CHIPSET(0x7551, 0x7551, GFX1201)
CHIPSET(0x7590, 0x7590, RADEON_9000)
36 changes: 36 additions & 0 deletions include/radeontop.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void die(const char *why);
// detect.c
void init_pci(const char *path, short *bus, unsigned int *device_id, const unsigned char forcemem);
int getfamily(unsigned int id);
int getfamily_gfx(unsigned int gfx_ver);
void initbits(int fam);
void cleanup();

Expand Down Expand Up @@ -138,6 +139,40 @@ enum radeon_family {
ALDEBARAN,
CYAN_SKILLFISH,
BEIGE_GOBY,
// RDNA 2 (gfx10.x)
GFX1030, // gfx1030, RX 6800/6900 XT, Pro W6800/V620
GFX1031, // gfx1031, RX 6700/6750/6800M/6850M
GFX1032, // gfx1032, RX 6600 series, Pro W6600
GFX1034, // gfx1034, RX 6300/6400/6500 XT, Pro W6300/W6400
// RDNA 3 APUs (gfx1103-1151)
GFX1035, // gfx1035, Radeon 660M/680M
MENDOCINO, // gfx1036, Radeon Graphics 128SP
GFX1033, // gfx1033, Steam Deck GPU
RADEON_780M, // gfx1103, Radeon 740M/760M/780M/ROG Ally
STRIX_POINT, // gfx1150, Radeon 890M (Strix Point)
RADEON_880M, // gfx1151, Radeon 880M (Strix Halo)
// RDNA 4 APUs (gfx115x - Krackan)
KRACKAN_POINT, // gfx1152, Radeon 820M/840M/860M (Krackan Point)
// RDNA 4 APUs (gfx117x - Medusa)
MEDUSA_POINT, // gfx1170, Medusa Point
MEDUSA_POINT_2, // gfx1171, Medusa Point (variant mapping TBD)
MEDUSA_POINT_3, // gfx1172, Medusa Point (variant mapping TBD)
// RDNA 4 dGPU (gfx12xx)
RADEON_9000, // gfx1200, Radeon 9000 series
GFX1201, // gfx1201
// RDNA 5 (gfx13xx)
GFX1300, // gfx1300, RDNA 5
GFX1310, // gfx1310, RDNA 5
// Instinct MI (gfx90x)
MI8, // gfx803, Instinct MI8/MI6
MI25, // gfx900, Instinct MI25
MI50, // gfx906, Instinct MI50/MI60
MI100, // gfx908, Instinct MI100
MI210, // gfx90a, Instinct MI210/MI250/MI250X
MI300, // gfx940, Instinct MI300/MI300X/MI325X
NAVI31, // gfx1100, RX 7900 series
NAVI32, // gfx1101, RX 7800/7700 series
NAVI33, // gfx1102, RX 7600/7500 series
};

extern const char * const family_str[];
Expand Down Expand Up @@ -178,5 +213,6 @@ void init_radeon(int fd, int drm_major, int drm_minor);
// amdgpu.c
void init_amdgpu(int fd);
void cleanup_amdgpu();
extern unsigned int gfx_version;

#endif
38 changes: 34 additions & 4 deletions radeontop.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,41 @@ int main(int argc, char **argv) {

setuid(getuid());

const int family = getfamily(device_id);
// The GC (Graphics & Compute) block number is the authoritative
// chip identifier on modern hardware (libdrm_amdgpu queries it
// directly via amdgpu_query_hw_ip_info), so try it first. PCI
// ID lookup is the fallback for legacy cards that don't expose
// a GC number, and for amdgpu init failures.
int family = 0;
if (gfx_version)
family = getfamily_gfx(gfx_version);
if (!family)
fprintf(stderr, _("Unknown Radeon card. <= R500 won't work, new cards might.\n"));

const char * const cardname = family_str[family];
family = getfamily(device_id);

const char *cardname;
static char gfx_fallback[40];

if (!family) {
if (gfx_version) {
// When the family is unknown but a GC number is
// available, show the GC number (certain - queried
// straight from the chip) together with the putative
// GFX shader target. The two coincide for GC 10.x but
// diverge for GC 11.0.x APUs, hence the '?' on GFX.
snprintf(gfx_fallback, sizeof(gfx_fallback),
"gfx%u? (GC %u.%u.%u unknown)",
gfx_version,
gfx_version / 100,
(gfx_version / 10) % 10,
gfx_version % 10);
cardname = gfx_fallback;
} else {
cardname = family_str[family];
fprintf(stderr, _("Unknown Radeon card. <= R500 won't work, new cards might.\n"));
}
} else {
cardname = family_str[family];
}

initbits(family);

Expand Down