diff -ur /tmp/linux-2.6.15/drivers/video/aty/ati_ids.h ./aty/ati_ids.h --- /tmp/linux-2.6.15/drivers/video/aty/ati_ids.h 2006-01-03 14:30:15.000000000 -0500 +++ ./aty/ati_ids.h 2006-01-03 15:12:01.000000000 -0500 @@ -185,6 +185,8 @@ #define PCI_CHIP_R423_UQ 0x5551 #define PCI_CHIP_R423_UR 0x5552 #define PCI_CHIP_R423_UT 0x5554 +#define PCI_CHIP_RV410_5652 0x5652 +#define PCI_CHIP_RV410_VS 0x5653 #define PCI_CHIP_MACH64VT 0x5654 #define PCI_CHIP_MACH64VU 0x5655 #define PCI_CHIP_MACH64VV 0x5656 diff -ur /tmp/linux-2.6.15/drivers/video/aty/radeon_base.c ./aty/radeon_base.c --- /tmp/linux-2.6.15/drivers/video/aty/radeon_base.c 2006-01-03 14:30:15.000000000 -0500 +++ ./aty/radeon_base.c 2006-01-03 15:13:48.000000000 -0500 @@ -214,6 +214,8 @@ CHIP_DEF(PCI_CHIP_R420_JL, R420, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_R420_JM, R420, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_R420_JN, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), + CHIP_DEF(PCI_CHIP_RV410_5652, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), + CHIP_DEF(PCI_CHIP_RV410_VS, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), CHIP_DEF(PCI_CHIP_R420_JP, R420, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_R423_UH, R420, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_R423_UI, R420, CHIP_HAS_CRTC2), @@ -342,7 +344,7 @@ * to phase out Open Firmware images. * * Currently, we only look at the first PCI data, we could iteratre and deal with - * them all, and we should use fb_bios_start relative to start of image and not + * them all, and we should use fp_bios_start relative to start of image and not * relative start of ROM, but so far, I never found a dual-image ATI card * * typedef struct { @@ -655,8 +657,6 @@ rinfo->pll.ref_clk = 2700; break; } - rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK; - #ifdef CONFIG_PPC_OF /* @@ -673,14 +673,31 @@ * and if yes, retreive them */ if (!force_measure_pll && rinfo->bios_seg) { - u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30); + u16 pll_info_block; + if (rinfo->is_atom_bios) { + pll_info_block = BIOS_IN16(rinfo->atom_data_start + 12); + + rinfo->pll.sclk = BIOS_IN32(pll_info_block + 8); + rinfo->pll.mclk = BIOS_IN32(pll_info_block + 12); + rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 82); + rinfo->pll.ref_div = 0; /* Have to get it elsewhere */ + rinfo->pll.ppll_min = BIOS_IN16(pll_info_block + 78); + rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 32); + + if (rinfo->pll.sclk == 0) rinfo->pll.sclk = 20000; + if (rinfo->pll.mclk == 0) rinfo->pll.mclk = 20000; - rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08); - rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a); - rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e); - rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10); - rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12); - rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16); + } else { + pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30); + + rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08); + rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a); + rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e); + rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10); + rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12); + rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16); + + } printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n"); goto found; @@ -701,6 +718,22 @@ printk(KERN_INFO "radeonfb: Used default PLL infos\n"); found: + + /* Check and fix-up the PLL divisor if necessary */ + if (rinfo->pll.ref_div < 2) { + int tmp = INPLL(PPLL_REF_DIV); + if (rinfo->family == CHIP_FAMILY_RS300) { + rinfo->pll.ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; + } else { + rinfo->pll.ref_div = tmp & PPLL_REF_DIV_MASK; + } + + /* Sane default */ + if (rinfo->pll.ref_div < 2) { + rinfo->pll.ref_div = 12; + } + } + /* * Some methods fail to retreive SCLK and MCLK values, we apply default * settings in this case (200Mhz). If that really happne often, we could @@ -2412,6 +2445,7 @@ * We probably need to make sure this is the primary display, * but that is difficult without some arch support. */ + #ifdef CONFIG_X86 if (rinfo->bios_seg == NULL) radeon_find_mem_vbios(rinfo); @@ -2423,6 +2457,28 @@ if (rinfo->bios_seg == NULL && rinfo->is_mobility) radeon_map_ROM(rinfo, pdev); + /* Check BIOS Type */ + { + int tmp = rinfo->fp_bios_start + 4; + if ((BIOS_IN8(tmp) == 'A' && + BIOS_IN8(tmp+1) == 'T' && + BIOS_IN8(tmp+2) == 'O' && + BIOS_IN8(tmp+3) == 'M') || + (BIOS_IN8(tmp) == 'M' && + BIOS_IN8(tmp+1) == 'O' && + BIOS_IN8(tmp+2) == 'T' && + BIOS_IN8(tmp+3) == 'A')) { + rinfo->is_atom_bios = 1; + } else { + rinfo->is_atom_bios = 0; + } + } + + if (rinfo->is_atom_bios) { + rinfo->atom_data_start = BIOS_IN16(rinfo->fp_bios_start + 32); + printk("ATOM BIOS detected\n"); + } + /* Get informations about the board's PLL */ radeon_get_pllinfo(rinfo); diff -ur /tmp/linux-2.6.15/drivers/video/aty/radeon_monitor.c ./aty/radeon_monitor.c --- /tmp/linux-2.6.15/drivers/video/aty/radeon_monitor.c 2005-10-27 20:02:08.000000000 -0400 +++ ./aty/radeon_monitor.c 2006-01-03 12:15:55.000000000 -0500 @@ -169,76 +169,117 @@ if (!rinfo->bios_seg) return 0; - if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) { - printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n"); - rinfo->panel_info.pwr_delay = 200; - return 0; - } - for(i=0; i<24; i++) - stmp[i] = BIOS_IN8(tmp+i+1); - stmp[24] = 0; - printk("radeonfb: panel ID string: %s\n", stmp); - rinfo->panel_info.xres = BIOS_IN16(tmp + 25); - rinfo->panel_info.yres = BIOS_IN16(tmp + 27); - printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n", - rinfo->panel_info.xres, rinfo->panel_info.yres); - - rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44); - RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay); - if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0) - rinfo->panel_info.pwr_delay = 2000; + if (rinfo->is_atom_bios) { + tmp = BIOS_IN16(rinfo->atom_data_start + 16); + if (!tmp) { + printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n"); + rinfo->panel_info.pwr_delay = 200; + return 0; + } - /* - * Some panels only work properly with some divider combinations - */ - rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46); - rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48); - rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49); - if (rinfo->panel_info.ref_divider != 0 && - rinfo->panel_info.fbk_divider > 3) { - rinfo->panel_info.use_bios_dividers = 1; - printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n"); - RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider); - RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider); - RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider); - } - RTRACE("Scanning BIOS table ...\n"); - for(i=0; i<32; i++) { - tmp0 = BIOS_IN16(tmp+64+i*2); - if (tmp0 == 0) - break; - RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2)); - if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) && - (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) { - rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8; - rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) - - BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff; - rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8; - rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26); - rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26); - rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11; - rinfo->panel_info.clock = BIOS_IN16(tmp0+9); - /* Assume high active syncs for now until ATI tells me more... maybe we - * can probe register values here ? - */ - rinfo->panel_info.hAct_high = 1; - rinfo->panel_info.vAct_high = 1; - /* Mark panel infos valid */ - rinfo->panel_info.valid = 1; - - RTRACE("Found panel in BIOS table:\n"); - RTRACE(" hblank: %d\n", rinfo->panel_info.hblank); - RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus); - RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width); - RTRACE(" vblank: %d\n", rinfo->panel_info.vblank); - RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus); - RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width); - RTRACE(" clock: %d\n", rinfo->panel_info.clock); + rinfo->panel_info.xres = BIOS_IN16(tmp+6); + rinfo->panel_info.yres = BIOS_IN16(tmp+10); + printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n", + rinfo->panel_info.xres, rinfo->panel_info.yres); + rinfo->panel_info.pwr_delay = BIOS_IN16(tmp+40); + RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay); + if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0) + rinfo->panel_info.pwr_delay = 2000; + + /* No special divider combinations? */ + + rinfo->panel_info.hblank = BIOS_IN16(tmp+8); + rinfo->panel_info.hOver_plus = BIOS_IN16(tmp+14); + rinfo->panel_info.hSync_width = BIOS_IN16(tmp+16); + rinfo->panel_info.vblank = BIOS_IN16(tmp+12); + rinfo->panel_info.vOver_plus = BIOS_IN16(tmp+18); + rinfo->panel_info.vSync_width = BIOS_IN16(tmp+20); + rinfo->panel_info.clock = BIOS_IN16(tmp+4); + + /* Assume high active syncs for now until ATI tells me more... maybe we + * can probe register values here ? + */ + rinfo->panel_info.hAct_high = 1; + rinfo->panel_info.vAct_high = 1; + /* Mark panel infos valid */ + rinfo->panel_info.valid = 1; + + return 1; + } else { + if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) { + printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n"); + rinfo->panel_info.pwr_delay = 200; + return 0; + } + + for(i=0; i<24; i++) + stmp[i] = BIOS_IN8(tmp+i+1); + stmp[24] = 0; + printk("radeonfb: panel ID string: %s\n", stmp); + rinfo->panel_info.xres = BIOS_IN16(tmp + 25); + rinfo->panel_info.yres = BIOS_IN16(tmp + 27); + printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n", + rinfo->panel_info.xres, rinfo->panel_info.yres); + + rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44); + RTRACE("BIOS provided panel power delay: %d\n", rinfo->panel_info.pwr_delay); + if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0) + rinfo->panel_info.pwr_delay = 2000; + + /* + * Some panels only work properly with some divider combinations + */ + rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46); + rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48); + rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49); + if (rinfo->panel_info.ref_divider != 0 && + rinfo->panel_info.fbk_divider > 3) { + rinfo->panel_info.use_bios_dividers = 1; + printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n"); + RTRACE("ref_divider = %x\n", rinfo->panel_info.ref_divider); + RTRACE("post_divider = %x\n", rinfo->panel_info.post_divider); + RTRACE("fbk_divider = %x\n", rinfo->panel_info.fbk_divider); + } + + RTRACE("Scanning BIOS table ...\n"); + for(i=0; i<32; i++) { + tmp0 = BIOS_IN16(tmp+64+i*2); + if (tmp0 == 0) + break; + RTRACE(" %d x %d\n", BIOS_IN16(tmp0), BIOS_IN16(tmp0+2)); + if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) && + (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) { + rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8; + rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) - + BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff; + rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8; + rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26); + rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26); + rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11; + rinfo->panel_info.clock = BIOS_IN16(tmp0+9); + /* Assume high active syncs for now until ATI tells me more... maybe we + * can probe register values here ? + */ + rinfo->panel_info.hAct_high = 1; + rinfo->panel_info.vAct_high = 1; + /* Mark panel infos valid */ + rinfo->panel_info.valid = 1; - return 1; + RTRACE("Found panel in BIOS table:\n"); + RTRACE(" hblank: %d\n", rinfo->panel_info.hblank); + RTRACE(" hOver_plus: %d\n", rinfo->panel_info.hOver_plus); + RTRACE(" hSync_width: %d\n", rinfo->panel_info.hSync_width); + RTRACE(" vblank: %d\n", rinfo->panel_info.vblank); + RTRACE(" vOver_plus: %d\n", rinfo->panel_info.vOver_plus); + RTRACE(" vSync_width: %d\n", rinfo->panel_info.vSync_width); + RTRACE(" clock: %d\n", rinfo->panel_info.clock); + + return 1; + } } } + RTRACE("Didn't find panel in BIOS table !\n"); return 0; @@ -261,29 +302,34 @@ if (!rinfo->bios_seg) return; - offset = BIOS_IN16(rinfo->fp_bios_start + 0x50); - if (offset == 0) { - printk(KERN_WARNING "radeonfb: No connector info table detected\n"); - return; - } - - /* Don't do much more at this point but displaying the data if - * DEBUG is enabled - */ - chips = BIOS_IN8(offset++) >> 4; - RTRACE("%d chips in connector info\n", chips); - for (i = 0; i < chips; i++) { - tmp = BIOS_IN8(offset++); - connectors = tmp & 0x0f; - RTRACE(" - chip %d has %d connectors\n", tmp >> 4, connectors); - for (conn = 0; ; conn++) { - tmp = BIOS_IN16(offset); - if (tmp == 0) - break; - offset += 2; - type = (tmp >> 12) & 0x0f; - RTRACE(" * connector %d of type %d (%s) : %04x\n", - conn, type, __conn_type_table[type], tmp); + if (rinfo->is_atom_bios) { + printk(KERN_WARNING "XXXX Write ATOM BIOS connector parse\n"); + } else { + + offset = BIOS_IN16(rinfo->fp_bios_start + 0x50); + if (offset == 0) { + printk(KERN_WARNING "radeonfb: No connector info table detected\n"); + return; + } + + /* Don't do much more at this point but displaying the data if + * DEBUG is enabled + */ + chips = BIOS_IN8(offset++) >> 4; + RTRACE("%d chips in connector info\n", chips); + for (i = 0; i < chips; i++) { + tmp = BIOS_IN8(offset++); + connectors = tmp & 0x0f; + RTRACE(" - chip %d has %d connectors\n", tmp >> 4, connectors); + for (conn = 0; ; conn++) { + tmp = BIOS_IN16(offset); + if (tmp == 0) + break; + offset += 2; + type = (tmp >> 12) & 0x0f; + RTRACE(" * connector %d of type %d (%s) : %04x\n", + conn, type, __conn_type_table[type], tmp); + } } } } @@ -519,6 +565,8 @@ /* * Check for cards with reversed DACs or TMDS controllers using BIOS */ + // XXXX What about atom_bios types? + if (rinfo->bios_seg && (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) { for (i = 1; i < 4; i++) { diff -ur /tmp/linux-2.6.15/drivers/video/aty/radeonfb.h ./aty/radeonfb.h --- /tmp/linux-2.6.15/drivers/video/aty/radeonfb.h 2006-01-03 14:30:15.000000000 -0500 +++ ./aty/radeonfb.h 2006-01-03 11:30:51.000000000 -0500 @@ -298,6 +298,9 @@ void __iomem *bios_seg; int fp_bios_start; + int is_atom_bios; + int atom_data_start; + u32 pseudo_palette[17]; struct { u8 red, green, blue, pad; } palette[256];