static void atomSetBacklightFromBIOSScratch(struct rhdOutput *Output) { RHDPtr rhdPtr = RHDPTRI(Output); struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private; RHDFUNC(Output); switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_UNIPHYC: case RHD_OUTPUT_UNIPHYD: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: rhdSetEncoderTransmitterConfig(Output, Private->PixelClock); if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransLcdBlBrightness, &Private->TransmitterConfig)) ERROR_MSG("rhdAtomDigTransmitterControl(atomTransEnable)"); break; default: if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputLcdBrightnessControl)) ERROR_MSG("rhdAtomOutputControl(atomOutputLcdBrightnessControl)"); break; } }
static inline void rhdAtomOutputSet(struct rhdOutput *Output, DisplayModePtr Mode) { RHDPtr rhdPtr = RHDPTRI(Output); struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private; struct atomEncoderConfig *EncoderConfig = &Private->EncoderConfig; struct atomCrtcSourceConfig CrtcSourceConfig; union AtomBiosArg data; RHDFUNC(Output); Private->Mode = Mode; data.Address = &Private->Save; RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); Private->PixelClock = Mode->SynthClock; rhdSetEncoderTransmitterConfig(Output, Private->PixelClock); switch ( Private->CrtcSourceVersion.cref){ case 1: CrtcSourceConfig.u.Device = Output->OutputDriverPrivate->Device; break; case 2: CrtcSourceConfig.u.crtc2.Encoder = Private->EncoderId; CrtcSourceConfig.u.crtc2.Mode = EncoderConfig->u.dig.EncoderMode; break; default: xf86DrvMsg(Output->scrnIndex, X_ERROR, "Unknown version of SelectCrtcSource code table: %i\n",Private->CrtcSourceVersion.cref); return; } switch (Output->Id) { case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_UNIPHYC: case RHD_OUTPUT_UNIPHYD: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: #if 1 rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransInit, &Private->TransmitterConfig); #endif case RHD_OUTPUT_KLDSKP_LVTMA: rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransSetup, &Private->TransmitterConfig); break; default: break; } rhdAtomSelectCrtcSource(rhdPtr->atomBIOS, Output->Crtc->Id ? atomCrtc2 : atomCrtc1, &CrtcSourceConfig); data.Address = NULL; RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); RHDHdmiSetMode(Private->Hdmi, Mode); }
static void atomSetBacklight(struct rhdOutput *Output, int value) { RHDPtr rhdPtr = RHDPTRI(Output); RHDFUNC(Output); RHDAtomBIOSScratchBlLevel(rhdPtr, rhdBIOSScratchBlSet, &value); atomSetBacklightFromBIOSScratch(Output); }
static void rhdAtomOutputRestore(struct rhdOutput *Output) { struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private; RHDPtr rhdPtr = RHDPTRI(Output); union AtomBiosArg data; data.Address = &Private->Save; RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_RESTORE_REGISTERS, &data); if (Output->Connector && Output->Connector->Type == RHD_CONNECTOR_PANEL) atomSetBacklightFromBIOSScratch(Output); RHDHdmiRestore(Private->Hdmi); }
static void rhdAtomScaleSet(struct rhdCrtc *Crtc, enum rhdCrtcScaleType Type, DisplayModePtr Mode, DisplayModePtr ScaledToMode) { RHDPtr rhdPtr = RHDPTRI(Crtc); struct rhdScalerOverscan Overscan; struct atomCrtcOverscan AtomOverscan; enum atomCrtc AtomCrtc = RHD_CRTC_1; enum atomScaler Scaler = 0; enum atomScaleMode ScaleMode = 0; union AtomBiosArg data; CARD32 RegOff = 0; LOG("FUNCTION: %s: %s viewport: %dx%d\n", __func__, Crtc->Name, Mode->CrtcHDisplay, Mode->CrtcVDisplay); /* D1Mode registers */ if (Crtc->Id == RHD_CRTC_1) RegOff = D1_REG_OFFSET; else RegOff = D2_REG_OFFSET; RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE, Mode->CrtcVDisplay | (Mode->CrtcHDisplay << 16)); RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, 0); Overscan = rhdCalculateOverscan(Mode, ScaledToMode, Type); Type = Overscan.Type; //ASSERT(Crtc->ScalePriv); data.Address = &((Crtc->ScalePriv)->RegList); RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); AtomOverscan.ovscnLeft = Overscan.OverscanLeft; AtomOverscan.ovscnRight = Overscan.OverscanRight; AtomOverscan.ovscnTop = Overscan.OverscanTop; AtomOverscan.ovscnBottom = Overscan.OverscanBottom; switch (Crtc->Id) { case RHD_CRTC_1: Scaler = atomScaler1; AtomCrtc = atomCrtc1; break; case RHD_CRTC_2: Scaler = atomScaler2; AtomCrtc = atomCrtc2; break; } rhdAtomSetCRTCOverscan(rhdPtr->atomBIOS, AtomCrtc, &AtomOverscan); switch (Type) { case RHD_CRTC_SCALE_TYPE_NONE: ScaleMode = atomScaleDisable; break; case RHD_CRTC_SCALE_TYPE_CENTER: ScaleMode = atomScaleCenter; break; case RHD_CRTC_SCALE_TYPE_SCALE: case RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO: /* scaled to fullscreen */ ScaleMode = atomScaleExpand; break; } rhdAtomSetScaler(rhdPtr->atomBIOS, Scaler, ScaleMode); data.Address = NULL; RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); RHDMCTuneAccessForDisplay(rhdPtr, Crtc->Id, Mode, ScaledToMode ? ScaledToMode : Mode); }
static inline void rhdSetEncoderTransmitterConfig(struct rhdOutput *Output, int PixelClock) { RHDPtr rhdPtr = RHDPTRI(Output); struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private; struct atomEncoderConfig *EncoderConfig = &Private->EncoderConfig; struct atomTransmitterConfig *TransmitterConfig = &Private->TransmitterConfig; RHDFUNC(Output); EncoderConfig->PixelClock = TransmitterConfig->PixelClock = PixelClock; switch (Output->Id) { case RHD_OUTPUT_NONE: break; case RHD_OUTPUT_DVO: EncoderConfig->u.dvo.DvoDeviceType = Output->OutputDriverPrivate->Device; switch (EncoderConfig->u.dvo.DvoDeviceType) { case atomCRT1: case atomCRT2: EncoderConfig->u.dvo.digital = FALSE; break; case atomTV1: case atomTV2: case atomCV: EncoderConfig->u.dvo.digital = FALSE; EncoderConfig->u.dvo.u.TVMode = rhdPtr->tvMode; break; case atomLCD1: case atomDFP1: case atomDFP2: case atomLCD2: case atomDFP3: case atomDFP4: case atomDFP5: EncoderConfig->u.dvo.digital = TRUE; /* @@@ no digital attributes, yet */ break; case atomNone: break; } break; case RHD_OUTPUT_DACA: case RHD_OUTPUT_DACB: switch (Output->SensedType) { case RHD_SENSED_VGA: EncoderConfig->u.dac.DacStandard = atomDAC_VGA; break; case RHD_SENSED_TV_COMPONENT: EncoderConfig->u.dac.DacStandard = atomDAC_CV; break; case RHD_SENSED_TV_SVIDEO: case RHD_SENSED_TV_COMPOSITE: switch (rhdPtr->tvMode) { case RHD_TV_NTSC: case RHD_TV_NTSCJ: EncoderConfig->u.dac.DacStandard = atomDAC_NTSC; /* NTSC */ break; case RHD_TV_PAL: case RHD_TV_PALN: case RHD_TV_PALCN: case RHD_TV_PAL60: default: EncoderConfig->u.dac.DacStandard = atomDAC_PAL; /* PAL */ break; } break; case RHD_SENSED_NONE: EncoderConfig->u.dac.DacStandard = atomDAC_VGA; break; default: xf86DrvMsg(Output->scrnIndex, X_ERROR, "Sensed incompatible output for DAC\n"); EncoderConfig->u.dac.DacStandard = atomDAC_VGA; break; } break; case RHD_OUTPUT_TMDSA: case RHD_OUTPUT_LVTMA: if (Output->Connector && PixelClock > 0) { if (Output->Connector->Type == RHD_CONNECTOR_DVI #if 0 || Output->Connector->Type == RHD_CONNECTOR_HDMI_B #endif ) Private->RunDualLink = (PixelClock > 165000) ? TRUE : FALSE; else Private->RunDualLink = FALSE; } else /* only get here for power down: thus power down both channels to be save */ Private->RunDualLink = TRUE; switch (Private->EncoderVersion.cref) { case 1: if (Private->RunDualLink) EncoderConfig->u.lvds.LinkCnt = atomDualLink; else EncoderConfig->u.lvds.LinkCnt = atomSingleLink; break; case 2: case 3: if (Private->RunDualLink) EncoderConfig->u.lvds2.LinkCnt = atomDualLink; else EncoderConfig->u.lvds2.LinkCnt = atomSingleLink; if (Private->Coherent) EncoderConfig->u.lvds2.Coherent = TRUE; else EncoderConfig->u.lvds2.Coherent = FALSE; break; } break; case RHD_OUTPUT_KLDSKP_LVTMA: case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_UNIPHYC: case RHD_OUTPUT_UNIPHYD: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: if (Output->Connector && PixelClock > 0) { if (Output->Connector->Type == RHD_CONNECTOR_DVI #if 0 || Output->Connector->Type == RHD_CONNECTOR_DP_DUAL || Output->Connector->Type == RHD_CONNECTOR_HDMI_B #endif ) Private->RunDualLink = (PixelClock > 165000) ? TRUE : FALSE; else Private->RunDualLink = FALSE; } else /* only get here for power down: thus power down both channels to be save */ Private->RunDualLink = TRUE; if (Private->RunDualLink) { TransmitterConfig->LinkCnt = EncoderConfig->u.dig.LinkCnt = atomDualLink; if (TransmitterConfig->Link == atomTransLinkA) TransmitterConfig->Link = atomTransLinkAB; else if (TransmitterConfig->Link == atomTransLinkB) TransmitterConfig->Link = atomTransLinkBA; } else { TransmitterConfig->LinkCnt = EncoderConfig->u.dig.LinkCnt = atomSingleLink; if (TransmitterConfig->Link == atomTransLinkAB) TransmitterConfig->Link = atomTransLinkA; else if (TransmitterConfig->Link == atomTransLinkBA) TransmitterConfig->Link = atomTransLinkB; } TransmitterConfig->Coherent = Private->Coherent; break; } }
static Bool RHDAtomOutputAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc) { struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private; struct atomTransmitterConfig *TransmitterConfig = &Private->TransmitterConfig; RHDPtr rhdPtr = RHDPTRI(Output); char *TransmitterName; RHDFUNC(rhdPtr); switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: TransmitterName = "KLDSKP_LVTMA"; break; case RHD_OUTPUT_UNIPHYA: TransmitterName = "KLDSKP_UNIPHYA"; break; case RHD_OUTPUT_UNIPHYB: TransmitterName = "KLDSKP_UNIPHYB"; break; case RHD_OUTPUT_UNIPHYC: TransmitterName = "KLDSKP_UNIPHYC"; break; case RHD_OUTPUT_UNIPHYD: TransmitterName = "KLDSKP_UNIPHYD"; break; case RHD_OUTPUT_UNIPHYE: TransmitterName = "KLDSKP_UNIPHYE"; break; case RHD_OUTPUT_UNIPHYF: TransmitterName = "KLDSKP_UNIPHYF"; break; default: return TRUE; } switch (Alloc) { case RHD_OUTPUT_ALLOC: /* * LVTMA can only use DIG2. Thus exclude * DIG1 for LVTMA and prefer it for the * UNIPHYs. */ if (Private->EncoderId != atomEncoderNone) return TRUE; if (Output->Id != RHD_OUTPUT_KLDSKP_LVTMA && !rhdPtr->DigEncoderOutput[0]) { rhdPtr->DigEncoderOutput[0] = Output; TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG1; xf86DrvMsg(Output->scrnIndex, X_INFO, "Mapping DIG1 encoder to %s\n",TransmitterName); return TRUE; } else if (!rhdPtr->DigEncoderOutput[1]) { rhdPtr->DigEncoderOutput[1] = Output; TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG2; xf86DrvMsg(Output->scrnIndex, X_INFO, "Mapping DIG2 encoder to %s\n",TransmitterName); return TRUE; } else return FALSE; case RHD_OUTPUT_FREE: TransmitterConfig->Encoder = Private->EncoderId = atomEncoderNone; if (rhdPtr->DigEncoderOutput[0] == Output) { rhdPtr->DigEncoderOutput[0] = NULL; return TRUE; } else if (rhdPtr->DigEncoderOutput[1] == Output) { rhdPtr->DigEncoderOutput[1] = NULL; return TRUE; } else return FALSE; break; default: return FALSE; } }
static inline void rhdAtomOutputPower(struct rhdOutput *Output, int Power) { RHDPtr rhdPtr = RHDPTRI(Output); struct rhdAtomOutputPrivate *Private = (struct rhdAtomOutputPrivate *) Output->Private; struct atomEncoderConfig *EncoderConfig = &Private->EncoderConfig; union AtomBiosArg data; Bool enableHDMI = FALSE; RHDFUNC(Output); if(Output->Connector != NULL) { enableHDMI = RHDConnectorEnableHDMI(Output->Connector); switch(Output->Id) { case RHD_OUTPUT_TMDSA: case RHD_OUTPUT_LVTMA: if(enableHDMI && !Private->EncoderConfig.u.lvds2.Hdmi) Private->EncoderConfig.u.lvds2.Hdmi = TRUE; else if(!enableHDMI && Private->EncoderConfig.u.lvds2.Hdmi) Private->EncoderConfig.u.lvds2.Hdmi = FALSE; break; case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_KLDSKP_LVTMA: if(enableHDMI && Private->TransmitterConfig.Mode == atomDVI) { Private->TransmitterConfig.Mode = atomHDMI; Private->EncoderConfig.u.dig.EncoderMode = atomHDMI; } else if(!enableHDMI && Private->TransmitterConfig.Mode == atomHDMI) { Private->TransmitterConfig.Mode = atomDVI; Private->EncoderConfig.u.dig.EncoderMode = atomDVI; } break; default: break; } } data.Address = &Private->Save; RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); rhdSetEncoderTransmitterConfig(Output, Private->PixelClock); switch (Power) { case RHD_POWER_ON: RHDDebug(Output->scrnIndex, "RHD_POWER_ON\n"); rhdAtomEncoderControl(rhdPtr->atomBIOS, Private->EncoderId, atomEncoderOn, EncoderConfig); switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_UNIPHYC: case RHD_OUTPUT_UNIPHYD: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransEnable, &Private->TransmitterConfig)) { ERROR_MSG("rhdAtomDigTransmitterControl(atomTransEnable)"); break; } if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransEnableOutput, &Private->TransmitterConfig)) ERROR_MSG("rhdAtomDigTransmitterControl(atomTransEnableOutput)"); break; default: if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputEnable)) ERROR_MSG("rhdAtomOutputControl(atomOutputEnable)"); break; } RHDHdmiEnable(Private->Hdmi, enableHDMI); break; case RHD_POWER_RESET: RHDDebug(Output->scrnIndex, "RHD_POWER_RESET\n"); switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_UNIPHYC: case RHD_OUTPUT_UNIPHYD: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransDisableOutput, &Private->TransmitterConfig)) ERROR_MSG("rhdAtomDigTransmitterControl(atomTransDisableOutput)"); break; default: if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputDisable)) ERROR_MSG("rhdAtomOutputControl(atomOutputDisable)"); break; } break; case RHD_POWER_SHUTDOWN: RHDDebug(Output->scrnIndex, "RHD_POWER_SHUTDOWN\n"); switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: case RHD_OUTPUT_UNIPHYA: case RHD_OUTPUT_UNIPHYB: case RHD_OUTPUT_UNIPHYC: case RHD_OUTPUT_UNIPHYD: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: if (Private->EncoderId == atomEncoderNone) break; if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransDisableOutput, &Private->TransmitterConfig)) { ERROR_MSG("rhdAtomDigTransmitterControl(atomTransDisableOutput)"); break; } if (!rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, Private->TransmitterId, atomTransDisable, &Private->TransmitterConfig)) ERROR_MSG("rhdAtomDigTransmitterControl(atomTransDisable)"); break; default: if (!rhdAtomOutputControl(rhdPtr->atomBIOS, Private->OutputControlId, atomOutputDisable)) ERROR_MSG("rhdAtomOutputControl(atomOutputDisable)"); break; } if (Private->EncoderId != atomEncoderNone) if (!rhdAtomEncoderControl(rhdPtr->atomBIOS, Private->EncoderId, atomEncoderOff, &Private->EncoderConfig)) ERROR_MSG("rhdAtomEncoderControl(atomEncoderOff)"); RHDHdmiEnable(Private->Hdmi, FALSE); break; } data.Address = NULL; RHDAtomBiosFunc(Output->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); }
/* * This sets up AtomBIOS based BL control if we need to use a non-standard method to control BL. */ int RhdAtomSetupBacklightControlProperty(struct rhdOutput *Output, Bool (**PropertyFunc)(struct rhdOutput *Output, enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val), void **PrivatePtr) { RHDPtr rhdPtr = RHDPTRI(Output); int BlLevel; struct rhdAtomOutputPrivate *Private; struct atomTransmitterConfig *TransmitterConfig; RHDFUNC(Output); Private = xnfcalloc(sizeof(struct rhdAtomOutputPrivate), 1); switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: case RHD_OUTPUT_UNIPHYE: case RHD_OUTPUT_UNIPHYF: /* We set up a those parameters although they may never be needed for BL control */ TransmitterConfig = &Private->TransmitterConfig; switch (Output->Id) { case RHD_OUTPUT_KLDSKP_LVTMA: Private->TransmitterId = atomTransmitterLVTMA; break; case RHD_OUTPUT_UNIPHYE: Private->TransmitterId = atomTransmitterUNIPHY2; TransmitterConfig->Link = atomTransLinkA; break; case RHD_OUTPUT_UNIPHYF: Private->TransmitterId = atomTransmitterUNIPHY2; TransmitterConfig->Link = atomTransLinkB; break; default: return 0; /* never get here */ } TransmitterConfig = &Private->TransmitterConfig; TransmitterConfig->Mode = atomLVDS; if (rhdPtr->DigEncoderOutput[0] == Output) TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG1; else if (rhdPtr->DigEncoderOutput[1] == Output) TransmitterConfig->Encoder = Private->EncoderId = atomEncoderDIG2; else TransmitterConfig->Encoder = Private->EncoderId = atomEncoderNone; LVDSInfoRetrieve(rhdPtr, Private); Private->PixelClock = 0; Private->Hdmi = NULL; break; case RHD_OUTPUT_LVTMA: Private->OutputControlId = atomLCDOutput; break; default: xfree(Private); return 0; } *PropertyFunc = atomLVDSPropertyControl; *PrivatePtr = Private; RHDAtomBIOSScratchBlLevel(rhdPtr, rhdBIOSScratchBlGet, &BlLevel); return BlLevel; }