radeon_atombios.c revision b13dfe66
1209ff23fSmrg/* 2209ff23fSmrg * Copyright 2007 Egbert Eich <eich@novell.com> 3209ff23fSmrg * Copyright 2007 Luc Verhaegen <lverhaegen@novell.com> 4209ff23fSmrg * Copyright 2007 Matthias Hopf <mhopf@novell.com> 5209ff23fSmrg * Copyright 2007 Advanced Micro Devices, Inc. 6209ff23fSmrg * 7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 8209ff23fSmrg * copy of this software and associated documentation files (the "Software"), 9209ff23fSmrg * to deal in the Software without restriction, including without limitation 10209ff23fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11209ff23fSmrg * and/or sell copies of the Software, and to permit persons to whom the 12209ff23fSmrg * Software is furnished to do so, subject to the following conditions: 13209ff23fSmrg * 14209ff23fSmrg * The above copyright notice and this permission notice shall be included in 15209ff23fSmrg * all copies or substantial portions of the Software. 16209ff23fSmrg * 17209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18209ff23fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19209ff23fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20209ff23fSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21209ff23fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22209ff23fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23209ff23fSmrg * OTHER DEALINGS IN THE SOFTWARE. 24209ff23fSmrg */ 25209ff23fSmrg 26209ff23fSmrg#ifdef HAVE_CONFIG_H 27209ff23fSmrg# include "config.h" 28209ff23fSmrg#endif 29209ff23fSmrg#include "xf86.h" 30209ff23fSmrg#include "xf86_OSproc.h" 31209ff23fSmrg 32209ff23fSmrg#include "radeon.h" 33ad43ddacSmrg#include "radeon_reg.h" 34209ff23fSmrg#include "radeon_atombios.h" 35209ff23fSmrg#include "radeon_atomwrapper.h" 36209ff23fSmrg#include "radeon_probe.h" 37209ff23fSmrg#include "radeon_macros.h" 38209ff23fSmrg 39209ff23fSmrg#include "ati_pciids_gen.h" 40209ff23fSmrg 41209ff23fSmrg#include "xorg-server.h" 42209ff23fSmrg 43209ff23fSmrg/* only for testing now */ 44209ff23fSmrg#include "xf86DDC.h" 45209ff23fSmrg 46209ff23fSmrgtypedef AtomBiosResult (*AtomBiosRequestFunc)(atomBiosHandlePtr handle, 47209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 48209ff23fSmrgtypedef struct rhdConnectorInfo *rhdConnectorInfoPtr; 49209ff23fSmrg 50209ff23fSmrgstatic AtomBiosResult rhdAtomInit(atomBiosHandlePtr unused1, 51209ff23fSmrg AtomBiosRequestID unused2, AtomBiosArgPtr data); 52209ff23fSmrgstatic AtomBiosResult rhdAtomTearDown(atomBiosHandlePtr handle, 53209ff23fSmrg AtomBiosRequestID unused1, AtomBiosArgPtr unused2); 54209ff23fSmrgstatic AtomBiosResult rhdAtomVramInfoQuery(atomBiosHandlePtr handle, 55209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 56209ff23fSmrgstatic AtomBiosResult rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, 57209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 58209ff23fSmrgstatic AtomBiosResult rhdAtomAllocateFbScratch(atomBiosHandlePtr handle, 59209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 60209ff23fSmrgstatic AtomBiosResult rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, 61209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 62209ff23fSmrgstatic AtomBiosResult rhdAtomCVGetTimings(atomBiosHandlePtr handle, 63209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 64209ff23fSmrgstatic AtomBiosResult rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, 65209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 66209ff23fSmrgstatic AtomBiosResult rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, 67209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 68209ff23fSmrgstatic AtomBiosResult rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, 69209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 70209ff23fSmrg/*static AtomBiosResult rhdAtomConnectorInfo(atomBiosHandlePtr handle, 71209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data);*/ 72209ff23fSmrg# ifdef ATOM_BIOS_PARSER 73209ff23fSmrgstatic AtomBiosResult rhdAtomExec(atomBiosHandlePtr handle, 74209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 75209ff23fSmrg# endif 76209ff23fSmrgstatic AtomBiosResult 77209ff23fSmrgrhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, 78209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 79209ff23fSmrg 80209ff23fSmrg 81b7e1c893Smrgstatic void 82b7e1c893SmrgRADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds); 83b7e1c893Smrg 84b7e1c893Smrg 85209ff23fSmrgenum msgDataFormat { 86209ff23fSmrg MSG_FORMAT_NONE, 87209ff23fSmrg MSG_FORMAT_HEX, 88209ff23fSmrg MSG_FORMAT_DEC 89209ff23fSmrg}; 90209ff23fSmrg 91209ff23fSmrgstruct atomBIOSRequests { 92209ff23fSmrg AtomBiosRequestID id; 93209ff23fSmrg AtomBiosRequestFunc request; 94209ff23fSmrg char *message; 95209ff23fSmrg enum msgDataFormat message_format; 96209ff23fSmrg} AtomBiosRequestList [] = { 97209ff23fSmrg {ATOMBIOS_INIT, rhdAtomInit, 98209ff23fSmrg "AtomBIOS Init", MSG_FORMAT_NONE}, 99209ff23fSmrg {ATOMBIOS_TEARDOWN, rhdAtomTearDown, 100209ff23fSmrg "AtomBIOS Teardown", MSG_FORMAT_NONE}, 101209ff23fSmrg# ifdef ATOM_BIOS_PARSER 102209ff23fSmrg {ATOMBIOS_EXEC, rhdAtomExec, 103209ff23fSmrg "AtomBIOS Exec", MSG_FORMAT_NONE}, 104209ff23fSmrg#endif 105209ff23fSmrg {ATOMBIOS_ALLOCATE_FB_SCRATCH, rhdAtomAllocateFbScratch, 106209ff23fSmrg "AtomBIOS Set FB Space", MSG_FORMAT_NONE}, 107209ff23fSmrg /*{ATOMBIOS_GET_CONNECTORS, rhdAtomConnectorInfo, 108209ff23fSmrg "AtomBIOS Get Connectors", MSG_FORMAT_NONE},*/ 109209ff23fSmrg {ATOMBIOS_GET_PANEL_MODE, rhdAtomLvdsGetTimings, 110209ff23fSmrg "AtomBIOS Get Panel Mode", MSG_FORMAT_NONE}, 111209ff23fSmrg {ATOMBIOS_GET_PANEL_EDID, rhdAtomLvdsGetTimings, 112209ff23fSmrg "AtomBIOS Get Panel EDID", MSG_FORMAT_NONE}, 113209ff23fSmrg {GET_DEFAULT_ENGINE_CLOCK, rhdAtomFirmwareInfoQuery, 114209ff23fSmrg "Default Engine Clock", MSG_FORMAT_DEC}, 115209ff23fSmrg {GET_DEFAULT_MEMORY_CLOCK, rhdAtomFirmwareInfoQuery, 116209ff23fSmrg "Default Memory Clock", MSG_FORMAT_DEC}, 117209ff23fSmrg {GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, 118209ff23fSmrg "Maximum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, 119209ff23fSmrg {GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, 120209ff23fSmrg "Minimum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, 121209ff23fSmrg {GET_MAX_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, 122209ff23fSmrg "Maximum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, 123209ff23fSmrg {GET_MIN_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, 124209ff23fSmrg "Minimum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, 125209ff23fSmrg {GET_MAX_PIXEL_CLK, rhdAtomFirmwareInfoQuery, 126209ff23fSmrg "Maximum Pixel Clock", MSG_FORMAT_DEC}, 127209ff23fSmrg {GET_REF_CLOCK, rhdAtomFirmwareInfoQuery, 128209ff23fSmrg "Reference Clock", MSG_FORMAT_DEC}, 129209ff23fSmrg {GET_FW_FB_START, rhdAtomVramInfoQuery, 130209ff23fSmrg "Start of VRAM area used by Firmware", MSG_FORMAT_HEX}, 131209ff23fSmrg {GET_FW_FB_SIZE, rhdAtomVramInfoQuery, 132209ff23fSmrg "Framebuffer space used by Firmware (kb)", MSG_FORMAT_DEC}, 133209ff23fSmrg {ATOM_TMDS_FREQUENCY, rhdAtomTmdsInfoQuery, 134209ff23fSmrg "TMDS Frequency", MSG_FORMAT_DEC}, 135209ff23fSmrg {ATOM_TMDS_PLL_CHARGE_PUMP, rhdAtomTmdsInfoQuery, 136209ff23fSmrg "TMDS PLL ChargePump", MSG_FORMAT_DEC}, 137209ff23fSmrg {ATOM_TMDS_PLL_DUTY_CYCLE, rhdAtomTmdsInfoQuery, 138209ff23fSmrg "TMDS PLL DutyCycle", MSG_FORMAT_DEC}, 139209ff23fSmrg {ATOM_TMDS_PLL_VCO_GAIN, rhdAtomTmdsInfoQuery, 140209ff23fSmrg "TMDS PLL VCO Gain", MSG_FORMAT_DEC}, 141209ff23fSmrg {ATOM_TMDS_PLL_VOLTAGE_SWING, rhdAtomTmdsInfoQuery, 142209ff23fSmrg "TMDS PLL VoltageSwing", MSG_FORMAT_DEC}, 143209ff23fSmrg {ATOM_LVDS_SUPPORTED_REFRESH_RATE, rhdAtomLvdsInfoQuery, 144209ff23fSmrg "LVDS Supported Refresh Rate", MSG_FORMAT_DEC}, 145209ff23fSmrg {ATOM_LVDS_OFF_DELAY, rhdAtomLvdsInfoQuery, 146209ff23fSmrg "LVDS Off Delay", MSG_FORMAT_DEC}, 147209ff23fSmrg {ATOM_LVDS_SEQ_DIG_ONTO_DE, rhdAtomLvdsInfoQuery, 148209ff23fSmrg "LVDS SEQ Dig onto DE", MSG_FORMAT_DEC}, 149209ff23fSmrg {ATOM_LVDS_SEQ_DE_TO_BL, rhdAtomLvdsInfoQuery, 150209ff23fSmrg "LVDS SEQ DE to BL", MSG_FORMAT_DEC}, 151209ff23fSmrg {ATOM_LVDS_DITHER, rhdAtomLvdsInfoQuery, 152209ff23fSmrg "LVDS Ditherc", MSG_FORMAT_HEX}, 153209ff23fSmrg {ATOM_LVDS_DUALLINK, rhdAtomLvdsInfoQuery, 154209ff23fSmrg "LVDS Duallink", MSG_FORMAT_HEX}, 155209ff23fSmrg {ATOM_LVDS_GREYLVL, rhdAtomLvdsInfoQuery, 156209ff23fSmrg "LVDS Grey Level", MSG_FORMAT_HEX}, 157209ff23fSmrg {ATOM_LVDS_FPDI, rhdAtomLvdsInfoQuery, 158209ff23fSmrg "LVDS FPDI", MSG_FORMAT_HEX}, 159209ff23fSmrg {ATOM_LVDS_24BIT, rhdAtomLvdsInfoQuery, 160209ff23fSmrg "LVDS 24Bit", MSG_FORMAT_HEX}, 161209ff23fSmrg {ATOM_GPIO_I2C_CLK_MASK, rhdAtomGPIOI2CInfoQuery, 162209ff23fSmrg "GPIO_I2C_Clk_Mask", MSG_FORMAT_HEX}, 163209ff23fSmrg {ATOM_DAC1_BG_ADJ, rhdAtomCompassionateDataQuery, 164209ff23fSmrg "DAC1 BG Adjustment", MSG_FORMAT_HEX}, 165209ff23fSmrg {ATOM_DAC1_DAC_ADJ, rhdAtomCompassionateDataQuery, 166209ff23fSmrg "DAC1 DAC Adjustment", MSG_FORMAT_HEX}, 167209ff23fSmrg {ATOM_DAC1_FORCE, rhdAtomCompassionateDataQuery, 168209ff23fSmrg "DAC1 Force Data", MSG_FORMAT_HEX}, 169209ff23fSmrg {ATOM_DAC2_CRTC2_BG_ADJ, rhdAtomCompassionateDataQuery, 170209ff23fSmrg "DAC2_CRTC2 BG Adjustment", MSG_FORMAT_HEX}, 171209ff23fSmrg {ATOM_DAC2_CRTC2_DAC_ADJ, rhdAtomCompassionateDataQuery, 172209ff23fSmrg "DAC2_CRTC2 DAC Adjustment", MSG_FORMAT_HEX}, 173209ff23fSmrg {ATOM_DAC2_CRTC2_FORCE, rhdAtomCompassionateDataQuery, 174209ff23fSmrg "DAC2_CRTC2 Force", MSG_FORMAT_HEX}, 175209ff23fSmrg {ATOM_DAC2_CRTC2_MUX_REG_IND,rhdAtomCompassionateDataQuery, 176209ff23fSmrg "DAC2_CRTC2 Mux Register Index", MSG_FORMAT_HEX}, 177209ff23fSmrg {ATOM_DAC2_CRTC2_MUX_REG_INFO,rhdAtomCompassionateDataQuery, 178209ff23fSmrg "DAC2_CRTC2 Mux Register Info", MSG_FORMAT_HEX}, 179209ff23fSmrg {ATOMBIOS_GET_CV_MODES, rhdAtomCVGetTimings, 180209ff23fSmrg "AtomBIOS Get CV Mode", MSG_FORMAT_NONE}, 181209ff23fSmrg {FUNC_END, NULL, 182209ff23fSmrg NULL, MSG_FORMAT_NONE} 183209ff23fSmrg}; 184209ff23fSmrg 185209ff23fSmrgenum { 186209ff23fSmrg legacyBIOSLocation = 0xC0000, 187209ff23fSmrg legacyBIOSMax = 0x10000 188209ff23fSmrg}; 189209ff23fSmrg 190209ff23fSmrg#define DEBUGP(x) {x;} 191209ff23fSmrg#define LOG_DEBUG 7 192209ff23fSmrg 193209ff23fSmrg# ifdef ATOM_BIOS_PARSER 194209ff23fSmrg 195209ff23fSmrg# define LOG_CAIL LOG_DEBUG + 1 196209ff23fSmrg 197209ff23fSmrg#if 0 198209ff23fSmrg 199209ff23fSmrgstatic void 200209ff23fSmrgRHDDebug(int scrnIndex, const char *format, ...) 201209ff23fSmrg{ 202209ff23fSmrg va_list ap; 203209ff23fSmrg 204209ff23fSmrg va_start(ap, format); 205209ff23fSmrg xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_DEBUG, format, ap); 206209ff23fSmrg va_end(ap); 207209ff23fSmrg} 208209ff23fSmrg 209209ff23fSmrgstatic void 210209ff23fSmrgRHDDebugCont(const char *format, ...) 211209ff23fSmrg{ 212209ff23fSmrg va_list ap; 213209ff23fSmrg 214209ff23fSmrg va_start(ap, format); 215209ff23fSmrg xf86VDrvMsgVerb(-1, X_NONE, LOG_DEBUG, format, ap); 216209ff23fSmrg va_end(ap); 217209ff23fSmrg} 218209ff23fSmrg 219209ff23fSmrg#endif 220209ff23fSmrg 221209ff23fSmrgstatic void 222209ff23fSmrgCailDebug(int scrnIndex, const char *format, ...) 223209ff23fSmrg{ 224209ff23fSmrg va_list ap; 225209ff23fSmrg 226209ff23fSmrg va_start(ap, format); 227209ff23fSmrg xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_CAIL, format, ap); 228209ff23fSmrg va_end(ap); 229209ff23fSmrg} 230209ff23fSmrg# define CAILFUNC(ptr) \ 231209ff23fSmrg CailDebug(((atomBiosHandlePtr)(ptr))->scrnIndex, "CAIL: %s\n", __func__) 232209ff23fSmrg 233209ff23fSmrg# endif 234209ff23fSmrg 235209ff23fSmrgstatic int 236209ff23fSmrgrhdAtomAnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr) 237209ff23fSmrg{ 238209ff23fSmrg if (le16_to_cpu(hdr->usStructureSize) == 0xaa55) 239209ff23fSmrg return FALSE; 240209ff23fSmrg 241209ff23fSmrg return TRUE; 242209ff23fSmrg} 243209ff23fSmrg 244209ff23fSmrgstatic int 245209ff23fSmrgrhdAtomAnalyzeRomHdr(unsigned char *rombase, 246209ff23fSmrg ATOM_ROM_HEADER *hdr, 247209ff23fSmrg unsigned int *data_offset, 248209ff23fSmrg unsigned int *command_offset) 249209ff23fSmrg{ 250209ff23fSmrg if (!rhdAtomAnalyzeCommonHdr(&hdr->sHeader)) { 251209ff23fSmrg return FALSE; 252209ff23fSmrg } 253209ff23fSmrg xf86DrvMsg(-1,X_NONE,"\tSubsystemVendorID: 0x%4.4x SubsystemID: 0x%4.4x\n", 254209ff23fSmrg le16_to_cpu(hdr->usSubsystemVendorID),le16_to_cpu(hdr->usSubsystemID)); 255209ff23fSmrg xf86DrvMsg(-1,X_NONE,"\tIOBaseAddress: 0x%4.4x\n",le16_to_cpu(hdr->usIoBaseAddress)); 256209ff23fSmrg xf86DrvMsgVerb(-1,X_NONE,3,"\tFilename: %s\n",rombase + le16_to_cpu(hdr->usConfigFilenameOffset)); 257209ff23fSmrg xf86DrvMsgVerb(-1,X_NONE,3,"\tBIOS Bootup Message: %s\n", 258209ff23fSmrg rombase + le16_to_cpu(hdr->usBIOS_BootupMessageOffset)); 259209ff23fSmrg 260209ff23fSmrg *data_offset = le16_to_cpu(hdr->usMasterDataTableOffset); 261209ff23fSmrg *command_offset = le16_to_cpu(hdr->usMasterCommandTableOffset); 262209ff23fSmrg 263209ff23fSmrg return TRUE; 264209ff23fSmrg} 265209ff23fSmrg 266209ff23fSmrgstatic int 267209ff23fSmrgrhdAtomAnalyzeRomDataTable(unsigned char *base, uint16_t offset, 268209ff23fSmrg void *ptr,unsigned short *size) 269209ff23fSmrg{ 270209ff23fSmrg ATOM_COMMON_TABLE_HEADER *table = (ATOM_COMMON_TABLE_HEADER *) 271209ff23fSmrg (base + le16_to_cpu(offset)); 272209ff23fSmrg 273209ff23fSmrg if (!*size || !rhdAtomAnalyzeCommonHdr(table)) { 274209ff23fSmrg if (*size) *size -= 2; 275209ff23fSmrg *(void **)ptr = NULL; 276209ff23fSmrg return FALSE; 277209ff23fSmrg } 278209ff23fSmrg *size -= 2; 279209ff23fSmrg *(void **)ptr = (void *)(table); 280209ff23fSmrg return TRUE; 281209ff23fSmrg} 282209ff23fSmrg 283209ff23fSmrgBool 284209ff23fSmrgrhdAtomGetTableRevisionAndSize(ATOM_COMMON_TABLE_HEADER *hdr, 285209ff23fSmrg uint8_t *contentRev, 286209ff23fSmrg uint8_t *formatRev, 287209ff23fSmrg unsigned short *size) 288209ff23fSmrg{ 289209ff23fSmrg if (!hdr) 290209ff23fSmrg return FALSE; 291209ff23fSmrg 292209ff23fSmrg if (contentRev) *contentRev = hdr->ucTableContentRevision; 293209ff23fSmrg if (formatRev) *formatRev = hdr->ucTableFormatRevision; 294209ff23fSmrg if (size) *size = (short)le16_to_cpu(hdr->usStructureSize) 295209ff23fSmrg - sizeof(ATOM_COMMON_TABLE_HEADER); 296209ff23fSmrg return TRUE; 297209ff23fSmrg} 298209ff23fSmrg 299209ff23fSmrgstatic Bool 300209ff23fSmrgrhdAtomAnalyzeMasterDataTable(unsigned char *base, 301209ff23fSmrg ATOM_MASTER_DATA_TABLE *table, 302209ff23fSmrg atomDataTablesPtr data) 303209ff23fSmrg{ 304209ff23fSmrg ATOM_MASTER_LIST_OF_DATA_TABLES *data_table = 305209ff23fSmrg &table->ListOfDataTables; 306209ff23fSmrg unsigned short size; 307209ff23fSmrg 308209ff23fSmrg if (!rhdAtomAnalyzeCommonHdr(&table->sHeader)) 309209ff23fSmrg return FALSE; 310209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize(&table->sHeader,NULL,NULL, 311209ff23fSmrg &size)) 312209ff23fSmrg return FALSE; 313209ff23fSmrg# define SET_DATA_TABLE(x) {\ 314209ff23fSmrg rhdAtomAnalyzeRomDataTable(base,data_table->x,(void *)(&(data->x)),&size); \ 315209ff23fSmrg } 316209ff23fSmrg 317209ff23fSmrg# define SET_DATA_TABLE_VERS(x) {\ 318209ff23fSmrg rhdAtomAnalyzeRomDataTable(base,data_table->x,&(data->x.base),&size); \ 319209ff23fSmrg } 320209ff23fSmrg 321209ff23fSmrg SET_DATA_TABLE(UtilityPipeLine); 322209ff23fSmrg SET_DATA_TABLE(MultimediaCapabilityInfo); 323209ff23fSmrg SET_DATA_TABLE(MultimediaConfigInfo); 324209ff23fSmrg SET_DATA_TABLE(StandardVESA_Timing); 325209ff23fSmrg SET_DATA_TABLE_VERS(FirmwareInfo); 326209ff23fSmrg SET_DATA_TABLE(DAC_Info); 327209ff23fSmrg SET_DATA_TABLE_VERS(LVDS_Info); 328209ff23fSmrg SET_DATA_TABLE(TMDS_Info); 329b7e1c893Smrg SET_DATA_TABLE_VERS(AnalogTV_Info); 330209ff23fSmrg SET_DATA_TABLE_VERS(SupportedDevicesInfo); 331209ff23fSmrg SET_DATA_TABLE(GPIO_I2C_Info); 332209ff23fSmrg SET_DATA_TABLE(VRAM_UsageByFirmware); 333209ff23fSmrg SET_DATA_TABLE(GPIO_Pin_LUT); 334209ff23fSmrg SET_DATA_TABLE(VESA_ToInternalModeLUT); 335209ff23fSmrg SET_DATA_TABLE_VERS(ComponentVideoInfo); 336209ff23fSmrg SET_DATA_TABLE(PowerPlayInfo); 337209ff23fSmrg SET_DATA_TABLE(CompassionateData); 338209ff23fSmrg SET_DATA_TABLE(SaveRestoreInfo); 339209ff23fSmrg SET_DATA_TABLE(PPLL_SS_Info); 340209ff23fSmrg SET_DATA_TABLE(OemInfo); 341209ff23fSmrg SET_DATA_TABLE(XTMDS_Info); 342209ff23fSmrg SET_DATA_TABLE(MclkSS_Info); 343209ff23fSmrg SET_DATA_TABLE(Object_Header); 344209ff23fSmrg SET_DATA_TABLE(IndirectIOAccess); 345209ff23fSmrg SET_DATA_TABLE(MC_InitParameter); 346209ff23fSmrg SET_DATA_TABLE(ASIC_VDDC_Info); 347209ff23fSmrg SET_DATA_TABLE(ASIC_InternalSS_Info); 348209ff23fSmrg SET_DATA_TABLE(TV_VideoMode); 349209ff23fSmrg SET_DATA_TABLE_VERS(VRAM_Info); 350209ff23fSmrg SET_DATA_TABLE(MemoryTrainingInfo); 351209ff23fSmrg SET_DATA_TABLE_VERS(IntegratedSystemInfo); 352209ff23fSmrg SET_DATA_TABLE(ASIC_ProfilingInfo); 353209ff23fSmrg SET_DATA_TABLE(VoltageObjectInfo); 354209ff23fSmrg SET_DATA_TABLE(PowerSourceInfo); 355209ff23fSmrg# undef SET_DATA_TABLE 356209ff23fSmrg 357209ff23fSmrg return TRUE; 358209ff23fSmrg} 359209ff23fSmrg 360209ff23fSmrgstatic Bool 361209ff23fSmrgrhdAtomGetDataTable(int scrnIndex, 362209ff23fSmrg unsigned char *base, 363209ff23fSmrg atomDataTables *atomDataPtr, 364209ff23fSmrg unsigned int *cmd_offset, 365209ff23fSmrg unsigned int BIOSImageSize) 366209ff23fSmrg{ 367209ff23fSmrg unsigned int data_offset; 368209ff23fSmrg unsigned int atom_romhdr_off = le16_to_cpu(*(unsigned short*) 369209ff23fSmrg (base + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); 370209ff23fSmrg ATOM_ROM_HEADER *atom_rom_hdr = 371209ff23fSmrg (ATOM_ROM_HEADER *)(base + atom_romhdr_off); 372209ff23fSmrg 373209ff23fSmrg //RHDFUNCI(scrnIndex); 374209ff23fSmrg 375209ff23fSmrg if (atom_romhdr_off + sizeof(ATOM_ROM_HEADER) > BIOSImageSize) { 376209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR, 377209ff23fSmrg "%s: AtomROM header extends beyond BIOS image\n",__func__); 378209ff23fSmrg return FALSE; 379209ff23fSmrg } 380209ff23fSmrg 381209ff23fSmrg if (memcmp("ATOM",&atom_rom_hdr->uaFirmWareSignature,4)) { 382209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"%s: No AtomBios signature found\n", 383209ff23fSmrg __func__); 384209ff23fSmrg return FALSE; 385209ff23fSmrg } 386209ff23fSmrg xf86DrvMsg(scrnIndex, X_INFO, "ATOM BIOS Rom: \n"); 387209ff23fSmrg if (!rhdAtomAnalyzeRomHdr(base, atom_rom_hdr, &data_offset, cmd_offset)) { 388209ff23fSmrg xf86DrvMsg(scrnIndex, X_ERROR, "RomHeader invalid\n"); 389209ff23fSmrg return FALSE; 390209ff23fSmrg } 391209ff23fSmrg 392209ff23fSmrg if (data_offset + sizeof (ATOM_MASTER_DATA_TABLE) > BIOSImageSize) { 393209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom data table outside of BIOS\n", 394209ff23fSmrg __func__); 395209ff23fSmrg } 396209ff23fSmrg 397209ff23fSmrg if (*cmd_offset + sizeof (ATOM_MASTER_COMMAND_TABLE) > BIOSImageSize) { 398209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom command table outside of BIOS\n", 399209ff23fSmrg __func__); 400209ff23fSmrg } 401209ff23fSmrg 402209ff23fSmrg if (!rhdAtomAnalyzeMasterDataTable(base, (ATOM_MASTER_DATA_TABLE *) 403209ff23fSmrg (base + data_offset), 404209ff23fSmrg atomDataPtr)) { 405209ff23fSmrg xf86DrvMsg(scrnIndex, X_ERROR, "%s: ROM Master Table invalid\n", 406209ff23fSmrg __func__); 407209ff23fSmrg return FALSE; 408209ff23fSmrg } 409209ff23fSmrg return TRUE; 410209ff23fSmrg} 411209ff23fSmrg 412209ff23fSmrgstatic Bool 413209ff23fSmrgrhdAtomGetFbBaseAndSize(atomBiosHandlePtr handle, unsigned int *base, 414209ff23fSmrg unsigned int *size) 415209ff23fSmrg{ 416209ff23fSmrg AtomBiosArgRec data; 417209ff23fSmrg if (RHDAtomBiosFunc(handle->scrnIndex, handle, GET_FW_FB_SIZE, &data) 418209ff23fSmrg == ATOM_SUCCESS) { 419209ff23fSmrg if (data.val == 0) { 420209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, "%s: AtomBIOS specified VRAM " 421209ff23fSmrg "scratch space size invalid\n", __func__); 422209ff23fSmrg return FALSE; 423209ff23fSmrg } 424209ff23fSmrg if (size) 425209ff23fSmrg *size = (int)data.val; 426209ff23fSmrg } else 427209ff23fSmrg return FALSE; 428209ff23fSmrg if (RHDAtomBiosFunc(handle->scrnIndex, handle, GET_FW_FB_START, &data) 429209ff23fSmrg == ATOM_SUCCESS) { 430209ff23fSmrg if (data.val == 0) 431209ff23fSmrg return FALSE; 432209ff23fSmrg if (base) 433209ff23fSmrg *base = (int)data.val; 434209ff23fSmrg } 435209ff23fSmrg return TRUE; 436209ff23fSmrg} 437209ff23fSmrg 438209ff23fSmrg/* 439209ff23fSmrg * Uses videoRam form ScrnInfoRec. 440209ff23fSmrg */ 441209ff23fSmrgstatic AtomBiosResult 442209ff23fSmrgrhdAtomAllocateFbScratch(atomBiosHandlePtr handle, 443209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 444209ff23fSmrg{ 445209ff23fSmrg unsigned int fb_base = 0; 446209ff23fSmrg unsigned int fb_size = 0; 447209ff23fSmrg unsigned int start = data->fb.start; 448209ff23fSmrg unsigned int size = data->fb.size; 449209ff23fSmrg handle->scratchBase = NULL; 450209ff23fSmrg handle->fbBase = 0; 451209ff23fSmrg 452209ff23fSmrg if (rhdAtomGetFbBaseAndSize(handle, &fb_base, &fb_size)) { 453209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS requests %ikB" 454209ff23fSmrg " of VRAM scratch space\n",fb_size); 455209ff23fSmrg fb_size *= 1024; /* convert to bytes */ 456209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS VRAM scratch base: 0x%x\n", 457209ff23fSmrg fb_base); 458209ff23fSmrg } else { 459209ff23fSmrg fb_size = 20 * 1024; 460209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, " default to: %i\n",fb_size); 461209ff23fSmrg } 462209ff23fSmrg if (fb_base && fb_size && size) { 463209ff23fSmrg /* 4k align */ 464209ff23fSmrg fb_size = (fb_size & ~(uint32_t)0xfff) + ((fb_size & 0xfff) ? 1 : 0); 465209ff23fSmrg if ((fb_base + fb_size) > (start + size)) { 466209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, 467209ff23fSmrg "%s: FW FB scratch area %i (size: %i)" 468209ff23fSmrg " extends beyond available framebuffer size %i\n", 469209ff23fSmrg __func__, fb_base, fb_size, size); 470209ff23fSmrg } else if ((fb_base + fb_size) < (start + size)) { 471209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, 472209ff23fSmrg "%s: FW FB scratch area not located " 473209ff23fSmrg "at the end of VRAM. Scratch End: " 474209ff23fSmrg "0x%x VRAM End: 0x%x\n", __func__, 475209ff23fSmrg (unsigned int)(fb_base + fb_size), 476209ff23fSmrg size); 477209ff23fSmrg } else if (fb_base < start) { 478209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, 479209ff23fSmrg "%s: FW FB scratch area extends below " 480209ff23fSmrg "the base of the free VRAM: 0x%x Base: 0x%x\n", 481209ff23fSmrg __func__, (unsigned int)(fb_base), start); 482209ff23fSmrg } else { 483209ff23fSmrg size -= fb_size; 484209ff23fSmrg handle->fbBase = fb_base; 485209ff23fSmrg return ATOM_SUCCESS; 486209ff23fSmrg } 487209ff23fSmrg } 488209ff23fSmrg 489209ff23fSmrg if (!handle->fbBase) { 490209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, 491209ff23fSmrg "Cannot get VRAM scratch space. " 492209ff23fSmrg "Allocating in main memory instead\n"); 4932f39173dSmrg handle->scratchBase = calloc(fb_size,1); 494209ff23fSmrg return ATOM_SUCCESS; 495209ff23fSmrg } 496209ff23fSmrg return ATOM_FAILED; 497209ff23fSmrg} 498209ff23fSmrg 499209ff23fSmrg# ifdef ATOM_BIOS_PARSER 500209ff23fSmrgBool 501209ff23fSmrgrhdAtomASICInit(atomBiosHandlePtr handle) 502209ff23fSmrg{ 503209ff23fSmrg ASIC_INIT_PS_ALLOCATION asicInit; 504209ff23fSmrg AtomBiosArgRec data; 505209ff23fSmrg 506209ff23fSmrg RHDAtomBiosFunc(handle->scrnIndex, handle, 507209ff23fSmrg GET_DEFAULT_ENGINE_CLOCK, 508209ff23fSmrg &data); 509b7e1c893Smrg asicInit.sASICInitClocks.ulDefaultEngineClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 510209ff23fSmrg RHDAtomBiosFunc(handle->scrnIndex, handle, 511209ff23fSmrg GET_DEFAULT_MEMORY_CLOCK, 512209ff23fSmrg &data); 513b7e1c893Smrg asicInit.sASICInitClocks.ulDefaultMemoryClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 514209ff23fSmrg data.exec.dataSpace = NULL; 515209ff23fSmrg data.exec.index = 0x0; 516209ff23fSmrg data.exec.pspace = &asicInit; 517209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling ASIC Init\n"); 518209ff23fSmrg if (RHDAtomBiosFunc(handle->scrnIndex, handle, 519209ff23fSmrg ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 520209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Successful\n"); 521209ff23fSmrg return TRUE; 522209ff23fSmrg } 523209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Failed\n"); 524209ff23fSmrg return FALSE; 525209ff23fSmrg} 526209ff23fSmrg 527209ff23fSmrgint 528ad43ddacSmrgatombios_clk_gating_setup(ScrnInfoPtr pScrn, Bool enable) 529209ff23fSmrg{ 530209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 531209ff23fSmrg DYNAMIC_CLOCK_GATING_PS_ALLOCATION dynclk_data; 532209ff23fSmrg AtomBiosArgRec data; 533209ff23fSmrg unsigned char *space; 534209ff23fSmrg 535209ff23fSmrg dynclk_data.ucEnable = enable; 536209ff23fSmrg 537209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); 538209ff23fSmrg data.exec.dataSpace = (void *)&space; 539209ff23fSmrg data.exec.pspace = &dynclk_data; 540209ff23fSmrg 541209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 542209ff23fSmrg ErrorF("Dynamic clock gating %s success\n", enable? "enable" : "disable"); 543209ff23fSmrg return ATOM_SUCCESS; 544209ff23fSmrg } 545209ff23fSmrg 546209ff23fSmrg ErrorF("Dynamic clock gating %s failure\n", enable? "enable" : "disable"); 547209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 548209ff23fSmrg 549209ff23fSmrg} 550209ff23fSmrg 551209ff23fSmrgint 552ad43ddacSmrgatombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, Bool enable) 553209ff23fSmrg{ 554209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 555209ff23fSmrg ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION pwrmgt_data; 556209ff23fSmrg AtomBiosArgRec data; 557209ff23fSmrg unsigned char *space; 558209ff23fSmrg 559ad43ddacSmrg /* disabling static power management causes hangs on some r4xx chips */ 560ad43ddacSmrg if (((info->ChipFamily == CHIP_FAMILY_R420) || 561ad43ddacSmrg (info->ChipFamily == CHIP_FAMILY_RV410)) && 562ad43ddacSmrg !enable) 563ad43ddacSmrg return ATOM_NOT_IMPLEMENTED; 564ad43ddacSmrg 565209ff23fSmrg pwrmgt_data.ucEnable = enable; 566209ff23fSmrg 567209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt); 568209ff23fSmrg data.exec.dataSpace = (void *)&space; 569209ff23fSmrg data.exec.pspace = &pwrmgt_data; 570209ff23fSmrg 571209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 572209ff23fSmrg ErrorF("Static power management %s success\n", enable? "enable" : "disable"); 573209ff23fSmrg return ATOM_SUCCESS; 574209ff23fSmrg } 575209ff23fSmrg 576209ff23fSmrg ErrorF("Static power management %s failure\n", enable? "enable" : "disable"); 577209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 578209ff23fSmrg 579209ff23fSmrg} 580209ff23fSmrg 581ad43ddacSmrgint 582ad43ddacSmrgatombios_set_engine_clock(ScrnInfoPtr pScrn, uint32_t engclock) 583ad43ddacSmrg{ 584ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 585ad43ddacSmrg SET_ENGINE_CLOCK_PS_ALLOCATION eng_clock_ps; 586ad43ddacSmrg AtomBiosArgRec data; 587ad43ddacSmrg unsigned char *space; 588ad43ddacSmrg 589ad43ddacSmrg RADEONWaitForIdleMMIO(pScrn); 590ad43ddacSmrg 591ad43ddacSmrg eng_clock_ps.ulTargetEngineClock = engclock; /* 10 khz */ 592ad43ddacSmrg 593ad43ddacSmrg /*ErrorF("Attempting to set engine clock to: %d\n", engclock);*/ 594ad43ddacSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, SetEngineClock); 595ad43ddacSmrg data.exec.dataSpace = (void *)&space; 596ad43ddacSmrg data.exec.pspace = &eng_clock_ps; 597ad43ddacSmrg 598ad43ddacSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 599ad43ddacSmrg /* ErrorF("Set engine clock success\n"); */ 600ad43ddacSmrg return ATOM_SUCCESS; 601ad43ddacSmrg } 602ad43ddacSmrg /* ErrorF("Set engine clock failed\n"); */ 603ad43ddacSmrg return ATOM_NOT_IMPLEMENTED; 604ad43ddacSmrg} 605ad43ddacSmrg 606ad43ddacSmrgint 607ad43ddacSmrgatombios_set_memory_clock(ScrnInfoPtr pScrn, uint32_t memclock) 608ad43ddacSmrg{ 609ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 610ad43ddacSmrg SET_MEMORY_CLOCK_PS_ALLOCATION mem_clock_ps; 611ad43ddacSmrg AtomBiosArgRec data; 612ad43ddacSmrg unsigned char *space; 613ad43ddacSmrg 614ad43ddacSmrg if (info->IsIGP) 615ad43ddacSmrg return ATOM_SUCCESS; 616ad43ddacSmrg 617ad43ddacSmrg RADEONWaitForIdleMMIO(pScrn); 618ad43ddacSmrg 619ad43ddacSmrg mem_clock_ps.ulTargetMemoryClock = memclock; /* 10 khz */ 620ad43ddacSmrg 621ad43ddacSmrg /* ErrorF("Attempting to set mem clock to: %d\n", memclock); */ 622ad43ddacSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock); 623ad43ddacSmrg data.exec.dataSpace = (void *)&space; 624ad43ddacSmrg data.exec.pspace = &mem_clock_ps; 625ad43ddacSmrg 626ad43ddacSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 627ad43ddacSmrg /* ErrorF("Set memory clock success\n"); */ 628ad43ddacSmrg return ATOM_SUCCESS; 629ad43ddacSmrg } 630ad43ddacSmrg /* ErrorF("Set memory clock failed\n"); */ 631ad43ddacSmrg return ATOM_NOT_IMPLEMENTED; 632ad43ddacSmrg} 633ad43ddacSmrg 634209ff23fSmrg# endif 635209ff23fSmrg 636209ff23fSmrgstatic AtomBiosResult 637209ff23fSmrgrhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2, 638209ff23fSmrg AtomBiosArgPtr data) 639209ff23fSmrg{ 640209ff23fSmrg int scrnIndex = data->val; 641209ff23fSmrg RADEONInfoPtr info = RADEONPTR(xf86Screens[scrnIndex]); 642209ff23fSmrg atomDataTablesPtr atomDataPtr; 643209ff23fSmrg unsigned int cmd_offset; 644209ff23fSmrg atomBiosHandlePtr handle = NULL; 645209ff23fSmrg unsigned int BIOSImageSize = 0; 646209ff23fSmrg data->atomhandle = NULL; 647209ff23fSmrg 648209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 649209ff23fSmrg BIOSImageSize = info->PciInfo->rom_size > RADEON_VBIOS_SIZE ? info->PciInfo->rom_size : RADEON_VBIOS_SIZE; 650209ff23fSmrg#else 651209ff23fSmrg BIOSImageSize = RADEON_VBIOS_SIZE; 652209ff23fSmrg#endif 653209ff23fSmrg 6542f39173dSmrg if (!(atomDataPtr = calloc(1, sizeof(atomDataTables)))) { 655209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory for " 656209ff23fSmrg "ATOM BIOS data tabes\n"); 657209ff23fSmrg goto error; 658209ff23fSmrg } 659209ff23fSmrg if (!rhdAtomGetDataTable(scrnIndex, info->VBIOS, atomDataPtr, &cmd_offset, BIOSImageSize)) 660209ff23fSmrg goto error1; 6612f39173dSmrg if (!(handle = calloc(1, sizeof(atomBiosHandleRec)))) { 662209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory\n"); 663209ff23fSmrg goto error1; 664209ff23fSmrg } 665209ff23fSmrg handle->BIOSBase = info->VBIOS; 666209ff23fSmrg handle->atomDataPtr = atomDataPtr; 667209ff23fSmrg handle->cmd_offset = cmd_offset; 668209ff23fSmrg handle->scrnIndex = scrnIndex; 669209ff23fSmrg#if XSERVER_LIBPCIACCESS 670209ff23fSmrg handle->device = info->PciInfo; 671209ff23fSmrg#else 672209ff23fSmrg handle->PciTag = info->PciTag; 673209ff23fSmrg#endif 674209ff23fSmrg handle->BIOSImageSize = BIOSImageSize; 675209ff23fSmrg 676209ff23fSmrg data->atomhandle = handle; 677209ff23fSmrg return ATOM_SUCCESS; 678209ff23fSmrg 679209ff23fSmrg error1: 6802f39173dSmrg free(atomDataPtr); 681209ff23fSmrg error: 682209ff23fSmrg return ATOM_FAILED; 683209ff23fSmrg} 684209ff23fSmrg 685209ff23fSmrgstatic AtomBiosResult 686209ff23fSmrgrhdAtomTearDown(atomBiosHandlePtr handle, 687209ff23fSmrg AtomBiosRequestID unused1, AtomBiosArgPtr unused2) 688209ff23fSmrg{ 689209ff23fSmrg //RHDFUNC(handle); 690209ff23fSmrg 6912f39173dSmrg free(handle->BIOSBase); 6922f39173dSmrg free(handle->atomDataPtr); 6932f39173dSmrg if (handle->scratchBase) free(handle->scratchBase); 6942f39173dSmrg free(handle); 695209ff23fSmrg return ATOM_SUCCESS; 696209ff23fSmrg} 697209ff23fSmrg 698209ff23fSmrgstatic AtomBiosResult 699209ff23fSmrgrhdAtomVramInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func, 700209ff23fSmrg AtomBiosArgPtr data) 701209ff23fSmrg{ 702209ff23fSmrg atomDataTablesPtr atomDataPtr; 703209ff23fSmrg uint32_t *val = &data->val; 704209ff23fSmrg //RHDFUNC(handle); 705209ff23fSmrg 706209ff23fSmrg atomDataPtr = handle->atomDataPtr; 707209ff23fSmrg 708209ff23fSmrg switch (func) { 709209ff23fSmrg case GET_FW_FB_START: 710b7e1c893Smrg if (atomDataPtr->VRAM_UsageByFirmware) 711b7e1c893Smrg *val = le32_to_cpu(atomDataPtr->VRAM_UsageByFirmware 712b7e1c893Smrg ->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware); 713b7e1c893Smrg else 714b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 715209ff23fSmrg break; 716209ff23fSmrg case GET_FW_FB_SIZE: 717b7e1c893Smrg if (atomDataPtr->VRAM_UsageByFirmware) 718b7e1c893Smrg *val = le16_to_cpu(atomDataPtr->VRAM_UsageByFirmware 719b7e1c893Smrg ->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); 720b7e1c893Smrg else 721b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 722209ff23fSmrg break; 723209ff23fSmrg default: 724209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 725209ff23fSmrg } 726209ff23fSmrg return ATOM_SUCCESS; 727209ff23fSmrg} 728209ff23fSmrg 729209ff23fSmrgstatic AtomBiosResult 730209ff23fSmrgrhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, 731209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 732209ff23fSmrg{ 733209ff23fSmrg atomDataTablesPtr atomDataPtr; 734209ff23fSmrg uint32_t *val = &data->val; 735209ff23fSmrg int idx = *val; 736209ff23fSmrg 737209ff23fSmrg atomDataPtr = handle->atomDataPtr; 738209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 739209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->TMDS_Info), 740209ff23fSmrg NULL,NULL,NULL)) { 741209ff23fSmrg return ATOM_FAILED; 742209ff23fSmrg } 743209ff23fSmrg 744209ff23fSmrg //RHDFUNC(handle); 745209ff23fSmrg 746209ff23fSmrg switch (func) { 747209ff23fSmrg case ATOM_TMDS_FREQUENCY: 748209ff23fSmrg *val = le16_to_cpu(atomDataPtr->TMDS_Info->asMiscInfo[idx].usFrequency); 749209ff23fSmrg break; 750209ff23fSmrg case ATOM_TMDS_PLL_CHARGE_PUMP: 751209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_ChargePump; 752209ff23fSmrg break; 753209ff23fSmrg case ATOM_TMDS_PLL_DUTY_CYCLE: 754209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_DutyCycle; 755209ff23fSmrg break; 756209ff23fSmrg case ATOM_TMDS_PLL_VCO_GAIN: 757209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_VCO_Gain; 758209ff23fSmrg break; 759209ff23fSmrg case ATOM_TMDS_PLL_VOLTAGE_SWING: 760209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_VoltageSwing; 761209ff23fSmrg break; 762209ff23fSmrg default: 763209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 764209ff23fSmrg } 765209ff23fSmrg return ATOM_SUCCESS; 766209ff23fSmrg} 767209ff23fSmrg 768209ff23fSmrgstatic DisplayModePtr 769209ff23fSmrgrhdAtomDTDTimings(atomBiosHandlePtr handle, ATOM_DTD_FORMAT *dtd) 770209ff23fSmrg{ 771209ff23fSmrg DisplayModePtr mode; 772209ff23fSmrg#define NAME_LEN 16 773209ff23fSmrg char name[NAME_LEN]; 774209ff23fSmrg 775209ff23fSmrg //RHDFUNC(handle); 776209ff23fSmrg 777209ff23fSmrg if (!dtd->usHActive || !dtd->usVActive) 778209ff23fSmrg return NULL; 779209ff23fSmrg 7802f39173dSmrg if (!(mode = (DisplayModePtr)calloc(1,sizeof(DisplayModeRec)))) 781209ff23fSmrg return NULL; 782209ff23fSmrg 783209ff23fSmrg mode->CrtcHDisplay = mode->HDisplay = le16_to_cpu(dtd->usHActive); 784209ff23fSmrg mode->CrtcVDisplay = mode->VDisplay = le16_to_cpu(dtd->usVActive); 785b13dfe66Smrg mode->CrtcHBlankStart = le16_to_cpu(dtd->usHActive) + dtd->ucHBorder; 786209ff23fSmrg mode->CrtcHBlankEnd = mode->CrtcHBlankStart + le16_to_cpu(dtd->usHBlanking_Time); 787209ff23fSmrg mode->CrtcHTotal = mode->HTotal = mode->CrtcHBlankEnd + dtd->ucHBorder; 788b13dfe66Smrg mode->CrtcVBlankStart = le16_to_cpu(dtd->usVActive) + dtd->ucVBorder; 789209ff23fSmrg mode->CrtcVBlankEnd = mode->CrtcVBlankStart + le16_to_cpu(dtd->usVBlanking_Time); 790209ff23fSmrg mode->CrtcVTotal = mode->VTotal = mode->CrtcVBlankEnd + dtd->ucVBorder; 791b13dfe66Smrg mode->CrtcHSyncStart = mode->HSyncStart = le16_to_cpu(dtd->usHActive) + le16_to_cpu(dtd->usHSyncOffset); 792209ff23fSmrg mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + le16_to_cpu(dtd->usHSyncWidth); 793b13dfe66Smrg mode->CrtcVSyncStart = mode->VSyncStart = le16_to_cpu(dtd->usVActive) + le16_to_cpu(dtd->usVSyncOffset); 794209ff23fSmrg mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + le16_to_cpu(dtd->usVSyncWidth); 795209ff23fSmrg 796209ff23fSmrg mode->SynthClock = mode->Clock = le16_to_cpu(dtd->usPixClk) * 10; 797209ff23fSmrg 798209ff23fSmrg mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal); 799209ff23fSmrg mode->VRefresh = (1000.0 * ((float) mode->Clock)) 800209ff23fSmrg / ((float)(((float)mode->HTotal) * ((float)mode->VTotal))); 801209ff23fSmrg 802209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.CompositeSync) 803209ff23fSmrg mode->Flags |= V_CSYNC; 804209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.Interlace) 805209ff23fSmrg mode->Flags |= V_INTERLACE; 806209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.DoubleClock) 807209ff23fSmrg mode->Flags |= V_DBLSCAN; 808209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.VSyncPolarity) 809209ff23fSmrg mode->Flags |= V_NVSYNC; 810209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.HSyncPolarity) 811209ff23fSmrg mode->Flags |= V_NHSYNC; 812209ff23fSmrg 813209ff23fSmrg snprintf(name, NAME_LEN, "%dx%d", 814209ff23fSmrg mode->HDisplay, mode->VDisplay); 815209ff23fSmrg mode->name = xstrdup(name); 816209ff23fSmrg 817209ff23fSmrg ErrorF("DTD Modeline: %s " 818209ff23fSmrg "%2.d %i (%i) %i %i (%i) %i %i (%i) %i %i (%i) %i flags: 0x%x\n", 819209ff23fSmrg mode->name, mode->Clock, 820209ff23fSmrg mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd, 821209ff23fSmrg mode->CrtcHBlankEnd, mode->HTotal, 822209ff23fSmrg mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd, 823209ff23fSmrg mode->CrtcVBlankEnd, mode->VTotal, mode->Flags); 824209ff23fSmrg 825209ff23fSmrg return mode; 826209ff23fSmrg} 827209ff23fSmrg 828209ff23fSmrgstatic unsigned char* 829209ff23fSmrgrhdAtomLvdsDDC(atomBiosHandlePtr handle, uint32_t offset, unsigned char *record) 830209ff23fSmrg{ 831209ff23fSmrg unsigned char *EDIDBlock; 832209ff23fSmrg 833209ff23fSmrg //RHDFUNC(handle); 834209ff23fSmrg 835209ff23fSmrg while (*record != ATOM_RECORD_END_TYPE) { 836209ff23fSmrg 837209ff23fSmrg switch (*record) { 838209ff23fSmrg case LCD_MODE_PATCH_RECORD_MODE_TYPE: 839209ff23fSmrg offset += sizeof(ATOM_PATCH_RECORD_MODE); 840209ff23fSmrg if (offset > handle->BIOSImageSize) break; 841209ff23fSmrg record += sizeof(ATOM_PATCH_RECORD_MODE); 842209ff23fSmrg break; 843209ff23fSmrg 844209ff23fSmrg case LCD_RTS_RECORD_TYPE: 845209ff23fSmrg offset += sizeof(ATOM_LCD_RTS_RECORD); 846209ff23fSmrg if (offset > handle->BIOSImageSize) break; 847209ff23fSmrg record += sizeof(ATOM_LCD_RTS_RECORD); 848209ff23fSmrg break; 849209ff23fSmrg 850209ff23fSmrg case LCD_CAP_RECORD_TYPE: 851209ff23fSmrg offset += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 852209ff23fSmrg if (offset > handle->BIOSImageSize) break; 853209ff23fSmrg record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 854209ff23fSmrg break; 855209ff23fSmrg 856209ff23fSmrg case LCD_FAKE_EDID_PATCH_RECORD_TYPE: 857209ff23fSmrg offset += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); 858209ff23fSmrg /* check if the structure still fully lives in the BIOS image */ 859209ff23fSmrg if (offset > handle->BIOSImageSize) break; 860209ff23fSmrg offset += ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength 861209ff23fSmrg - sizeof(UCHAR); 862209ff23fSmrg if (offset > handle->BIOSImageSize) break; 863209ff23fSmrg /* dup string as we free it later */ 8642f39173dSmrg if (!(EDIDBlock = (unsigned char *)malloc( 865209ff23fSmrg ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength))) 866209ff23fSmrg return NULL; 867209ff23fSmrg memcpy(EDIDBlock,&((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDString, 868209ff23fSmrg ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength); 869209ff23fSmrg 870209ff23fSmrg /* for testing */ 871209ff23fSmrg { 872209ff23fSmrg xf86MonPtr mon = xf86InterpretEDID(handle->scrnIndex,EDIDBlock); 873209ff23fSmrg xf86PrintEDID(mon); 8742f39173dSmrg free(mon); 875209ff23fSmrg } 876209ff23fSmrg return EDIDBlock; 877209ff23fSmrg 878209ff23fSmrg case LCD_PANEL_RESOLUTION_RECORD_TYPE: 879209ff23fSmrg offset += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 880209ff23fSmrg if (offset > handle->BIOSImageSize) break; 881209ff23fSmrg record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 882209ff23fSmrg break; 883209ff23fSmrg 884209ff23fSmrg default: 885209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, 886209ff23fSmrg "%s: unknown record type: %x\n",__func__,*record); 887209ff23fSmrg return NULL; 888209ff23fSmrg } 889209ff23fSmrg } 890209ff23fSmrg 891209ff23fSmrg return NULL; 892209ff23fSmrg} 893209ff23fSmrg 894209ff23fSmrgstatic AtomBiosResult 895209ff23fSmrgrhdAtomCVGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, 896209ff23fSmrg AtomBiosArgPtr data) 897209ff23fSmrg{ 898209ff23fSmrg atomDataTablesPtr atomDataPtr; 899209ff23fSmrg uint8_t crev, frev; 900209ff23fSmrg DisplayModePtr last = NULL; 901209ff23fSmrg DisplayModePtr new = NULL; 902209ff23fSmrg DisplayModePtr first = NULL; 903209ff23fSmrg int i; 904ad43ddacSmrg uint16_t size; 905209ff23fSmrg 906209ff23fSmrg data->modes = NULL; 907209ff23fSmrg 908209ff23fSmrg atomDataPtr = handle->atomDataPtr; 909209ff23fSmrg 910209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 911209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->ComponentVideoInfo.base), 912ad43ddacSmrg &crev,&frev,&size)) { 913209ff23fSmrg return ATOM_FAILED; 914209ff23fSmrg } 915209ff23fSmrg 916209ff23fSmrg switch (frev) { 917209ff23fSmrg case 1: 918209ff23fSmrg switch (func) { 919209ff23fSmrg case ATOMBIOS_GET_CV_MODES: 920209ff23fSmrg for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { 921209ff23fSmrg new = rhdAtomDTDTimings(handle, 922209ff23fSmrg &atomDataPtr->ComponentVideoInfo 923209ff23fSmrg .ComponentVideoInfo->aModeTimings[i]); 924209ff23fSmrg 925209ff23fSmrg if (!new) 926209ff23fSmrg continue; 927209ff23fSmrg 928209ff23fSmrg new->type |= M_T_DRIVER; 929209ff23fSmrg new->next = NULL; 930209ff23fSmrg new->prev = last; 931209ff23fSmrg 932209ff23fSmrg if (last) last->next = new; 933209ff23fSmrg last = new; 934209ff23fSmrg if (!first) first = new; 935209ff23fSmrg } 936209ff23fSmrg if (last) { 937209ff23fSmrg last->next = NULL; //first; 938209ff23fSmrg first->prev = NULL; //last; 939209ff23fSmrg data->modes = first; 940209ff23fSmrg } 941209ff23fSmrg if (data->modes) 942209ff23fSmrg return ATOM_SUCCESS; 943209ff23fSmrg default: 944209ff23fSmrg return ATOM_FAILED; 945209ff23fSmrg } 946209ff23fSmrg case 2: 947209ff23fSmrg switch (func) { 948209ff23fSmrg case ATOMBIOS_GET_CV_MODES: 949209ff23fSmrg for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { 950ad43ddacSmrg /* my rv730 table has only room for one mode */ 951ad43ddacSmrg if ((void *)&atomDataPtr->ComponentVideoInfo.ComponentVideoInfo_v21->aModeTimings[i] - 952ad43ddacSmrg atomDataPtr->ComponentVideoInfo.base > size) 953ad43ddacSmrg break; 954ad43ddacSmrg 955209ff23fSmrg new = rhdAtomDTDTimings(handle, 956209ff23fSmrg &atomDataPtr->ComponentVideoInfo 957209ff23fSmrg .ComponentVideoInfo_v21->aModeTimings[i]); 958209ff23fSmrg 959209ff23fSmrg if (!new) 960209ff23fSmrg continue; 961209ff23fSmrg 962209ff23fSmrg new->type |= M_T_DRIVER; 963209ff23fSmrg new->next = NULL; 964209ff23fSmrg new->prev = last; 965209ff23fSmrg 966209ff23fSmrg if (last) last->next = new; 967209ff23fSmrg last = new; 968209ff23fSmrg if (!first) first = new; 969209ff23fSmrg 970209ff23fSmrg } 971209ff23fSmrg if (last) { 972209ff23fSmrg last->next = NULL; //first; 973209ff23fSmrg first->prev = NULL; //last; 974209ff23fSmrg data->modes = first; 975209ff23fSmrg } 976209ff23fSmrg if (data->modes) 977209ff23fSmrg return ATOM_SUCCESS; 978209ff23fSmrg return ATOM_FAILED; 979209ff23fSmrg 980209ff23fSmrg default: 981209ff23fSmrg return ATOM_FAILED; 982209ff23fSmrg } 983209ff23fSmrg default: 984209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 985209ff23fSmrg } 986209ff23fSmrg/*NOTREACHED*/ 987209ff23fSmrg} 988209ff23fSmrg 989209ff23fSmrgstatic AtomBiosResult 990209ff23fSmrgrhdAtomLvdsGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, 991209ff23fSmrg AtomBiosArgPtr data) 992209ff23fSmrg{ 993209ff23fSmrg atomDataTablesPtr atomDataPtr; 994209ff23fSmrg uint8_t crev, frev; 995209ff23fSmrg unsigned long offset; 996209ff23fSmrg 997209ff23fSmrg //RHDFUNC(handle); 998209ff23fSmrg 999209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1000209ff23fSmrg 1001209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1002209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 1003209ff23fSmrg &frev,&crev,NULL)) { 1004209ff23fSmrg return ATOM_FAILED; 1005209ff23fSmrg } 1006209ff23fSmrg 1007209ff23fSmrg switch (crev) { 1008209ff23fSmrg 1009209ff23fSmrg case 1: 1010209ff23fSmrg switch (func) { 1011209ff23fSmrg case ATOMBIOS_GET_PANEL_MODE: 1012209ff23fSmrg data->modes = rhdAtomDTDTimings(handle, 1013209ff23fSmrg &atomDataPtr->LVDS_Info 1014209ff23fSmrg .LVDS_Info->sLCDTiming); 1015209ff23fSmrg if (data->modes) 1016209ff23fSmrg return ATOM_SUCCESS; 1017209ff23fSmrg default: 1018209ff23fSmrg return ATOM_FAILED; 1019209ff23fSmrg } 1020209ff23fSmrg case 2: 1021209ff23fSmrg switch (func) { 1022209ff23fSmrg case ATOMBIOS_GET_PANEL_MODE: 1023209ff23fSmrg data->modes = rhdAtomDTDTimings(handle, 1024209ff23fSmrg &atomDataPtr->LVDS_Info 1025209ff23fSmrg .LVDS_Info_v12->sLCDTiming); 1026209ff23fSmrg if (data->modes) 1027209ff23fSmrg return ATOM_SUCCESS; 1028209ff23fSmrg return ATOM_FAILED; 1029209ff23fSmrg 1030209ff23fSmrg case ATOMBIOS_GET_PANEL_EDID: 1031209ff23fSmrg offset = (unsigned long)&atomDataPtr->LVDS_Info.base 1032209ff23fSmrg - (unsigned long)handle->BIOSBase 1033209ff23fSmrg + le16_to_cpu(atomDataPtr->LVDS_Info 1034209ff23fSmrg .LVDS_Info_v12->usExtInfoTableOffset); 1035209ff23fSmrg 1036209ff23fSmrg data->EDIDBlock 1037209ff23fSmrg = rhdAtomLvdsDDC(handle, offset, 1038209ff23fSmrg (unsigned char *) 1039209ff23fSmrg &atomDataPtr->LVDS_Info.base 1040209ff23fSmrg + le16_to_cpu(atomDataPtr->LVDS_Info 1041209ff23fSmrg .LVDS_Info_v12->usExtInfoTableOffset)); 1042209ff23fSmrg if (data->EDIDBlock) 1043209ff23fSmrg return ATOM_SUCCESS; 1044209ff23fSmrg default: 1045209ff23fSmrg return ATOM_FAILED; 1046209ff23fSmrg } 1047209ff23fSmrg default: 1048209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1049209ff23fSmrg } 1050209ff23fSmrg/*NOTREACHED*/ 1051209ff23fSmrg} 1052209ff23fSmrg 1053209ff23fSmrgstatic AtomBiosResult 1054209ff23fSmrgrhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, 1055209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1056209ff23fSmrg{ 1057209ff23fSmrg atomDataTablesPtr atomDataPtr; 1058209ff23fSmrg uint8_t crev, frev; 1059209ff23fSmrg uint32_t *val = &data->val; 1060209ff23fSmrg 1061209ff23fSmrg //RHDFUNC(handle); 1062209ff23fSmrg 1063209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1064209ff23fSmrg 1065209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1066209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 1067209ff23fSmrg &frev,&crev,NULL)) { 1068209ff23fSmrg return ATOM_FAILED; 1069209ff23fSmrg } 1070209ff23fSmrg 1071209ff23fSmrg switch (crev) { 1072209ff23fSmrg case 1: 1073209ff23fSmrg switch (func) { 1074209ff23fSmrg case ATOM_LVDS_SUPPORTED_REFRESH_RATE: 1075209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1076209ff23fSmrg .LVDS_Info->usSupportedRefreshRate); 1077209ff23fSmrg break; 1078209ff23fSmrg case ATOM_LVDS_OFF_DELAY: 1079209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1080209ff23fSmrg .LVDS_Info->usOffDelayInMs); 1081209ff23fSmrg break; 1082209ff23fSmrg case ATOM_LVDS_SEQ_DIG_ONTO_DE: 1083209ff23fSmrg *val = atomDataPtr->LVDS_Info 1084209ff23fSmrg .LVDS_Info->ucPowerSequenceDigOntoDEin10Ms * 10; 1085209ff23fSmrg break; 1086209ff23fSmrg case ATOM_LVDS_SEQ_DE_TO_BL: 1087209ff23fSmrg *val = atomDataPtr->LVDS_Info 1088209ff23fSmrg .LVDS_Info->ucPowerSequenceDEtoBLOnin10Ms * 10; 1089209ff23fSmrg break; 1090209ff23fSmrg case ATOM_LVDS_DITHER: 1091209ff23fSmrg *val = atomDataPtr->LVDS_Info 1092209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x40; 1093209ff23fSmrg break; 1094209ff23fSmrg case ATOM_LVDS_DUALLINK: 1095209ff23fSmrg *val = atomDataPtr->LVDS_Info 1096209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x01; 1097209ff23fSmrg break; 1098209ff23fSmrg case ATOM_LVDS_24BIT: 1099209ff23fSmrg *val = atomDataPtr->LVDS_Info 1100209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x02; 1101209ff23fSmrg break; 1102209ff23fSmrg case ATOM_LVDS_GREYLVL: 1103209ff23fSmrg *val = atomDataPtr->LVDS_Info 1104209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x0C; 1105209ff23fSmrg break; 1106209ff23fSmrg case ATOM_LVDS_FPDI: 1107209ff23fSmrg *val = atomDataPtr->LVDS_Info 1108209ff23fSmrg .LVDS_Info->ucLVDS_Misc * 0x10; 1109209ff23fSmrg break; 1110209ff23fSmrg default: 1111209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1112209ff23fSmrg } 1113209ff23fSmrg break; 1114209ff23fSmrg case 2: 1115209ff23fSmrg switch (func) { 1116209ff23fSmrg case ATOM_LVDS_SUPPORTED_REFRESH_RATE: 1117209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1118209ff23fSmrg .LVDS_Info_v12->usSupportedRefreshRate); 1119209ff23fSmrg break; 1120209ff23fSmrg case ATOM_LVDS_OFF_DELAY: 1121209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1122209ff23fSmrg .LVDS_Info_v12->usOffDelayInMs); 1123209ff23fSmrg break; 1124209ff23fSmrg case ATOM_LVDS_SEQ_DIG_ONTO_DE: 1125209ff23fSmrg *val = atomDataPtr->LVDS_Info 1126209ff23fSmrg .LVDS_Info_v12->ucPowerSequenceDigOntoDEin10Ms * 10; 1127209ff23fSmrg break; 1128209ff23fSmrg case ATOM_LVDS_SEQ_DE_TO_BL: 1129209ff23fSmrg *val = atomDataPtr->LVDS_Info 1130209ff23fSmrg .LVDS_Info_v12->ucPowerSequenceDEtoBLOnin10Ms * 10; 1131209ff23fSmrg break; 1132209ff23fSmrg case ATOM_LVDS_DITHER: 1133209ff23fSmrg *val = atomDataPtr->LVDS_Info 1134209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x40; 1135209ff23fSmrg break; 1136209ff23fSmrg case ATOM_LVDS_DUALLINK: 1137209ff23fSmrg *val = atomDataPtr->LVDS_Info 1138209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x01; 1139209ff23fSmrg break; 1140209ff23fSmrg case ATOM_LVDS_24BIT: 1141209ff23fSmrg *val = atomDataPtr->LVDS_Info 1142209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x02; 1143209ff23fSmrg break; 1144209ff23fSmrg case ATOM_LVDS_GREYLVL: 1145209ff23fSmrg *val = atomDataPtr->LVDS_Info 1146209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x0C; 1147209ff23fSmrg break; 1148209ff23fSmrg case ATOM_LVDS_FPDI: 1149209ff23fSmrg *val = atomDataPtr->LVDS_Info 1150209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc * 0x10; 1151209ff23fSmrg break; 1152209ff23fSmrg default: 1153209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1154209ff23fSmrg } 1155209ff23fSmrg break; 1156209ff23fSmrg default: 1157209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1158209ff23fSmrg } 1159209ff23fSmrg 1160209ff23fSmrg return ATOM_SUCCESS; 1161209ff23fSmrg} 1162209ff23fSmrg 1163209ff23fSmrgstatic AtomBiosResult 1164209ff23fSmrgrhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, 1165209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1166209ff23fSmrg{ 1167209ff23fSmrg atomDataTablesPtr atomDataPtr; 1168209ff23fSmrg uint8_t crev, frev; 1169209ff23fSmrg uint32_t *val = &data->val; 1170209ff23fSmrg 1171209ff23fSmrg //RHDFUNC(handle); 1172209ff23fSmrg 1173209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1174209ff23fSmrg 1175209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1176209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->CompassionateData), 1177209ff23fSmrg &frev,&crev,NULL)) { 1178209ff23fSmrg return ATOM_FAILED; 1179209ff23fSmrg } 1180209ff23fSmrg 1181209ff23fSmrg switch (func) { 1182209ff23fSmrg case ATOM_DAC1_BG_ADJ: 1183209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1184209ff23fSmrg ucDAC1_BG_Adjustment; 1185209ff23fSmrg break; 1186209ff23fSmrg case ATOM_DAC1_DAC_ADJ: 1187209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1188209ff23fSmrg ucDAC1_DAC_Adjustment; 1189209ff23fSmrg break; 1190209ff23fSmrg case ATOM_DAC1_FORCE: 1191209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1192209ff23fSmrg usDAC1_FORCE_Data; 1193209ff23fSmrg break; 1194209ff23fSmrg case ATOM_DAC2_CRTC2_BG_ADJ: 1195209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1196209ff23fSmrg ucDAC2_CRT2_BG_Adjustment; 1197209ff23fSmrg break; 1198209ff23fSmrg case ATOM_DAC2_CRTC2_DAC_ADJ: 1199209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1200209ff23fSmrg ucDAC2_CRT2_DAC_Adjustment; 1201209ff23fSmrg break; 1202209ff23fSmrg case ATOM_DAC2_CRTC2_FORCE: 1203209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1204209ff23fSmrg usDAC2_CRT2_FORCE_Data; 1205209ff23fSmrg break; 1206209ff23fSmrg case ATOM_DAC2_CRTC2_MUX_REG_IND: 1207209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1208209ff23fSmrg usDAC2_CRT2_MUX_RegisterIndex; 1209209ff23fSmrg break; 1210209ff23fSmrg case ATOM_DAC2_CRTC2_MUX_REG_INFO: 1211209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1212209ff23fSmrg ucDAC2_CRT2_MUX_RegisterInfo; 1213209ff23fSmrg break; 1214209ff23fSmrg default: 1215209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1216209ff23fSmrg } 1217209ff23fSmrg return ATOM_SUCCESS; 1218209ff23fSmrg} 1219209ff23fSmrg 1220209ff23fSmrgstatic AtomBiosResult 1221209ff23fSmrgrhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, 1222209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1223209ff23fSmrg{ 1224209ff23fSmrg atomDataTablesPtr atomDataPtr; 1225209ff23fSmrg uint8_t crev, frev; 1226209ff23fSmrg uint32_t *val = &data->val; 1227209ff23fSmrg unsigned short size; 1228209ff23fSmrg 1229209ff23fSmrg //RHDFUNC(handle); 1230209ff23fSmrg 1231209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1232209ff23fSmrg 1233209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1234209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->GPIO_I2C_Info), 1235209ff23fSmrg &frev,&crev,&size)) { 1236209ff23fSmrg return ATOM_FAILED; 1237209ff23fSmrg } 1238209ff23fSmrg 1239209ff23fSmrg switch (func) { 1240209ff23fSmrg case ATOM_GPIO_I2C_CLK_MASK: 1241209ff23fSmrg if ((sizeof(ATOM_COMMON_TABLE_HEADER) 1242209ff23fSmrg + (*val * sizeof(ATOM_GPIO_I2C_ASSIGMENT))) > size) { 1243209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: GPIO_I2C Device " 1244209ff23fSmrg "num %lu exeeds table size %u\n",__func__, 1245209ff23fSmrg (unsigned long)val, 1246209ff23fSmrg size); 1247209ff23fSmrg return ATOM_FAILED; 1248209ff23fSmrg } 1249209ff23fSmrg 1250209ff23fSmrg *val = le16_to_cpu(atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] 1251209ff23fSmrg .usClkMaskRegisterIndex); 1252209ff23fSmrg break; 1253209ff23fSmrg 1254209ff23fSmrg default: 1255209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1256209ff23fSmrg } 1257209ff23fSmrg return ATOM_SUCCESS; 1258209ff23fSmrg} 1259209ff23fSmrg 1260209ff23fSmrgstatic AtomBiosResult 1261209ff23fSmrgrhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, 1262209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1263209ff23fSmrg{ 1264209ff23fSmrg atomDataTablesPtr atomDataPtr; 1265209ff23fSmrg uint8_t crev, frev; 1266209ff23fSmrg uint32_t *val = &data->val; 1267209ff23fSmrg 1268209ff23fSmrg //RHDFUNC(handle); 1269209ff23fSmrg 1270209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1271209ff23fSmrg 1272209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1273209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), 1274209ff23fSmrg &crev,&frev,NULL)) { 1275209ff23fSmrg return ATOM_FAILED; 1276209ff23fSmrg } 1277209ff23fSmrg 1278209ff23fSmrg switch (crev) { 1279209ff23fSmrg case 1: 1280209ff23fSmrg switch (func) { 1281209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1282209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1283209ff23fSmrg .FirmwareInfo->ulDefaultEngineClock) * 10; 1284209ff23fSmrg break; 1285209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1286209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1287209ff23fSmrg .FirmwareInfo->ulDefaultMemoryClock) * 10; 1288209ff23fSmrg break; 1289209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1290209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1291209ff23fSmrg .FirmwareInfo->ulMaxPixelClockPLL_Output) * 10; 1292209ff23fSmrg break; 1293209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1294209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1295209ff23fSmrg .FirmwareInfo->usMinPixelClockPLL_Output) * 10; 1296209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1297209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1298209ff23fSmrg .FirmwareInfo->usMaxPixelClockPLL_Input) * 10; 1299209ff23fSmrg break; 1300209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1301209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1302209ff23fSmrg .FirmwareInfo->usMinPixelClockPLL_Input) * 10; 1303209ff23fSmrg break; 1304209ff23fSmrg case GET_MAX_PIXEL_CLK: 1305209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1306209ff23fSmrg .FirmwareInfo->usMaxPixelClock) * 10; 1307209ff23fSmrg break; 1308209ff23fSmrg case GET_REF_CLOCK: 1309209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1310209ff23fSmrg .FirmwareInfo->usReferenceClock) * 10; 1311209ff23fSmrg break; 1312209ff23fSmrg default: 1313209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1314209ff23fSmrg } 1315209ff23fSmrg case 2: 1316209ff23fSmrg switch (func) { 1317209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1318209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1319209ff23fSmrg .FirmwareInfo_V_1_2->ulDefaultEngineClock) * 10; 1320209ff23fSmrg break; 1321209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1322209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1323209ff23fSmrg .FirmwareInfo_V_1_2->ulDefaultMemoryClock) * 10; 1324209ff23fSmrg break; 1325209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1326209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1327209ff23fSmrg .FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output) * 10; 1328209ff23fSmrg break; 1329209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1330209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1331209ff23fSmrg .FirmwareInfo_V_1_2->usMinPixelClockPLL_Output) * 10; 1332209ff23fSmrg break; 1333209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1334209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1335209ff23fSmrg .FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input) * 10; 1336209ff23fSmrg break; 1337209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1338209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1339209ff23fSmrg .FirmwareInfo_V_1_2->usMinPixelClockPLL_Input) * 10; 1340209ff23fSmrg break; 1341209ff23fSmrg case GET_MAX_PIXEL_CLK: 1342209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1343209ff23fSmrg .FirmwareInfo_V_1_2->usMaxPixelClock) * 10; 1344209ff23fSmrg break; 1345209ff23fSmrg case GET_REF_CLOCK: 1346209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1347209ff23fSmrg .FirmwareInfo_V_1_2->usReferenceClock) * 10; 1348209ff23fSmrg break; 1349209ff23fSmrg default: 1350209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1351209ff23fSmrg } 1352209ff23fSmrg break; 1353209ff23fSmrg case 3: 1354209ff23fSmrg switch (func) { 1355209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1356209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1357209ff23fSmrg .FirmwareInfo_V_1_3->ulDefaultEngineClock) * 10; 1358209ff23fSmrg break; 1359209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1360209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1361209ff23fSmrg .FirmwareInfo_V_1_3->ulDefaultMemoryClock) * 10; 1362209ff23fSmrg break; 1363209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1364209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1365209ff23fSmrg .FirmwareInfo_V_1_3->ulMaxPixelClockPLL_Output) * 10; 1366209ff23fSmrg break; 1367209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1368209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1369209ff23fSmrg .FirmwareInfo_V_1_3->usMinPixelClockPLL_Output) * 10; 1370209ff23fSmrg break; 1371209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1372209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1373209ff23fSmrg .FirmwareInfo_V_1_3->usMaxPixelClockPLL_Input) * 10; 1374209ff23fSmrg break; 1375209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1376209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1377209ff23fSmrg .FirmwareInfo_V_1_3->usMinPixelClockPLL_Input) * 10; 1378209ff23fSmrg break; 1379209ff23fSmrg case GET_MAX_PIXEL_CLK: 1380209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1381209ff23fSmrg .FirmwareInfo_V_1_3->usMaxPixelClock) * 10; 1382209ff23fSmrg break; 1383209ff23fSmrg case GET_REF_CLOCK: 1384209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1385209ff23fSmrg .FirmwareInfo_V_1_3->usReferenceClock) * 10; 1386209ff23fSmrg break; 1387209ff23fSmrg default: 1388209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1389209ff23fSmrg } 1390209ff23fSmrg break; 1391209ff23fSmrg case 4: 1392209ff23fSmrg switch (func) { 1393209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1394209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1395209ff23fSmrg .FirmwareInfo_V_1_4->ulDefaultEngineClock) * 10; 1396209ff23fSmrg break; 1397209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1398209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1399209ff23fSmrg .FirmwareInfo_V_1_4->ulDefaultMemoryClock) * 10; 1400209ff23fSmrg break; 1401209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1402209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1403209ff23fSmrg .FirmwareInfo_V_1_4->usMaxPixelClockPLL_Input) * 10; 1404209ff23fSmrg break; 1405209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1406209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1407209ff23fSmrg .FirmwareInfo_V_1_4->usMinPixelClockPLL_Input) * 10; 1408209ff23fSmrg break; 1409209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1410209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1411209ff23fSmrg .FirmwareInfo_V_1_4->ulMaxPixelClockPLL_Output) * 10; 1412209ff23fSmrg break; 1413209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1414209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1415209ff23fSmrg .FirmwareInfo_V_1_4->usMinPixelClockPLL_Output) * 10; 1416209ff23fSmrg break; 1417209ff23fSmrg case GET_MAX_PIXEL_CLK: 1418209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1419209ff23fSmrg .FirmwareInfo_V_1_4->usMaxPixelClock) * 10; 1420209ff23fSmrg break; 1421209ff23fSmrg case GET_REF_CLOCK: 1422209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1423209ff23fSmrg .FirmwareInfo_V_1_4->usReferenceClock) * 10; 1424209ff23fSmrg break; 1425209ff23fSmrg default: 1426209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1427209ff23fSmrg } 1428209ff23fSmrg break; 1429209ff23fSmrg default: 1430209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1431209ff23fSmrg } 1432209ff23fSmrg return ATOM_SUCCESS; 1433209ff23fSmrg} 1434209ff23fSmrg 1435209ff23fSmrgconst int object_connector_convert[] = 1436209ff23fSmrg { CONNECTOR_NONE, 1437209ff23fSmrg CONNECTOR_DVI_I, 1438209ff23fSmrg CONNECTOR_DVI_I, 1439209ff23fSmrg CONNECTOR_DVI_D, 1440209ff23fSmrg CONNECTOR_DVI_D, 1441209ff23fSmrg CONNECTOR_VGA, 1442209ff23fSmrg CONNECTOR_CTV, 1443209ff23fSmrg CONNECTOR_STV, 1444209ff23fSmrg CONNECTOR_NONE, 1445c503f109Smrg CONNECTOR_NONE, 1446209ff23fSmrg CONNECTOR_DIN, 1447209ff23fSmrg CONNECTOR_SCART, 1448209ff23fSmrg CONNECTOR_HDMI_TYPE_A, 1449209ff23fSmrg CONNECTOR_HDMI_TYPE_B, 1450209ff23fSmrg CONNECTOR_LVDS, 1451209ff23fSmrg CONNECTOR_DIN, 1452209ff23fSmrg CONNECTOR_NONE, 1453209ff23fSmrg CONNECTOR_NONE, 1454209ff23fSmrg CONNECTOR_NONE, 1455209ff23fSmrg CONNECTOR_DISPLAY_PORT, 1456ad43ddacSmrg CONNECTOR_EDP, 1457ad43ddacSmrg CONNECTOR_NONE, 1458209ff23fSmrg }; 1459209ff23fSmrg 1460b7e1c893Smrgxf86MonPtr radeon_atom_get_edid(xf86OutputPtr output) 1461209ff23fSmrg{ 1462b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1463b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1464b7e1c893Smrg READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION edid_data; 1465b7e1c893Smrg AtomBiosArgRec data; 1466b7e1c893Smrg unsigned char *space; 1467b7e1c893Smrg int i2c_clock = 50; 1468b7e1c893Smrg int engine_clk = (int)info->sclk * 100; 1469b7e1c893Smrg int prescale; 1470b7e1c893Smrg unsigned char *edid; 1471b7e1c893Smrg xf86MonPtr mon = NULL; 1472b7e1c893Smrg 1473b7e1c893Smrg if (!radeon_output->ddc_i2c.hw_capable) 1474b7e1c893Smrg return mon; 1475b7e1c893Smrg 1476b7e1c893Smrg if (info->atomBIOS->fbBase) 1477b7e1c893Smrg edid = (unsigned char *)info->FB + info->atomBIOS->fbBase; 1478b7e1c893Smrg else if (info->atomBIOS->scratchBase) 1479b7e1c893Smrg edid = (unsigned char *)info->atomBIOS->scratchBase; 1480b7e1c893Smrg else 1481b7e1c893Smrg return mon; 1482b7e1c893Smrg 1483b7e1c893Smrg memset(edid, 0, ATOM_EDID_RAW_DATASIZE); 1484b7e1c893Smrg 1485b7e1c893Smrg if (info->ChipFamily == CHIP_FAMILY_R520) 1486b7e1c893Smrg prescale = (127 << 8) + (engine_clk * 10) / (4 * 127 * i2c_clock); 1487b7e1c893Smrg else if (info->ChipFamily < CHIP_FAMILY_R600) 1488b7e1c893Smrg prescale = (((engine_clk * 10)/(4 * 128 * 100) + 1) << 8) + 128; 1489b7e1c893Smrg else 1490b7e1c893Smrg prescale = (info->pll.reference_freq * 10) / i2c_clock; 1491b7e1c893Smrg 1492b7e1c893Smrg edid_data.usPrescale = prescale; 1493b7e1c893Smrg edid_data.usVRAMAddress = 0; 1494b7e1c893Smrg edid_data.ucSlaveAddr = 0xa0; 1495b7e1c893Smrg edid_data.ucLineNumber = radeon_output->ddc_i2c.hw_line; 1496b7e1c893Smrg 1497b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, ReadEDIDFromHWAssistedI2C); 1498b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1499b7e1c893Smrg data.exec.pspace = &edid_data; 1500b7e1c893Smrg 1501b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) 1502b7e1c893Smrg ErrorF("Atom Get EDID success\n"); 1503b7e1c893Smrg else 1504b7e1c893Smrg ErrorF("Atom Get EDID failed\n"); 1505b7e1c893Smrg 1506b7e1c893Smrg if (edid[1] == 0xff) 1507b7e1c893Smrg mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); 1508b7e1c893Smrg 1509b7e1c893Smrg return mon; 1510b7e1c893Smrg 1511209ff23fSmrg} 1512209ff23fSmrg 1513209ff23fSmrgstatic RADEONI2CBusRec 1514209ff23fSmrgRADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id) 1515209ff23fSmrg{ 1516209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1517209ff23fSmrg atomDataTablesPtr atomDataPtr; 1518ad43ddacSmrg ATOM_GPIO_I2C_ASSIGMENT *gpio; 1519209ff23fSmrg RADEONI2CBusRec i2c; 1520209ff23fSmrg uint8_t crev, frev; 1521ad43ddacSmrg unsigned short size; 1522ad43ddacSmrg int i, num_indices; 1523209ff23fSmrg 1524209ff23fSmrg memset(&i2c, 0, sizeof(RADEONI2CBusRec)); 1525209ff23fSmrg i2c.valid = FALSE; 1526209ff23fSmrg 1527209ff23fSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 1528209ff23fSmrg 1529209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1530209ff23fSmrg &(atomDataPtr->GPIO_I2C_Info->sHeader), 1531ad43ddacSmrg &crev,&frev,&size)) { 1532209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No GPIO Info Table found!\n"); 1533209ff23fSmrg return i2c; 1534209ff23fSmrg } 1535209ff23fSmrg 1536921a55d8Smrg num_indices = size / sizeof(ATOM_GPIO_I2C_ASSIGMENT); 1537ad43ddacSmrg 1538ad43ddacSmrg for (i = 0; i < num_indices; i++) { 1539ad43ddacSmrg gpio = &atomDataPtr->GPIO_I2C_Info->asGPIO_Info[i]; 15400974d292Smrg 15410974d292Smrg if (IS_DCE4_VARIANT) { 15420974d292Smrg if ((i == 7) && 1543b13dfe66Smrg (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && 15440974d292Smrg (gpio->sucI2cId.ucAccess == 0)) { 15450974d292Smrg gpio->sucI2cId.ucAccess = 0x97; 15460974d292Smrg gpio->ucDataMaskShift = 8; 15470974d292Smrg gpio->ucDataEnShift = 8; 15480974d292Smrg gpio->ucDataY_Shift = 8; 15490974d292Smrg gpio->ucDataA_Shift = 8; 15500974d292Smrg } 15510974d292Smrg } 15520974d292Smrg 1553ad43ddacSmrg if (gpio->sucI2cId.ucAccess == id) { 1554ad43ddacSmrg i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; 1555ad43ddacSmrg i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; 1556ad43ddacSmrg i2c.put_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; 1557ad43ddacSmrg i2c.put_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; 1558ad43ddacSmrg i2c.get_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; 1559ad43ddacSmrg i2c.get_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; 1560ad43ddacSmrg i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; 1561ad43ddacSmrg i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; 1562ad43ddacSmrg i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); 1563ad43ddacSmrg i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); 1564ad43ddacSmrg i2c.put_clk_mask = (1 << gpio->ucClkEnShift); 1565ad43ddacSmrg i2c.put_data_mask = (1 << gpio->ucDataEnShift); 1566ad43ddacSmrg i2c.get_clk_mask = (1 << gpio->ucClkY_Shift); 1567ad43ddacSmrg i2c.get_data_mask = (1 << gpio->ucDataY_Shift); 1568ad43ddacSmrg i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); 1569ad43ddacSmrg i2c.a_data_mask = (1 << gpio->ucDataA_Shift); 1570ad43ddacSmrg i2c.hw_line = gpio->sucI2cId.ucAccess; 1571ad43ddacSmrg i2c.hw_capable = gpio->sucI2cId.sbfAccess.bfHW_Capable; 1572ad43ddacSmrg i2c.valid = TRUE; 1573ad43ddacSmrg break; 1574ad43ddacSmrg } 1575ad43ddacSmrg } 1576209ff23fSmrg 1577209ff23fSmrg#if 0 1578b7e1c893Smrg ErrorF("id: %d\n", id); 1579ad43ddacSmrg ErrorF("hw capable: %d\n", gpio->sucI2cId.sbfAccess.bfHW_Capable); 1580ad43ddacSmrg ErrorF("hw engine id: %d\n", gpio->sucI2cId.sbfAccess.bfHW_EngineID); 1581ad43ddacSmrg ErrorF("line mux %d\n", gpio->sucI2cId.sbfAccess.bfI2C_LineMux); 1582b13dfe66Smrg ErrorF("mask_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4); 1583b13dfe66Smrg ErrorF("mask_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4); 1584b13dfe66Smrg ErrorF("put_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkEnRegisterIndex) * 4); 1585b13dfe66Smrg ErrorF("put_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataEnRegisterIndex) * 4); 1586b13dfe66Smrg ErrorF("get_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkY_RegisterIndex) * 4); 1587b13dfe66Smrg ErrorF("get_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataY_RegisterIndex) * 4); 1588b13dfe66Smrg ErrorF("a_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkA_RegisterIndex) * 4); 1589b13dfe66Smrg ErrorF("a_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataA_RegisterIndex) * 4); 1590ad43ddacSmrg ErrorF("mask_clk_mask: %d\n", gpio->ucClkMaskShift); 1591ad43ddacSmrg ErrorF("mask_data_mask: %d\n", gpio->ucDataMaskShift); 1592ad43ddacSmrg ErrorF("put_clk_mask: %d\n", gpio->ucClkEnShift); 1593ad43ddacSmrg ErrorF("put_data_mask: %d\n", gpio->ucDataEnShift); 1594ad43ddacSmrg ErrorF("get_clk_mask: %d\n", gpio->ucClkY_Shift); 1595ad43ddacSmrg ErrorF("get_data_mask: %d\n", gpio->ucDataY_Shift); 1596ad43ddacSmrg ErrorF("a_clk_mask: %d\n", gpio->ucClkA_Shift); 1597ad43ddacSmrg ErrorF("a_data_mask: %d\n", gpio->ucDataA_Shift); 1598209ff23fSmrg#endif 1599209ff23fSmrg 1600209ff23fSmrg return i2c; 1601209ff23fSmrg} 1602209ff23fSmrg 1603b7e1c893Smrgstatic RADEONI2CBusRec 1604b7e1c893SmrgrhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, 1605b7e1c893Smrg ATOM_I2C_RECORD *Record, int i) 1606b7e1c893Smrg{ 1607b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1608ad43ddacSmrg uint8_t *temp = &Record->sucI2cId; 1609b7e1c893Smrg 1610ad43ddacSmrg info->BiosConnector[i].i2c_line_mux = *temp; 1611ad43ddacSmrg info->BiosConnector[i].ucI2cId = *temp; 1612ad43ddacSmrg return RADEONLookupGPIOLineForDDC(pScrn, *temp); 1613ad43ddacSmrg} 1614ad43ddacSmrg 1615ad43ddacSmrgstatic uint8_t 1616ad43ddacSmrgradeon_lookup_hpd_id(ScrnInfoPtr pScrn, ATOM_HPD_INT_RECORD *record) 1617ad43ddacSmrg{ 1618ad43ddacSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1619ad43ddacSmrg unsigned short size; 1620ad43ddacSmrg uint8_t hpd = 0; 1621ad43ddacSmrg int i, num_indices; 1622ad43ddacSmrg struct _ATOM_GPIO_PIN_LUT *gpio_info; 1623ad43ddacSmrg ATOM_GPIO_PIN_ASSIGNMENT *pin; 1624ad43ddacSmrg atomDataTablesPtr atomDataPtr; 1625ad43ddacSmrg uint8_t crev, frev; 1626ad43ddacSmrg uint32_t reg; 1627ad43ddacSmrg 1628ad43ddacSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 1629ad43ddacSmrg 1630ad43ddacSmrg if (!rhdAtomGetTableRevisionAndSize( 1631ad43ddacSmrg &(atomDataPtr->GPIO_Pin_LUT->sHeader), 1632ad43ddacSmrg &crev,&frev,&size)) { 1633ad43ddacSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No GPIO Pin Table found!\n"); 1634ad43ddacSmrg return hpd; 1635ad43ddacSmrg } 1636ad43ddacSmrg 1637921a55d8Smrg num_indices = size / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 1638ad43ddacSmrg 1639ad43ddacSmrg if (IS_DCE4_VARIANT) 1640ad43ddacSmrg reg = EVERGREEN_DC_GPIO_HPD_A; 1641ad43ddacSmrg else 1642ad43ddacSmrg reg = AVIVO_DC_GPIO_HPD_A; 1643ad43ddacSmrg 1644ad43ddacSmrg gpio_info = atomDataPtr->GPIO_Pin_LUT; 1645ad43ddacSmrg for (i = 0; i < num_indices; i++) { 1646ad43ddacSmrg pin = &gpio_info->asGPIO_Pin[i]; 1647ad43ddacSmrg if (record->ucHPDIntGPIOID == pin->ucGPIO_ID) { 1648b13dfe66Smrg if ((le16_to_cpu(pin->usGpioPin_AIndex) * 4) == reg) { 1649ad43ddacSmrg switch (pin->ucGpioPinBitShift) { 1650ad43ddacSmrg case 0: 1651ad43ddacSmrg default: 1652ad43ddacSmrg hpd = 0; 1653ad43ddacSmrg break; 1654ad43ddacSmrg case 8: 1655ad43ddacSmrg hpd = 1; 1656ad43ddacSmrg break; 1657ad43ddacSmrg case 16: 1658ad43ddacSmrg hpd = 2; 1659ad43ddacSmrg break; 1660ad43ddacSmrg case 24: 1661ad43ddacSmrg hpd = 3; 1662ad43ddacSmrg break; 1663ad43ddacSmrg case 26: 1664ad43ddacSmrg hpd = 4; 1665ad43ddacSmrg break; 1666ad43ddacSmrg case 28: 1667ad43ddacSmrg hpd = 5; 1668ad43ddacSmrg break; 1669ad43ddacSmrg } 1670ad43ddacSmrg break; 1671ad43ddacSmrg } 1672ad43ddacSmrg } 1673ad43ddacSmrg } 1674ad43ddacSmrg 1675ad43ddacSmrg return hpd; 1676b7e1c893Smrg} 1677b7e1c893Smrg 1678b7e1c893Smrgstatic void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index) 1679b7e1c893Smrg{ 1680b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1681b7e1c893Smrg 1682b7e1c893Smrg /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ 1683b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RS690_791E) && 1684b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1685b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x826d)) { 1686b7e1c893Smrg if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1687b7e1c893Smrg (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1688b7e1c893Smrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1689b7e1c893Smrg } 1690b7e1c893Smrg } 1691c503f109Smrg 1692ad43ddacSmrg /* RS600 board lists the DVI port as HDMI */ 1693ad43ddacSmrg if ((info->Chipset == PCI_CHIP_RS600_7941) && 1694ad43ddacSmrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1849) && 1695ad43ddacSmrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x7941)) { 1696ad43ddacSmrg if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1697ad43ddacSmrg (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1698ad43ddacSmrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1699ad43ddacSmrg } 1700ad43ddacSmrg } 1701ad43ddacSmrg 1702b7e1c893Smrg /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ 1703b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RS600_7941) && 1704b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x147b) && 1705b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2412)) { 1706b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) 1707b7e1c893Smrg info->BiosConnector[index].valid = FALSE; 1708b7e1c893Smrg } 1709b7e1c893Smrg 1710b7e1c893Smrg /* Falcon NW laptop lists vga ddc line for LVDS */ 1711b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV410_5653) && 1712b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1462) && 1713b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0291)) { 1714b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_LVDS) { 1715b7e1c893Smrg info->BiosConnector[index].ddc_i2c.valid = FALSE; 1716b7e1c893Smrg } 1717b7e1c893Smrg } 1718b7e1c893Smrg 1719b7e1c893Smrg /* Funky macbooks */ 1720b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1721b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1722b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1723b7e1c893Smrg if ((index == ATOM_DEVICE_CRT1_INDEX) || 1724b7e1c893Smrg (index == ATOM_DEVICE_CRT2_INDEX) || 1725b7e1c893Smrg (index == ATOM_DEVICE_DFP2_INDEX)) 1726b7e1c893Smrg info->BiosConnector[index].valid = FALSE; 1727b7e1c893Smrg 1728b7e1c893Smrg if (index == ATOM_DEVICE_DFP1_INDEX) { 1729b7e1c893Smrg info->BiosConnector[index].devices |= ATOM_DEVICE_CRT2_SUPPORT; 1730b7e1c893Smrg } 1731b7e1c893Smrg } 1732b7e1c893Smrg 1733b7e1c893Smrg /* ASUS HD 3600 XT board lists the DVI port as HDMI */ 1734b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV635_9598) && 1735b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1736b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) { 1737ad43ddacSmrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) 1738ad43ddacSmrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I; 1739b7e1c893Smrg } 1740b7e1c893Smrg 1741c503f109Smrg /* ASUS HD 3450 board lists the DVI port as HDMI */ 1742c503f109Smrg if ((info->Chipset == PCI_CHIP_RV620_95C5) && 1743c503f109Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1744c503f109Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) { 1745ad43ddacSmrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) 1746ad43ddacSmrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I; 1747c503f109Smrg } 1748c503f109Smrg 1749c503f109Smrg /* some BIOSes seem to report DAC on HDMI - usually this is a board with 1750c503f109Smrg * HDMI + VGA reporting as HDMI 1751c503f109Smrg */ 1752ad43ddacSmrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) { 1753c503f109Smrg if (info->BiosConnector[index].devices & (ATOM_DEVICE_CRT_SUPPORT)) { 1754c503f109Smrg info->BiosConnector[index].devices &= ~(ATOM_DEVICE_DFP_SUPPORT); 1755c503f109Smrg info->BiosConnector[index].ConnectorType = CONNECTOR_VGA; 1756c503f109Smrg info->BiosConnector[index].connector_object = 0; 1757ad43ddacSmrg } 1758c503f109Smrg } 1759b7e1c893Smrg 1760b7e1c893Smrg} 1761b7e1c893Smrg 1762b7e1c893Smrguint32_t 1763b7e1c893Smrgradeon_get_device_index(uint32_t device_support) 1764b7e1c893Smrg{ 1765b7e1c893Smrg uint32_t device_index = 0; 1766b7e1c893Smrg 1767b7e1c893Smrg if (device_support == 0) 1768b7e1c893Smrg return 0; 1769b7e1c893Smrg 1770b7e1c893Smrg while ((device_support & 1) == 0) { 1771b7e1c893Smrg device_support >>= 1; 1772b7e1c893Smrg device_index++; 1773b7e1c893Smrg } 1774b7e1c893Smrg return device_index; 1775b7e1c893Smrg} 1776b7e1c893Smrg 1777b7e1c893Smrgradeon_encoder_ptr 1778b7e1c893Smrgradeon_get_encoder(xf86OutputPtr output) 1779b7e1c893Smrg{ 1780b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1781b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1782b7e1c893Smrg 1783b7e1c893Smrg if (radeon_output->active_device) 1784b7e1c893Smrg return info->encoders[radeon_get_device_index(radeon_output->active_device)]; 1785b7e1c893Smrg else 1786b7e1c893Smrg return NULL; 1787b7e1c893Smrg} 1788b7e1c893Smrg 1789b7e1c893SmrgBool 1790b7e1c893Smrgradeon_add_encoder(ScrnInfoPtr pScrn, uint32_t encoder_id, uint32_t device_support) 1791b7e1c893Smrg{ 1792b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1793b7e1c893Smrg uint32_t device_index = radeon_get_device_index(device_support); 1794b7e1c893Smrg int i; 1795b7e1c893Smrg 1796b7e1c893Smrg if (device_support == 0) { 1797b7e1c893Smrg ErrorF("device support == 0\n"); 1798b7e1c893Smrg return FALSE; 1799b7e1c893Smrg } 1800b7e1c893Smrg 1801b7e1c893Smrg if (info->encoders[device_index] != NULL) 1802b7e1c893Smrg return TRUE; 1803b7e1c893Smrg else { 1804b7e1c893Smrg /* look for the encoder */ 1805b7e1c893Smrg for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { 1806b7e1c893Smrg if ((info->encoders[i] != NULL) && (info->encoders[i]->encoder_id == encoder_id)) { 1807b7e1c893Smrg info->encoders[device_index] = info->encoders[i]; 1808b7e1c893Smrg switch (encoder_id) { 1809b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1810b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1811b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1812b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1813b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1814b7e1c893Smrg if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1815b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1816b7e1c893Smrg info->encoders[device_index]->dev_priv = 18172f39173dSmrg (radeon_lvds_ptr)calloc(1,sizeof(radeon_lvds_rec)); 1818b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 18192f39173dSmrg ErrorF("calloc failed\n"); 1820b7e1c893Smrg return FALSE; 1821b7e1c893Smrg } else 1822b7e1c893Smrg RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1823b7e1c893Smrg } 1824b7e1c893Smrg } 1825b7e1c893Smrg break; 1826b7e1c893Smrg } 1827b7e1c893Smrg return TRUE; 1828b7e1c893Smrg } 1829b7e1c893Smrg } 1830b7e1c893Smrg 18312f39173dSmrg info->encoders[device_index] = (radeon_encoder_ptr)calloc(1,sizeof(radeon_encoder_rec)); 1832b7e1c893Smrg if (info->encoders[device_index] != NULL) { 1833b7e1c893Smrg info->encoders[device_index]->encoder_id = encoder_id; 1834b7e1c893Smrg info->encoders[device_index]->devices = 0; 1835b7e1c893Smrg info->encoders[device_index]->dev_priv = NULL; 1836b7e1c893Smrg // add dev_priv stuff 1837b7e1c893Smrg switch (encoder_id) { 1838b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 18392f39173dSmrg info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)calloc(1,sizeof(radeon_lvds_rec)); 1840b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 18412f39173dSmrg ErrorF("calloc failed\n"); 1842b7e1c893Smrg return FALSE; 1843b7e1c893Smrg } else { 1844b7e1c893Smrg if (info->IsAtomBios) 1845b7e1c893Smrg RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1846b7e1c893Smrg else 1847b7e1c893Smrg RADEONGetLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1848b7e1c893Smrg } 1849b7e1c893Smrg break; 1850b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1851b7e1c893Smrg if (!IS_AVIVO_VARIANT) { 18522f39173dSmrg info->encoders[device_index]->dev_priv = (radeon_tvdac_ptr)calloc(1,sizeof(radeon_tvdac_rec)); 1853b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 18542f39173dSmrg ErrorF("calloc failed\n"); 1855b7e1c893Smrg return FALSE; 1856b7e1c893Smrg } else 1857b7e1c893Smrg RADEONGetTVDacAdjInfo(pScrn, (radeon_tvdac_ptr)info->encoders[device_index]->dev_priv); 1858b7e1c893Smrg } 1859b7e1c893Smrg break; 1860b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1861b7e1c893Smrg if (!IS_AVIVO_VARIANT) { 18622f39173dSmrg info->encoders[device_index]->dev_priv = (radeon_tmds_ptr)calloc(1,sizeof(radeon_tmds_rec)); 1863b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 18642f39173dSmrg ErrorF("calloc failed\n"); 1865b7e1c893Smrg return FALSE; 1866b7e1c893Smrg } else 1867b7e1c893Smrg RADEONGetTMDSInfo(pScrn, (radeon_tmds_ptr)info->encoders[device_index]->dev_priv); 1868b7e1c893Smrg } 1869b7e1c893Smrg break; 1870b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1871b7e1c893Smrg if (!IS_AVIVO_VARIANT) { 18722f39173dSmrg info->encoders[device_index]->dev_priv = (radeon_dvo_ptr)calloc(1,sizeof(radeon_dvo_rec)); 1873b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 18742f39173dSmrg ErrorF("calloc failed\n"); 1875b7e1c893Smrg return FALSE; 1876b7e1c893Smrg } else 1877b7e1c893Smrg RADEONGetExtTMDSInfo(pScrn, (radeon_dvo_ptr)info->encoders[device_index]->dev_priv); 1878b7e1c893Smrg } 1879b7e1c893Smrg break; 1880b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1881b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1882b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1883b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1884b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1885b7e1c893Smrg if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 18862f39173dSmrg info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)calloc(1,sizeof(radeon_lvds_rec)); 1887b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 18882f39173dSmrg ErrorF("calloc failed\n"); 1889b7e1c893Smrg return FALSE; 1890b7e1c893Smrg } else 1891b7e1c893Smrg RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1892b7e1c893Smrg } 1893b7e1c893Smrg break; 1894b7e1c893Smrg } 1895b7e1c893Smrg return TRUE; 1896b7e1c893Smrg } else { 18972f39173dSmrg ErrorF("calloc failed\n"); 1898b7e1c893Smrg return FALSE; 1899b7e1c893Smrg } 1900b7e1c893Smrg } 1901b7e1c893Smrg 1902b7e1c893Smrg} 1903b7e1c893Smrg 1904209ff23fSmrgBool 1905209ff23fSmrgRADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn) 1906209ff23fSmrg{ 1907209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1908209ff23fSmrg uint8_t crev, frev; 1909209ff23fSmrg unsigned short size; 1910209ff23fSmrg atomDataTablesPtr atomDataPtr; 1911209ff23fSmrg ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 1912b7e1c893Smrg ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 1913209ff23fSmrg ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj = NULL; 1914b7e1c893Smrg int i, j, path_size, device_support; 1915b7e1c893Smrg Bool enable_tv = FALSE; 1916b7e1c893Smrg 1917b7e1c893Smrg if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 1918b7e1c893Smrg enable_tv = TRUE; 1919209ff23fSmrg 1920209ff23fSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 1921209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->Object_Header), &crev, &frev, &size)) 1922209ff23fSmrg return FALSE; 1923209ff23fSmrg 1924209ff23fSmrg if (crev < 2) 1925209ff23fSmrg return FALSE; 1926209ff23fSmrg 1927b7e1c893Smrg path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) 1928b7e1c893Smrg ((char *)&atomDataPtr->Object_Header->sHeader + 1929b7e1c893Smrg le16_to_cpu(atomDataPtr->Object_Header->usDisplayPathTableOffset)); 1930209ff23fSmrg con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) 1931209ff23fSmrg ((char *)&atomDataPtr->Object_Header->sHeader + 1932209ff23fSmrg le16_to_cpu(atomDataPtr->Object_Header->usConnectorObjectTableOffset)); 1933b7e1c893Smrg device_support = le16_to_cpu(atomDataPtr->Object_Header->usDeviceSupport); 1934b7e1c893Smrg 1935b7e1c893Smrg path_size = 0; 1936b7e1c893Smrg for (i = 0; i < path_obj->ucNumOfDispPath; i++) { 1937b7e1c893Smrg uint8_t *addr = (uint8_t *)path_obj->asDispPath; 1938b7e1c893Smrg ATOM_DISPLAY_OBJECT_PATH *path; 1939b7e1c893Smrg addr += path_size; 1940b7e1c893Smrg path = (ATOM_DISPLAY_OBJECT_PATH *)addr; 1941c503f109Smrg path_size += le16_to_cpu(path->usSize); 1942b7e1c893Smrg 1943c503f109Smrg if (device_support & le16_to_cpu(path->usDeviceTag)) { 1944b7e1c893Smrg uint8_t con_obj_id, con_obj_num, con_obj_type; 1945b7e1c893Smrg 1946c503f109Smrg con_obj_id = (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1947c503f109Smrg con_obj_num = (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1948c503f109Smrg con_obj_type = (le16_to_cpu(path->usConnObjectId) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 1949b7e1c893Smrg 1950c503f109Smrg if ((le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV1_SUPPORT) || 1951c503f109Smrg (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV2_SUPPORT)) { 1952b7e1c893Smrg if (!enable_tv) { 1953b7e1c893Smrg info->BiosConnector[i].valid = FALSE; 1954b7e1c893Smrg continue; 1955b7e1c893Smrg } 1956b7e1c893Smrg } 1957209ff23fSmrg 1958b7e1c893Smrg /* don't support CV yet */ 1959c503f109Smrg if (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_CV_SUPPORT) { 1960b7e1c893Smrg info->BiosConnector[i].valid = FALSE; 1961b7e1c893Smrg continue; 1962b7e1c893Smrg } 1963209ff23fSmrg 1964b7e1c893Smrg if (info->IsIGP && 1965b7e1c893Smrg (con_obj_id == CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { 1966b7e1c893Smrg uint32_t slot_config, ct; 1967209ff23fSmrg 1968b7e1c893Smrg igp_obj = info->atomBIOS->atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2; 1969209ff23fSmrg 1970b7e1c893Smrg if (!igp_obj) 1971b7e1c893Smrg info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1972b7e1c893Smrg else { 1973b7e1c893Smrg if (con_obj_num == 1) 1974b7e1c893Smrg slot_config = igp_obj->ulDDISlot1Config; 1975b7e1c893Smrg else 1976b7e1c893Smrg slot_config = igp_obj->ulDDISlot2Config; 1977209ff23fSmrg 1978b7e1c893Smrg ct = (slot_config >> 16) & 0xff; 1979b7e1c893Smrg info->BiosConnector[i].ConnectorType = object_connector_convert[ct]; 1980ad43ddacSmrg info->BiosConnector[i].connector_object_id = ct; 1981b7e1c893Smrg info->BiosConnector[i].igp_lane_info = slot_config & 0xffff; 1982b7e1c893Smrg } 1983ad43ddacSmrg } else { 1984b7e1c893Smrg info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1985ad43ddacSmrg info->BiosConnector[i].connector_object_id = con_obj_id; 1986ad43ddacSmrg } 1987b7e1c893Smrg 1988b7e1c893Smrg if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 1989b7e1c893Smrg info->BiosConnector[i].valid = FALSE; 1990b7e1c893Smrg continue; 1991b7e1c893Smrg } else 1992b7e1c893Smrg info->BiosConnector[i].valid = TRUE; 1993c503f109Smrg info->BiosConnector[i].devices = le16_to_cpu(path->usDeviceTag); 1994c503f109Smrg info->BiosConnector[i].connector_object = le16_to_cpu(path->usConnObjectId); 1995b7e1c893Smrg 1996c503f109Smrg for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { 1997b7e1c893Smrg uint8_t enc_obj_id, enc_obj_num, enc_obj_type; 1998b7e1c893Smrg 1999c503f109Smrg enc_obj_id = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 2000c503f109Smrg enc_obj_num = (le16_to_cpu(path->usGraphicObjIds[j]) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 2001c503f109Smrg enc_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 2002b7e1c893Smrg 2003b7e1c893Smrg if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { 2004b7e1c893Smrg if (enc_obj_num == 2) 2005b7e1c893Smrg info->BiosConnector[i].linkb = TRUE; 2006b7e1c893Smrg else 2007b7e1c893Smrg info->BiosConnector[i].linkb = FALSE; 2008b7e1c893Smrg 2009c503f109Smrg if (!radeon_add_encoder(pScrn, enc_obj_id, le16_to_cpu(path->usDeviceTag))) 2010b7e1c893Smrg return FALSE; 2011b7e1c893Smrg } 2012209ff23fSmrg } 2013209ff23fSmrg 2014b7e1c893Smrg /* look up gpio for ddc */ 2015c503f109Smrg if ((le16_to_cpu(path->usDeviceTag) & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { 2016b7e1c893Smrg for (j = 0; j < con_obj->ucNumberOfObjects; j++) { 2017c503f109Smrg if (le16_to_cpu(path->usConnObjectId) == le16_to_cpu(con_obj->asObjects[j].usObjectID)) { 2018b7e1c893Smrg ATOM_COMMON_RECORD_HEADER *Record = (ATOM_COMMON_RECORD_HEADER *) 2019b7e1c893Smrg ((char *)&atomDataPtr->Object_Header->sHeader 2020b7e1c893Smrg + le16_to_cpu(con_obj->asObjects[j].usRecordOffset)); 2021b7e1c893Smrg 2022b7e1c893Smrg while (Record->ucRecordType > 0 2023b7e1c893Smrg && Record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER ) { 2024b7e1c893Smrg 2025b7e1c893Smrg /*ErrorF("record type %d\n", Record->ucRecordType);*/ 2026b7e1c893Smrg switch (Record->ucRecordType) { 2027b7e1c893Smrg case ATOM_I2C_RECORD_TYPE: 2028b7e1c893Smrg info->BiosConnector[i].ddc_i2c = 2029b7e1c893Smrg rhdAtomParseI2CRecord(pScrn, info->atomBIOS, 2030b7e1c893Smrg (ATOM_I2C_RECORD *)Record, j); 2031b7e1c893Smrg break; 2032b7e1c893Smrg case ATOM_HPD_INT_RECORD_TYPE: 2033ad43ddacSmrg info->BiosConnector[i].hpd_id = 2034ad43ddacSmrg radeon_lookup_hpd_id(pScrn, 2035ad43ddacSmrg (ATOM_HPD_INT_RECORD *)Record); 2036b7e1c893Smrg break; 2037b7e1c893Smrg case ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE: 2038b7e1c893Smrg break; 2039b7e1c893Smrg } 2040b7e1c893Smrg 2041b7e1c893Smrg Record = (ATOM_COMMON_RECORD_HEADER*) 2042b7e1c893Smrg ((char *)Record + Record->ucRecordSize); 2043b7e1c893Smrg } 2044b7e1c893Smrg break; 2045b7e1c893Smrg } 2046b7e1c893Smrg } 2047b7e1c893Smrg } 2048b7e1c893Smrg } 2049b7e1c893Smrg RADEONApplyATOMQuirks(pScrn, i); 2050b7e1c893Smrg } 2051209ff23fSmrg 2052b7e1c893Smrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2053b7e1c893Smrg if (info->BiosConnector[i].valid) { 2054b7e1c893Smrg /* shared connectors */ 2055b7e1c893Smrg for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2056b7e1c893Smrg if (info->BiosConnector[j].valid && (i != j) ) { 2057b7e1c893Smrg if (info->BiosConnector[i].connector_object == info->BiosConnector[j].connector_object) { 2058b7e1c893Smrg info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2059b7e1c893Smrg info->BiosConnector[j].valid = FALSE; 2060b7e1c893Smrg } 2061b7e1c893Smrg } 2062b7e1c893Smrg } 2063b7e1c893Smrg /* shared ddc */ 2064b7e1c893Smrg for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2065b7e1c893Smrg if (info->BiosConnector[j].valid && (i != j) ) { 2066b7e1c893Smrg if (info->BiosConnector[i].i2c_line_mux == info->BiosConnector[j].i2c_line_mux) { 2067b7e1c893Smrg info->BiosConnector[i].shared_ddc = TRUE; 2068b7e1c893Smrg info->BiosConnector[j].shared_ddc = TRUE; 2069b7e1c893Smrg } 2070b7e1c893Smrg } 2071209ff23fSmrg } 2072209ff23fSmrg } 2073b7e1c893Smrg } 2074209ff23fSmrg 2075b7e1c893Smrg return TRUE; 2076b7e1c893Smrg} 2077209ff23fSmrg 2078b7e1c893Smrgstatic void 2079b7e1c893SmrgRADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 2080b7e1c893Smrg{ 2081b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 2082b7e1c893Smrg radeon_native_mode_ptr native_mode = &lvds->native_mode; 2083b7e1c893Smrg atomDataTablesPtr atomDataPtr; 2084b7e1c893Smrg uint8_t crev, frev; 2085ad43ddacSmrg uint16_t misc; 2086209ff23fSmrg 2087b7e1c893Smrg atomDataPtr = info->atomBIOS->atomDataPtr; 2088209ff23fSmrg 2089b7e1c893Smrg if (!rhdAtomGetTableRevisionAndSize( 2090b7e1c893Smrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 2091b7e1c893Smrg &frev,&crev,NULL)) { 2092b7e1c893Smrg return; 2093b7e1c893Smrg } 2094209ff23fSmrg 2095b7e1c893Smrg switch (crev) { 2096b7e1c893Smrg case 1: 2097b7e1c893Smrg native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHActive); 2098b7e1c893Smrg native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVActive); 2099b7e1c893Smrg native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usPixClk) * 10; 2100b7e1c893Smrg native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHBlanking_Time); 2101b7e1c893Smrg native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncOffset); 2102b7e1c893Smrg native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncWidth); 2103b7e1c893Smrg native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVBlanking_Time); 2104b7e1c893Smrg native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncOffset); 2105b7e1c893Smrg native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncWidth); 2106ad43ddacSmrg misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.susModeMiscInfo.usAccess); 2107ad43ddacSmrg if (misc & ATOM_VSYNC_POLARITY) 2108ad43ddacSmrg native_mode->Flags |= V_NVSYNC; 2109ad43ddacSmrg if (misc & ATOM_HSYNC_POLARITY) 2110ad43ddacSmrg native_mode->Flags |= V_NHSYNC; 2111ad43ddacSmrg if (misc & ATOM_COMPOSITESYNC) 2112ad43ddacSmrg native_mode->Flags |= V_CSYNC; 2113ad43ddacSmrg if (misc & ATOM_INTERLACE) 2114ad43ddacSmrg native_mode->Flags |= V_INTERLACE; 2115ad43ddacSmrg if (misc & ATOM_DOUBLE_CLOCK_MODE) 2116ad43ddacSmrg native_mode->Flags |= V_DBLSCAN; 2117b7e1c893Smrg lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->usOffDelayInMs); 2118b7e1c893Smrg lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info->ucLVDS_Misc; 2119b7e1c893Smrg lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info->ucSS_Id; 2120b7e1c893Smrg break; 2121b7e1c893Smrg case 2: 2122b7e1c893Smrg native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHActive); 2123b7e1c893Smrg native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVActive); 2124b7e1c893Smrg native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usPixClk) * 10; 2125b7e1c893Smrg native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHBlanking_Time); 2126b7e1c893Smrg native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncOffset); 2127b7e1c893Smrg native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncWidth); 2128b7e1c893Smrg native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVBlanking_Time); 2129b7e1c893Smrg native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncOffset); 2130b7e1c893Smrg native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncWidth); 2131ad43ddacSmrg misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.susModeMiscInfo.usAccess); 2132ad43ddacSmrg if (misc & ATOM_VSYNC_POLARITY) 2133ad43ddacSmrg native_mode->Flags |= V_NVSYNC; 2134ad43ddacSmrg if (misc & ATOM_HSYNC_POLARITY) 2135ad43ddacSmrg native_mode->Flags |= V_NHSYNC; 2136ad43ddacSmrg if (misc & ATOM_COMPOSITESYNC) 2137ad43ddacSmrg native_mode->Flags |= V_CSYNC; 2138ad43ddacSmrg if (misc & ATOM_INTERLACE) 2139ad43ddacSmrg native_mode->Flags |= V_INTERLACE; 2140ad43ddacSmrg if (misc & ATOM_DOUBLE_CLOCK_MODE) 2141ad43ddacSmrg native_mode->Flags |= V_DBLSCAN; 2142b7e1c893Smrg lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->usOffDelayInMs); 2143b7e1c893Smrg lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucLVDS_Misc; 2144b7e1c893Smrg lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucSS_Id; 2145b7e1c893Smrg break; 2146209ff23fSmrg } 2147b7e1c893Smrg native_mode->Flags = 0; 2148b7e1c893Smrg 2149b7e1c893Smrg if (lvds->PanelPwrDly > 2000 || lvds->PanelPwrDly < 0) 2150b7e1c893Smrg lvds->PanelPwrDly = 2000; 2151b7e1c893Smrg 2152b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2153b7e1c893Smrg "LVDS Info:\n" 2154b7e1c893Smrg "XRes: %d, YRes: %d, DotClock: %d\n" 2155b7e1c893Smrg "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" 2156b7e1c893Smrg "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", 2157b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes, native_mode->DotClock, 2158b7e1c893Smrg native_mode->HBlank, native_mode->HOverPlus, native_mode->HSyncWidth, 2159b7e1c893Smrg native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth); 2160209ff23fSmrg} 2161209ff23fSmrg 2162ad43ddacSmrgvoid 2163ad43ddacSmrgRADEONATOMGetIGPInfo(ScrnInfoPtr pScrn) 2164ad43ddacSmrg{ 2165ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2166ad43ddacSmrg atomDataTablesPtr atomDataPtr; 2167ad43ddacSmrg unsigned short size; 2168ad43ddacSmrg uint8_t crev, frev; 2169ad43ddacSmrg 2170ad43ddacSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 2171ad43ddacSmrg 2172ad43ddacSmrg if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base), &frev, &crev, &size)) 2173ad43ddacSmrg return; 2174ad43ddacSmrg 2175ad43ddacSmrg switch (crev) { 2176ad43ddacSmrg case 1: 2177ad43ddacSmrg info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ulBootUpMemoryClock / 100.0; 2178ad43ddacSmrg info->igp_system_mclk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usK8MemoryClock); 2179ad43ddacSmrg info->igp_ht_link_clk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usFSBClock); 2180ad43ddacSmrg info->igp_ht_link_width = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ucHTLinkWidth; 2181ad43ddacSmrg break; 2182ad43ddacSmrg case 2: 2183ad43ddacSmrg info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpSidePortClock / 100.0; 2184ad43ddacSmrg info->igp_system_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpUMAClock / 100.0; 2185ad43ddacSmrg info->igp_ht_link_clk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulHTLinkFreq / 100.0; 2186ad43ddacSmrg info->igp_ht_link_width = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->usMinHTLinkWidth); 2187ad43ddacSmrg break; 2188ad43ddacSmrg } 2189ad43ddacSmrg} 2190ad43ddacSmrg 2191209ff23fSmrgBool 2192209ff23fSmrgRADEONGetATOMTVInfo(xf86OutputPtr output) 2193209ff23fSmrg{ 2194209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 2195209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2196209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 2197b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 2198209ff23fSmrg ATOM_ANALOG_TV_INFO *tv_info; 2199209ff23fSmrg 2200b7e1c893Smrg tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2201209ff23fSmrg 2202209ff23fSmrg if (!tv_info) 2203209ff23fSmrg return FALSE; 2204209ff23fSmrg 2205209ff23fSmrg switch(tv_info->ucTV_BootUpDefaultStandard) { 2206209ff23fSmrg case NTSCJ_SUPPORT: 2207b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC_J; 2208209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); 2209209ff23fSmrg break; 2210209ff23fSmrg case PAL_SUPPORT: 2211b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL; 2212209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); 2213209ff23fSmrg break; 2214209ff23fSmrg case PALM_SUPPORT: 2215b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_M; 2216209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); 2217209ff23fSmrg break; 2218209ff23fSmrg case PAL60_SUPPORT: 2219b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_60; 2220209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); 2221209ff23fSmrg break; 2222b7e1c893Smrg default: 2223b7e1c893Smrg case NTSC_SUPPORT: 2224b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC; 2225b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); 2226b7e1c893Smrg break; 2227209ff23fSmrg } 2228209ff23fSmrg 2229b7e1c893Smrg tvout->tvStd = tvout->default_tvStd; 2230209ff23fSmrg 2231209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); 2232b7e1c893Smrg tvout->SupportedTVStds = tvout->default_tvStd; 2233209ff23fSmrg if (tv_info->ucTV_SupportedStandard & NTSC_SUPPORT) { 2234209ff23fSmrg ErrorF("NTSC "); 2235b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC; 2236209ff23fSmrg } 2237209ff23fSmrg if (tv_info->ucTV_SupportedStandard & NTSCJ_SUPPORT) { 2238209ff23fSmrg ErrorF("NTSC-J "); 2239b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC_J; 2240209ff23fSmrg } 2241209ff23fSmrg if (tv_info->ucTV_SupportedStandard & PAL_SUPPORT) { 2242209ff23fSmrg ErrorF("PAL "); 2243b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL; 2244209ff23fSmrg } 2245209ff23fSmrg if (tv_info->ucTV_SupportedStandard & PALM_SUPPORT) { 2246209ff23fSmrg ErrorF("PAL-M "); 2247b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_M; 2248209ff23fSmrg } 2249209ff23fSmrg if (tv_info->ucTV_SupportedStandard & PAL60_SUPPORT) { 2250209ff23fSmrg ErrorF("PAL-60 "); 2251b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_60; 2252209ff23fSmrg } 2253209ff23fSmrg ErrorF("\n"); 2254209ff23fSmrg 2255209ff23fSmrg if (tv_info->ucExt_TV_ASIC_ID) { 2256209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown external TV ASIC\n"); 2257209ff23fSmrg return FALSE; 2258209ff23fSmrg } 2259209ff23fSmrg 2260209ff23fSmrg return TRUE; 2261209ff23fSmrg} 2262209ff23fSmrg 2263209ff23fSmrgBool 2264ad43ddacSmrgRADEONGetATOMClockInfo(ScrnInfoPtr pScrn) 2265ad43ddacSmrg{ 2266ad43ddacSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 2267ad43ddacSmrg RADEONPLLPtr pll = &info->pll; 2268ad43ddacSmrg atomDataTablesPtr atomDataPtr; 2269ad43ddacSmrg uint8_t crev, frev; 2270ad43ddacSmrg 2271ad43ddacSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 2272ad43ddacSmrg if (!rhdAtomGetTableRevisionAndSize( 2273ad43ddacSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), 2274ad43ddacSmrg &crev,&frev,NULL)) { 2275ad43ddacSmrg return FALSE; 2276ad43ddacSmrg } 2277ad43ddacSmrg 2278ad43ddacSmrg switch(crev) { 2279ad43ddacSmrg case 1: 2280ad43ddacSmrg info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultEngineClock) / 100.0; 2281ad43ddacSmrg info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultMemoryClock) / 100.0; 2282ad43ddacSmrg pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClock); 2283ad43ddacSmrg pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Input); 2284ad43ddacSmrg pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClockPLL_Input); 2285ad43ddacSmrg pll->pll_out_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Output); 2286ad43ddacSmrg pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulMaxPixelClockPLL_Output); 2287ad43ddacSmrg pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usReferenceClock); 2288ad43ddacSmrg break; 2289ad43ddacSmrg case 2: 2290ad43ddacSmrg case 3: 2291ad43ddacSmrg case 4: 2292ad43ddacSmrg default: 2293ad43ddacSmrg info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultEngineClock) / 100.0; 2294ad43ddacSmrg info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultMemoryClock) / 100.0; 2295ad43ddacSmrg pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClock); 2296ad43ddacSmrg pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMinPixelClockPLL_Input); 2297ad43ddacSmrg pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input); 2298ad43ddacSmrg pll->pll_out_min = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMinPixelClockPLL_Output); 2299ad43ddacSmrg pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output); 2300ad43ddacSmrg pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usReferenceClock); 2301ad43ddacSmrg break; 2302ad43ddacSmrg } 2303ad43ddacSmrg pll->reference_div = 0; 23042f39173dSmrg if (pll->pll_out_min == 0) { 23052f39173dSmrg if (IS_AVIVO_VARIANT) 23062f39173dSmrg pll->pll_out_min = 64800; 23072f39173dSmrg else 23082f39173dSmrg pll->pll_out_min = 20000; 23092f39173dSmrg } 2310ad43ddacSmrg 2311ad43ddacSmrg /* limiting the range is a good thing in most cases 2312ad43ddacSmrg * as it limits the number of matching pll combinations, 2313ad43ddacSmrg * however, some duallink DVI monitors seem to prefer combinations that 2314ad43ddacSmrg * would be limited by this. This may need to be revisited 2315ad43ddacSmrg * per chip family. 2316ad43ddacSmrg */ 2317ad43ddacSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) { 2318ad43ddacSmrg if (pll->pll_out_min > 64800) 2319ad43ddacSmrg pll->pll_out_min = 64800; 2320ad43ddacSmrg } 2321ad43ddacSmrg 23220974d292Smrg if (IS_DCE4_VARIANT) { 23230974d292Smrg info->default_dispclk = 23240974d292Smrg le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_2_1->ulDefaultDispEngineClkFreq); 23250974d292Smrg if (info->default_dispclk == 0) 23260974d292Smrg info->default_dispclk = 60000; 23270974d292Smrg info->dp_extclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_2_1->usUniphyDPModeExtClkFreq); 23280974d292Smrg } 2329ad43ddacSmrg return TRUE; 2330ad43ddacSmrg} 2331ad43ddacSmrg 2332ad43ddacSmrgBool 2333ad43ddacSmrgRADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode) 2334209ff23fSmrg{ 2335209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2336209ff23fSmrg ATOM_ANALOG_TV_INFO *tv_info; 2337b7e1c893Smrg ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; 2338b7e1c893Smrg ATOM_DTD_FORMAT *dtd_timings; 2339b7e1c893Smrg atomDataTablesPtr atomDataPtr; 2340b7e1c893Smrg uint8_t crev, frev; 2341ad43ddacSmrg uint16_t misc; 2342209ff23fSmrg 2343b7e1c893Smrg atomDataPtr = info->atomBIOS->atomDataPtr; 2344b7e1c893Smrg if (!rhdAtomGetTableRevisionAndSize( 2345b7e1c893Smrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info.base), 2346b7e1c893Smrg &crev,&frev,NULL)) { 2347209ff23fSmrg return FALSE; 2348b7e1c893Smrg } 2349209ff23fSmrg 2350b7e1c893Smrg switch(crev) { 2351b7e1c893Smrg case 1: 2352b7e1c893Smrg tv_info = atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2353ad43ddacSmrg 2354b7e1c893Smrg if (index > MAX_SUPPORTED_TV_TIMING) 2355b7e1c893Smrg return FALSE; 2356ad43ddacSmrg 2357ad43ddacSmrg mode->CrtcHTotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); 2358ad43ddacSmrg mode->CrtcHDisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); 2359ad43ddacSmrg mode->CrtcHSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); 2360ad43ddacSmrg mode->CrtcHSyncEnd = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) + 2361ad43ddacSmrg le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); 2362ad43ddacSmrg 2363ad43ddacSmrg mode->CrtcVTotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); 2364ad43ddacSmrg mode->CrtcVDisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); 2365ad43ddacSmrg mode->CrtcVSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); 2366ad43ddacSmrg mode->CrtcVSyncEnd = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) + 2367ad43ddacSmrg le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); 2368ad43ddacSmrg 2369ad43ddacSmrg mode->Flags = 0; 2370ad43ddacSmrg misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess); 2371ad43ddacSmrg if (misc & ATOM_VSYNC_POLARITY) 2372ad43ddacSmrg mode->Flags |= V_NVSYNC; 2373ad43ddacSmrg if (misc & ATOM_HSYNC_POLARITY) 2374ad43ddacSmrg mode->Flags |= V_NHSYNC; 2375ad43ddacSmrg if (misc & ATOM_COMPOSITESYNC) 2376ad43ddacSmrg mode->Flags |= V_CSYNC; 2377ad43ddacSmrg if (misc & ATOM_INTERLACE) 2378ad43ddacSmrg mode->Flags |= V_INTERLACE; 2379ad43ddacSmrg if (misc & ATOM_DOUBLE_CLOCK_MODE) 2380ad43ddacSmrg mode->Flags |= V_DBLSCAN; 2381ad43ddacSmrg 2382ad43ddacSmrg mode->Clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; 2383b7e1c893Smrg 2384b7e1c893Smrg if (index == 1) { 2385b7e1c893Smrg /* PAL timings appear to have wrong values for totals */ 2386ad43ddacSmrg mode->CrtcHTotal -= 1; 2387ad43ddacSmrg mode->CrtcVTotal -= 1; 2388b7e1c893Smrg } 2389b7e1c893Smrg break; 2390b7e1c893Smrg case 2: 2391b7e1c893Smrg tv_info_v1_2 = atomDataPtr->AnalogTV_Info.AnalogTV_Info_v1_2; 2392b7e1c893Smrg if (index > MAX_SUPPORTED_TV_TIMING_V1_2) 2393b7e1c893Smrg return FALSE; 2394209ff23fSmrg 2395b7e1c893Smrg dtd_timings = &tv_info_v1_2->aModeTimings[index]; 2396ad43ddacSmrg mode->CrtcHTotal = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time); 2397ad43ddacSmrg mode->CrtcHDisplay = le16_to_cpu(dtd_timings->usHActive); 2398ad43ddacSmrg mode->CrtcHSyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset); 2399ad43ddacSmrg mode->CrtcHSyncEnd = mode->CrtcHSyncStart + le16_to_cpu(dtd_timings->usHSyncWidth); 2400ad43ddacSmrg 2401ad43ddacSmrg mode->CrtcVTotal = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time); 2402ad43ddacSmrg mode->CrtcVDisplay = le16_to_cpu(dtd_timings->usVActive); 2403ad43ddacSmrg mode->CrtcVSyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset); 2404ad43ddacSmrg mode->CrtcVSyncEnd = mode->CrtcVSyncStart + le16_to_cpu(dtd_timings->usVSyncWidth); 2405ad43ddacSmrg 2406ad43ddacSmrg mode->Flags = 0; 2407ad43ddacSmrg misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); 2408ad43ddacSmrg if (misc & ATOM_VSYNC_POLARITY) 2409ad43ddacSmrg mode->Flags |= V_NVSYNC; 2410ad43ddacSmrg if (misc & ATOM_HSYNC_POLARITY) 2411ad43ddacSmrg mode->Flags |= V_NHSYNC; 2412ad43ddacSmrg if (misc & ATOM_COMPOSITESYNC) 2413ad43ddacSmrg mode->Flags |= V_CSYNC; 2414ad43ddacSmrg if (misc & ATOM_INTERLACE) 2415ad43ddacSmrg mode->Flags |= V_INTERLACE; 2416ad43ddacSmrg if (misc & ATOM_DOUBLE_CLOCK_MODE) 2417ad43ddacSmrg mode->Flags |= V_DBLSCAN; 2418ad43ddacSmrg 2419ad43ddacSmrg mode->Clock = le16_to_cpu(dtd_timings->usPixClk) * 10; 2420ad43ddacSmrg 2421b7e1c893Smrg break; 2422b7e1c893Smrg } 2423209ff23fSmrg 2424209ff23fSmrg return TRUE; 2425209ff23fSmrg} 2426209ff23fSmrg 2427b7e1c893Smrguint32_t 2428b7e1c893Smrgradeon_get_encoder_id_from_supported_device(ScrnInfoPtr pScrn, uint32_t supported_device, int dac) 2429209ff23fSmrg{ 2430209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 2431b7e1c893Smrg uint32_t ret = 0; 2432b7e1c893Smrg 2433b7e1c893Smrg switch (supported_device) { 2434b7e1c893Smrg case ATOM_DEVICE_CRT1_SUPPORT: 2435b7e1c893Smrg case ATOM_DEVICE_TV1_SUPPORT: 2436b7e1c893Smrg case ATOM_DEVICE_TV2_SUPPORT: 2437b7e1c893Smrg case ATOM_DEVICE_CRT2_SUPPORT: 2438b7e1c893Smrg case ATOM_DEVICE_CV_SUPPORT: 2439b7e1c893Smrg switch (dac) { 2440b7e1c893Smrg // primary dac 2441b7e1c893Smrg case 1: 2442b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2443b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS400) || 2444b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) 2445b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2446b7e1c893Smrg else if (IS_AVIVO_VARIANT) 2447b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 2448b7e1c893Smrg else 2449b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 2450b7e1c893Smrg break; 2451b7e1c893Smrg // secondary dac 2452b7e1c893Smrg case 2: 2453b7e1c893Smrg if (IS_AVIVO_VARIANT) 2454b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 2455b7e1c893Smrg else { 2456b7e1c893Smrg /*if (info->ChipFamily == CHIP_FAMILY_R200) 2457b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2458b7e1c893Smrg else*/ 2459b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2460b7e1c893Smrg } 2461b7e1c893Smrg break; 2462b7e1c893Smrg // external dac 2463b7e1c893Smrg case 3: 2464b7e1c893Smrg if (IS_AVIVO_VARIANT) 2465b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2466b7e1c893Smrg else 2467b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2468b7e1c893Smrg break; 2469209ff23fSmrg } 2470b7e1c893Smrg break; 2471b7e1c893Smrg case ATOM_DEVICE_LCD1_SUPPORT: 2472b7e1c893Smrg if (IS_AVIVO_VARIANT) 2473b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2474b7e1c893Smrg else 2475b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 2476b7e1c893Smrg break; 2477b7e1c893Smrg case ATOM_DEVICE_DFP1_SUPPORT: 2478b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2479b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS400) || 2480b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) 2481b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2482b7e1c893Smrg else if (IS_AVIVO_VARIANT) 2483b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 2484b7e1c893Smrg else 2485b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 2486b7e1c893Smrg break; 2487b7e1c893Smrg case ATOM_DEVICE_LCD2_SUPPORT: 2488b7e1c893Smrg case ATOM_DEVICE_DFP2_SUPPORT: 2489b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS600) || 2490b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS690) || 2491b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS740)) 2492b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 2493b7e1c893Smrg else if (IS_AVIVO_VARIANT) 2494b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2495b7e1c893Smrg else 2496b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2497b7e1c893Smrg break; 2498b7e1c893Smrg case ATOM_DEVICE_DFP3_SUPPORT: 2499b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2500b7e1c893Smrg break; 2501209ff23fSmrg } 2502209ff23fSmrg 2503b7e1c893Smrg return ret; 2504209ff23fSmrg} 2505209ff23fSmrg 2506209ff23fSmrgBool 2507209ff23fSmrgRADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn) 2508209ff23fSmrg{ 2509209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 2510209ff23fSmrg atomDataTablesPtr atomDataPtr; 2511209ff23fSmrg uint8_t crev, frev; 2512209ff23fSmrg int i, j; 2513b7e1c893Smrg Bool enable_tv = FALSE; 2514b7e1c893Smrg 2515b7e1c893Smrg if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 2516b7e1c893Smrg enable_tv = TRUE; 2517209ff23fSmrg 2518209ff23fSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 2519209ff23fSmrg 2520209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 2521209ff23fSmrg &(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader), 2522209ff23fSmrg &crev,&frev,NULL)) { 2523209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); 2524209ff23fSmrg return FALSE; 2525209ff23fSmrg } 2526209ff23fSmrg 2527209ff23fSmrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2528209ff23fSmrg ATOM_CONNECTOR_INFO_I2C ci 2529209ff23fSmrg = atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[i]; 2530209ff23fSmrg 2531209ff23fSmrg if (!(le16_to_cpu(atomDataPtr->SupportedDevicesInfo 2532209ff23fSmrg .SupportedDevicesInfo->usDeviceSupport) & (1 << i))) { 2533209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2534209ff23fSmrg continue; 2535209ff23fSmrg } 2536209ff23fSmrg 2537b7e1c893Smrg /* don't support CV yet */ 2538209ff23fSmrg if (i == ATOM_DEVICE_CV_INDEX) { 2539209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping Component Video\n"); 2540209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2541209ff23fSmrg continue; 2542209ff23fSmrg } 2543b7e1c893Smrg 2544b7e1c893Smrg if (!enable_tv && (i == ATOM_DEVICE_TV1_INDEX)) { 2545209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping TV-Out\n"); 2546209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2547209ff23fSmrg continue; 2548209ff23fSmrg } 2549209ff23fSmrg 2550209ff23fSmrg info->BiosConnector[i].valid = TRUE; 2551b7e1c893Smrg info->BiosConnector[i].load_detection = TRUE; 2552b7e1c893Smrg info->BiosConnector[i].shared_ddc = FALSE; 2553ad43ddacSmrg info->BiosConnector[i].output_id = ci.sucI2cId.ucAccess; 2554209ff23fSmrg info->BiosConnector[i].devices = (1 << i); 2555209ff23fSmrg info->BiosConnector[i].ConnectorType = ci.sucConnectorInfo.sbfAccess.bfConnectorType; 2556209ff23fSmrg 2557209ff23fSmrg if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 2558209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2559209ff23fSmrg continue; 2560209ff23fSmrg } 2561209ff23fSmrg 2562209ff23fSmrg /* don't assign a gpio for tv */ 2563209ff23fSmrg if ((i == ATOM_DEVICE_TV1_INDEX) || 2564209ff23fSmrg (i == ATOM_DEVICE_TV2_INDEX) || 2565209ff23fSmrg (i == ATOM_DEVICE_CV_INDEX)) 2566209ff23fSmrg info->BiosConnector[i].ddc_i2c.valid = FALSE; 2567ad43ddacSmrg else 2568209ff23fSmrg info->BiosConnector[i].ddc_i2c = 2569ad43ddacSmrg RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.ucAccess); 2570209ff23fSmrg 2571b7e1c893Smrg if (!radeon_add_encoder(pScrn, 2572b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, (1 << i), 2573b7e1c893Smrg ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC), 2574b7e1c893Smrg (1 << i))) 2575b7e1c893Smrg return FALSE; 2576209ff23fSmrg 2577209ff23fSmrg /* Always set the connector type to VGA for CRT1/CRT2. if they are 2578209ff23fSmrg * shared with a DVI port, we'll pick up the DVI connector below when we 2579209ff23fSmrg * merge the outputs 2580209ff23fSmrg */ 2581209ff23fSmrg if ((i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) && 2582209ff23fSmrg (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I || 2583209ff23fSmrg info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D || 2584209ff23fSmrg info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A)) { 2585209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; 2586209ff23fSmrg } 2587209ff23fSmrg 2588209ff23fSmrg if (crev > 1) { 2589209ff23fSmrg ATOM_CONNECTOR_INC_SRC_BITMAP isb 2590209ff23fSmrg = atomDataPtr->SupportedDevicesInfo 2591209ff23fSmrg .SupportedDevicesInfo_HD->asIntSrcInfo[i]; 2592209ff23fSmrg 2593209ff23fSmrg switch (isb.ucIntSrcBitmap) { 2594209ff23fSmrg case 0x4: 2595209ff23fSmrg info->BiosConnector[i].hpd_mask = 0x00000001; 2596209ff23fSmrg break; 2597209ff23fSmrg case 0xa: 2598209ff23fSmrg info->BiosConnector[i].hpd_mask = 0x00000100; 2599209ff23fSmrg break; 2600209ff23fSmrg default: 2601209ff23fSmrg info->BiosConnector[i].hpd_mask = 0; 2602209ff23fSmrg break; 2603209ff23fSmrg } 2604b7e1c893Smrg } else 2605209ff23fSmrg info->BiosConnector[i].hpd_mask = 0; 2606209ff23fSmrg 2607209ff23fSmrg RADEONApplyATOMQuirks(pScrn, i); 2608209ff23fSmrg 2609209ff23fSmrg } 2610209ff23fSmrg 2611209ff23fSmrg /* CRTs/DFPs may share a port */ 2612209ff23fSmrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2613209ff23fSmrg if (info->BiosConnector[i].valid) { 2614209ff23fSmrg for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2615209ff23fSmrg if (info->BiosConnector[j].valid && (i != j) ) { 2616209ff23fSmrg if (info->BiosConnector[i].output_id == info->BiosConnector[j].output_id) { 2617209ff23fSmrg if (((i == ATOM_DEVICE_DFP1_INDEX) || 2618209ff23fSmrg (i == ATOM_DEVICE_DFP2_INDEX) || 2619209ff23fSmrg (i == ATOM_DEVICE_DFP3_INDEX)) && 2620b7e1c893Smrg ((j == ATOM_DEVICE_CRT1_INDEX) || 2621b7e1c893Smrg (j == ATOM_DEVICE_CRT2_INDEX))) { 2622209ff23fSmrg info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2623c503f109Smrg if (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) 2624c503f109Smrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; 2625209ff23fSmrg info->BiosConnector[j].valid = FALSE; 2626209ff23fSmrg } else if (((j == ATOM_DEVICE_DFP1_INDEX) || 2627b7e1c893Smrg (j == ATOM_DEVICE_DFP2_INDEX) || 2628b7e1c893Smrg (j == ATOM_DEVICE_DFP3_INDEX)) && 2629b7e1c893Smrg ((i == ATOM_DEVICE_CRT1_INDEX) || 2630b7e1c893Smrg (i == ATOM_DEVICE_CRT2_INDEX))) { 2631209ff23fSmrg info->BiosConnector[j].devices |= info->BiosConnector[i].devices; 2632c503f109Smrg if (info->BiosConnector[j].ConnectorType == CONNECTOR_DVI_D) 2633c503f109Smrg info->BiosConnector[j].ConnectorType = CONNECTOR_DVI_I; 2634209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2635b7e1c893Smrg } else { 2636b7e1c893Smrg info->BiosConnector[i].shared_ddc = TRUE; 2637b7e1c893Smrg info->BiosConnector[j].shared_ddc = TRUE; 2638209ff23fSmrg } 2639209ff23fSmrg /* other possible combos? */ 2640209ff23fSmrg } 2641209ff23fSmrg } 2642209ff23fSmrg } 2643209ff23fSmrg } 2644209ff23fSmrg } 2645209ff23fSmrg 2646209ff23fSmrg return TRUE; 2647209ff23fSmrg} 2648209ff23fSmrg 2649209ff23fSmrg# ifdef ATOM_BIOS_PARSER 2650209ff23fSmrgstatic AtomBiosResult 2651209ff23fSmrgrhdAtomExec (atomBiosHandlePtr handle, 2652209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data) 2653209ff23fSmrg{ 2654209ff23fSmrg RADEONInfoPtr info = RADEONPTR (xf86Screens[handle->scrnIndex]); 2655209ff23fSmrg Bool ret = FALSE; 2656209ff23fSmrg char *msg; 2657209ff23fSmrg int idx = data->exec.index; 2658209ff23fSmrg void *pspace = data->exec.pspace; 2659209ff23fSmrg pointer *dataSpace = data->exec.dataSpace; 2660209ff23fSmrg 2661209ff23fSmrg //RHDFUNCI(handle->scrnIndex); 2662209ff23fSmrg 2663209ff23fSmrg if (dataSpace) { 2664209ff23fSmrg if (!handle->fbBase && !handle->scratchBase) 2665209ff23fSmrg return ATOM_FAILED; 2666209ff23fSmrg if (handle->fbBase) { 2667209ff23fSmrg if (!info->FB) { 2668209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: " 2669209ff23fSmrg "Cannot exec AtomBIOS: framebuffer not mapped\n", 2670209ff23fSmrg __func__); 2671209ff23fSmrg return ATOM_FAILED; 2672209ff23fSmrg } 2673209ff23fSmrg *dataSpace = (uint8_t*)info->FB + handle->fbBase; 2674209ff23fSmrg } else 2675209ff23fSmrg *dataSpace = (uint8_t*)handle->scratchBase; 2676209ff23fSmrg } 2677209ff23fSmrg ret = ParseTableWrapper(pspace, idx, handle, 2678209ff23fSmrg handle->BIOSBase, 2679209ff23fSmrg &msg); 2680209ff23fSmrg if (!ret) 2681209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s\n",msg); 2682209ff23fSmrg else 2683209ff23fSmrg xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 5, "%s\n",msg); 2684209ff23fSmrg 2685209ff23fSmrg return (ret) ? ATOM_SUCCESS : ATOM_FAILED; 2686209ff23fSmrg} 2687209ff23fSmrg# endif 2688209ff23fSmrg 2689209ff23fSmrgAtomBiosResult 2690209ff23fSmrgRHDAtomBiosFunc(int scrnIndex, atomBiosHandlePtr handle, 2691209ff23fSmrg AtomBiosRequestID id, AtomBiosArgPtr data) 2692209ff23fSmrg{ 2693209ff23fSmrg AtomBiosResult ret = ATOM_FAILED; 2694209ff23fSmrg int i; 2695209ff23fSmrg char *msg = NULL; 2696209ff23fSmrg enum msgDataFormat msg_f = MSG_FORMAT_NONE; 2697209ff23fSmrg AtomBiosRequestFunc req_func = NULL; 2698209ff23fSmrg 2699209ff23fSmrg //RHDFUNCI(scrnIndex); 2700209ff23fSmrg 2701209ff23fSmrg for (i = 0; AtomBiosRequestList[i].id != FUNC_END; i++) { 2702209ff23fSmrg if (id == AtomBiosRequestList[i].id) { 2703209ff23fSmrg req_func = AtomBiosRequestList[i].request; 2704209ff23fSmrg msg = AtomBiosRequestList[i].message; 2705209ff23fSmrg msg_f = AtomBiosRequestList[i].message_format; 2706209ff23fSmrg break; 2707209ff23fSmrg } 2708209ff23fSmrg } 2709209ff23fSmrg 2710209ff23fSmrg if (req_func == NULL) { 2711209ff23fSmrg xf86DrvMsg(scrnIndex, X_ERROR, "Unknown AtomBIOS request: %i\n",id); 2712209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 2713209ff23fSmrg } 2714209ff23fSmrg /* Hack for now */ 2715209ff23fSmrg if (id == ATOMBIOS_INIT) 2716209ff23fSmrg data->val = scrnIndex; 2717209ff23fSmrg 2718209ff23fSmrg if (id == ATOMBIOS_INIT || handle) 2719209ff23fSmrg ret = req_func(handle, id, data); 2720209ff23fSmrg 2721209ff23fSmrg if (ret == ATOM_SUCCESS) { 2722209ff23fSmrg 2723209ff23fSmrg switch (msg_f) { 2724209ff23fSmrg case MSG_FORMAT_DEC: 2725209ff23fSmrg xf86DrvMsg(scrnIndex,X_INFO,"%s: %li\n", msg, 2726209ff23fSmrg (unsigned long) data->val); 2727209ff23fSmrg break; 2728209ff23fSmrg case MSG_FORMAT_HEX: 2729209ff23fSmrg xf86DrvMsg(scrnIndex,X_INFO,"%s: 0x%lx\n",msg , 2730209ff23fSmrg (unsigned long) data->val); 2731209ff23fSmrg break; 2732209ff23fSmrg case MSG_FORMAT_NONE: 2733209ff23fSmrg xf86DrvMsgVerb(scrnIndex, 7, X_INFO, 2734209ff23fSmrg "Call to %s succeeded\n", msg); 2735209ff23fSmrg break; 2736209ff23fSmrg } 2737209ff23fSmrg 2738209ff23fSmrg } else { 2739209ff23fSmrg 2740209ff23fSmrg char *result = (ret == ATOM_FAILED) ? "failed" 2741209ff23fSmrg : "not implemented"; 2742209ff23fSmrg switch (msg_f) { 2743209ff23fSmrg case MSG_FORMAT_DEC: 2744209ff23fSmrg case MSG_FORMAT_HEX: 2745209ff23fSmrg xf86DrvMsgVerb(scrnIndex, 1, X_WARNING, 2746209ff23fSmrg "Call to %s %s\n", msg, result); 2747209ff23fSmrg break; 2748209ff23fSmrg case MSG_FORMAT_NONE: 2749209ff23fSmrg xf86DrvMsg(scrnIndex,X_INFO,"Query for %s: %s\n", msg, result); 2750209ff23fSmrg break; 2751209ff23fSmrg } 2752209ff23fSmrg } 2753209ff23fSmrg return ret; 2754209ff23fSmrg} 2755209ff23fSmrg 2756209ff23fSmrg# ifdef ATOM_BIOS_PARSER 2757209ff23fSmrgVOID* 2758209ff23fSmrgCailAllocateMemory(VOID *CAIL,UINT16 size) 2759209ff23fSmrg{ 2760b7e1c893Smrg void *ret; 2761209ff23fSmrg CAILFUNC(CAIL); 2762209ff23fSmrg 2763b7e1c893Smrg ret = malloc(size); 2764b7e1c893Smrg memset(ret, 0, size); 2765b7e1c893Smrg return ret; 2766209ff23fSmrg} 2767209ff23fSmrg 2768209ff23fSmrgVOID 2769209ff23fSmrgCailReleaseMemory(VOID *CAIL, VOID *addr) 2770209ff23fSmrg{ 2771209ff23fSmrg CAILFUNC(CAIL); 2772209ff23fSmrg 2773209ff23fSmrg free(addr); 2774209ff23fSmrg} 2775209ff23fSmrg 2776209ff23fSmrgVOID 2777209ff23fSmrgCailDelayMicroSeconds(VOID *CAIL, UINT32 delay) 2778209ff23fSmrg{ 2779209ff23fSmrg CAILFUNC(CAIL); 2780209ff23fSmrg 2781209ff23fSmrg usleep(delay); 2782209ff23fSmrg 2783209ff23fSmrg /*DEBUGP(xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_INFO,"Delay %i usec\n",delay));*/ 2784209ff23fSmrg} 2785209ff23fSmrg 2786209ff23fSmrgUINT32 2787209ff23fSmrgCailReadATIRegister(VOID* CAIL, UINT32 idx) 2788209ff23fSmrg{ 2789209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2790ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2791209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2792209ff23fSmrg unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2793209ff23fSmrg UINT32 ret; 2794ad43ddacSmrg UINT32 mm_reg = idx << 2; 2795209ff23fSmrg CAILFUNC(CAIL); 2796209ff23fSmrg 2797ad43ddacSmrg if (mm_reg < info->MMIOSize) 2798ad43ddacSmrg ret = INREG(mm_reg); 2799ad43ddacSmrg else { 2800ad43ddacSmrg OUTREG(RADEON_MM_INDEX, mm_reg); 2801ad43ddacSmrg ret = INREG(RADEON_MM_DATA); 2802ad43ddacSmrg } 2803ad43ddacSmrg 2804209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret));*/ 2805209ff23fSmrg return ret; 2806209ff23fSmrg} 2807209ff23fSmrg 2808209ff23fSmrgVOID 2809209ff23fSmrgCailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data) 2810209ff23fSmrg{ 2811209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2812ad43ddacSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2813209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2814209ff23fSmrg unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2815ad43ddacSmrg UINT32 mm_reg = idx << 2; 2816209ff23fSmrg CAILFUNC(CAIL); 2817209ff23fSmrg 2818ad43ddacSmrg if (mm_reg < info->MMIOSize) 2819ad43ddacSmrg OUTREG(mm_reg, data); 2820ad43ddacSmrg else { 2821ad43ddacSmrg OUTREG(RADEON_MM_INDEX, mm_reg); 2822ad43ddacSmrg OUTREG(RADEON_MM_DATA, data); 2823ad43ddacSmrg } 2824ad43ddacSmrg 2825209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx << 2,data));*/ 2826209ff23fSmrg} 2827209ff23fSmrg 2828209ff23fSmrgUINT32 2829209ff23fSmrgCailReadFBData(VOID* CAIL, UINT32 idx) 2830209ff23fSmrg{ 2831209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2832209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2833209ff23fSmrg UINT32 ret; 2834209ff23fSmrg 2835209ff23fSmrg CAILFUNC(CAIL); 2836209ff23fSmrg 2837209ff23fSmrg if (((atomBiosHandlePtr)CAIL)->fbBase) { 2838209ff23fSmrg uint8_t *FBBase = (uint8_t*)info->FB; 2839209ff23fSmrg ret = *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)); 2840209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2841209ff23fSmrg } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2842209ff23fSmrg ret = *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx); 2843209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2844209ff23fSmrg } else { 2845209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2846209ff23fSmrg "%s: no fbbase set\n",__func__); 2847209ff23fSmrg return 0; 2848209ff23fSmrg } 2849209ff23fSmrg return ret; 2850209ff23fSmrg} 2851209ff23fSmrg 2852209ff23fSmrgVOID 2853209ff23fSmrgCailWriteFBData(VOID *CAIL, UINT32 idx, UINT32 data) 2854209ff23fSmrg{ 2855209ff23fSmrg CAILFUNC(CAIL); 2856209ff23fSmrg 2857209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,data));*/ 2858209ff23fSmrg if (((atomBiosHandlePtr)CAIL)->fbBase) { 2859209ff23fSmrg uint8_t *FBBase = (uint8_t*) 2860209ff23fSmrg RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->FB; 2861209ff23fSmrg *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)) = data; 2862209ff23fSmrg } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2863209ff23fSmrg *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx) = data; 2864209ff23fSmrg } else 2865209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2866209ff23fSmrg "%s: no fbbase set\n",__func__); 2867209ff23fSmrg} 2868209ff23fSmrg 2869209ff23fSmrgULONG 2870209ff23fSmrgCailReadMC(VOID *CAIL, ULONG Address) 2871209ff23fSmrg{ 2872209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2873209ff23fSmrg ULONG ret; 2874209ff23fSmrg 2875209ff23fSmrg CAILFUNC(CAIL); 2876209ff23fSmrg 2877209ff23fSmrg ret = INMC(pScrn, Address); 2878209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2879209ff23fSmrg return ret; 2880209ff23fSmrg} 2881209ff23fSmrg 2882209ff23fSmrgVOID 2883209ff23fSmrgCailWriteMC(VOID *CAIL, ULONG Address, ULONG data) 2884209ff23fSmrg{ 2885209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2886209ff23fSmrg 2887209ff23fSmrg CAILFUNC(CAIL); 2888209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,data));*/ 2889209ff23fSmrg OUTMC(pScrn, Address, data); 2890209ff23fSmrg} 2891209ff23fSmrg 2892209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 2893209ff23fSmrg 2894209ff23fSmrgVOID 2895209ff23fSmrgCailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2896209ff23fSmrg{ 2897209ff23fSmrg pci_device_cfg_read(RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->PciInfo, 2898209ff23fSmrg ret,idx << 2 , size >> 3, NULL); 2899209ff23fSmrg} 2900209ff23fSmrg 2901209ff23fSmrgVOID 2902209ff23fSmrgCailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2903209ff23fSmrg{ 2904209ff23fSmrg pci_device_cfg_write(RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->PciInfo, 2905209ff23fSmrg src, idx << 2, size >> 3, NULL); 2906209ff23fSmrg} 2907209ff23fSmrg 2908209ff23fSmrg#else 2909209ff23fSmrg 2910209ff23fSmrgVOID 2911209ff23fSmrgCailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2912209ff23fSmrg{ 2913209ff23fSmrg PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2914209ff23fSmrg 2915209ff23fSmrg CAILFUNC(CAIL); 2916209ff23fSmrg 2917209ff23fSmrg switch (size) { 2918209ff23fSmrg case 8: 2919209ff23fSmrg *(uint8_t*)ret = pciReadByte(tag,idx << 2); 2920209ff23fSmrg break; 2921209ff23fSmrg case 16: 2922209ff23fSmrg *(uint16_t*)ret = pciReadWord(tag,idx << 2); 2923209ff23fSmrg break; 2924209ff23fSmrg case 32: 2925209ff23fSmrg *(uint32_t*)ret = pciReadLong(tag,idx << 2); 2926209ff23fSmrg break; 2927209ff23fSmrg default: 2928209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex, 2929209ff23fSmrg X_ERROR,"%s: Unsupported size: %i\n", 2930209ff23fSmrg __func__,(int)size); 2931209ff23fSmrg return; 2932209ff23fSmrg break; 2933209ff23fSmrg } 2934209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,*(unsigned int*)ret));*/ 2935209ff23fSmrg 2936209ff23fSmrg} 2937209ff23fSmrg 2938209ff23fSmrgVOID 2939209ff23fSmrgCailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2940209ff23fSmrg{ 2941209ff23fSmrg PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2942209ff23fSmrg 2943209ff23fSmrg CAILFUNC(CAIL); 2944209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,(*(unsigned int*)src)));*/ 2945209ff23fSmrg switch (size) { 2946209ff23fSmrg case 8: 2947209ff23fSmrg pciWriteByte(tag,idx << 2,*(uint8_t*)src); 2948209ff23fSmrg break; 2949209ff23fSmrg case 16: 2950209ff23fSmrg pciWriteWord(tag,idx << 2,*(uint16_t*)src); 2951209ff23fSmrg break; 2952209ff23fSmrg case 32: 2953209ff23fSmrg pciWriteLong(tag,idx << 2,*(uint32_t*)src); 2954209ff23fSmrg break; 2955209ff23fSmrg default: 2956209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2957209ff23fSmrg "%s: Unsupported size: %i\n",__func__,(int)size); 2958209ff23fSmrg break; 2959209ff23fSmrg } 2960209ff23fSmrg} 2961209ff23fSmrg#endif 2962209ff23fSmrg 2963209ff23fSmrgULONG 2964209ff23fSmrgCailReadPLL(VOID *CAIL, ULONG Address) 2965209ff23fSmrg{ 2966209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2967209ff23fSmrg ULONG ret; 2968209ff23fSmrg 2969209ff23fSmrg CAILFUNC(CAIL); 2970209ff23fSmrg 2971209ff23fSmrg ret = RADEONINPLL(pScrn, Address); 2972209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2973209ff23fSmrg return ret; 2974209ff23fSmrg} 2975209ff23fSmrg 2976209ff23fSmrgVOID 2977209ff23fSmrgCailWritePLL(VOID *CAIL, ULONG Address,ULONG Data) 2978209ff23fSmrg{ 2979209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2980209ff23fSmrg CAILFUNC(CAIL); 2981209ff23fSmrg 2982209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,Data));*/ 2983209ff23fSmrg RADEONOUTPLL(pScrn, Address, Data); 2984209ff23fSmrg} 2985209ff23fSmrg 2986209ff23fSmrgvoid 2987209ff23fSmrgatombios_get_command_table_version(atomBiosHandlePtr atomBIOS, int index, int *major, int *minor) 2988209ff23fSmrg{ 2989209ff23fSmrg ATOM_MASTER_COMMAND_TABLE *cmd_table = (void *)(atomBIOS->BIOSBase + atomBIOS->cmd_offset); 2990209ff23fSmrg ATOM_MASTER_LIST_OF_COMMAND_TABLES *table_start; 2991209ff23fSmrg ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *table_hdr; 2992209ff23fSmrg 2993209ff23fSmrg //unsigned short *ptr; 2994209ff23fSmrg unsigned short offset; 2995209ff23fSmrg 2996209ff23fSmrg table_start = &cmd_table->ListOfCommandTables; 2997209ff23fSmrg 2998209ff23fSmrg offset = *(((unsigned short *)table_start) + index); 2999209ff23fSmrg 3000209ff23fSmrg offset = le16_to_cpu(offset); 3001209ff23fSmrg table_hdr = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)(atomBIOS->BIOSBase + offset); 3002209ff23fSmrg 3003209ff23fSmrg *major = table_hdr->CommonHeader.ucTableFormatRevision; 3004209ff23fSmrg *minor = table_hdr->CommonHeader.ucTableContentRevision; 3005209ff23fSmrg} 3006209ff23fSmrg 3007209ff23fSmrg 3008b7e1c893SmrgUINT16 ATOM_BSWAP16(UINT16 x) 3009b7e1c893Smrg{ 3010b7e1c893Smrg return bswap_16(x); 3011b7e1c893Smrg} 3012b7e1c893Smrg 3013b7e1c893SmrgUINT32 ATOM_BSWAP32(UINT32 x) 3014b7e1c893Smrg{ 3015b7e1c893Smrg return bswap_32(x); 3016b7e1c893Smrg} 3017b7e1c893Smrg 3018b7e1c893Smrg 3019209ff23fSmrg#endif /* ATOM_BIOS */ 3020