/* * Copyright 2007, 2008 Egbert Eich <eich@novell.com> * Copyright 2007, 2008 Luc Verhaegen <lverhaegen@novell.com> * Copyright 2007, 2008 Matthias Hopf <mhopf@novell.com> * Copyright 2007, 2008 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef ATOM_BIOS # include "xf86.h" #include "rhd.h" # include "edid.h" # include "xf86DDC.h" # if HAVE_XF86_ANSIC_H # include "xf86_ansic.h" # else # include <unistd.h> # include <string.h> # include <stdio.h> # endif # include "rhd_atombios.h" # include "rhd_connector.h" # include "rhd_output.h" # include "rhd_biosscratch.h" # include "rhd_crtc.h" # include "rhd_card.h" # ifdef ATOM_BIOS_PARSER # define INT8 INT8 # define INT16 INT16 # define INT32 INT32 # include "CD_Common_Types.h" # else # ifndef ULONG typedef unsigned int ULONG; # define ULONG ULONG # endif # ifndef UCHAR typedef unsigned char UCHAR; # define UCHAR UCHAR # endif # ifndef USHORT typedef unsigned short USHORT; # define USHORT USHORT # endif # endif # include "atombios.h" struct rhdOutputDevices { enum atomDevice DeviceId; enum rhdConnectorType ConnectorType; }; #if defined (ATOM_BIOS_PARSER) /* * */ static enum rhdSensedOutput rhdAtomBIOSScratchDACSenseResults(struct rhdOutput *Output, enum atomDAC DAC, enum atomDevice Device) { RHDPtr rhdPtr = RHDPTRI(Output); CARD32 BIOS_0; Bool TV = FALSE; RHDFUNC(Output); if (rhdPtr->ChipSet < RHD_R600) BIOS_0 = RHDRegRead(Output, 0x10); else BIOS_0 = RHDRegRead(Output, 0x1724); switch (Device) { case atomNone: case atomCRT2: case atomCRT1: case atomLCD1: case atomLCD2: case atomDFP1: case atomDFP2: case atomDFP3: case atomDFP4: case atomDFP5: TV = FALSE; break; case atomTV1: case atomTV2: case atomCV: TV = TRUE; break; } RHDDebug(Output->scrnIndex, "BIOSScratch_0: 0x%4.4x\n",BIOS_0); switch (DAC) { case atomDACA: break; case atomDACB: BIOS_0 >>= 8; break; case atomDACExt: return RHD_SENSED_NONE; } if (!TV) { if (BIOS_0 & ATOM_S0_CRT1_MASK) { RHDDebug(Output->scrnIndex, "%s sensed RHD_SENSED_VGA\n",__func__); return RHD_SENSED_VGA; } } else { if (BIOS_0 & ATOM_S0_TV1_COMPOSITE_A) { RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_COMPOSITE\n",__func__); return RHD_SENSED_TV_COMPOSITE; } else if (BIOS_0 & ATOM_S0_TV1_SVIDEO_A) { RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_SVIDE\n",__func__); return RHD_SENSED_TV_SVIDEO; } else if (BIOS_0 & ATOM_S0_CV_MASK_A) { RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_COMPONENT\n",__func__); return RHD_SENSED_TV_COMPONENT; } } RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_NONE\n",__func__); return RHD_SENSED_NONE; } /* * */ enum rhdSensedOutput RHDBIOSScratchDACSense(struct rhdOutput *Output, struct rhdConnector *Connector) { RHDPtr rhdPtr = RHDPTRI(Output); enum atomDAC DAC; Bool ret; Bool TV; enum atomDevice Device; enum rhdSensedOutput retVal; int i = 0; RHDFUNC(Output); if (!Output->OutputDriverPrivate) return RHD_SENSED_NONE; switch (Output->Id) { case RHD_OUTPUT_DACA: RHDDebug(Output->scrnIndex, "Sensing DACA on Output %s\n",Output->Name); DAC = atomDACA; break; case RHD_OUTPUT_DACB: RHDDebug(Output->scrnIndex, "Sensing DACB on Output %s\n",Output->Name); DAC = atomDACB; break; default: return FALSE; } switch (Connector->Type) { case RHD_CONNECTOR_DVI: case RHD_CONNECTOR_DVI_SINGLE: case RHD_CONNECTOR_VGA: TV = FALSE; break; default: TV = TRUE; } while ((Device = Output->OutputDriverPrivate->OutputDevices[i++].DeviceId) != atomNone) { switch (Device) { case atomCRT1: case atomCRT2: if (TV) continue; break; case atomTV1: case atomTV2: case atomCV: if (!TV) continue; break; default: /* should not get here */ return RHD_SENSED_NONE; } ret = AtomDACLoadDetection(rhdPtr->atomBIOS, Device, DAC); if (!ret) continue; if ((retVal = rhdAtomBIOSScratchDACSenseResults(Output, DAC, Device)) != RHD_SENSED_NONE) return retVal; } return RHD_SENSED_NONE; } # endif /* ATOM_BIOS_PARSER */ /* * */ static void rhdAtomBIOSScratchUpdateAttachedState(RHDPtr rhdPtr, enum atomDevice dev, Bool attached) { CARD32 BIOS_0; CARD32 Addr; CARD32 Mask; RHDFUNC(rhdPtr); if (rhdPtr->ChipSet < RHD_R600) Addr = 0x10; else Addr = 0x1724; BIOS_0 = RHDRegRead(rhdPtr, Addr); switch (dev) { case atomDFP1: Mask = ATOM_S0_DFP1; break; case atomDFP2: Mask = ATOM_S0_DFP2; break; case atomLCD1: Mask = ATOM_S0_LCD1; break; case atomLCD2: Mask = ATOM_S0_LCD2; break; case atomTV2: Mask = ATOM_S0_TV2; break; case atomDFP3: Mask = ATOM_S0_DFP3; break; case atomDFP4: Mask = ATOM_S0_DFP4; break; case atomDFP5: Mask = ATOM_S0_DFP5; break; default: return; } if (attached) BIOS_0 |= Mask; else BIOS_0 &= ~Mask; RHDRegWrite(rhdPtr, Addr, BIOS_0); } /* * */ static void rhdAtomBIOSScratchUpdateOnState(RHDPtr rhdPtr, enum atomDevice dev, Bool on) { CARD32 BIOS_3; CARD32 Addr; CARD32 Mask = 0; RHDFUNC(rhdPtr); if (rhdPtr->ChipSet < RHD_R600) Addr = 0x1C; else Addr = 0x1730; BIOS_3 = RHDRegRead(rhdPtr, Addr); switch (dev) { case atomCRT1: Mask = ATOM_S3_CRT1_ACTIVE; break; case atomLCD1: Mask = ATOM_S3_LCD1_ACTIVE; break; case atomTV1: Mask = ATOM_S3_TV1_ACTIVE; break; case atomDFP1: Mask = ATOM_S3_DFP1_ACTIVE; break; case atomCRT2: Mask = ATOM_S3_CRT2_ACTIVE; break; case atomLCD2: Mask = ATOM_S3_LCD2_ACTIVE; break; case atomTV2: Mask = ATOM_S3_TV2_ACTIVE; break; case atomDFP2: Mask = ATOM_S3_DFP2_ACTIVE; break; case atomCV: Mask = ATOM_S3_CV_ACTIVE; break; case atomDFP3: Mask = ATOM_S3_DFP3_ACTIVE; break; case atomDFP4: Mask = ATOM_S3_DFP4_ACTIVE; break; case atomDFP5: Mask = ATOM_S3_DFP5_ACTIVE; break; case atomNone: return; } if (on) BIOS_3 |= Mask; else BIOS_3 &= ~Mask; RHDRegWrite(rhdPtr, Addr, BIOS_3); } /* * */ void RHDAtomBIOSScratchSetAccelratorMode(RHDPtr rhdPtr, Bool on) { CARD32 Addr; CARD32 Mask = ATOM_S6_ACC_MODE | ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; if (rhdPtr->ChipSet < RHD_R600) Addr = 0x10 + (6 << 2); else Addr = 0x1724 + (6 << 2); RHDRegMask(rhdPtr, Addr, on ? Mask : 0, Mask); } /* * */ static void rhdAtomBIOSScratchSetAcceleratorModeForDevice(RHDPtr rhdPtr, enum atomDevice Device, Bool on) { CARD32 Addr; CARD32 Mask = 0; if (rhdPtr->ChipSet < RHD_R600) Addr = 0x10 + (6 << 2); else Addr = 0x1724 + (6 << 2); switch (Device) { case atomCRT1: Mask = ATOM_S6_ACC_REQ_CRT1; break; case atomLCD1: Mask = ATOM_S6_ACC_REQ_LCD1; break; case atomTV1: Mask = ATOM_S6_ACC_REQ_TV1; break; case atomDFP1: Mask = ATOM_S6_ACC_REQ_DFP1; break; case atomCRT2: Mask = ATOM_S6_ACC_REQ_CRT2; break; case atomLCD2: Mask = ATOM_S6_ACC_REQ_LCD2; break; case atomTV2: Mask = ATOM_S6_ACC_REQ_TV2; break; case atomDFP2: Mask = ATOM_S6_ACC_REQ_DFP2; break; case atomCV: Mask = ATOM_S6_ACC_REQ_CV; break; case atomDFP3: Mask = ATOM_S6_ACC_REQ_DFP3; break; case atomDFP4: Mask = ATOM_S6_ACC_REQ_DFP4; break; case atomDFP5: Mask = ATOM_S6_ACC_REQ_DFP5; break; case atomNone: return; } RHDRegMask(rhdPtr, Addr, on ? Mask : 0, Mask); } /* * */ static void rhdAtomBIOSScratchSetCrtcState(RHDPtr rhdPtr, enum atomDevice dev, enum atomCrtc Crtc) { CARD32 BIOS_3; CARD32 Addr; CARD32 Mask = 0; RHDFUNC(rhdPtr); if (rhdPtr->ChipSet < RHD_R600) Addr = 0x1C; else Addr = 0x1730; BIOS_3 = RHDRegRead(rhdPtr, Addr); switch (dev) { case atomCRT1: Mask = ATOM_S3_CRT1_CRTC_ACTIVE; break; case atomLCD1: Mask = ATOM_S3_LCD1_CRTC_ACTIVE; break; case atomTV1: Mask = ATOM_S3_TV1_CRTC_ACTIVE; break; case atomDFP1: Mask = ATOM_S3_DFP1_CRTC_ACTIVE; break; case atomCRT2: Mask = ATOM_S3_CRT2_CRTC_ACTIVE; break; case atomLCD2: Mask = ATOM_S3_LCD2_CRTC_ACTIVE; break; case atomTV2: Mask = ATOM_S3_TV2_CRTC_ACTIVE; break; case atomDFP2: Mask = ATOM_S3_DFP2_CRTC_ACTIVE; break; case atomCV: Mask = ATOM_S3_CV_CRTC_ACTIVE; break; case atomDFP3: Mask = ATOM_S3_DFP3_CRTC_ACTIVE; break; case atomDFP4: Mask = ATOM_S3_DFP4_CRTC_ACTIVE; break; case atomDFP5: Mask = ATOM_S3_DFP5_CRTC_ACTIVE; break; case atomNone: return; } if (Crtc == atomCrtc2) BIOS_3 |= Mask; else BIOS_3 &= ~Mask; RHDRegWrite(rhdPtr, Addr, BIOS_3); } /* * */ void RHDAtomBIOSScratchPMState(RHDPtr rhdPtr, struct rhdOutput *Output, int PowerManagementMode) { CARD32 Addr; CARD32 Mask = 0, Mask1; enum atomDevice Device = Output->OutputDriverPrivate->Device; if (rhdPtr->ChipSet < RHD_R600) Addr = 0x10 + (2 << 2); else Addr = 0x1724 + (2 << 2); switch (Device) { case atomCRT1: Mask = ATOM_S2_CRT1_DPMS_STATE; break; case atomLCD1: Mask = ATOM_S2_LCD1_DPMS_STATE; break; case atomTV1: Mask = ATOM_S2_TV1_DPMS_STATE; break; case atomDFP1: Mask = ATOM_S2_DFP1_DPMS_STATE; break; case atomCRT2: Mask = ATOM_S2_CRT2_DPMS_STATE; break; case atomLCD2: Mask = ATOM_S2_LCD2_DPMS_STATE; break; case atomTV2: Mask = ATOM_S2_TV2_DPMS_STATE; break; case atomDFP2: Mask = ATOM_S2_DFP2_DPMS_STATE; break; case atomCV: Mask = ATOM_S2_CV_DPMS_STATE; break; case atomDFP3: Mask = ATOM_S2_DFP3_DPMS_STATE; break; case atomDFP4: Mask = ATOM_S2_DFP4_DPMS_STATE; break; case atomDFP5: Mask = ATOM_S2_DFP5_DPMS_STATE; break; case atomNone: return; } switch (PowerManagementMode) { case DPMSModeOn: Mask1 = 0; break; case DPMSModeStandby: case DPMSModeSuspend: case DPMSModeOff: default: Mask1 = Mask; break; } RHDRegMask(rhdPtr, Addr, Mask1, Mask); } /* * */ void RHDAtomBIOSScratchBlLevel(RHDPtr rhdPtr, enum rhdBIOSScratchBlAction action, int *val) { CARD32 Addr; RHDFUNC(rhdPtr); if (rhdPtr->ChipSet < RHD_R600) Addr = 0x18; else Addr = 0x172C; switch (action) { case rhdBIOSScratchBlGet: *val = (RHDRegRead(rhdPtr, Addr) >> 8) & 0xFF; RHDDebug(rhdPtr->scrnIndex, "Get BL level: 0x%x\n",*val); break; case rhdBIOSScratchBlSet: RHDDebug(rhdPtr->scrnIndex, "Set BL level: 0x%x\n",*val); RHDRegMask(rhdPtr, Addr, (*val) << 8, 0xFF00); break; } } /* * This function finds the AtomBIOS device ID of the device that we currently * want to drive with a specific output. It contains a logic to deal with CRTC vs. TV * on DACs. * This function preferrably gets called from within the function that also updates * the BIOS scratch registers. */ static enum atomDevice rhdBIOSScratchSetDeviceForOutput(struct rhdOutput *Output) { int i = 0; RHDFUNC(Output); if (!Output->Connector) { RHDDebug(Output->scrnIndex,"%s: No connector assigned to output %s\n",__func__,Output->Name); return atomNone; } if (!Output->OutputDriverPrivate) { RHDDebug(Output->scrnIndex,"%s: Output %s has no DriverPrivate\n",__func__,Output->Name); return atomNone; } while (Output->OutputDriverPrivate->OutputDevices[i].DeviceId != atomNone) { if (Output->OutputDriverPrivate->OutputDevices[i].ConnectorType == Output->Connector->Type){ switch (Output->OutputDriverPrivate->OutputDevices[i].DeviceId) { case atomCrtc1: case atomCrtc2: if (Output->SensedType == RHD_SENSED_VGA || Output->SensedType == RHD_SENSED_NONE) /* if nothing was sensed default to VGA */ break; i++; continue; case atomTV1: case atomTV2: if (Output->SensedType == RHD_SENSED_TV_SVIDEO || Output->SensedType == RHD_SENSED_TV_COMPOSITE) break; i++; continue; case atomCV: if (Output->SensedType == RHD_SENSED_TV_COMPONENT) break; i++; continue; default: break; } Output->OutputDriverPrivate->Device = Output->OutputDriverPrivate->OutputDevices[i].DeviceId; return Output->OutputDriverPrivate->Device; } i++; } RHDDebugVerb(Output->scrnIndex,1,"%s: No device found: ConnectorType: %2.2x SensedType: %2.2x\n", __func__, Output->Connector->Type, Output->SensedType); return atomNone; } /* * This function is public as it is used from within other outputs, too. */ static enum atomDevice rhdBIOSScratchUpdateBIOSScratchForOutput(struct rhdOutput *Output) { RHDPtr rhdPtr = RHDPTRI(Output); struct rhdOutputDevices *devList; enum atomDevice Device; int i = 0; RHDFUNC(Output); if (!Output->OutputDriverPrivate) { RHDDebug(Output->scrnIndex,"%s: no output driver private present\n",__func__); return atomNone; } devList = Output->OutputDriverPrivate->OutputDevices; if (Output->Connector) { /* connected - enable */ Device = rhdBIOSScratchSetDeviceForOutput(Output); if (Device == atomNone && rhdPtr->Card->ConnectorInfo[0].Type != RHD_CONNECTOR_NONE) { xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: AtomBIOS DeviceID unknown\n",__func__); return Device; } ASSERT(Device != atomNone); if (Output->Crtc) rhdAtomBIOSScratchSetCrtcState(rhdPtr, Device, Output->Crtc->Id == 1 ? atomCrtc2 : atomCrtc1); rhdAtomBIOSScratchUpdateOnState(rhdPtr, Device, Output->Active); rhdAtomBIOSScratchSetAcceleratorModeForDevice(rhdPtr, Device, Output->Active); rhdAtomBIOSScratchUpdateAttachedState(rhdPtr, Device, TRUE); while (devList[i].DeviceId != atomNone) { if (devList[i].DeviceId != Device) rhdAtomBIOSScratchUpdateOnState(rhdPtr, devList[i].DeviceId, FALSE); i++; } } else { /* not connected - just disable everything */ Device = atomNone; Output->OutputDriverPrivate->Device = Device; while (devList[i].DeviceId != atomNone) { rhdAtomBIOSScratchUpdateOnState(rhdPtr, devList[i].DeviceId, FALSE); rhdAtomBIOSScratchSetAcceleratorModeForDevice(rhdPtr, devList[i].DeviceId, FALSE); rhdAtomBIOSScratchUpdateAttachedState(rhdPtr, devList[i].DeviceId, FALSE); i++; } } return Device; } /* * */ static void rhdBIOSScratchPower(struct rhdOutput *Output, int Power) { rhdBIOSScratchUpdateBIOSScratchForOutput(Output); Output->OutputDriverPrivate->Power(Output, Power); } /* * */ static void rhdBIOSScratchMode(struct rhdOutput *Output, DisplayModePtr Mode) { rhdBIOSScratchUpdateBIOSScratchForOutput(Output); Output->OutputDriverPrivate->Mode(Output, Mode); } /* * This destroys the privates again. It is implemented as an output destroy wrapper. */ static void rhdBIOSScratchDestroyOutputDriverPrivate(struct rhdOutput *Output) { RHDFUNC(Output); if (Output->OutputDriverPrivate) { void (*Destroy) (struct rhdOutput *Output) = Output->OutputDriverPrivate->Destroy; xfree(Output->OutputDriverPrivate->OutputDevices); xfree(Output->OutputDriverPrivate); Output->OutputDriverPrivate = NULL; if (Destroy) Destroy(Output); } } /* * This sets up the AtomBIOS driver output private. * It allocates the data structure and sets up the list of devices * including the connector they are associated with. */ Bool RHDAtomSetupOutputDriverPrivate(struct rhdAtomOutputDeviceList *Devices, struct rhdOutput *Output) { struct rhdOutputDevices *od = NULL; struct BIOSScratchOutputPrivate *OutputDriverPrivate; int i = 0, cnt = 0; RHDFUNC(Output); if (!Devices) { RHDDebug(Output->scrnIndex, "%s: Device list doesn't exist.\n"); return FALSE; } RHDDebugVerb(Output->scrnIndex, 1, " Output: %s[0x%2.2x] - adding devices:\n", Output->Name, Output->Id); while (Devices[i].DeviceId != atomNone) { RHDDebugVerb(Output->scrnIndex,1," Looking at DeviceID: 0x%2.2x OutputType: 0x%2.2x ConnectorType: 0x%2.2x\n", Devices[i].DeviceId,Devices[i].OutputType,Devices[i].ConnectorType); if (Devices[i].OutputType == Output->Id) { if (!(od = (struct rhdOutputDevices *)xrealloc(od, sizeof(struct rhdOutputDevices) * (cnt + 1)))) return FALSE; RHDDebugVerb(Output->scrnIndex,1," >> 0x%2.2x\n", Devices[i].DeviceId); od[cnt].DeviceId = Devices[i].DeviceId; od[cnt].ConnectorType = Devices[i].ConnectorType; cnt++; } i++; } if (!(od = (struct rhdOutputDevices *)xrealloc(od, sizeof(struct rhdOutputDevices) * (cnt + 1)))) return FALSE; od[cnt].DeviceId = atomNone; if (!(OutputDriverPrivate = (struct BIOSScratchOutputPrivate *)xalloc(sizeof(struct BIOSScratchOutputPrivate)))) { xfree(od); return FALSE; } OutputDriverPrivate->OutputDevices = od; OutputDriverPrivate->Destroy = Output->Destroy; Output->Destroy = rhdBIOSScratchDestroyOutputDriverPrivate; OutputDriverPrivate->Power = Output->Power; Output->Power = rhdBIOSScratchPower; OutputDriverPrivate->Mode = Output->Mode; Output->Mode = rhdBIOSScratchMode; Output->OutputDriverPrivate = OutputDriverPrivate; return TRUE; } /* * Find the connector and output type for a specific atom device. * This information is kept in the output lists. */ Bool RHDFindConnectorAndOutputTypesForDevice(RHDPtr rhdPtr, enum atomDevice Device, enum rhdOutputType *ot, enum rhdConnectorType *ct) { struct rhdOutput *Output; *ot = RHD_OUTPUT_NONE; *ct = RHD_CONNECTOR_NONE; for (Output = rhdPtr->Outputs; Output; Output = Output->Next) { struct rhdOutputDevices *DeviceList; int i = 0; if (!Output->OutputDriverPrivate) continue; DeviceList = Output->OutputDriverPrivate->OutputDevices; while (DeviceList[i].DeviceId != atomNone) { if (DeviceList[i].DeviceId == Device) { *ot = Output->Id; *ct = DeviceList[i].ConnectorType; return TRUE; } i++; } } return FALSE; } /* * */ enum atomDevice RHDGetDeviceOnCrtc(RHDPtr rhdPtr, enum atomCrtc Crtc) { CARD32 BIOS_3; CARD32 Addr; CARD32 Mask = 0; RHDFUNC(rhdPtr); if (rhdPtr->ChipSet < RHD_R600) Addr = 0x1C; else Addr = 0x1730; if (Crtc == atomCrtc1) Mask = ~Mask; BIOS_3 = RHDRegRead(rhdPtr, Addr); RHDDebug(rhdPtr->scrnIndex, "%s: BIOS_3 = 0x%x\n",__func__,BIOS_3); if (BIOS_3 & ATOM_S3_CRT1_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_CRT1_CRTC_ACTIVE)) return atomCRT1; else if (BIOS_3 & ATOM_S3_LCD1_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_LCD1_CRTC_ACTIVE)) return atomLCD1; else if (BIOS_3 & ATOM_S3_DFP1_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_DFP1_CRTC_ACTIVE)) return atomDFP1; else if (BIOS_3 & ATOM_S3_CRT2_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_CRT2_CRTC_ACTIVE)) return atomCRT2; else if (BIOS_3 & ATOM_S3_LCD2_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_LCD2_CRTC_ACTIVE)) return atomLCD2; else if (BIOS_3 & ATOM_S3_TV2_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_TV2_CRTC_ACTIVE)) return atomTV2; else if (BIOS_3 & ATOM_S3_DFP2_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_DFP2_CRTC_ACTIVE)) return atomDFP2; else if (BIOS_3 & ATOM_S3_CV_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_CV_CRTC_ACTIVE)) return atomCV; else if (BIOS_3 & ATOM_S3_DFP3_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_DFP3_CRTC_ACTIVE)) return atomDFP3; else if (BIOS_3 & ATOM_S3_DFP4_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_DFP4_CRTC_ACTIVE)) return atomDFP4; else if (BIOS_3 & ATOM_S3_DFP5_ACTIVE && ((BIOS_3 ^ Mask) & ATOM_S3_DFP5_CRTC_ACTIVE)) return atomDFP5; else return atomNone; } struct rhdBiosScratchRegisters { CARD32 Scratch0; CARD32 Scratch2; CARD32 Scratch3; CARD32 Scratch6; }; struct rhdBiosScratchRegisters * RHDSaveBiosScratchRegisters(RHDPtr rhdPtr) { struct rhdBiosScratchRegisters *regs; CARD32 S0Addr, S2Addr, S3Addr, S6Addr; RHDFUNC(rhdPtr); if (!(regs = (struct rhdBiosScratchRegisters *)xalloc(sizeof(struct rhdBiosScratchRegisters)))) return NULL; if (rhdPtr->ChipSet < RHD_R600) { S0Addr = 0x10; S2Addr = 0x18; S3Addr = 0x1C; S6Addr = 0x10 + (6 << 2); } else { S0Addr = 0x1724; S2Addr = 0x172C; S3Addr = 0x1730; S6Addr = 0x1724 + (6 << 2); } regs->Scratch0 = RHDRegRead(rhdPtr, S0Addr); regs->Scratch2 = RHDRegRead(rhdPtr, S2Addr); regs->Scratch3 = RHDRegRead(rhdPtr, S3Addr); regs->Scratch6 = RHDRegRead(rhdPtr, S6Addr); return regs; } void RHDRestoreBiosScratchRegisters(RHDPtr rhdPtr, struct rhdBiosScratchRegisters *regs) { CARD32 S0Addr, S2Addr, S3Addr, S6Addr; RHDFUNC(rhdPtr); if (!regs) return; if (rhdPtr->ChipSet < RHD_R600) { S0Addr = 0x10; S2Addr = 0x18; S3Addr = 0x1C; S6Addr = 0x10 + (6 << 2); } else { S0Addr = 0x1724; S2Addr = 0x172C; S3Addr = 0x1730; S6Addr = 0x1724 + (6 << 2); } RHDRegWrite(rhdPtr, S0Addr, regs->Scratch0); RHDRegWrite(rhdPtr, S2Addr, regs->Scratch2); RHDRegWrite(rhdPtr, S3Addr, regs->Scratch3); RHDRegWrite(rhdPtr, S6Addr, regs->Scratch6); xfree(regs); } #endif /* ATOM_BIOS */