--- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c.dvi_fix_orig 2003-09-30 06:53:08.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2003-09-30 07:04:58.000000000 -0400 @@ -382,6 +382,24 @@ {720, 400, 70}, }; +static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x400f7/*0x40111*/}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ +}; + extern int gRADEONEntityIndex; struct RADEONInt10Save { @@ -1303,19 +1321,6 @@ if (!pRADEONEnt->MonType2) pRADEONEnt->MonType2 = RADEONCrtIsPhysicallyConnected(pScrn, !pRADEONEnt->ReversedDAC); - /* no display detected on DVI port*/ - if (pRADEONEnt->MonType1 == MT_NONE) { - if (pRADEONEnt->MonType2 != MT_NONE) { - /* Only one detected on VGA, let it to be primary */ - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - pRADEONEnt->MonType2 = MT_NONE; - } else { - /* Non detected, Default to a CRT connected */ - pRADEONEnt->MonType1 = MT_CRT; - } - } - if(pRADEONEnt->ReversedTMDS) { /* always keep internal TMDS as primary head */ if (pRADEONEnt->MonType1 == MT_DFP || @@ -1332,6 +1337,19 @@ } } } + + /* no display detected on DVI port*/ + if (pRADEONEnt->MonType1 == MT_NONE) { + if (pRADEONEnt->MonType2 != MT_NONE) { + /* Only one detected on VGA, let it to be primary */ + pRADEONEnt->MonType1 = pRADEONEnt->MonType2; + pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; + pRADEONEnt->MonType2 = MT_NONE; + } else { + /* Non detected, Default to a CRT connected */ + pRADEONEnt->MonType1 = MT_CRT; + } + } } if(s) { @@ -1635,6 +1653,56 @@ return TRUE; } +static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 tmp; + int i, n; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = 0; + info->tmds_pll[i].freq = 0; + } + + if (info->VBIOS) { + tmp = RADEON_BIOS16(info->FPBIOSstart + 0x34); + if (tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DFP table revision: %d\n", RADEON_BIOS8(tmp)); + if (RADEON_BIOS8(tmp) == 3) { + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; itmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); + } + return; + } + + /* revision 4 has some problem as it appears in RV280, + comment it off for new, use default instead */ + /* + else if (RADEON_BIOS8(tmp) == 4) { + int stride = 0; + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; itmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); + if (i == 0) stride += 10; + else stride += 6; + } + return; + } + */ + } + } + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; + } +} /* Read PLL parameters from BIOS block. Default to typical values if * there is no BIOS. @@ -3808,6 +3876,8 @@ if (!RADEONGetBIOSParameters(pScrn, pInt10)) goto fail; + RADEONGetTMDSInfo(pScrn); + if (!RADEONGetPLLParameters(pScrn)) goto fail; if (!RADEONPreInitGamma(pScrn)) goto fail; @@ -5125,6 +5195,11 @@ save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL); save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL); save->bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH); + + if (info->ChipFamily == CHIP_FAMILY_RV280) { + /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ + save->tmds_pll_cntl ^= (1 << 22); + } } /* Read CRTC2 registers */ @@ -5813,16 +5888,6 @@ save->lvds_gen_cntl = orig->lvds_gen_cntl; save->lvds_pll_cntl = orig->lvds_pll_cntl; - /* This is needed for some panel at high resolution (>=1600x1200) - */ - if ((save->dot_clock_freq > 15000) && - (info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) - save->tmds_pll_cntl = 0xA3F; - else - save->tmds_pll_cntl = orig->tmds_pll_cntl; - info->PanelOff = FALSE; /* This option is used to force the ONLY DEVICE in XFConfig to use * CRT port, instead of default DVI port. @@ -5831,6 +5896,7 @@ info->PanelOff = TRUE; } + save->tmds_pll_cntl = orig->tmds_pll_cntl; save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; if (info->PanelOff && info->Clone) { info->OverlayOnCRTC2 = TRUE; @@ -5859,13 +5925,28 @@ save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); } else if (info->DisplayType == MT_DFP) { - /* This is needed for some panel at high resolution (>=1600x1200) - */ - if ((save->dot_clock_freq > 15000) && - (info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) - save->tmds_pll_cntl = 0xA3F; + int i; + CARD32 tmp = orig->tmds_pll_cntl & 0xfffff; + for (i=0; i<4; i++) { + if (info->tmds_pll[i].freq == 0) break; + if (save->dot_clock_freq < info->tmds_pll[i].freq) { + tmp = info->tmds_pll[i].value ; + break; + } + } + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else + save->tmds_pll_cntl = (orig->tmds_pll_cntl & 0xfff00000) | tmp; + } else save->tmds_pll_cntl = tmp; + + RADEONTRACE(("TMDS_PLL from %x to %x\n", + orig->tmds_pll_cntl, + save->tmds_pll_cntl)); save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); if ((info->ChipFamily == CHIP_FAMILY_R300) || --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h.dvi_fix_orig 2003-09-30 06:54:10.000000000 -0400 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2003-09-30 07:04:58.000000000 -0400 @@ -261,10 +261,16 @@ CHIP_FAMILY_RV280, CHIP_FAMILY_R300, CHIP_FAMILY_R350, - CHIP_FAMILY_RV350 + CHIP_FAMILY_RV350, + CHIP_FAMILY_LAST } RADEONChipFamily; typedef struct { + CARD32 freq; + CARD32 value; +}RADEONTMDSPll; + +typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; PCITAG PciTag; @@ -325,7 +331,6 @@ int FeedbackDivider; int PostDivider; Bool UseBiosDividers; - /* EDID data using DDC interface */ Bool ddc_bios; Bool ddc1; @@ -335,6 +340,7 @@ RADEONPLLRec pll; RADEONRAMPtr ram; + RADEONTMDSPll tmds_pll[4]; RADEONSaveRec SavedReg; /* Original (text) mode */ RADEONSaveRec ModeReg; /* Current mode */