diff --git a/radeontool.c b/radeontool.c index 2f878bb..d7c335e 100644 --- a/radeontool.c +++ b/radeontool.c @@ -936,11 +936,15 @@ static struct nametable_entry hdr_type_name[] = { static void radeon_rom_legacy_clocks(unsigned char *bios, int hdr) { int pll_info_block = BIOS16(hdr + 0x30); + int rev; if (pll_info_block == 0) { printf("No clock info block in BIOS\n"); return; } + rev = BIOS8(pll_info_block); + printf("revision %d\n", rev); + printf("Clock info block:\n"); printf(" SCLK : %f\n", BIOS16(pll_info_block + 0x08) / 100.0); printf(" MCLK : %f\n", BIOS16(pll_info_block + 0x0a) / 100.0); @@ -948,6 +952,14 @@ static void radeon_rom_legacy_clocks(unsigned char *bios, int hdr) printf(" RefDiv : %d\n", BIOS16(pll_info_block + 0x10)); printf(" VCO Min: %f\n", BIOS32(pll_info_block + 0x12) / 100.0); printf(" VCO Max: %f\n", BIOS32(pll_info_block + 0x16) / 100.0); + + if (rev > 9) { + printf(" VCO in Min: %f\n", BIOS32(pll_info_block + 0x36) / 100.0); + printf(" VCO in Max: %f\n", BIOS32(pll_info_block + 0x3a) / 100.0); + printf(" VCO out Min: %f\n", BIOS32(pll_info_block + 0x3e) / 100.0); + printf(" VCO out Max: %f\n", BIOS32(pll_info_block + 0x42) / 100.0); + } + printf("\n"); } @@ -964,8 +976,10 @@ static void radeon_rom_atom_clocks(unsigned char *bios, int master) printf(" SCLK : %f\n", BIOS32(pll_info_block + 8) / 100.0); printf(" MCLK : %f\n", BIOS32(pll_info_block + 12) / 100.0); printf(" RefClk : %f\n", BIOS16(pll_info_block + 82) / 100.0); - printf(" PPLL Min: %f\n", BIOS16(pll_info_block + 78) / 100.0); - printf(" PPLL Max: %f\n", BIOS32(pll_info_block + 32) / 100.0); + printf(" PPLL in Min: %f\n", BIOS16(pll_info_block + 74) / 100.0); + printf(" PPLL in Max: %f\n", BIOS16(pll_info_block + 76) / 100.0); + printf(" PPLL out Min: %f\n", BIOS16(pll_info_block + 78) / 100.0); + printf(" PPLL out Max: %f\n", BIOS32(pll_info_block + 32) / 100.0); } @@ -1025,7 +1039,7 @@ static void radeon_rom_legacy_connectors(unsigned char *bios, int hdr) entries = BIOS8(offset + 1) & 0xf; printf(" Table for chip %d has %d connector(s):\n", BIOS8(offset + 1) >> 4, entries); - for (i = 0; i < 4; i++) { + for (i = 0; i < entries; i++) { entry = offset + 2 + i*2; /* End of table */ @@ -1040,11 +1054,18 @@ static void radeon_rom_legacy_connectors(unsigned char *bios, int hdr) printf(" %08x ", tmp); printf("Type:%s", radeon_valname(lconn_type_name, (tmp >> 12) & 0xf)); - printf(", DDC:%s", radeon_valname(lddc_type_name, - (tmp >> 8) & 0xf)); + if (((tmp >> 8) & 0xf) == 5) { + printf(", DDC:0x%x", BIOS8(entry+2)); + } else { + printf(", DDC:%s", radeon_valname(lddc_type_name, + (tmp >> 8) & 0xf)); + } printf(", DAC:%s", radeon_valname(ldac_type_name, tmp & 0x3)); printf(", TMDS:%s", (tmp & 0x10) ? "External" : "Internal"); - + printf(", MUX switch:%s", (tmp & 0x20) ? "yes" : "no"); + + + printf("\n"); } printf("\n"); @@ -1060,7 +1081,11 @@ static struct nametable_entry atomconn_type_name[] = { { 6, "CTV"}, { 7, "LVDS"}, { 8, "Digital"}, - { 9, "Unsupported"}, + { 9, "SCART"}, + { 10, "HDMI A"}, + { 11, "HDMI B"}, + { 14, "Special DIN"}, + { 15, "Unsupported"}, { 0, NULL} }; @@ -1077,14 +1102,51 @@ static void radeon_rom_atom_connectors(unsigned char *bios, int master) tmp = BIOS16(offset + 4); printf("Connector table:\n"); - for (i=0; i<8; i++) { + for (i=0; i<16; i++) { if (tmp & (1<> 8) & 0xf; dac = (portinfo & 0xf) - 1; connector = (portinfo >> 4) & 0xf; + printf("output id: %d\n", crtc); + tmp0 = BIOS16(master + 24); if (1/*crtc*/) { int gpio = BIOS16(tmp0 + 4 + 27 * crtc) * 4; @@ -1110,6 +1172,8 @@ static void radeon_rom_atom_connectors(unsigned char *bios, int master) printf(" TMDS: Internal\n"); else if (i==7) printf(" TMDS: External\n"); + else if (i==9) + printf(" TMDS: External\n"); else printf("\n"); @@ -1117,6 +1181,448 @@ static void radeon_rom_atom_connectors(unsigned char *bios, int master) } } +static void radeon_rom_legacy_lcdtable(unsigned char *bios, int hdr) +{ + int offset, i, type_info, extended_offset; + unsigned int setup; + char stmp[30]; + + offset = BIOS16(hdr + 0x40); + if (offset == 0) { + printf("No LCD info table\n"); + return; + } + printf("\nLCD info table:\n"); + printf("lcd panel id: %d\n", BIOS8(offset)); + for (i = 0; i < 24; i++) + stmp[i] = BIOS8(offset+i+1); + stmp[24] = 0; + printf("lcd panel id string: %s\n", stmp); + printf("lcd panel x: %d\n", BIOS16(offset+0x19)); + printf("lcd panel y: %d\n", BIOS16(offset+0x1b)); + + type_info = BIOS16(offset+0x1d); + if (type_info & 0x1) + printf("color "); + else + printf("mono "); + + if (type_info & 0x2) + printf("single "); + else + printf("dual "); + + switch ((type_info & 0xfc) >> 2) { + case 0: + printf("STN\n"); + break; + case 1: + default: + printf("TFT\n"); + break; + case 2: + printf("active addressed STN\n"); + break; + case 3: + printf("EL\n"); + break; + case 4: + printf("Plasma\n"); + break; + } + + printf("lcd panel power delay: %d\n", BIOS16(offset+0x24)); + + extended_offset = BIOS16(offset+0x26); + if (extended_offset) { + printf("lcd panel extended info offset: %d\n", extended_offset); + printf("lcd extended info rev: %d\n", BIOS8(extended_offset)); + } + + printf("lcd panel vcc delay: %d\n", BIOS16(offset+0x2c)); + printf("lcd panel ref div: %d\n", BIOS16(offset+0x2e)); + printf("lcd panel post div: %d\n", BIOS8(offset+0x30)); + printf("lcd panel fb div: %d\n", BIOS16(offset+0x31)); + printf("lcd panel DIGON to LVDS active: %d\n", BIOS8(offset+0x38) & 0xf); + printf("lcd panel LVDS active to BLON: %d\n", (BIOS8(offset+0x38) >> 4) & 0xf); + setup = BIOS32(offset+0x39); + printf("lcd panel LVDS setup: 0x%x\n", setup); + + if (setup & 0x1) + printf("888 RGB\n"); + else + printf("666 RGB\n"); + + switch ((setup >> 8) & 0x8) { + case 0: + printf("no frame modulation\n"); + break; + case 1: + printf("2 levels of grey\n"); + break; + case 2: + printf("4 levels of grey\n"); + break; + default: + printf("STN panel\n"); + break; + } + + if ((setup >> 16) & 0x1) + printf("frame pulse high\n"); + else + printf("frame pulse low\n"); + + if ((setup >> 17) & 0x1) + printf("line pulse high\n"); + else + printf("line pulse low\n"); + + if ((setup >> 18) & 0x1) + printf("MOD high\n"); + else + printf("MOD low\n"); + + if ((setup >> 23) & 0x1) + printf("backlight mod 29 Mhz\n"); + else + printf("backlight mod 29 Mhz / 3\n"); +} + +static void radeon_rom_legacy_mobiletable(unsigned char *bios, int hdr) +{ + int offset, rev, i, gpiooffset, blocks, powerplayoffset, lcdddcoffset, tmdspoweroffset; + unsigned int reg, andmask, ormask; + + offset = BIOS16(hdr + 0x42); + if (offset == 0) { + printf("No mobile info table\n"); + return; + } + rev = BIOS8(offset); + printf("mobile table revision: %d\n", rev); + + switch (BIOS8(offset + 0x8) & 0xf) { + case 1: + printf("CRT i2c clk=GPIO0, data=GPIO1\n"); + break; + case 2: + printf("CRT i2c clk=GPIO4, data=GPIO3\n"); + break; + default: + printf("%d\n", BIOS8(offset + 0x8) & 0xf); + break; + } + + gpiooffset = BIOS16(offset+0x13); + if (gpiooffset) { + printf("gpio table revision: %d\n", BIOS8(gpiooffset)); + blocks = BIOS8(gpiooffset + 0x2); + printf("gpio blocks: %d\n", blocks); + + for (i = 0; i < blocks; i++) { + reg = BIOS16(gpiooffset + 3 + (i * 10) + 0); + andmask = BIOS32(gpiooffset + 3 + (i * 10) + 0x2); + ormask = BIOS32(gpiooffset + 3 + (i * 10) + 0x6); + printf("reg: 0x%x, AND: 0x%x, OR: 0x%x\n", reg * 4, andmask, ormask); + } + } + powerplayoffset = BIOS16(offset+0x11); + if (powerplayoffset) { + unsigned int powerplay_flags; + int powerplay_rev = BIOS8(powerplayoffset); + printf("powerplay table revision: %d\n", powerplay_rev); + blocks = BIOS8(powerplayoffset+0x2); + printf("powerplay states: %d\n", blocks); + for (i = 0; i < blocks; i++) { + printf("state %d\n", i); + powerplay_flags = BIOS16(powerplayoffset + 5 + (i * 0x10)); + if (powerplay_flags & 0x1) + printf("\tMCLK_SRC_SPLL\n"); + else if (powerplay_flags & 0x2) + printf("\tSCLK_SRC_MPLL\n"); + else + printf("\tsplit clock\n"); + if (powerplay_flags & 0x4) { + printf("\tvoltage drop supported\n"); + if (powerplay_flags & 0x8) + printf("\tvoltage drop active high\n"); + else + printf("\tvoltage drop active low\n"); + } + if (powerplay_flags & 0x10) + printf("\tlcd refresh rate change\n"); + if (powerplay_flags & 0x20) + printf("\tengine clk control enabled\n"); + if (powerplay_flags & 0x40) + printf("\tmemory clk control enabled\n"); + if (powerplay_flags & 0x80) + printf("\toverclock mode\n"); + else if (powerplay_rev <= 3) + printf("\tpowersave mode\n"); + if (powerplay_flags & 0x100) + printf("\thalf engine clk\n"); + if (powerplay_flags & 0x200) + printf("\tdynamic voltage control enabled\n"); + if (powerplay_flags & 0x400) + printf("\tpower state sleep mode enabled\n"); + if (powerplay_flags & 0x800) + printf("\tpower state load balancing enabled\n"); + if (powerplay_flags & 0x1000) + printf("\tdefault DC state\n"); + if (powerplay_flags & 0x2000) + printf("\tdefault DC low state\n"); + if (powerplay_rev > 3) { + if (powerplay_flags & 0x4000) + printf("\tpowersave mode\n"); + if (powerplay_flags & 0x8000) + printf("\tthermal diode mode\n"); + } + printf("\tmclk/sclk: %f/%f\n", + BIOS32(powerplayoffset + 5 + (i * 0x10) + 0x2) / 100.0, + BIOS32(powerplayoffset + 5 + (i * 0x10) + 0x6) / 100.0); + switch (BIOS8(powerplayoffset + 5 + (i * 0x10) + 0xa)) { + case 0: + printf("\tLCD refresh: 50 Hz\n"); + break; + case 2: + printf("\tLCD refresh: 56 Hz\n"); + break; + case 4: + printf("\tLCD refresh: 60 Hz\n"); + break; + case 6: + printf("\tLCD refresh: 67 Hz\n"); + break; + case 8: + printf("\tLCD refresh: 70 Hz\n"); + break; + case 10: + printf("\tLCD refresh: 72 Hz\n"); + break; + case 12: + printf("\tLCD refresh: 75 Hz\n"); + break; + case 14: + printf("\tLCD refresh: 76 Hz\n"); + break; + case 16: + printf("\tLCD refresh: 85 Hz\n"); + break; + case 18: + printf("\tLCD refresh: 90 Hz\n"); + break; + case 20: + printf("\tLCD refresh: 100 Hz\n"); + break; + case 22: + printf("\tLCD refresh: 120 Hz\n"); + break; + case 24: + printf("\tLCD refresh: 140 Hz\n"); + break; + case 26: + printf("\tLCD refresh: 150 Hz\n"); + break; + case 28: + printf("\tLCD refresh: 160 Hz\n"); + break; + case 30: + printf("\tLCD refresh: 200 Hz\n"); + break; + case 1: + printf("\tLCD refresh: 40 Hz\n"); + break; + case 3: + printf("\tLCD refresh: 30 Hz\n"); + break; + default: + break; + } + if (powerplay_rev < 6) { + printf("\tvoltage control reg: 0x%x\n", BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xb) * 4); + printf("\tvoltage control bits: %d\n", BIOS8(powerplayoffset + 5 + (i * 0x10) + 0xd)); + } else { + int j; + int entries = BIOS8(powerplayoffset + 5 + (i * 0x10) + 0xb); + int voltage_table_offset = BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xc); + if (entries && voltage_table_offset) { + printf("\t%d entries in voltage drop table\n", entries); + printf("\tvoltage drop table at 0x%x\n", voltage_table_offset); + for (j = 0; j < entries; j++) { + printf("\t\tvoltage drop register: 0x%x\n", + BIOS16(voltage_table_offset) * 4); + printf("\t\tvoltage drop register bits: %d\n", + BIOS16(voltage_table_offset + 0x2)); + } + } + } + if (powerplay_rev < 5) { + if (BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xe)) + printf("\tpowerplay memory reset table at 0x%x\n", + BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xe)); + } else { + int powerplay_flags2 = BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xe); + if (powerplay_flags2 & 0x1) + printf("\tenable frame modulation w/ 2 level grey\n"); + else if (powerplay_flags2 & 0x2) + printf("\tenable frame modulation w/ 4 level grey\n"); + else + printf("\tdisable frame modulation\n"); + if (powerplay_flags2 & 0x4) + printf("\tenable dynamic half clock\n"); + if (powerplay_flags2 & 0x8) + printf("\tenable dynamic clock on static screen\n"); + if (powerplay_flags2 & 0x10) + printf("\tenable dynamic clocking in 2D\n"); + if ((powerplay_flags2 & 0xe0) == 0x20) + printf("\tdynamic clocking divider: 1/2\n"); + else if ((powerplay_flags2 & 0xe0) == 0x40) + printf("\tdynamic clocking divider: 1/3\n"); + else if ((powerplay_flags2 & 0xe0) == 0x60) + printf("\tdynamic clocking divider: 1/4\n"); + printf("\tdelay between voltage drop and sclk change: "); + if ((powerplay_flags2 & 0x700) == 0) + printf("no delay\n"); + else if ((powerplay_flags2 & 0x700) == 0x100) + printf("33 us\n"); + else if ((powerplay_flags2 & 0x700) == 0x200) + printf("66 us\n"); + else if ((powerplay_flags2 & 0x700) == 0x300) + printf("99 us\n"); + else if ((powerplay_flags2 & 0x700) == 0x400) + printf("132 us\n"); + if (powerplay_rev > 6) { + int pcie_lanes; + if (powerplay_flags2 & 0x800) + printf("\tperformance mode\n"); + if (powerplay_flags2 & 0x1000) + printf("\tvri-brightness required\n"); + pcie_lanes = BIOS8(powerplayoffset + 5 + (i * 0x10) + 0x10); + if (pcie_lanes == 0) + pcie_lanes = 16; + printf("\t%d pcie lanes\n", pcie_lanes); + } + } + } + } + lcdddcoffset = BIOS16(offset+0x15); + if (lcdddcoffset) { + int i2cline; + printf("LCD DDC table revision: %d\n", BIOS8(lcdddcoffset)); + i2cline = BIOS8(lcdddcoffset+0x2); + printf("LCD DDC table i2c line: %d\n", i2cline); + if (i2cline > 4) { + printf("LCD DDC table i2c clock pin mask: 0x%x\n", BIOS32(lcdddcoffset+0x3)); + printf("LCD DDC table i2c data pin mask: 0x%x\n", BIOS32(lcdddcoffset+0x7)); + } + } + tmdspoweroffset = BIOS16(offset+0x17); + if (tmdspoweroffset) { + int tmdsflags = BIOS8(tmdspoweroffset + 1); + int ontable_offset = BIOS16(tmdspoweroffset + 2); + int ontable_rev = BIOS8(ontable_offset); + int offtable_offset = BIOS16(tmdspoweroffset + 4); + int offtable_rev = BIOS8(offtable_offset); + printf("tmds power on/off table at offset: 0x%x\n", tmdspoweroffset); + printf("tmds power on/off table revision: %d\n", BIOS8(tmdspoweroffset)); + if (tmdsflags & 1) + printf("external tmds\n"); + else + printf("internal tmds\n"); + printf("tmds power on table revision: %d\n", ontable_rev); + if (ontable_rev == 1) { + // fix me + } else if (ontable_rev == 2) { + int j = 4; + int type; + int blocks = BIOS8(ontable_offset + 3); + int start = BIOS16(ontable_offset + j); + int size = BIOS16(ontable_offset + 1); + printf("tmds on table size: %d bytes\n", size); + printf("tmds on table blocks: %d \n", blocks); + while (blocks > 0) { + type = (start & 0xe000) >> 13; + if (type == 0) { + unsigned int reg = BIOS16(ontable_offset + j) & 0x1fff; + unsigned int val = BIOS32(ontable_offset + j + 2); + printf("mmio reg: 0x%x, val: 0x%x\n", reg, val); + j += 6; + } else if (type == 2) { + unsigned int reg = BIOS16(ontable_offset + j) & 0x1fff; + unsigned int and_mask = BIOS32(ontable_offset + j + 2); + unsigned int or_mask = BIOS32(ontable_offset + j + 6); + printf("mmio reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n", + reg * 4, and_mask, or_mask); + j += 10; + } else if (type == 3) { + printf("delay %d ms\n", BIOS16(ontable_offset + j + 2)); + j += 4; + } else if (type == 4) { + printf("delay %d us\n", BIOS16(ontable_offset + j + 2)); + j += 4; + } else if (type == 6) { + int i2c_slave_addr = BIOS16(ontable_offset + j) & 0xff; + int i2c_id = BIOS8(ontable_offset + j + 2); + int i2c_reg = BIOS8(ontable_offset + j + 3); + int i2c_reg_val = BIOS8(ontable_offset + j + 4); + printf("write to i2c addr 0x%x (i2c id %d) reg: 0x%x, val: 0x%x\n", + i2c_slave_addr, i2c_id, i2c_reg, i2c_reg_val); + j += 5; + } else + break; + blocks--;; + start = BIOS16(ontable_offset + j); + } + } + printf("tmds power off table revision: %d\n", offtable_rev); + if (offtable_rev == 1) { + // fix me + } else if (offtable_rev == 2) { + int j = 4; + int type; + int blocks = BIOS8(offtable_offset + 3); + int start = BIOS16(offtable_offset + j); + int size = BIOS16(offtable_offset + 1); + printf("tmds off table size: %d bytes\n", size); + printf("tmds off table blocks: %d \n", blocks); + while (blocks > 0) { + type = (start & 0xe000) >> 13; + if (type == 0) { + unsigned int reg = BIOS16(offtable_offset + j) & 0x1fff; + unsigned int val = BIOS32(offtable_offset + j + 2); + printf("mmio reg: 0x%x, val: 0x%x\n", reg, val); + j += 6; + } else if (type == 2) { + unsigned int reg = BIOS16(offtable_offset + j) & 0x1fff; + unsigned int and_mask = BIOS32(offtable_offset + j + 2); + unsigned int or_mask = BIOS32(offtable_offset + j + 6); + printf("pll reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n", + reg * 4, and_mask, or_mask); + j += 10; + } else if (type == 3) { + printf("delay %d ms\n", BIOS16(offtable_offset + j + 2)); + j += 4; + } else if (type == 4) { + printf("delay %d us\n", BIOS16(offtable_offset + j + 2)); + j += 4; + } else if (type == 6) { + int i2c_slave_addr = BIOS16(offtable_offset + j) & 0xff; + int i2c_id = BIOS8(offtable_offset + j + 2); + int i2c_reg = BIOS8(offtable_offset + j + 3); + int i2c_reg_val = BIOS8(offtable_offset + j + 4); + printf("write to i2c addr 0x%x (i2c id %d) reg: 0x%x, val: 0x%x\n", + i2c_slave_addr, i2c_id, i2c_reg, i2c_reg_val); + j += 5; + } else + break; + blocks--; + start = BIOS16(offtable_offset + j); + } + } + } +} + static void radeon_rom_legacy_dfptable(unsigned char *bios, int hdr) { int offset, i, n, rev, stride; @@ -1162,6 +1668,519 @@ static void radeon_rom_legacy_dfptable(unsigned char *bios, int hdr) } } +static void radeon_rom_legacy_crttable(unsigned char *bios, int hdr) +{ + int offset, rev, dac2table, dac2muxreg, bgadjcrt1, dacwhitecrt1, bgadjcrt2, dacadjcrt2, temp; + + offset = BIOS16(hdr + 0x60); + if (offset == 0) { + printf("No CRT info table\n"); + return; + } + rev = BIOS8(offset) & 0x3; + printf("\nCRT table revision: %d\n", rev); + + printf("\nCRT table size: %d bytes\n", BIOS8(offset+1)); + + if (rev == 2) { + + bgadjcrt1 = BIOS8(offset + 0x2); + dacwhitecrt1 = BIOS8(offset + 0x3); + printf("crt1: 0x%x, 0x%x\n", bgadjcrt1, dacwhitecrt1); + + bgadjcrt2 = BIOS8(offset + 0x4); + dacadjcrt2 = BIOS8(offset + 0x5); + printf("crt2: 0x%x, 0x%x\n", bgadjcrt2, dacadjcrt2); + + dac2table = BIOS16(offset+8); + + } else { + + bgadjcrt1 = BIOS8(offset + 0x2) & 0xf; + dacwhitecrt1 = (BIOS8(offset + 0x2) >> 4) & 0xf; + printf("crt1: 0x%x, 0x%x\n", bgadjcrt1, dacwhitecrt1); + + bgadjcrt2 = BIOS8(offset + 0x3) & 0xf; + dacadjcrt2 = (BIOS8(offset + 0x3) >> 4) & 0xf; + printf("crt2: 0x%x, 0x%x\n", bgadjcrt2, dacadjcrt2); + + dac2table = BIOS16(offset + 0x5); + } + + printf("reg val 0x%x\n", (bgadjcrt2 << 16) | (dacadjcrt2 << 20)); + + if (dac2table) { + printf("\nDac2 table: 0x%x\n", dac2table); + printf("revision: %d\n", (BIOS16(dac2table) & 0x3)); + dac2muxreg = BIOS16(dac2table + 0x2); + printf("\nmux reg: 0x%x\n", dac2muxreg); + temp = BIOS8(dac2table + 0x4); + if (temp & 0x80) + printf("CRT2 active high\n"); + else + printf("CRT2 active low\n"); + + printf("pin detection bits: 0x%x\n", (temp & 0x1f)); + printf("access mode: 0x%x\n", ((temp >> 5) & 0x3)); + + } + +} + +static void radeon_rom_legacy_list_tables_present(unsigned char *bios, int hdr) +{ + int offset; + + offset = BIOS16(hdr + 0xc); + if (offset) { + printf("asic init table 1\n"); + } + offset = BIOS16(hdr + 0x14); + if (offset) { + printf("bios support info table\n"); + } + offset = BIOS16(hdr + 0x2a); + if (offset) { + printf("dac programming info table\n"); + } + offset = BIOS16(hdr + 0x2c); + if (offset) { + printf("max color depth info table\n"); + } + offset = BIOS16(hdr + 0x2e); + if (offset) { + printf("crtc info table\n"); + } + offset = BIOS16(hdr + 0x30); + if (offset) { + printf("pll info table\n"); + } + offset = BIOS16(hdr + 0x32); + if (offset) { + printf("TV info table\n"); + } + offset = BIOS16(hdr + 0x34); + if (offset) { + printf("DFP info table\n"); + } + offset = BIOS16(hdr + 0x36); + if (offset) { + printf("HW config info table\n"); + } + offset = BIOS16(hdr + 0x38); + if (offset) { + printf("multimedia info table\n"); + } + offset = BIOS16(hdr + 0x3e); + if (offset) { + printf("tv standard patch table\n"); + } + offset = BIOS16(hdr + 0x40); + if (offset) { + printf("LCD info table\n"); + } + offset = BIOS16(hdr + 0x42); + if (offset) { + printf("Mobile info table\n"); + } + offset = BIOS16(hdr + 0x46); + if (offset) { + printf("pll init info table\n"); + } + offset = BIOS16(hdr + 0x48); + if (offset) { + printf("mem config info table\n"); + } + offset = BIOS16(hdr + 0x4a); + if (offset) { + printf("save mask info table\n"); + } + offset = BIOS16(hdr + 0x4c); + if (offset) { + printf("Hardcoded DFP edid\n"); + } + offset = BIOS16(hdr + 0x4e); + if (offset) { + printf("asic init table 2\n"); + } + offset = BIOS16(hdr + 0x50); + if (offset) { + printf("connector info table\n"); + } + offset = BIOS16(hdr + 0x52); + if (offset) { + printf("dyn clock 1 info table\n"); + } + offset = BIOS16(hdr + 0x54); + if (offset) { + printf("reserved mem info table\n"); + } + offset = BIOS16(hdr + 0x58); + if (offset) { + printf("Ext TMDS info table\n"); + } + offset = BIOS16(hdr + 0x5a); + if (offset) { + printf("mem clock info table\n"); + } + offset = BIOS16(hdr + 0x5c); + if (offset) { + printf("ext DAC info table\n"); + } + offset = BIOS16(hdr + 0x5e); + if (offset) { + printf("misc info table\n"); + } + offset = BIOS16(hdr + 0x60); + if (offset) { + printf("CRT info table\n"); + } + offset = BIOS16(hdr + 0x62); + if (offset) { + printf("integrated system info table\n"); + } + offset = BIOS16(hdr + 0x64); + if (offset) { + printf("Component video info table\n"); + } + offset = BIOS16(hdr + 0x66); + if (offset) { + printf("fan speed info table\n"); + } + offset = BIOS16(hdr + 0x68); + if (offset) { + printf("overdrive info table\n"); + } + offset = BIOS16(hdr + 0x6a); + if (offset) { + printf("OEM info table\n"); + } + offset = BIOS16(hdr + 0x6c); + if (offset) { + printf("dyn clock 2 info table\n"); + } + offset = BIOS16(hdr + 0x6e); + if (offset) { + printf("power connector info table\n"); + } + offset = BIOS16(hdr + 0x70); + if (offset) { + printf("i2c info table\n"); + } + offset = BIOS16(hdr + 0x72); + if (offset) { + printf("object header info table\n\n"); + } + printf("\n"); +} + +static void radeon_rom_legacy_biosinfotable(unsigned char *bios, int hdr) +{ + int offset, i; + char strp[4]; + + offset = BIOS16(hdr + 0x14); + if (offset == 0) { + printf("bios info table\n"); + return; + } + printf("bios info table\n"); + for (i = 0; i < 4; i++) + strp[i] = BIOS8(offset + i); + printf("chip type: %s\n", strp); + for (i = 0; i < 4; i++) + strp[i] = BIOS32(offset + 4 + i); + printf("bus type: %s\n", strp); + for (i = 0; i < 4; i++) + strp[i] = BIOS32(offset + 8 + i); + printf("mem type: %s\n", strp); + + +} + +static void radeon_rom_legacy_miscinfotable(unsigned char *bios, int hdr) +{ + int offset, rev, start, size; + + offset = BIOS16(hdr + 0x5e); + if (offset == 0) { + printf("No misc info table\n"); + return; + } + rev = BIOS8(offset); + printf("misc info table revision: %d\n", rev); + if (rev > 0) { + size = BIOS8(offset + 2); + printf("misc info table size: %d bytes\n", size); + + } + start = BIOS8(offset + 1); + if (start & 0x1) + printf("dualview supported\n"); + if (rev == 8) + if (start & 0x8) + printf("sleep mode enabled in perfomance mode\n"); + if (start & 0x20) + printf("hypermemory flag\n"); + if (rev == 5) { + if (start & 0x40) + printf("sleep mode enabled in perfomance mode\n"); + } else if (rev == 8) { + if (start & 0x40) + printf("power state load balancing is enabled in perfomance mode\n"); + } + if (rev == 6) + if (start & 0x80) + printf("WMI thermal method supported\n"); + if (rev > 0) { + if (BIOS16(offset + 0x3)) + printf("asic init table 3 offset: 0x%x\n", BIOS16(offset + 0x3)); + if (BIOS16(offset + 0x5)) + printf("asic init table 4 offset: 0x%x\n", BIOS16(offset + 0x5)); + if (BIOS16(offset + 0x7)) + printf("detected mem config table offset: 0x%x\n", BIOS16(offset + 0x7)); + if (rev == 2) { + if (BIOS16(offset + 0x9)) + printf("asic init table 5 offset: 0x%x\n", BIOS16(offset + 0x9)); + if (BIOS16(offset + 0xb)) + printf("memreset sequence table offset: 0x%x\n", BIOS16(offset + 0xb)); + } else if ((rev == 4) || (rev == 5) || (rev == 6)) { + if (BIOS16(offset + 0x9)) + printf("pointer to asic init table 5 offset list: 0x%x\n", BIOS16(offset + 0x9)); + if (BIOS16(offset + 0xb)) + printf("pointer to memreset sequence table offset list: 0x%x\n", BIOS16(offset + 0xb)); + } + if ((rev == 5) || (rev == 6)) { + if (BIOS16(offset + 0xd)) + printf("mem info table offset: 0x%x\n", BIOS16(offset + 0xd)); + printf("min backlight value: 0x%x\n", BIOS8(offset + 0xf)); + } + if (rev == 7) { + if (BIOS16(offset + 0x7)) + printf("pointer to detected mem config table offset list: 0x%x\n", BIOS16(offset + 0x7)); + if (BIOS16(offset + 0x9)) + printf("pointer to asic init table 5 offset list: 0x%x\n", BIOS16(offset + 0x9)); + if (BIOS16(offset + 0xb)) + printf("pointer to memreset sequence table offset list: 0x%x\n", BIOS16(offset + 0xb)); + } + if (rev >= 6) { + int flags = BIOS8(offset + 0x10); + if (flags & 0x1) + printf("driver controls brightness\n"); + if (flags & 0x2) + printf("bios controls powerplay\n"); + if (flags & 0x4) + printf("use new mem reset sequence\n"); + if (flags & 0x8) + printf("power state load balancing is disabled in performance mode\n"); + if (rev == 9) + if (flags & 0x40) + printf("PCIE to PCI bridge present\n"); + } + + } +} + +static void radeon_rom_legacy_dynclk1table(unsigned char *bios, int hdr) +{ + int offset, type, start, i = 0; + + offset = BIOS16(hdr + 0x52); + if (offset == 0) { + printf("No dyn clock 1 info table\n"); + return; + } + start = BIOS8(offset); + printf("dyn clock 1 info table\n"); + while (start != 0) { + type = (start & 0xc0) >> 6; + if (type == 0) { + int reg = BIOS8(offset + i) & 0x3f; + unsigned int val = BIOS32(offset + i + 1); + printf("pll reg: 0x%x, val: 0x%x\n", reg, val); + i += 5; + } else if (type == 1) { + int reg = BIOS8(offset + i) & 0x3f; + int byte_offset = BIOS8(offset + i + 1); + int and_mask = BIOS8(offset + i + 2); + int or_mask = BIOS8(offset + i + 3); + printf("pll reg: 0x%x, byte offset of dword 0x%x, AND mask: 0x%x, OR mask: 0x%x\n", + reg, byte_offset, and_mask, or_mask); + i += 4; + } else if (type >= 2) { + int cmd = BIOS8(offset + i) & 0x3f; + switch (cmd) { + case 1: + printf("delay 150 us\n"); + break; + case 2: + printf("delay 1 ms\n"); + break; + case 3: + printf("wait for MC_BUSY = 0 in CLK_PWRMGT_CNTL\n"); + break; + case 4: + printf("wait for DLL_READY = 1 in CLK_PWRMGT_CNTL\n"); + break; + case 5: + printf("check and set bit 24 in CLK_PWRMGT_CNTL to 0\n"); + break; + } + i += 1; + } else + break; + start = BIOS8(offset + i); + } + +} + +static void radeon_rom_legacy_dynclk2table(unsigned char *bios, int hdr) +{ + int offset, type, start, rev, i = 0; + + offset = BIOS16(hdr + 0x52); + if (offset == 0) { + printf("No dyn clock 2 info table\n"); + return; + } + rev = BIOS8(offset - 1); + start = BIOS16(offset); + printf("dyn clock 2 info table revision %d\n", rev); + while (start != 0) { + type = (start & 0xe000) >> 13; + if (type == 0) { + unsigned int reg = BIOS16(offset + i) & 0x1fff; + unsigned int val = BIOS32(offset + i + 2); + printf("mmio reg: 0x%x, val: 0x%x\n", reg * 4, val); + i += 6; + } else if (type == 1) { + unsigned int reg = BIOS16(offset + i) & 0x1fff; + unsigned int val = BIOS32(offset + i + 2); + printf("I/O reg: 0x%x, val: 0x%x\n", reg * 4, val); + i += 6; + } else if (type == 2) { + unsigned int reg = BIOS16(offset + i) & 0x1fff; + unsigned int and_mask = BIOS32(offset + i + 2); + unsigned int or_mask = BIOS32(offset + i + 6); + printf("mmio reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n", + reg * 4, and_mask, or_mask); + i += 10; + } else if (type == 3) { + unsigned int reg = BIOS16(offset + i) & 0x1fff; + unsigned int and_mask = BIOS32(offset + i + 2); + unsigned int or_mask = BIOS32(offset + i + 6); + printf("I/O reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n", + reg * 4, and_mask, or_mask); + i += 10; + } else if (type == 4) { + printf("delay %d us\n", BIOS16(offset + i + 2)); + i += 4; + } else + break; + start = BIOS16(offset + i); + } +} + +static void radeon_rom_legacy_igptable(unsigned char *bios, int hdr) +{ + int offset, rev, fsb; + + offset = BIOS16(hdr + 0x62); + if (offset == 0) { + printf("No igp info table\n"); + return; + } + rev = BIOS8(offset); + printf("\nigp table revision: %d\n", rev); + + fsb = BIOS16(offset + 0x2); + if (rev < 2) + fsb *= 100; + printf("FSB: %f Mhz\n", fsb); + + printf("mclk reference frequency: %f Mhz\n", BIOS16(offset + 0x4) / 100.00); + printf("mclk reference divider: %d \n", BIOS16(offset + 0x6)); + printf("memory refresh period from SPD: %d \n", BIOS8(offset + 0x8)); + if (rev > 0) + printf("min mclk: %f \n", BIOS16(offset + 0xd) / 100.00); + if (rev > 1) + printf("max mclk: %f \n", BIOS16(offset + 0xf) / 100.00); + if (rev > 2) { + printf("K8 mclk: %f \n", BIOS16(offset + 0x11)); + printf("K8 sync start delay: %f us\n", BIOS16(offset + 0x13) / 100); + printf("K8 data return time: %f us\n", BIOS16(offset + 0x15) / 100); + } + if (rev > 3) { + if (BIOS16(offset + 0x17) & 1) + printf("PCIE lane reserved\n"); + else + printf("PCIE lane not reserved\n"); + } +} + +static void radeon_rom_legacy_componenttv_table(unsigned char *bios, int hdr) +{ + int offset, rev, temp; + + offset = BIOS16(hdr + 0x62); + if (offset == 0) { + printf("No component tv info table\n"); + return; + } + rev = BIOS8(offset); + printf("\ncomponent tv table revision: %d\n", rev); + + if (rev < 3) { + if (BIOS8(offset + 0x2) & 0x4) + printf("CRT2 Mux used as well to switch to CV\n"); + if (BIOS8(offset + 0x2) & 0x8) + printf("Low voltage TV/CV MUX control\n"); + } else { + if (BIOS8(offset + 0x2) & 0x10) + printf("enable access for i2c D-Connect Support\n"); + } + printf("GPIO register for detection: 0x%x \n", BIOS16(offset + 0x3)); + temp = BIOS8(offset + 0x5); + if (temp & 0x80) + printf("Active high\n"); + else + printf("Active low\n"); + printf("GPIO TV/HDTV MUX control register: 0x%x \n", BIOS16(offset + 0x6)); + temp = BIOS8(offset + 0x8); + if (temp & 0x80) + printf("Active high\n"); + else + printf("Active low\n"); + +} + +static void radeon_rom_legacy_i2ctable(unsigned char *bios, int hdr) +{ + int offset, rev, size, blocks, i, id, reg, clock, data; + + offset = BIOS16(hdr + 0x70); + if (offset == 0) { + printf("No i2c info table\n"); + return; + } + rev = BIOS8(offset); + printf("\ni2c table revision: %d\n", rev); + size = BIOS8(offset + 1); + printf("i2c table size: %d\n", size); + + blocks = BIOS8(offset + 2); + printf("i2c blocks: %d\n", blocks); + + for (i = 0; i < blocks; i++) { + id = BIOS8(offset + 3 + (i * 5) + 0); + reg = BIOS16(offset + 3 + (i * 5) + 1); + clock = BIOS8(offset + 3 + (i * 5) + 3); + data = BIOS8(offset + 3 + (i * 5) + 4); + printf("id: %d, reg: 0x%x, clk: %d, data: %d\n", id, reg * 4, clock, data); + } + +} + static void radeon_rom_legacy_tvtable(unsigned char *bios, int hdr) { int offset, rev, refclk, drvstds, biosstds; @@ -1174,6 +2193,9 @@ static void radeon_rom_legacy_tvtable(unsigned char *bios, int hdr) rev = BIOS8(offset + 3); printf("\nTV table revision: %d\n", rev); + + printf("\nTV table size: %d\n", BIOS16(offset + 4)); + if (BIOS8(offset + 6) == 'T') printf("TV out on board\n"); else @@ -1246,11 +2268,64 @@ static void radeon_rom_legacy_tvtable(unsigned char *bios, int hdr) if (biosstds & 32) printf("SCART-PAL"); printf("\n"); + + if (rev >= 5) { + int temp, temp2; + + temp = BIOS8(offset + 0xc); + temp2 = BIOS8(offset + 0xd); + printf("crt2 ps2: 0x%x, 0x%x\n", temp, temp2); + + temp = BIOS8(offset + 0xe); + temp2 = BIOS8(offset + 0xf); + printf("crt2 pal: 0x%x, 0x%x\n", temp, temp2); + + temp = BIOS8(offset + 0x10); + temp2 = BIOS8(offset + 0x11); + printf("crt2 ntsc: 0x%x, 0x%x\n", temp, temp2); + + temp = BIOS16(offset + 0x12); + printf("gpio reg: 0x%x\n", temp); + + temp = BIOS16(offset + 0x14); + printf("gpio AND mask: 0x%x\n", temp); + + temp = BIOS16(offset + 0x18); + printf("gpio OR mask: 0x%x\n", temp); + + } else if (rev >= 2) { + int temp, temp2; + + temp = BIOS8(offset + 0xc) & 0xf; + temp2 = (BIOS8(offset + 0xc) >> 4) & 0xf; + printf("crt2 ps2: 0x%x, 0x%x\n", temp, temp2); + + temp = BIOS8(offset + 0xd) & 0xf; + temp2 = (BIOS8(offset + 0xd) >> 4) & 0xf; + printf("crt2 pal: 0x%x, 0x%x\n", temp, temp2); + + temp = BIOS8(offset + 0xe) & 0xf; + temp2 = (BIOS8(offset + 0xe) >> 4) & 0xf; + printf("crt2 ntsc: 0x%x, 0x%x\n", temp, temp2); + + if (rev > 2) { + temp = BIOS8(offset + 0x10); + printf("gpio bit: 0x%x\n", temp); + } + + if (rev > 3) { + temp = BIOS16(offset + 0x11); + printf("gpio reg: 0x%x\n", temp); + } + + } + + } static void radeon_rom_legacy_exttmdstable(unsigned char *bios, int hdr) { - int offset; + int offset, rev; int nr_blocks; int table_start; unsigned short index; @@ -1261,7 +2336,14 @@ static void radeon_rom_legacy_exttmdstable(unsigned char *bios, int hdr) return; } - printf("Found External TMDS Table rev %d\n", BIOS8(offset)); + rev = BIOS8(offset); + + printf("Found External TMDS Table rev %d\n", rev); + + if (rev == 2) + printf("single link\n"); + else if (rev == 3) + printf("dual link\n"); printf("table size %08x\n", BIOS16(offset+1)); @@ -1353,11 +2435,38 @@ void radeon_rom_tables(const char * file) } else { printf("Legacy BIOS detected !\n"); printf("BIOS Rev: %x.%x\n\n", BIOS8(hdr+4), BIOS8(hdr+5)); + radeon_rom_legacy_list_tables_present(bios, hdr); + printf("-------------\n"); radeon_rom_legacy_clocks(bios, hdr); + printf("-------------\n"); radeon_rom_legacy_connectors(bios, hdr); + printf("-------------\n"); radeon_rom_legacy_dfptable(bios, hdr); + printf("-------------\n"); radeon_rom_legacy_exttmdstable(bios, hdr); + printf("-------------\n"); radeon_rom_legacy_tvtable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_crttable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_i2ctable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_lcdtable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_mobiletable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_igptable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_componenttv_table(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_dynclk1table(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_dynclk2table(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_miscinfotable(bios, hdr); + printf("-------------\n"); + radeon_rom_legacy_biosinfotable(bios, hdr); + printf("-------------\n"); } }