📄 radeon_driver.c
字号:
RADEONGetHardCodedEDIDFromBIOS(pScrn); else if (!info->IsSecondary) RADEONUpdatePanelSize(pScrn); } }}static void RADEONGetClockInfo(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR (pScrn); RADEONPLLPtr pll = &info->pll; double min_dotclock; if (RADEONGetClockInfoFromBIOS(pScrn)) { if (pll->reference_div < 2) { /* retrive it from register setting for fitting into current PLL algorithm. We'll probably need a new routine to calculate the best ref_div from BIOS provided min_input_pll and max_input_pll */ CARD32 tmp; tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300)) { pll->reference_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; } else { pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; } if (pll->reference_div < 2) pll->reference_div = 12; } } else { xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Video BIOS not detected, using default clock settings!\n"); /* Default min/max PLL values */ if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) { pll->min_pll_freq = 20000; pll->max_pll_freq = 50000; } else { pll->min_pll_freq = 12500; pll->max_pll_freq = 35000; } if (RADEONProbePLLParameters(pScrn)) return; if (info->IsIGP) pll->reference_freq = 1432; else pll->reference_freq = 2700; pll->reference_div = 12; pll->xclk = 10300; info->sclk = 200.00; info->mclk = 200.00; } if (info->ChipFamily == CHIP_FAMILY_RV100 && !info->HasCRTC2) { /* Avoid RN50 corruption due to memory bandwidth starvation. * 18 is an empirical value based on the databook and Windows driver. * * Empirical value changed to 24 to raise pixel clock limit and * allow higher resolution modes on capable monitors */ pll->max_pll_freq = min(pll->max_pll_freq, 24 * info->mclk * 100 / pScrn->bitsPerPixel * info->RamWidth / 16); } xf86DrvMsg (pScrn->scrnIndex, X_INFO, "PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n", pll->reference_freq, pll->reference_div, pll->min_pll_freq, pll->max_pll_freq, pll->xclk); /* (Some?) Radeon BIOSes seem too lie about their minimum dot * clocks. Allow users to override the detected minimum dot clock * value (e.g., and allow it to be suitable for TV sets). */ if (xf86GetOptValFreq(info->Options, OPTION_MIN_DOTCLOCK, OPTUNITS_MHZ, &min_dotclock)) { if (min_dotclock < 12 || min_dotclock*100 >= pll->max_pll_freq) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Illegal minimum dotclock specified %.2f MHz " "(option ignored)\n", min_dotclock); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Forced minimum dotclock to %.2f MHz " "(instead of detected %.2f MHz)\n", min_dotclock, ((double)pll->min_pll_freq/1000)); pll->min_pll_freq = min_dotclock * 1000; } }}static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; const char *s; Bool ignore_edid = FALSE; int i = 0, second = 0, max_mt; const char *MonTypeName[7] = { "AUTO", "NONE", "CRT", "LVDS", "TMDS", "CTV", "STV" }; const RADEONMonitorType MonTypeID[7] = { MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ MT_NONE, /* NONE -> NONE */ MT_CRT, /* CRT -> CRT */ MT_LCD, /* Laptop LCDs are driven via LVDS port */ MT_DFP, /* DFPs are driven via TMDS */ MT_CTV, /* CTV -> CTV */ MT_STV, /* STV -> STV */ }; const char *TMDSTypeName[3] = { "NONE", "Internal", "External" }; const char *DDCTypeName[5] = { "NONE", "MONID", "DVI_DDC", "VGA_DDC", "CRT2_DDC" }; const char *DACTypeName[3] = { "Unknown", "Primary", "TVDAC/ExtDAC", }; const char *ConnectorTypeName[8] = { "None", "Proprietary", "VGA", "DVI-I", "DVI-D", "CTV", "STV", "Unsupported" }; const char *ConnectorTypeNameATOM[10] = { "None", "VGA", "DVI-I", "DVI-D", "DVI-A", "STV", "CTV", "LVDS", "Digital", "Unsupported" }; max_mt = 5; if(info->IsSecondary) { info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; if(info->DisplayType == MT_NONE) return FALSE; return TRUE; } /* 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 < 2; i++) { pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN; pRADEONEnt->PortInfo[i].MonInfo = NULL; 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)) { /* Below is the most common setting, but may not be true */ pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN; pRADEONEnt->PortInfo[0].MonInfo = NULL; pRADEONEnt->PortInfo[0].DDCType = DDC_DVI; pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_D; pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN; pRADEONEnt->PortInfo[1].MonInfo = NULL; 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) { RADEONConnector connector; connector = pRADEONEnt->PortInfo[0]; pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; pRADEONEnt->PortInfo[1] = connector; } 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[1].DACType == DAC_PRIMARY) && (pRADEONEnt->PortInfo[0].DACType != DAC_PRIMARY)) { RADEONConnector connector; connector = pRADEONEnt->PortInfo[0]; pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; pRADEONEnt->PortInfo[1] = connector; } } 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 (!info->HasCRTC2) { pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; } /* IgnoreEDID option is different from the NoDDCxx options used by DDC module * When IgnoreEDID is used, monitor detection will still use DDC * detection, but all EDID data will not be used in mode validation. * You can use this option when you have a DDC monitor but want specify your own * monitor timing parameters by using HSync, VRefresh and Modeline, */ if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { if (ignore_edid) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "IgnoreEDID is specified, EDID data will be ignored\n"); } /* * 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. */ 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; } } 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"); 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 if (!ignore_edid) { if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) && (pRADEONEnt->PortInfo[0].MonType < MT_STV)) RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, &pRADEONEnt->PortInfo[0]); if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) && (pRADEONEnt->PortInfo[1].MonType < MT_STV)) RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, &pRADEONEnt->PortInfo[1]); } } if(((!info->HasCRTC2) || info->IsDellServer)) { if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0]))); else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0]))); else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0]))); else pRADEONEnt->PortInfo[0].MonType = MT_CRT; } if (!ignore_edid) { if (pRADEONEnt->PortInfo[0].MonInfo) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); } } pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; pRADEONEnt->MonType2 = MT_NONE; pRADEONEnt->MonInfo2 = NULL; info->MergeType = MT_NONE; info->DisplayType = pRADEONEnt->MonType1; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], info->IsAtomBios ? ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); return TRUE; } if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { /* Primary Head (DVI or Laptop Int. panel)*/ /* A ddc capable display connected on DVI port */ if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, pRADEONEnt->Po
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -