diff options
author | Alex Deucher <alex@t41p.hsd1.va.comcast.net> | 2007-05-11 17:34:35 +0200 |
---|---|---|
committer | Alex Deucher <alex@t41p.hsd1.va.comcast.net> | 2007-05-11 17:34:35 +0200 |
commit | ab5603edd8fc3ef0560bdfb6a6d9c6af2a49d1e5 (patch) | |
tree | 6688a1b6336dbfb2d18594167b2e2c12d3a972e9 /src/radeon_display.c | |
parent | 94eb0681de0641e490f06486468617a727fefe86 (diff) |
RADEON: Move LVDS, TMDS, DAC properties to the output rec
Diffstat (limited to 'src/radeon_display.c')
-rw-r--r-- | src/radeon_display.c | 551 |
1 files changed, 424 insertions, 127 deletions
diff --git a/src/radeon_display.c b/src/radeon_display.c index cebb2e6..f7a307b 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -669,28 +669,30 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCT return MonType; } -static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) +static void RADEONGetPanelInfoFromReg (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; unsigned char *RADEONMMIO = info->MMIO; CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); - info->PanelPwrDly = 200; + radeon_output->PanelPwrDly = 200; if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { - info->PanelYRes = (fp_vert_stretch>>12) + 1; + radeon_output->PanelYRes = (fp_vert_stretch>>12) + 1; } else { - info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; + radeon_output->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; } if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { - info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; + radeon_output->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; } else { - info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; + radeon_output->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; } - if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { - info->PanelXRes = 640; - info->PanelYRes = 480; + if ((radeon_output->PanelXRes < 640) || (radeon_output->PanelYRes < 480)) { + radeon_output->PanelXRes = 640; + radeon_output->PanelYRes = 480; } if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { @@ -701,10 +703,10 @@ static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); if ((ppll_val & 0x000707ff) == 0x1bb) goto noprobe; - info->FeedbackDivider = ppll_val & 0x7ff; - info->PostDivider = (ppll_val >> 16) & 0x7; - info->RefDivider = info->pll.reference_div; - info->UseBiosDividers = TRUE; + radeon_output->FeedbackDivider = ppll_val & 0x7ff; + radeon_output->PostDivider = (ppll_val >> 16) & 0x7; + radeon_output->RefDivider = info->pll.reference_div; + radeon_output->UseBiosDividers = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Existing panel PLL dividers will be used.\n"); @@ -714,21 +716,24 @@ static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Panel size %dx%d is derived, this may not be correct.\n" "If not, use PanelSize option to overwrite this setting\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); } /* BIOS may not have right panel size, we search through all supported * DDC modes looking for the maximum panel size. */ -static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) +static void RADEONUpdatePanelSize(xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; int j; - RADEONInfoPtr info = RADEONPTR (pScrn); + /* XXX: fixme */ xf86MonPtr ddc = pScrn->monitor->DDC; DisplayModePtr p; - if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) + if ((radeon_output->UseBiosDividers && radeon_output->DotClock != 0) || (ddc == NULL)) return; /* Go thru detailed timing table first */ @@ -743,49 +748,49 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) * clock, or ValidateFPModes will fail, even when UseBiosDividers * is set. */ - if (info->DotClock == 0 && - info->PanelXRes == d_timings->h_active && - info->PanelYRes == d_timings->v_active) + if (radeon_output->DotClock == 0 && + radeon_output->PanelXRes == d_timings->h_active && + radeon_output->PanelYRes == d_timings->v_active) match = 1; /* If we don't have a BIOS provided panel data with fixed dividers, * check for a larger panel size */ - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active && - !info->UseBiosDividers) + if (radeon_output->PanelXRes < d_timings->h_active && + radeon_output->PanelYRes < d_timings->v_active && + !radeon_output->UseBiosDividers) match = 1; if (match) { - info->PanelXRes = d_timings->h_active; - info->PanelYRes = d_timings->v_active; - info->DotClock = d_timings->clock / 1000; - info->HOverPlus = d_timings->h_sync_off; - info->HSyncWidth = d_timings->h_sync_width; - info->HBlank = d_timings->h_blanking; - info->VOverPlus = d_timings->v_sync_off; - info->VSyncWidth = d_timings->v_sync_width; - info->VBlank = d_timings->v_blanking; - info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + radeon_output->PanelXRes = d_timings->h_active; + radeon_output->PanelYRes = d_timings->v_active; + radeon_output->DotClock = d_timings->clock / 1000; + radeon_output->HOverPlus = d_timings->h_sync_off; + radeon_output->HSyncWidth = d_timings->h_sync_width; + radeon_output->HBlank = d_timings->h_blanking; + radeon_output->VOverPlus = d_timings->v_sync_off; + radeon_output->VSyncWidth = d_timings->v_sync_width; + radeon_output->VBlank = d_timings->v_blanking; + radeon_output->Flags = (d_timings->interlaced ? V_INTERLACE : 0); switch (d_timings->misc) { - case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; + case 0: radeon_output->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: radeon_output->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: radeon_output->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: radeon_output->Flags |= V_PHSYNC | V_PVSYNC; break; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); } } } - if (info->UseBiosDividers && info->DotClock != 0) + if (radeon_output->UseBiosDividers && radeon_output->DotClock != 0) return; /* Search thru standard VESA modes from EDID */ for (j = 0; j < 8; j++) { - if ((info->PanelXRes < ddc->timings2[j].hsize) && - (info->PanelYRes < ddc->timings2[j].vsize)) { + if ((radeon_output->PanelXRes < ddc->timings2[j].hsize) && + (radeon_output->PanelYRes < ddc->timings2[j].vsize)) { for (p = pScrn->monitor->Modes; p; p = p->next) { if ((ddc->timings2[j].hsize == p->HDisplay) && (ddc->timings2[j].vsize == p->VDisplay)) { @@ -794,18 +799,18 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { /* Is this good enough? */ - info->PanelXRes = ddc->timings2[j].hsize; - info->PanelYRes = ddc->timings2[j].vsize; - info->HBlank = p->HTotal - p->HDisplay; - info->HOverPlus = p->HSyncStart - p->HDisplay; - info->HSyncWidth = p->HSyncEnd - p->HSyncStart; - info->VBlank = p->VTotal - p->VDisplay; - info->VOverPlus = p->VSyncStart - p->VDisplay; - info->VSyncWidth = p->VSyncEnd - p->VSyncStart; - info->DotClock = p->Clock; - info->Flags = p->Flags; + radeon_output->PanelXRes = ddc->timings2[j].hsize; + radeon_output->PanelYRes = ddc->timings2[j].vsize; + radeon_output->HBlank = p->HTotal - p->HDisplay; + radeon_output->HOverPlus = p->HSyncStart - p->HDisplay; + radeon_output->HSyncWidth = p->HSyncEnd - p->HSyncStart; + radeon_output->VBlank = p->VTotal - p->VDisplay; + radeon_output->VOverPlus = p->VSyncStart - p->VDisplay; + radeon_output->VSyncWidth = p->VSyncEnd - p->VSyncStart; + radeon_output->DotClock = p->Clock; + radeon_output->Flags = p->Flags; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); } } } @@ -813,21 +818,25 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) } } -static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) +static Bool RADEONGetLVDSInfo (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; - if (!RADEONGetLVDSInfoFromBIOS(pScrn)) - RADEONGetPanelInfoFromReg(pScrn); + ErrorF("LVDS get info"); + + if (!RADEONGetLVDSInfoFromBIOS(output)) + RADEONGetPanelInfoFromReg(output); /* The panel size we collected from BIOS may not be the * maximum size supported by the panel. If not, we update * it now. These will be used if no matching mode can be * found from EDID data. */ - RADEONUpdatePanelSize(pScrn); + RADEONUpdatePanelSize(output); - if (info->DotClock == 0) { + if (radeon_output->DotClock == 0) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); DisplayModePtr tmp_mode = NULL; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -840,27 +849,27 @@ static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) */ tmp_mode = pScrn->monitor->Modes; while(tmp_mode) { - if ((tmp_mode->HDisplay == info->PanelXRes) && - (tmp_mode->VDisplay == info->PanelYRes)) { + if ((tmp_mode->HDisplay == radeon_output->PanelXRes) && + (tmp_mode->VDisplay == radeon_output->PanelYRes)) { float refresh = (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; if ((abs(60.0 - refresh) < 1.0) || (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; + radeon_output->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + radeon_output->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + radeon_output->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + radeon_output->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + radeon_output->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + radeon_output->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + radeon_output->DotClock = tmp_mode->Clock; + radeon_output->Flags = 0; break; } tmp_mode = tmp_mode->next; } } - if ((info->DotClock == 0) && !pRADEONEnt->pOutput[0]->MonInfo) { + if ((radeon_output->DotClock == 0) && !pRADEONEnt->pOutput[0]->MonInfo) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Panel size is not correctly detected.\n" "Please try to use PanelSize option for correct settings.\n"); @@ -871,24 +880,27 @@ static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) return TRUE; } -static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +static void RADEONGetTMDSInfo(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; int i; for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; + radeon_output->tmds_pll[i].value = 0; + radeon_output->tmds_pll[i].freq = 0; } - if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; + if (RADEONGetTMDSInfoFromBIOS(output)) 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; + radeon_output->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + radeon_output->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; } } +#if 0 void RADEONGetPanelInfo (ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -898,20 +910,23 @@ void RADEONGetPanelInfo (ScrnInfoPtr pScrn) info->PanelPwrDly = 200; if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); - RADEONGetPanelInfoFromReg(pScrn); + RADEONGetPanelInfoFromReg(output); } } } +#endif -void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn) +void RADEONGetTVDacAdjInfo(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; /* Todo: get this setting from BIOS */ - info->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; + radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; if (info->IsMobility) { /* some mobility chips may different */ if (info->ChipFamily == CHIP_FAMILY_RV250) - info->tv_dac_adj = 0x00880000; + radeon_output->tv_dac_adj = 0x00880000; } } @@ -929,12 +944,15 @@ static void RADEONSwapOutputs(ScrnInfoPtr pScrn) pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; pRADEONEnt->PortInfo[1] = conn_priv; } +#if 0 /* * initialise the static data sos we don't have to re-do at randr change */ void RADEONSetupConnectors(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; const char *s; int i = 0, second = 0, max_mt = 5; @@ -1137,45 +1155,60 @@ void RADEONSetupConnectors(ScrnInfoPtr pScrn) } #endif - for (i = 0; i < info->max_connectors; i++) { - RADEONOutputPrivatePtr radeon_output = pRADEONEnt->PortInfo[i]; - - int DDCReg = 0; - char *names[] = { "DDC1", "DDC2", "DDC3" }; - - RADEONSetOutputType(pScrn, radeon_output); - switch(radeon_output->DDCType) { - case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; - case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; - case DDC_VGA: DDCReg = RADEON_GPIO_VGA_DDC; break; - case DDC_CRT2: DDCReg = RADEON_GPIO_CRT2_DDC; break; - default: break; - } - - if (DDCReg) { - radeon_output->DDCReg = DDCReg; - RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, names[i]); - } + // for (i = 0; i < xf86_config->num_output; i++) { + for (i = 0 ; i < info->max_connectors; i++) { + RADEONOutputPrivatePtr radeon_output = pRADEONEnt->PortInfo[i]; - if (radeon_output->type == OUTPUT_LVDS) { - RADEONGetLVDSInfo(pScrn); - } + int DDCReg = 0; + char *names[] = { "DDC1", "DDC2", "DDC3" }; - if (radeon_output->type == OUTPUT_DVI) { - RADEONGetTMDSInfo(pScrn); + RADEONSetOutputType(pScrn, radeon_output); - if (i == 0) - RADEONGetHardCodedEDIDFromBIOS(pScrn); + pRADEONEnt->pOutput[i] = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[pRADEONEnt->PortInfo[i]->type]); + if (!pRADEONEnt->pOutput[i]) + return FALSE; + + pRADEONEnt->pOutput[i]->driver_private = pRADEONEnt->PortInfo[i]; + pRADEONEnt->PortInfo[i]->num = i; - /*RADEONUpdatePanelSize(pScrn);*/ + pRADEONEnt->pOutput[i]->possible_crtcs = 1; + if (pRADEONEnt->PortInfo[i]->type != OUTPUT_LVDS) + pRADEONEnt->pOutput[i]->possible_crtcs |= 2; - } + pRADEONEnt->pOutput[i]->possible_clones = 0 /*1|2*/; + switch(radeon_output->DDCType) { + case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; + case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; + case DDC_VGA: DDCReg = RADEON_GPIO_VGA_DDC; break; + case DDC_CRT2: DDCReg = RADEON_GPIO_CRT2_DDC; break; + default: break; + } - } + if (DDCReg) { + radeon_output->DDCReg = DDCReg; + RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, names[i]); + } - + if (radeon_output->type == OUTPUT_LVDS) { + RADEONGetLVDSInfo(output); + } + + if (radeon_output->type == OUTPUT_DVI) { + RADEONGetTMDSInfo(output); + + if (i == 0) + RADEONGetHardCodedEDIDFromBIOS(output); + + /*RADEONUpdatePanelSize(output);*/ + } + + if (radeon_output->DACType == DAC_TVDAC) { + RADEONGetTVDacAdjInfo(output); + } + } } +#endif static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output) { @@ -1651,7 +1684,7 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, xf86OutputPtr output, BOOL bEnable) ErrorF("read in LVDS reg\n"); tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); tmp &= ~(RADEON_LVDS_DISPLAY_DIS); - usleep (info->PanelPwrDly * 1000); + usleep (radeon_output->PanelPwrDly * 1000); OUTREG(RADEON_LVDS_GEN_CNTL, tmp); ErrorF("wrote out LVDS reg\n"); save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); @@ -2135,7 +2168,7 @@ static void RADEONDPMSSetOn(xf86OutputPtr output) switch(MonType) { case MT_LCD: OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); - usleep (info->PanelPwrDly * 1000); + usleep (radeon_output->PanelPwrDly * 1000); OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); break; case MT_DFP: @@ -2278,14 +2311,13 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, double dot_clock = 0; for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - RADEONOutputPrivatePtr radeon_output = output->driver_private; + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; - if (output->crtc == crtc) { - montype = radeon_output->MonType; - radeon_output->crtc_num = radeon_crtc->crtc_id + 1; - ErrorF("using crtc: %d on output %s montype: %d\n", radeon_output->crtc_num, OutputType[radeon_output->type], montype); - } + if (output->crtc == crtc) { + montype = radeon_output->MonType; + radeon_output->crtc_num = radeon_crtc->crtc_id + 1; + } } ErrorF("init memmap\n"); @@ -2307,7 +2339,7 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl; } break; - case 1: + case 1: ErrorF("init crtc2\n"); RADEONInitCrtc2Registers(pScrn, &info->ModeReg, adjusted_mode, info); dot_clock = adjusted_mode->Clock / 1000.0; @@ -2484,8 +2516,8 @@ radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) if (radeon_output->type != OUTPUT_LVDS) return MODE_OK; - if (pMode->HDisplay > info->PanelXRes || - pMode->VDisplay > info->PanelYRes) + if (pMode->HDisplay > radeon_output->PanelXRes || + pMode->VDisplay > radeon_output->PanelYRes) return MODE_PANEL; return MODE_OK; @@ -2502,8 +2534,8 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, if (radeon_output->type != OUTPUT_LVDS) return TRUE; - if (mode->HDisplay < info->PanelXRes || - mode->VDisplay < info->PanelYRes) + if (mode->HDisplay < radeon_output->PanelXRes || + mode->VDisplay < radeon_output->PanelYRes) adjusted_mode->Flags |= RADEON_USE_RMX; return TRUE; @@ -2707,7 +2739,7 @@ Bool RADEONAllocateConnectors(ScrnInfoPtr pScrn) if (pRADEONEnt->pOutput[0]) return TRUE; - + /* for now always allocate max connectors */ for (i = 0 ; i < info->max_connectors; i++) { @@ -2728,6 +2760,271 @@ Bool RADEONAllocateConnectors(ScrnInfoPtr pScrn) return TRUE; } +/* + * initialise the static data sos we don't have to re-do at randr change */ +void RADEONSetupConnectors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + const char *s; + int i = 0, second = 0, max_mt = 5; + + /* We first get the information about all connectors from BIOS. + * This is how the card is phyiscally wired up. + * The information should be correct even on a OEM card. + * If not, we may have problem -- need to use MonitorLayout option. + */ + for (i = 0; i < info->max_connectors; i++) { + pRADEONEnt->PortInfo[i]->MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[i]->DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[i]->DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[i]->TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[i]->ConnectorType = CONNECTOR_NONE; + } + + if (!RADEONGetConnectorInfoFromBIOS(pScrn) || + ((pRADEONEnt->PortInfo[0]->DDCType == 0) && + (pRADEONEnt->PortInfo[1]->DDCType == 0))) { + /* Below is the most common setting, but may not be true */ + pRADEONEnt->PortInfo[0]->MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[0]->DDCType = DDC_DVI; + pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0]->TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[0]->ConnectorType = CONNECTOR_DVI_I; + + pRADEONEnt->PortInfo[1]->MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[1]->DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1]->DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1]->TMDSType = TMDS_EXT; + pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_CRT; + + + /* Some cards have the DDC lines swapped and we have no way to + * detect it yet (Mac cards) + */ + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { + pRADEONEnt->PortInfo[0]->DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1]->DDCType = DDC_DVI; + } + } + + /* always make TMDS_INT port first*/ + if (pRADEONEnt->PortInfo[1]->TMDSType == TMDS_INT) { + RADEONSwapOutputs(pScrn); + } else if ((pRADEONEnt->PortInfo[0]->TMDSType != TMDS_INT && + pRADEONEnt->PortInfo[1]->TMDSType != TMDS_INT)) { + /* no TMDS_INT port, make primary DAC port first */ + /* On my Inspiron 8600 both internal and external ports are + marked DAC_PRIMARY in BIOS. So be extra careful - only + swap when the first port is not DAC_PRIMARY */ + if ((!(pRADEONEnt->PortInfo[0]->ConnectorType == CONNECTOR_PROPRIETARY)) && (pRADEONEnt->PortInfo[1]->DACType == DAC_PRIMARY) && + (pRADEONEnt->PortInfo[0]->DACType != DAC_PRIMARY)) { + RADEONSwapOutputs(pScrn); + } + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + if (pRADEONEnt->PortInfo[0]->ConnectorType == CONNECTOR_CRT) { + pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[1]->DACType = DAC_PRIMARY; + } else { + pRADEONEnt->PortInfo[1]->DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0]->DACType = DAC_PRIMARY; + } + } else if (!pRADEONEnt->HasCRTC2) { + pRADEONEnt->PortInfo[0]->DACType = DAC_PRIMARY; + } + + /* + * MonitorLayout option takes a string for two monitors connected in following format: + * Option "MonitorLayout" "primary-port-display, secondary-port-display" + * primary and secondary port displays can have one of following: + * NONE, CRT, LVDS, TMDS + * With this option, driver will bring up monitors as specified, + * not using auto-detection routines to probe monitors. + * + * This option can be used when the false monitor detection occurs. + * + * This option can also be used to disable one connected display. + * For example, if you have a laptop connected to an external CRT + * and you want to disable the internal LCD panel, you can specify + * Option "MonitorLayout" "NONE, CRT" + * + * This option can also used to disable Clone mode. One there is only + * one monitor is specified, clone mode will be turned off automatically + * even you have two monitors connected. + * + * Another usage of this option is you want to config the server + * to start up with a certain monitor arrangement even one monitor + * is not plugged in when server starts. + * For example, you can config your laptop with + * Option "MonitorLayout" "LVDS, CRT" + * Option "CloneHSync" "40-150" + * Option "CloneVRefresh" "60-120" + * With these options, you can connect in your CRT monitor later + * after the X server has started. + */ + if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { + char s1[5], s2[5]; + i = 0; + /* When using user specified monitor types, we will not do DDC detection + * + */ + do { + switch(*s) { + case ',': + s1[i] = '\0'; + i = 0; + second = 1; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + if (second) + s2[i] = *s; + else + s1[i] = *s; + i++; + break; + } + if (i > 4) i = 4; + } while(*s++); + s2[i] = '\0'; + + for (i = 0; i < max_mt; i++) + { + if (strcmp(s1, MonTypeName[i]) == 0) + { + pRADEONEnt->PortInfo[0]->MonType = MonTypeID[i]; + break; + } + } + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 1st port \n"); + + for (i = 0; i < max_mt; i++) + { + if (strcmp(s2, MonTypeName[i]) == 0) + { + pRADEONEnt->PortInfo[1]->MonType = MonTypeID[i]; + break; + } + + } + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 2nd port \n"); + + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 2nd port \n"); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); +#if 0 + if (pRADEONEnt->PortInfo[1]->MonType == MT_CRT) { + pRADEONEnt->PortInfo[1]->DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1]->TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1]->DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_CRT; + pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[0]->DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[0]->ConnectorType = pRADEONEnt->PortInfo[0]->MonType+1; + pRADEONEnt->PortInfo[0]->MonInfo = NULL; + } +#endif + + /* some thinkpads and powerbooks use lvds and internal tmds + * at the same time. --AGD + */ + if ((pRADEONEnt->PortInfo[0]->MonType == MT_LCD) && + (pRADEONEnt->PortInfo[1]->MonType == MT_DFP)) { + pRADEONEnt->PortInfo[1]->DDCType = DDC_DVI; + pRADEONEnt->PortInfo[0]->DDCType = DDC_MONID; + pRADEONEnt->PortInfo[1]->TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_DVI_I; + pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; + } + } + +#if 1 + if (info->IsMobility) { + pRADEONEnt->PortInfo[2]->DDCType = DDC_DVI; + pRADEONEnt->PortInfo[2]->TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[2]->ConnectorType = CONNECTOR_DVI_D; + pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; + if (pRADEONEnt->PortInfo[0]->DDCType == DDC_DVI) { + pRADEONEnt->PortInfo[0]->DDCType = DDC_MONID; + } + if (pRADEONEnt->PortInfo[0]->TMDSType == TMDS_INT) { + pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; + } + } +#endif + + // for (i = 0; i < xf86_config->num_output; i++) { + for (i = 0 ; i < info->max_connectors; i++) { + RADEONOutputPrivatePtr radeon_output = pRADEONEnt->PortInfo[i]; + + int DDCReg = 0; + char *names[] = { "DDC1", "DDC2", "DDC3" }; + + RADEONSetOutputType(pScrn, radeon_output); + + pRADEONEnt->pOutput[i] = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[pRADEONEnt->PortInfo[i]->type]); + /*if (!pRADEONEnt->pOutput[i]) + return FALSE;*/ + + pRADEONEnt->pOutput[i]->driver_private = pRADEONEnt->PortInfo[i]; + pRADEONEnt->PortInfo[i]->num = i; + + pRADEONEnt->pOutput[i]->possible_crtcs = 1; + if (pRADEONEnt->PortInfo[i]->type != OUTPUT_LVDS) + pRADEONEnt->pOutput[i]->possible_crtcs |= 2; + + pRADEONEnt->pOutput[i]->possible_clones = 0 /*1|2*/; + + output = pRADEONEnt->pOutput[i]; + + switch(radeon_output->DDCType) { + case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; + case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; + case DDC_VGA: DDCReg = RADEON_GPIO_VGA_DDC; break; + case DDC_CRT2: DDCReg = RADEON_GPIO_CRT2_DDC; break; + default: break; + } + + if (DDCReg) { + radeon_output->DDCReg = DDCReg; + RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, names[i]); + } + + if (radeon_output->type == OUTPUT_LVDS) { + RADEONGetLVDSInfo(output); + } + + if (radeon_output->type == OUTPUT_DVI) { + RADEONGetTMDSInfo(output); + + if (i == 0) + RADEONGetHardCodedEDIDFromBIOS(output); + + /*RADEONUpdatePanelSize(output);*/ + } + + if (radeon_output->DACType == DAC_TVDAC) { + RADEONGetTVDacAdjInfo(output); + } + } +} #if 0 xf86OutputPtr RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num) |