radeon_atombios.c revision c503f109
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" 33209ff23fSmrg#include "radeon_atombios.h" 34209ff23fSmrg#include "radeon_atomwrapper.h" 35209ff23fSmrg#include "radeon_probe.h" 36209ff23fSmrg#include "radeon_macros.h" 37209ff23fSmrg 38209ff23fSmrg#include "ati_pciids_gen.h" 39209ff23fSmrg 40209ff23fSmrg#include "xorg-server.h" 41209ff23fSmrg 42209ff23fSmrg/* only for testing now */ 43209ff23fSmrg#include "xf86DDC.h" 44209ff23fSmrg 45209ff23fSmrgtypedef AtomBiosResult (*AtomBiosRequestFunc)(atomBiosHandlePtr handle, 46209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 47209ff23fSmrgtypedef struct rhdConnectorInfo *rhdConnectorInfoPtr; 48209ff23fSmrg 49209ff23fSmrgstatic AtomBiosResult rhdAtomInit(atomBiosHandlePtr unused1, 50209ff23fSmrg AtomBiosRequestID unused2, AtomBiosArgPtr data); 51209ff23fSmrgstatic AtomBiosResult rhdAtomTearDown(atomBiosHandlePtr handle, 52209ff23fSmrg AtomBiosRequestID unused1, AtomBiosArgPtr unused2); 53209ff23fSmrgstatic AtomBiosResult rhdAtomVramInfoQuery(atomBiosHandlePtr handle, 54209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 55209ff23fSmrgstatic AtomBiosResult rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, 56209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 57209ff23fSmrgstatic AtomBiosResult rhdAtomAllocateFbScratch(atomBiosHandlePtr handle, 58209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 59209ff23fSmrgstatic AtomBiosResult rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, 60209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 61209ff23fSmrgstatic AtomBiosResult rhdAtomCVGetTimings(atomBiosHandlePtr handle, 62209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 63209ff23fSmrgstatic AtomBiosResult rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, 64209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 65209ff23fSmrgstatic AtomBiosResult rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, 66209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 67209ff23fSmrgstatic AtomBiosResult rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, 68209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 69209ff23fSmrg/*static AtomBiosResult rhdAtomConnectorInfo(atomBiosHandlePtr handle, 70209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data);*/ 71209ff23fSmrg# ifdef ATOM_BIOS_PARSER 72209ff23fSmrgstatic AtomBiosResult rhdAtomExec(atomBiosHandlePtr handle, 73209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data); 74209ff23fSmrg# endif 75209ff23fSmrgstatic AtomBiosResult 76209ff23fSmrgrhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, 77209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data); 78209ff23fSmrg 79209ff23fSmrg 80b7e1c893Smrgstatic void 81b7e1c893SmrgRADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds); 82b7e1c893Smrg 83b7e1c893Smrg 84209ff23fSmrgenum msgDataFormat { 85209ff23fSmrg MSG_FORMAT_NONE, 86209ff23fSmrg MSG_FORMAT_HEX, 87209ff23fSmrg MSG_FORMAT_DEC 88209ff23fSmrg}; 89209ff23fSmrg 90209ff23fSmrgstruct atomBIOSRequests { 91209ff23fSmrg AtomBiosRequestID id; 92209ff23fSmrg AtomBiosRequestFunc request; 93209ff23fSmrg char *message; 94209ff23fSmrg enum msgDataFormat message_format; 95209ff23fSmrg} AtomBiosRequestList [] = { 96209ff23fSmrg {ATOMBIOS_INIT, rhdAtomInit, 97209ff23fSmrg "AtomBIOS Init", MSG_FORMAT_NONE}, 98209ff23fSmrg {ATOMBIOS_TEARDOWN, rhdAtomTearDown, 99209ff23fSmrg "AtomBIOS Teardown", MSG_FORMAT_NONE}, 100209ff23fSmrg# ifdef ATOM_BIOS_PARSER 101209ff23fSmrg {ATOMBIOS_EXEC, rhdAtomExec, 102209ff23fSmrg "AtomBIOS Exec", MSG_FORMAT_NONE}, 103209ff23fSmrg#endif 104209ff23fSmrg {ATOMBIOS_ALLOCATE_FB_SCRATCH, rhdAtomAllocateFbScratch, 105209ff23fSmrg "AtomBIOS Set FB Space", MSG_FORMAT_NONE}, 106209ff23fSmrg /*{ATOMBIOS_GET_CONNECTORS, rhdAtomConnectorInfo, 107209ff23fSmrg "AtomBIOS Get Connectors", MSG_FORMAT_NONE},*/ 108209ff23fSmrg {ATOMBIOS_GET_PANEL_MODE, rhdAtomLvdsGetTimings, 109209ff23fSmrg "AtomBIOS Get Panel Mode", MSG_FORMAT_NONE}, 110209ff23fSmrg {ATOMBIOS_GET_PANEL_EDID, rhdAtomLvdsGetTimings, 111209ff23fSmrg "AtomBIOS Get Panel EDID", MSG_FORMAT_NONE}, 112209ff23fSmrg {GET_DEFAULT_ENGINE_CLOCK, rhdAtomFirmwareInfoQuery, 113209ff23fSmrg "Default Engine Clock", MSG_FORMAT_DEC}, 114209ff23fSmrg {GET_DEFAULT_MEMORY_CLOCK, rhdAtomFirmwareInfoQuery, 115209ff23fSmrg "Default Memory Clock", MSG_FORMAT_DEC}, 116209ff23fSmrg {GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, 117209ff23fSmrg "Maximum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, 118209ff23fSmrg {GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, 119209ff23fSmrg "Minimum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, 120209ff23fSmrg {GET_MAX_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, 121209ff23fSmrg "Maximum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, 122209ff23fSmrg {GET_MIN_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, 123209ff23fSmrg "Minimum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, 124209ff23fSmrg {GET_MAX_PIXEL_CLK, rhdAtomFirmwareInfoQuery, 125209ff23fSmrg "Maximum Pixel Clock", MSG_FORMAT_DEC}, 126209ff23fSmrg {GET_REF_CLOCK, rhdAtomFirmwareInfoQuery, 127209ff23fSmrg "Reference Clock", MSG_FORMAT_DEC}, 128209ff23fSmrg {GET_FW_FB_START, rhdAtomVramInfoQuery, 129209ff23fSmrg "Start of VRAM area used by Firmware", MSG_FORMAT_HEX}, 130209ff23fSmrg {GET_FW_FB_SIZE, rhdAtomVramInfoQuery, 131209ff23fSmrg "Framebuffer space used by Firmware (kb)", MSG_FORMAT_DEC}, 132209ff23fSmrg {ATOM_TMDS_FREQUENCY, rhdAtomTmdsInfoQuery, 133209ff23fSmrg "TMDS Frequency", MSG_FORMAT_DEC}, 134209ff23fSmrg {ATOM_TMDS_PLL_CHARGE_PUMP, rhdAtomTmdsInfoQuery, 135209ff23fSmrg "TMDS PLL ChargePump", MSG_FORMAT_DEC}, 136209ff23fSmrg {ATOM_TMDS_PLL_DUTY_CYCLE, rhdAtomTmdsInfoQuery, 137209ff23fSmrg "TMDS PLL DutyCycle", MSG_FORMAT_DEC}, 138209ff23fSmrg {ATOM_TMDS_PLL_VCO_GAIN, rhdAtomTmdsInfoQuery, 139209ff23fSmrg "TMDS PLL VCO Gain", MSG_FORMAT_DEC}, 140209ff23fSmrg {ATOM_TMDS_PLL_VOLTAGE_SWING, rhdAtomTmdsInfoQuery, 141209ff23fSmrg "TMDS PLL VoltageSwing", MSG_FORMAT_DEC}, 142209ff23fSmrg {ATOM_LVDS_SUPPORTED_REFRESH_RATE, rhdAtomLvdsInfoQuery, 143209ff23fSmrg "LVDS Supported Refresh Rate", MSG_FORMAT_DEC}, 144209ff23fSmrg {ATOM_LVDS_OFF_DELAY, rhdAtomLvdsInfoQuery, 145209ff23fSmrg "LVDS Off Delay", MSG_FORMAT_DEC}, 146209ff23fSmrg {ATOM_LVDS_SEQ_DIG_ONTO_DE, rhdAtomLvdsInfoQuery, 147209ff23fSmrg "LVDS SEQ Dig onto DE", MSG_FORMAT_DEC}, 148209ff23fSmrg {ATOM_LVDS_SEQ_DE_TO_BL, rhdAtomLvdsInfoQuery, 149209ff23fSmrg "LVDS SEQ DE to BL", MSG_FORMAT_DEC}, 150209ff23fSmrg {ATOM_LVDS_DITHER, rhdAtomLvdsInfoQuery, 151209ff23fSmrg "LVDS Ditherc", MSG_FORMAT_HEX}, 152209ff23fSmrg {ATOM_LVDS_DUALLINK, rhdAtomLvdsInfoQuery, 153209ff23fSmrg "LVDS Duallink", MSG_FORMAT_HEX}, 154209ff23fSmrg {ATOM_LVDS_GREYLVL, rhdAtomLvdsInfoQuery, 155209ff23fSmrg "LVDS Grey Level", MSG_FORMAT_HEX}, 156209ff23fSmrg {ATOM_LVDS_FPDI, rhdAtomLvdsInfoQuery, 157209ff23fSmrg "LVDS FPDI", MSG_FORMAT_HEX}, 158209ff23fSmrg {ATOM_LVDS_24BIT, rhdAtomLvdsInfoQuery, 159209ff23fSmrg "LVDS 24Bit", MSG_FORMAT_HEX}, 160209ff23fSmrg {ATOM_GPIO_I2C_CLK_MASK, rhdAtomGPIOI2CInfoQuery, 161209ff23fSmrg "GPIO_I2C_Clk_Mask", MSG_FORMAT_HEX}, 162209ff23fSmrg {ATOM_DAC1_BG_ADJ, rhdAtomCompassionateDataQuery, 163209ff23fSmrg "DAC1 BG Adjustment", MSG_FORMAT_HEX}, 164209ff23fSmrg {ATOM_DAC1_DAC_ADJ, rhdAtomCompassionateDataQuery, 165209ff23fSmrg "DAC1 DAC Adjustment", MSG_FORMAT_HEX}, 166209ff23fSmrg {ATOM_DAC1_FORCE, rhdAtomCompassionateDataQuery, 167209ff23fSmrg "DAC1 Force Data", MSG_FORMAT_HEX}, 168209ff23fSmrg {ATOM_DAC2_CRTC2_BG_ADJ, rhdAtomCompassionateDataQuery, 169209ff23fSmrg "DAC2_CRTC2 BG Adjustment", MSG_FORMAT_HEX}, 170209ff23fSmrg {ATOM_DAC2_CRTC2_DAC_ADJ, rhdAtomCompassionateDataQuery, 171209ff23fSmrg "DAC2_CRTC2 DAC Adjustment", MSG_FORMAT_HEX}, 172209ff23fSmrg {ATOM_DAC2_CRTC2_FORCE, rhdAtomCompassionateDataQuery, 173209ff23fSmrg "DAC2_CRTC2 Force", MSG_FORMAT_HEX}, 174209ff23fSmrg {ATOM_DAC2_CRTC2_MUX_REG_IND,rhdAtomCompassionateDataQuery, 175209ff23fSmrg "DAC2_CRTC2 Mux Register Index", MSG_FORMAT_HEX}, 176209ff23fSmrg {ATOM_DAC2_CRTC2_MUX_REG_INFO,rhdAtomCompassionateDataQuery, 177209ff23fSmrg "DAC2_CRTC2 Mux Register Info", MSG_FORMAT_HEX}, 178209ff23fSmrg {ATOMBIOS_GET_CV_MODES, rhdAtomCVGetTimings, 179209ff23fSmrg "AtomBIOS Get CV Mode", MSG_FORMAT_NONE}, 180209ff23fSmrg {FUNC_END, NULL, 181209ff23fSmrg NULL, MSG_FORMAT_NONE} 182209ff23fSmrg}; 183209ff23fSmrg 184209ff23fSmrgenum { 185209ff23fSmrg legacyBIOSLocation = 0xC0000, 186209ff23fSmrg legacyBIOSMax = 0x10000 187209ff23fSmrg}; 188209ff23fSmrg 189209ff23fSmrg#define DEBUGP(x) {x;} 190209ff23fSmrg#define LOG_DEBUG 7 191209ff23fSmrg 192209ff23fSmrg# ifdef ATOM_BIOS_PARSER 193209ff23fSmrg 194209ff23fSmrg# define LOG_CAIL LOG_DEBUG + 1 195209ff23fSmrg 196209ff23fSmrg#if 0 197209ff23fSmrg 198209ff23fSmrgstatic void 199209ff23fSmrgRHDDebug(int scrnIndex, const char *format, ...) 200209ff23fSmrg{ 201209ff23fSmrg va_list ap; 202209ff23fSmrg 203209ff23fSmrg va_start(ap, format); 204209ff23fSmrg xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_DEBUG, format, ap); 205209ff23fSmrg va_end(ap); 206209ff23fSmrg} 207209ff23fSmrg 208209ff23fSmrgstatic void 209209ff23fSmrgRHDDebugCont(const char *format, ...) 210209ff23fSmrg{ 211209ff23fSmrg va_list ap; 212209ff23fSmrg 213209ff23fSmrg va_start(ap, format); 214209ff23fSmrg xf86VDrvMsgVerb(-1, X_NONE, LOG_DEBUG, format, ap); 215209ff23fSmrg va_end(ap); 216209ff23fSmrg} 217209ff23fSmrg 218209ff23fSmrg#endif 219209ff23fSmrg 220209ff23fSmrgstatic void 221209ff23fSmrgCailDebug(int scrnIndex, const char *format, ...) 222209ff23fSmrg{ 223209ff23fSmrg va_list ap; 224209ff23fSmrg 225209ff23fSmrg va_start(ap, format); 226209ff23fSmrg xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_CAIL, format, ap); 227209ff23fSmrg va_end(ap); 228209ff23fSmrg} 229209ff23fSmrg# define CAILFUNC(ptr) \ 230209ff23fSmrg CailDebug(((atomBiosHandlePtr)(ptr))->scrnIndex, "CAIL: %s\n", __func__) 231209ff23fSmrg 232209ff23fSmrg# endif 233209ff23fSmrg 234209ff23fSmrgstatic int 235209ff23fSmrgrhdAtomAnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr) 236209ff23fSmrg{ 237209ff23fSmrg if (le16_to_cpu(hdr->usStructureSize) == 0xaa55) 238209ff23fSmrg return FALSE; 239209ff23fSmrg 240209ff23fSmrg return TRUE; 241209ff23fSmrg} 242209ff23fSmrg 243209ff23fSmrgstatic int 244209ff23fSmrgrhdAtomAnalyzeRomHdr(unsigned char *rombase, 245209ff23fSmrg ATOM_ROM_HEADER *hdr, 246209ff23fSmrg unsigned int *data_offset, 247209ff23fSmrg unsigned int *command_offset) 248209ff23fSmrg{ 249209ff23fSmrg if (!rhdAtomAnalyzeCommonHdr(&hdr->sHeader)) { 250209ff23fSmrg return FALSE; 251209ff23fSmrg } 252209ff23fSmrg xf86DrvMsg(-1,X_NONE,"\tSubsystemVendorID: 0x%4.4x SubsystemID: 0x%4.4x\n", 253209ff23fSmrg le16_to_cpu(hdr->usSubsystemVendorID),le16_to_cpu(hdr->usSubsystemID)); 254209ff23fSmrg xf86DrvMsg(-1,X_NONE,"\tIOBaseAddress: 0x%4.4x\n",le16_to_cpu(hdr->usIoBaseAddress)); 255209ff23fSmrg xf86DrvMsgVerb(-1,X_NONE,3,"\tFilename: %s\n",rombase + le16_to_cpu(hdr->usConfigFilenameOffset)); 256209ff23fSmrg xf86DrvMsgVerb(-1,X_NONE,3,"\tBIOS Bootup Message: %s\n", 257209ff23fSmrg rombase + le16_to_cpu(hdr->usBIOS_BootupMessageOffset)); 258209ff23fSmrg 259209ff23fSmrg *data_offset = le16_to_cpu(hdr->usMasterDataTableOffset); 260209ff23fSmrg *command_offset = le16_to_cpu(hdr->usMasterCommandTableOffset); 261209ff23fSmrg 262209ff23fSmrg return TRUE; 263209ff23fSmrg} 264209ff23fSmrg 265209ff23fSmrgstatic int 266209ff23fSmrgrhdAtomAnalyzeRomDataTable(unsigned char *base, uint16_t offset, 267209ff23fSmrg void *ptr,unsigned short *size) 268209ff23fSmrg{ 269209ff23fSmrg ATOM_COMMON_TABLE_HEADER *table = (ATOM_COMMON_TABLE_HEADER *) 270209ff23fSmrg (base + le16_to_cpu(offset)); 271209ff23fSmrg 272209ff23fSmrg if (!*size || !rhdAtomAnalyzeCommonHdr(table)) { 273209ff23fSmrg if (*size) *size -= 2; 274209ff23fSmrg *(void **)ptr = NULL; 275209ff23fSmrg return FALSE; 276209ff23fSmrg } 277209ff23fSmrg *size -= 2; 278209ff23fSmrg *(void **)ptr = (void *)(table); 279209ff23fSmrg return TRUE; 280209ff23fSmrg} 281209ff23fSmrg 282209ff23fSmrgBool 283209ff23fSmrgrhdAtomGetTableRevisionAndSize(ATOM_COMMON_TABLE_HEADER *hdr, 284209ff23fSmrg uint8_t *contentRev, 285209ff23fSmrg uint8_t *formatRev, 286209ff23fSmrg unsigned short *size) 287209ff23fSmrg{ 288209ff23fSmrg if (!hdr) 289209ff23fSmrg return FALSE; 290209ff23fSmrg 291209ff23fSmrg if (contentRev) *contentRev = hdr->ucTableContentRevision; 292209ff23fSmrg if (formatRev) *formatRev = hdr->ucTableFormatRevision; 293209ff23fSmrg if (size) *size = (short)le16_to_cpu(hdr->usStructureSize) 294209ff23fSmrg - sizeof(ATOM_COMMON_TABLE_HEADER); 295209ff23fSmrg return TRUE; 296209ff23fSmrg} 297209ff23fSmrg 298209ff23fSmrgstatic Bool 299209ff23fSmrgrhdAtomAnalyzeMasterDataTable(unsigned char *base, 300209ff23fSmrg ATOM_MASTER_DATA_TABLE *table, 301209ff23fSmrg atomDataTablesPtr data) 302209ff23fSmrg{ 303209ff23fSmrg ATOM_MASTER_LIST_OF_DATA_TABLES *data_table = 304209ff23fSmrg &table->ListOfDataTables; 305209ff23fSmrg unsigned short size; 306209ff23fSmrg 307209ff23fSmrg if (!rhdAtomAnalyzeCommonHdr(&table->sHeader)) 308209ff23fSmrg return FALSE; 309209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize(&table->sHeader,NULL,NULL, 310209ff23fSmrg &size)) 311209ff23fSmrg return FALSE; 312209ff23fSmrg# define SET_DATA_TABLE(x) {\ 313209ff23fSmrg rhdAtomAnalyzeRomDataTable(base,data_table->x,(void *)(&(data->x)),&size); \ 314209ff23fSmrg } 315209ff23fSmrg 316209ff23fSmrg# define SET_DATA_TABLE_VERS(x) {\ 317209ff23fSmrg rhdAtomAnalyzeRomDataTable(base,data_table->x,&(data->x.base),&size); \ 318209ff23fSmrg } 319209ff23fSmrg 320209ff23fSmrg SET_DATA_TABLE(UtilityPipeLine); 321209ff23fSmrg SET_DATA_TABLE(MultimediaCapabilityInfo); 322209ff23fSmrg SET_DATA_TABLE(MultimediaConfigInfo); 323209ff23fSmrg SET_DATA_TABLE(StandardVESA_Timing); 324209ff23fSmrg SET_DATA_TABLE_VERS(FirmwareInfo); 325209ff23fSmrg SET_DATA_TABLE(DAC_Info); 326209ff23fSmrg SET_DATA_TABLE_VERS(LVDS_Info); 327209ff23fSmrg SET_DATA_TABLE(TMDS_Info); 328b7e1c893Smrg SET_DATA_TABLE_VERS(AnalogTV_Info); 329209ff23fSmrg SET_DATA_TABLE_VERS(SupportedDevicesInfo); 330209ff23fSmrg SET_DATA_TABLE(GPIO_I2C_Info); 331209ff23fSmrg SET_DATA_TABLE(VRAM_UsageByFirmware); 332209ff23fSmrg SET_DATA_TABLE(GPIO_Pin_LUT); 333209ff23fSmrg SET_DATA_TABLE(VESA_ToInternalModeLUT); 334209ff23fSmrg SET_DATA_TABLE_VERS(ComponentVideoInfo); 335209ff23fSmrg SET_DATA_TABLE(PowerPlayInfo); 336209ff23fSmrg SET_DATA_TABLE(CompassionateData); 337209ff23fSmrg SET_DATA_TABLE(SaveRestoreInfo); 338209ff23fSmrg SET_DATA_TABLE(PPLL_SS_Info); 339209ff23fSmrg SET_DATA_TABLE(OemInfo); 340209ff23fSmrg SET_DATA_TABLE(XTMDS_Info); 341209ff23fSmrg SET_DATA_TABLE(MclkSS_Info); 342209ff23fSmrg SET_DATA_TABLE(Object_Header); 343209ff23fSmrg SET_DATA_TABLE(IndirectIOAccess); 344209ff23fSmrg SET_DATA_TABLE(MC_InitParameter); 345209ff23fSmrg SET_DATA_TABLE(ASIC_VDDC_Info); 346209ff23fSmrg SET_DATA_TABLE(ASIC_InternalSS_Info); 347209ff23fSmrg SET_DATA_TABLE(TV_VideoMode); 348209ff23fSmrg SET_DATA_TABLE_VERS(VRAM_Info); 349209ff23fSmrg SET_DATA_TABLE(MemoryTrainingInfo); 350209ff23fSmrg SET_DATA_TABLE_VERS(IntegratedSystemInfo); 351209ff23fSmrg SET_DATA_TABLE(ASIC_ProfilingInfo); 352209ff23fSmrg SET_DATA_TABLE(VoltageObjectInfo); 353209ff23fSmrg SET_DATA_TABLE(PowerSourceInfo); 354209ff23fSmrg# undef SET_DATA_TABLE 355209ff23fSmrg 356209ff23fSmrg return TRUE; 357209ff23fSmrg} 358209ff23fSmrg 359209ff23fSmrgstatic Bool 360209ff23fSmrgrhdAtomGetDataTable(int scrnIndex, 361209ff23fSmrg unsigned char *base, 362209ff23fSmrg atomDataTables *atomDataPtr, 363209ff23fSmrg unsigned int *cmd_offset, 364209ff23fSmrg unsigned int BIOSImageSize) 365209ff23fSmrg{ 366209ff23fSmrg unsigned int data_offset; 367209ff23fSmrg unsigned int atom_romhdr_off = le16_to_cpu(*(unsigned short*) 368209ff23fSmrg (base + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); 369209ff23fSmrg ATOM_ROM_HEADER *atom_rom_hdr = 370209ff23fSmrg (ATOM_ROM_HEADER *)(base + atom_romhdr_off); 371209ff23fSmrg 372209ff23fSmrg //RHDFUNCI(scrnIndex); 373209ff23fSmrg 374209ff23fSmrg if (atom_romhdr_off + sizeof(ATOM_ROM_HEADER) > BIOSImageSize) { 375209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR, 376209ff23fSmrg "%s: AtomROM header extends beyond BIOS image\n",__func__); 377209ff23fSmrg return FALSE; 378209ff23fSmrg } 379209ff23fSmrg 380209ff23fSmrg if (memcmp("ATOM",&atom_rom_hdr->uaFirmWareSignature,4)) { 381209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"%s: No AtomBios signature found\n", 382209ff23fSmrg __func__); 383209ff23fSmrg return FALSE; 384209ff23fSmrg } 385209ff23fSmrg xf86DrvMsg(scrnIndex, X_INFO, "ATOM BIOS Rom: \n"); 386209ff23fSmrg if (!rhdAtomAnalyzeRomHdr(base, atom_rom_hdr, &data_offset, cmd_offset)) { 387209ff23fSmrg xf86DrvMsg(scrnIndex, X_ERROR, "RomHeader invalid\n"); 388209ff23fSmrg return FALSE; 389209ff23fSmrg } 390209ff23fSmrg 391209ff23fSmrg if (data_offset + sizeof (ATOM_MASTER_DATA_TABLE) > BIOSImageSize) { 392209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom data table outside of BIOS\n", 393209ff23fSmrg __func__); 394209ff23fSmrg } 395209ff23fSmrg 396209ff23fSmrg if (*cmd_offset + sizeof (ATOM_MASTER_COMMAND_TABLE) > BIOSImageSize) { 397209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom command table outside of BIOS\n", 398209ff23fSmrg __func__); 399209ff23fSmrg } 400209ff23fSmrg 401209ff23fSmrg if (!rhdAtomAnalyzeMasterDataTable(base, (ATOM_MASTER_DATA_TABLE *) 402209ff23fSmrg (base + data_offset), 403209ff23fSmrg atomDataPtr)) { 404209ff23fSmrg xf86DrvMsg(scrnIndex, X_ERROR, "%s: ROM Master Table invalid\n", 405209ff23fSmrg __func__); 406209ff23fSmrg return FALSE; 407209ff23fSmrg } 408209ff23fSmrg return TRUE; 409209ff23fSmrg} 410209ff23fSmrg 411209ff23fSmrgstatic Bool 412209ff23fSmrgrhdAtomGetFbBaseAndSize(atomBiosHandlePtr handle, unsigned int *base, 413209ff23fSmrg unsigned int *size) 414209ff23fSmrg{ 415209ff23fSmrg AtomBiosArgRec data; 416209ff23fSmrg if (RHDAtomBiosFunc(handle->scrnIndex, handle, GET_FW_FB_SIZE, &data) 417209ff23fSmrg == ATOM_SUCCESS) { 418209ff23fSmrg if (data.val == 0) { 419209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, "%s: AtomBIOS specified VRAM " 420209ff23fSmrg "scratch space size invalid\n", __func__); 421209ff23fSmrg return FALSE; 422209ff23fSmrg } 423209ff23fSmrg if (size) 424209ff23fSmrg *size = (int)data.val; 425209ff23fSmrg } else 426209ff23fSmrg return FALSE; 427209ff23fSmrg if (RHDAtomBiosFunc(handle->scrnIndex, handle, GET_FW_FB_START, &data) 428209ff23fSmrg == ATOM_SUCCESS) { 429209ff23fSmrg if (data.val == 0) 430209ff23fSmrg return FALSE; 431209ff23fSmrg if (base) 432209ff23fSmrg *base = (int)data.val; 433209ff23fSmrg } 434209ff23fSmrg return TRUE; 435209ff23fSmrg} 436209ff23fSmrg 437209ff23fSmrg/* 438209ff23fSmrg * Uses videoRam form ScrnInfoRec. 439209ff23fSmrg */ 440209ff23fSmrgstatic AtomBiosResult 441209ff23fSmrgrhdAtomAllocateFbScratch(atomBiosHandlePtr handle, 442209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 443209ff23fSmrg{ 444209ff23fSmrg unsigned int fb_base = 0; 445209ff23fSmrg unsigned int fb_size = 0; 446209ff23fSmrg unsigned int start = data->fb.start; 447209ff23fSmrg unsigned int size = data->fb.size; 448209ff23fSmrg handle->scratchBase = NULL; 449209ff23fSmrg handle->fbBase = 0; 450209ff23fSmrg 451209ff23fSmrg if (rhdAtomGetFbBaseAndSize(handle, &fb_base, &fb_size)) { 452209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS requests %ikB" 453209ff23fSmrg " of VRAM scratch space\n",fb_size); 454209ff23fSmrg fb_size *= 1024; /* convert to bytes */ 455209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS VRAM scratch base: 0x%x\n", 456209ff23fSmrg fb_base); 457209ff23fSmrg } else { 458209ff23fSmrg fb_size = 20 * 1024; 459209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, " default to: %i\n",fb_size); 460209ff23fSmrg } 461209ff23fSmrg if (fb_base && fb_size && size) { 462209ff23fSmrg /* 4k align */ 463209ff23fSmrg fb_size = (fb_size & ~(uint32_t)0xfff) + ((fb_size & 0xfff) ? 1 : 0); 464209ff23fSmrg if ((fb_base + fb_size) > (start + size)) { 465209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, 466209ff23fSmrg "%s: FW FB scratch area %i (size: %i)" 467209ff23fSmrg " extends beyond available framebuffer size %i\n", 468209ff23fSmrg __func__, fb_base, fb_size, size); 469209ff23fSmrg } else if ((fb_base + fb_size) < (start + size)) { 470209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, 471209ff23fSmrg "%s: FW FB scratch area not located " 472209ff23fSmrg "at the end of VRAM. Scratch End: " 473209ff23fSmrg "0x%x VRAM End: 0x%x\n", __func__, 474209ff23fSmrg (unsigned int)(fb_base + fb_size), 475209ff23fSmrg size); 476209ff23fSmrg } else if (fb_base < start) { 477209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_WARNING, 478209ff23fSmrg "%s: FW FB scratch area extends below " 479209ff23fSmrg "the base of the free VRAM: 0x%x Base: 0x%x\n", 480209ff23fSmrg __func__, (unsigned int)(fb_base), start); 481209ff23fSmrg } else { 482209ff23fSmrg size -= fb_size; 483209ff23fSmrg handle->fbBase = fb_base; 484209ff23fSmrg return ATOM_SUCCESS; 485209ff23fSmrg } 486209ff23fSmrg } 487209ff23fSmrg 488209ff23fSmrg if (!handle->fbBase) { 489209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, 490209ff23fSmrg "Cannot get VRAM scratch space. " 491209ff23fSmrg "Allocating in main memory instead\n"); 492209ff23fSmrg handle->scratchBase = xcalloc(fb_size,1); 493209ff23fSmrg return ATOM_SUCCESS; 494209ff23fSmrg } 495209ff23fSmrg return ATOM_FAILED; 496209ff23fSmrg} 497209ff23fSmrg 498209ff23fSmrg# ifdef ATOM_BIOS_PARSER 499209ff23fSmrgBool 500209ff23fSmrgrhdAtomASICInit(atomBiosHandlePtr handle) 501209ff23fSmrg{ 502209ff23fSmrg ASIC_INIT_PS_ALLOCATION asicInit; 503209ff23fSmrg AtomBiosArgRec data; 504209ff23fSmrg 505209ff23fSmrg RHDAtomBiosFunc(handle->scrnIndex, handle, 506209ff23fSmrg GET_DEFAULT_ENGINE_CLOCK, 507209ff23fSmrg &data); 508b7e1c893Smrg asicInit.sASICInitClocks.ulDefaultEngineClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 509209ff23fSmrg RHDAtomBiosFunc(handle->scrnIndex, handle, 510209ff23fSmrg GET_DEFAULT_MEMORY_CLOCK, 511209ff23fSmrg &data); 512b7e1c893Smrg asicInit.sASICInitClocks.ulDefaultMemoryClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 513209ff23fSmrg data.exec.dataSpace = NULL; 514209ff23fSmrg data.exec.index = 0x0; 515209ff23fSmrg data.exec.pspace = &asicInit; 516209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling ASIC Init\n"); 517209ff23fSmrg if (RHDAtomBiosFunc(handle->scrnIndex, handle, 518209ff23fSmrg ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 519209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Successful\n"); 520209ff23fSmrg return TRUE; 521209ff23fSmrg } 522209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Failed\n"); 523209ff23fSmrg return FALSE; 524209ff23fSmrg} 525209ff23fSmrg 526209ff23fSmrgint 527209ff23fSmrgatombios_dyn_clk_setup(ScrnInfoPtr pScrn, int enable) 528209ff23fSmrg{ 529209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 530209ff23fSmrg DYNAMIC_CLOCK_GATING_PS_ALLOCATION dynclk_data; 531209ff23fSmrg AtomBiosArgRec data; 532209ff23fSmrg unsigned char *space; 533209ff23fSmrg 534209ff23fSmrg dynclk_data.ucEnable = enable; 535209ff23fSmrg 536209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); 537209ff23fSmrg data.exec.dataSpace = (void *)&space; 538209ff23fSmrg data.exec.pspace = &dynclk_data; 539209ff23fSmrg 540209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 541209ff23fSmrg ErrorF("Dynamic clock gating %s success\n", enable? "enable" : "disable"); 542209ff23fSmrg return ATOM_SUCCESS; 543209ff23fSmrg } 544209ff23fSmrg 545209ff23fSmrg ErrorF("Dynamic clock gating %s failure\n", enable? "enable" : "disable"); 546209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 547209ff23fSmrg 548209ff23fSmrg} 549209ff23fSmrg 550209ff23fSmrgint 551209ff23fSmrgatombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, int enable) 552209ff23fSmrg{ 553209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 554209ff23fSmrg ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION pwrmgt_data; 555209ff23fSmrg AtomBiosArgRec data; 556209ff23fSmrg unsigned char *space; 557209ff23fSmrg 558209ff23fSmrg pwrmgt_data.ucEnable = enable; 559209ff23fSmrg 560209ff23fSmrg data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt); 561209ff23fSmrg data.exec.dataSpace = (void *)&space; 562209ff23fSmrg data.exec.pspace = &pwrmgt_data; 563209ff23fSmrg 564209ff23fSmrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 565209ff23fSmrg ErrorF("Static power management %s success\n", enable? "enable" : "disable"); 566209ff23fSmrg return ATOM_SUCCESS; 567209ff23fSmrg } 568209ff23fSmrg 569209ff23fSmrg ErrorF("Static power management %s failure\n", enable? "enable" : "disable"); 570209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 571209ff23fSmrg 572209ff23fSmrg} 573209ff23fSmrg 574209ff23fSmrg# endif 575209ff23fSmrg 576209ff23fSmrgstatic AtomBiosResult 577209ff23fSmrgrhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2, 578209ff23fSmrg AtomBiosArgPtr data) 579209ff23fSmrg{ 580209ff23fSmrg int scrnIndex = data->val; 581209ff23fSmrg RADEONInfoPtr info = RADEONPTR(xf86Screens[scrnIndex]); 582209ff23fSmrg atomDataTablesPtr atomDataPtr; 583209ff23fSmrg unsigned int cmd_offset; 584209ff23fSmrg atomBiosHandlePtr handle = NULL; 585209ff23fSmrg unsigned int BIOSImageSize = 0; 586209ff23fSmrg data->atomhandle = NULL; 587209ff23fSmrg 588209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 589209ff23fSmrg BIOSImageSize = info->PciInfo->rom_size > RADEON_VBIOS_SIZE ? info->PciInfo->rom_size : RADEON_VBIOS_SIZE; 590209ff23fSmrg#else 591209ff23fSmrg BIOSImageSize = RADEON_VBIOS_SIZE; 592209ff23fSmrg#endif 593209ff23fSmrg 594209ff23fSmrg if (!(atomDataPtr = xcalloc(1, sizeof(atomDataTables)))) { 595209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory for " 596209ff23fSmrg "ATOM BIOS data tabes\n"); 597209ff23fSmrg goto error; 598209ff23fSmrg } 599209ff23fSmrg if (!rhdAtomGetDataTable(scrnIndex, info->VBIOS, atomDataPtr, &cmd_offset, BIOSImageSize)) 600209ff23fSmrg goto error1; 601209ff23fSmrg if (!(handle = xcalloc(1, sizeof(atomBiosHandleRec)))) { 602209ff23fSmrg xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory\n"); 603209ff23fSmrg goto error1; 604209ff23fSmrg } 605209ff23fSmrg handle->BIOSBase = info->VBIOS; 606209ff23fSmrg handle->atomDataPtr = atomDataPtr; 607209ff23fSmrg handle->cmd_offset = cmd_offset; 608209ff23fSmrg handle->scrnIndex = scrnIndex; 609209ff23fSmrg#if XSERVER_LIBPCIACCESS 610209ff23fSmrg handle->device = info->PciInfo; 611209ff23fSmrg#else 612209ff23fSmrg handle->PciTag = info->PciTag; 613209ff23fSmrg#endif 614209ff23fSmrg handle->BIOSImageSize = BIOSImageSize; 615209ff23fSmrg 616209ff23fSmrg data->atomhandle = handle; 617209ff23fSmrg return ATOM_SUCCESS; 618209ff23fSmrg 619209ff23fSmrg error1: 620209ff23fSmrg xfree(atomDataPtr); 621209ff23fSmrg error: 622209ff23fSmrg return ATOM_FAILED; 623209ff23fSmrg} 624209ff23fSmrg 625209ff23fSmrgstatic AtomBiosResult 626209ff23fSmrgrhdAtomTearDown(atomBiosHandlePtr handle, 627209ff23fSmrg AtomBiosRequestID unused1, AtomBiosArgPtr unused2) 628209ff23fSmrg{ 629209ff23fSmrg //RHDFUNC(handle); 630209ff23fSmrg 631209ff23fSmrg xfree(handle->BIOSBase); 632209ff23fSmrg xfree(handle->atomDataPtr); 633209ff23fSmrg if (handle->scratchBase) xfree(handle->scratchBase); 634209ff23fSmrg xfree(handle); 635209ff23fSmrg return ATOM_SUCCESS; 636209ff23fSmrg} 637209ff23fSmrg 638209ff23fSmrgstatic AtomBiosResult 639209ff23fSmrgrhdAtomVramInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func, 640209ff23fSmrg AtomBiosArgPtr data) 641209ff23fSmrg{ 642209ff23fSmrg atomDataTablesPtr atomDataPtr; 643209ff23fSmrg uint32_t *val = &data->val; 644209ff23fSmrg //RHDFUNC(handle); 645209ff23fSmrg 646209ff23fSmrg atomDataPtr = handle->atomDataPtr; 647209ff23fSmrg 648209ff23fSmrg switch (func) { 649209ff23fSmrg case GET_FW_FB_START: 650b7e1c893Smrg if (atomDataPtr->VRAM_UsageByFirmware) 651b7e1c893Smrg *val = le32_to_cpu(atomDataPtr->VRAM_UsageByFirmware 652b7e1c893Smrg ->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware); 653b7e1c893Smrg else 654b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 655209ff23fSmrg break; 656209ff23fSmrg case GET_FW_FB_SIZE: 657b7e1c893Smrg if (atomDataPtr->VRAM_UsageByFirmware) 658b7e1c893Smrg *val = le16_to_cpu(atomDataPtr->VRAM_UsageByFirmware 659b7e1c893Smrg ->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); 660b7e1c893Smrg else 661b7e1c893Smrg return ATOM_NOT_IMPLEMENTED; 662209ff23fSmrg break; 663209ff23fSmrg default: 664209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 665209ff23fSmrg } 666209ff23fSmrg return ATOM_SUCCESS; 667209ff23fSmrg} 668209ff23fSmrg 669209ff23fSmrgstatic AtomBiosResult 670209ff23fSmrgrhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, 671209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 672209ff23fSmrg{ 673209ff23fSmrg atomDataTablesPtr atomDataPtr; 674209ff23fSmrg uint32_t *val = &data->val; 675209ff23fSmrg int idx = *val; 676209ff23fSmrg 677209ff23fSmrg atomDataPtr = handle->atomDataPtr; 678209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 679209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->TMDS_Info), 680209ff23fSmrg NULL,NULL,NULL)) { 681209ff23fSmrg return ATOM_FAILED; 682209ff23fSmrg } 683209ff23fSmrg 684209ff23fSmrg //RHDFUNC(handle); 685209ff23fSmrg 686209ff23fSmrg switch (func) { 687209ff23fSmrg case ATOM_TMDS_FREQUENCY: 688209ff23fSmrg *val = le16_to_cpu(atomDataPtr->TMDS_Info->asMiscInfo[idx].usFrequency); 689209ff23fSmrg break; 690209ff23fSmrg case ATOM_TMDS_PLL_CHARGE_PUMP: 691209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_ChargePump; 692209ff23fSmrg break; 693209ff23fSmrg case ATOM_TMDS_PLL_DUTY_CYCLE: 694209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_DutyCycle; 695209ff23fSmrg break; 696209ff23fSmrg case ATOM_TMDS_PLL_VCO_GAIN: 697209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_VCO_Gain; 698209ff23fSmrg break; 699209ff23fSmrg case ATOM_TMDS_PLL_VOLTAGE_SWING: 700209ff23fSmrg *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_VoltageSwing; 701209ff23fSmrg break; 702209ff23fSmrg default: 703209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 704209ff23fSmrg } 705209ff23fSmrg return ATOM_SUCCESS; 706209ff23fSmrg} 707209ff23fSmrg 708209ff23fSmrgstatic DisplayModePtr 709209ff23fSmrgrhdAtomDTDTimings(atomBiosHandlePtr handle, ATOM_DTD_FORMAT *dtd) 710209ff23fSmrg{ 711209ff23fSmrg DisplayModePtr mode; 712209ff23fSmrg#define NAME_LEN 16 713209ff23fSmrg char name[NAME_LEN]; 714209ff23fSmrg 715209ff23fSmrg //RHDFUNC(handle); 716209ff23fSmrg 717209ff23fSmrg if (!dtd->usHActive || !dtd->usVActive) 718209ff23fSmrg return NULL; 719209ff23fSmrg 720209ff23fSmrg if (!(mode = (DisplayModePtr)xcalloc(1,sizeof(DisplayModeRec)))) 721209ff23fSmrg return NULL; 722209ff23fSmrg 723209ff23fSmrg mode->CrtcHDisplay = mode->HDisplay = le16_to_cpu(dtd->usHActive); 724209ff23fSmrg mode->CrtcVDisplay = mode->VDisplay = le16_to_cpu(dtd->usVActive); 725209ff23fSmrg mode->CrtcHBlankStart = dtd->usHActive + dtd->ucHBorder; 726209ff23fSmrg mode->CrtcHBlankEnd = mode->CrtcHBlankStart + le16_to_cpu(dtd->usHBlanking_Time); 727209ff23fSmrg mode->CrtcHTotal = mode->HTotal = mode->CrtcHBlankEnd + dtd->ucHBorder; 728209ff23fSmrg mode->CrtcVBlankStart = dtd->usVActive + dtd->ucVBorder; 729209ff23fSmrg mode->CrtcVBlankEnd = mode->CrtcVBlankStart + le16_to_cpu(dtd->usVBlanking_Time); 730209ff23fSmrg mode->CrtcVTotal = mode->VTotal = mode->CrtcVBlankEnd + dtd->ucVBorder; 731209ff23fSmrg mode->CrtcHSyncStart = mode->HSyncStart = dtd->usHActive + le16_to_cpu(dtd->usHSyncOffset); 732209ff23fSmrg mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + le16_to_cpu(dtd->usHSyncWidth); 733209ff23fSmrg mode->CrtcVSyncStart = mode->VSyncStart = dtd->usVActive + le16_to_cpu(dtd->usVSyncOffset); 734209ff23fSmrg mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + le16_to_cpu(dtd->usVSyncWidth); 735209ff23fSmrg 736209ff23fSmrg mode->SynthClock = mode->Clock = le16_to_cpu(dtd->usPixClk) * 10; 737209ff23fSmrg 738209ff23fSmrg mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal); 739209ff23fSmrg mode->VRefresh = (1000.0 * ((float) mode->Clock)) 740209ff23fSmrg / ((float)(((float)mode->HTotal) * ((float)mode->VTotal))); 741209ff23fSmrg 742209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.CompositeSync) 743209ff23fSmrg mode->Flags |= V_CSYNC; 744209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.Interlace) 745209ff23fSmrg mode->Flags |= V_INTERLACE; 746209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.DoubleClock) 747209ff23fSmrg mode->Flags |= V_DBLSCAN; 748209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.VSyncPolarity) 749209ff23fSmrg mode->Flags |= V_NVSYNC; 750209ff23fSmrg if (dtd->susModeMiscInfo.sbfAccess.HSyncPolarity) 751209ff23fSmrg mode->Flags |= V_NHSYNC; 752209ff23fSmrg 753209ff23fSmrg snprintf(name, NAME_LEN, "%dx%d", 754209ff23fSmrg mode->HDisplay, mode->VDisplay); 755209ff23fSmrg mode->name = xstrdup(name); 756209ff23fSmrg 757209ff23fSmrg ErrorF("DTD Modeline: %s " 758209ff23fSmrg "%2.d %i (%i) %i %i (%i) %i %i (%i) %i %i (%i) %i flags: 0x%x\n", 759209ff23fSmrg mode->name, mode->Clock, 760209ff23fSmrg mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd, 761209ff23fSmrg mode->CrtcHBlankEnd, mode->HTotal, 762209ff23fSmrg mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd, 763209ff23fSmrg mode->CrtcVBlankEnd, mode->VTotal, mode->Flags); 764209ff23fSmrg 765209ff23fSmrg return mode; 766209ff23fSmrg} 767209ff23fSmrg 768209ff23fSmrgstatic unsigned char* 769209ff23fSmrgrhdAtomLvdsDDC(atomBiosHandlePtr handle, uint32_t offset, unsigned char *record) 770209ff23fSmrg{ 771209ff23fSmrg unsigned char *EDIDBlock; 772209ff23fSmrg 773209ff23fSmrg //RHDFUNC(handle); 774209ff23fSmrg 775209ff23fSmrg while (*record != ATOM_RECORD_END_TYPE) { 776209ff23fSmrg 777209ff23fSmrg switch (*record) { 778209ff23fSmrg case LCD_MODE_PATCH_RECORD_MODE_TYPE: 779209ff23fSmrg offset += sizeof(ATOM_PATCH_RECORD_MODE); 780209ff23fSmrg if (offset > handle->BIOSImageSize) break; 781209ff23fSmrg record += sizeof(ATOM_PATCH_RECORD_MODE); 782209ff23fSmrg break; 783209ff23fSmrg 784209ff23fSmrg case LCD_RTS_RECORD_TYPE: 785209ff23fSmrg offset += sizeof(ATOM_LCD_RTS_RECORD); 786209ff23fSmrg if (offset > handle->BIOSImageSize) break; 787209ff23fSmrg record += sizeof(ATOM_LCD_RTS_RECORD); 788209ff23fSmrg break; 789209ff23fSmrg 790209ff23fSmrg case LCD_CAP_RECORD_TYPE: 791209ff23fSmrg offset += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 792209ff23fSmrg if (offset > handle->BIOSImageSize) break; 793209ff23fSmrg record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 794209ff23fSmrg break; 795209ff23fSmrg 796209ff23fSmrg case LCD_FAKE_EDID_PATCH_RECORD_TYPE: 797209ff23fSmrg offset += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); 798209ff23fSmrg /* check if the structure still fully lives in the BIOS image */ 799209ff23fSmrg if (offset > handle->BIOSImageSize) break; 800209ff23fSmrg offset += ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength 801209ff23fSmrg - sizeof(UCHAR); 802209ff23fSmrg if (offset > handle->BIOSImageSize) break; 803209ff23fSmrg /* dup string as we free it later */ 804209ff23fSmrg if (!(EDIDBlock = (unsigned char *)xalloc( 805209ff23fSmrg ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength))) 806209ff23fSmrg return NULL; 807209ff23fSmrg memcpy(EDIDBlock,&((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDString, 808209ff23fSmrg ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength); 809209ff23fSmrg 810209ff23fSmrg /* for testing */ 811209ff23fSmrg { 812209ff23fSmrg xf86MonPtr mon = xf86InterpretEDID(handle->scrnIndex,EDIDBlock); 813209ff23fSmrg xf86PrintEDID(mon); 814209ff23fSmrg xfree(mon); 815209ff23fSmrg } 816209ff23fSmrg return EDIDBlock; 817209ff23fSmrg 818209ff23fSmrg case LCD_PANEL_RESOLUTION_RECORD_TYPE: 819209ff23fSmrg offset += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 820209ff23fSmrg if (offset > handle->BIOSImageSize) break; 821209ff23fSmrg record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 822209ff23fSmrg break; 823209ff23fSmrg 824209ff23fSmrg default: 825209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, 826209ff23fSmrg "%s: unknown record type: %x\n",__func__,*record); 827209ff23fSmrg return NULL; 828209ff23fSmrg } 829209ff23fSmrg } 830209ff23fSmrg 831209ff23fSmrg return NULL; 832209ff23fSmrg} 833209ff23fSmrg 834209ff23fSmrgstatic AtomBiosResult 835209ff23fSmrgrhdAtomCVGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, 836209ff23fSmrg AtomBiosArgPtr data) 837209ff23fSmrg{ 838209ff23fSmrg atomDataTablesPtr atomDataPtr; 839209ff23fSmrg uint8_t crev, frev; 840209ff23fSmrg DisplayModePtr last = NULL; 841209ff23fSmrg DisplayModePtr new = NULL; 842209ff23fSmrg DisplayModePtr first = NULL; 843209ff23fSmrg int i; 844209ff23fSmrg 845209ff23fSmrg data->modes = NULL; 846209ff23fSmrg 847209ff23fSmrg atomDataPtr = handle->atomDataPtr; 848209ff23fSmrg 849209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 850209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->ComponentVideoInfo.base), 851209ff23fSmrg &frev,&crev,NULL)) { 852209ff23fSmrg return ATOM_FAILED; 853209ff23fSmrg } 854209ff23fSmrg 855209ff23fSmrg switch (frev) { 856209ff23fSmrg 857209ff23fSmrg case 1: 858209ff23fSmrg switch (func) { 859209ff23fSmrg case ATOMBIOS_GET_CV_MODES: 860209ff23fSmrg for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { 861209ff23fSmrg new = rhdAtomDTDTimings(handle, 862209ff23fSmrg &atomDataPtr->ComponentVideoInfo 863209ff23fSmrg .ComponentVideoInfo->aModeTimings[i]); 864209ff23fSmrg 865209ff23fSmrg if (!new) 866209ff23fSmrg continue; 867209ff23fSmrg 868209ff23fSmrg new->type |= M_T_DRIVER; 869209ff23fSmrg new->next = NULL; 870209ff23fSmrg new->prev = last; 871209ff23fSmrg 872209ff23fSmrg if (last) last->next = new; 873209ff23fSmrg last = new; 874209ff23fSmrg if (!first) first = new; 875209ff23fSmrg } 876209ff23fSmrg if (last) { 877209ff23fSmrg last->next = NULL; //first; 878209ff23fSmrg first->prev = NULL; //last; 879209ff23fSmrg data->modes = first; 880209ff23fSmrg } 881209ff23fSmrg if (data->modes) 882209ff23fSmrg return ATOM_SUCCESS; 883209ff23fSmrg default: 884209ff23fSmrg return ATOM_FAILED; 885209ff23fSmrg } 886209ff23fSmrg case 2: 887209ff23fSmrg switch (func) { 888209ff23fSmrg case ATOMBIOS_GET_CV_MODES: 889209ff23fSmrg for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { 890209ff23fSmrg new = rhdAtomDTDTimings(handle, 891209ff23fSmrg &atomDataPtr->ComponentVideoInfo 892209ff23fSmrg .ComponentVideoInfo_v21->aModeTimings[i]); 893209ff23fSmrg 894209ff23fSmrg if (!new) 895209ff23fSmrg continue; 896209ff23fSmrg 897209ff23fSmrg new->type |= M_T_DRIVER; 898209ff23fSmrg new->next = NULL; 899209ff23fSmrg new->prev = last; 900209ff23fSmrg 901209ff23fSmrg if (last) last->next = new; 902209ff23fSmrg last = new; 903209ff23fSmrg if (!first) first = new; 904209ff23fSmrg 905209ff23fSmrg } 906209ff23fSmrg if (last) { 907209ff23fSmrg last->next = NULL; //first; 908209ff23fSmrg first->prev = NULL; //last; 909209ff23fSmrg data->modes = first; 910209ff23fSmrg } 911209ff23fSmrg if (data->modes) 912209ff23fSmrg return ATOM_SUCCESS; 913209ff23fSmrg return ATOM_FAILED; 914209ff23fSmrg 915209ff23fSmrg default: 916209ff23fSmrg return ATOM_FAILED; 917209ff23fSmrg } 918209ff23fSmrg default: 919209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 920209ff23fSmrg } 921209ff23fSmrg/*NOTREACHED*/ 922209ff23fSmrg} 923209ff23fSmrg 924209ff23fSmrgstatic AtomBiosResult 925209ff23fSmrgrhdAtomLvdsGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, 926209ff23fSmrg AtomBiosArgPtr data) 927209ff23fSmrg{ 928209ff23fSmrg atomDataTablesPtr atomDataPtr; 929209ff23fSmrg uint8_t crev, frev; 930209ff23fSmrg unsigned long offset; 931209ff23fSmrg 932209ff23fSmrg //RHDFUNC(handle); 933209ff23fSmrg 934209ff23fSmrg atomDataPtr = handle->atomDataPtr; 935209ff23fSmrg 936209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 937209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 938209ff23fSmrg &frev,&crev,NULL)) { 939209ff23fSmrg return ATOM_FAILED; 940209ff23fSmrg } 941209ff23fSmrg 942209ff23fSmrg switch (crev) { 943209ff23fSmrg 944209ff23fSmrg case 1: 945209ff23fSmrg switch (func) { 946209ff23fSmrg case ATOMBIOS_GET_PANEL_MODE: 947209ff23fSmrg data->modes = rhdAtomDTDTimings(handle, 948209ff23fSmrg &atomDataPtr->LVDS_Info 949209ff23fSmrg .LVDS_Info->sLCDTiming); 950209ff23fSmrg if (data->modes) 951209ff23fSmrg return ATOM_SUCCESS; 952209ff23fSmrg default: 953209ff23fSmrg return ATOM_FAILED; 954209ff23fSmrg } 955209ff23fSmrg case 2: 956209ff23fSmrg switch (func) { 957209ff23fSmrg case ATOMBIOS_GET_PANEL_MODE: 958209ff23fSmrg data->modes = rhdAtomDTDTimings(handle, 959209ff23fSmrg &atomDataPtr->LVDS_Info 960209ff23fSmrg .LVDS_Info_v12->sLCDTiming); 961209ff23fSmrg if (data->modes) 962209ff23fSmrg return ATOM_SUCCESS; 963209ff23fSmrg return ATOM_FAILED; 964209ff23fSmrg 965209ff23fSmrg case ATOMBIOS_GET_PANEL_EDID: 966209ff23fSmrg offset = (unsigned long)&atomDataPtr->LVDS_Info.base 967209ff23fSmrg - (unsigned long)handle->BIOSBase 968209ff23fSmrg + le16_to_cpu(atomDataPtr->LVDS_Info 969209ff23fSmrg .LVDS_Info_v12->usExtInfoTableOffset); 970209ff23fSmrg 971209ff23fSmrg data->EDIDBlock 972209ff23fSmrg = rhdAtomLvdsDDC(handle, offset, 973209ff23fSmrg (unsigned char *) 974209ff23fSmrg &atomDataPtr->LVDS_Info.base 975209ff23fSmrg + le16_to_cpu(atomDataPtr->LVDS_Info 976209ff23fSmrg .LVDS_Info_v12->usExtInfoTableOffset)); 977209ff23fSmrg if (data->EDIDBlock) 978209ff23fSmrg return ATOM_SUCCESS; 979209ff23fSmrg default: 980209ff23fSmrg return ATOM_FAILED; 981209ff23fSmrg } 982209ff23fSmrg default: 983209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 984209ff23fSmrg } 985209ff23fSmrg/*NOTREACHED*/ 986209ff23fSmrg} 987209ff23fSmrg 988209ff23fSmrgstatic AtomBiosResult 989209ff23fSmrgrhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, 990209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 991209ff23fSmrg{ 992209ff23fSmrg atomDataTablesPtr atomDataPtr; 993209ff23fSmrg uint8_t crev, frev; 994209ff23fSmrg uint32_t *val = &data->val; 995209ff23fSmrg 996209ff23fSmrg //RHDFUNC(handle); 997209ff23fSmrg 998209ff23fSmrg atomDataPtr = handle->atomDataPtr; 999209ff23fSmrg 1000209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1001209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 1002209ff23fSmrg &frev,&crev,NULL)) { 1003209ff23fSmrg return ATOM_FAILED; 1004209ff23fSmrg } 1005209ff23fSmrg 1006209ff23fSmrg switch (crev) { 1007209ff23fSmrg case 1: 1008209ff23fSmrg switch (func) { 1009209ff23fSmrg case ATOM_LVDS_SUPPORTED_REFRESH_RATE: 1010209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1011209ff23fSmrg .LVDS_Info->usSupportedRefreshRate); 1012209ff23fSmrg break; 1013209ff23fSmrg case ATOM_LVDS_OFF_DELAY: 1014209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1015209ff23fSmrg .LVDS_Info->usOffDelayInMs); 1016209ff23fSmrg break; 1017209ff23fSmrg case ATOM_LVDS_SEQ_DIG_ONTO_DE: 1018209ff23fSmrg *val = atomDataPtr->LVDS_Info 1019209ff23fSmrg .LVDS_Info->ucPowerSequenceDigOntoDEin10Ms * 10; 1020209ff23fSmrg break; 1021209ff23fSmrg case ATOM_LVDS_SEQ_DE_TO_BL: 1022209ff23fSmrg *val = atomDataPtr->LVDS_Info 1023209ff23fSmrg .LVDS_Info->ucPowerSequenceDEtoBLOnin10Ms * 10; 1024209ff23fSmrg break; 1025209ff23fSmrg case ATOM_LVDS_DITHER: 1026209ff23fSmrg *val = atomDataPtr->LVDS_Info 1027209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x40; 1028209ff23fSmrg break; 1029209ff23fSmrg case ATOM_LVDS_DUALLINK: 1030209ff23fSmrg *val = atomDataPtr->LVDS_Info 1031209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x01; 1032209ff23fSmrg break; 1033209ff23fSmrg case ATOM_LVDS_24BIT: 1034209ff23fSmrg *val = atomDataPtr->LVDS_Info 1035209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x02; 1036209ff23fSmrg break; 1037209ff23fSmrg case ATOM_LVDS_GREYLVL: 1038209ff23fSmrg *val = atomDataPtr->LVDS_Info 1039209ff23fSmrg .LVDS_Info->ucLVDS_Misc & 0x0C; 1040209ff23fSmrg break; 1041209ff23fSmrg case ATOM_LVDS_FPDI: 1042209ff23fSmrg *val = atomDataPtr->LVDS_Info 1043209ff23fSmrg .LVDS_Info->ucLVDS_Misc * 0x10; 1044209ff23fSmrg break; 1045209ff23fSmrg default: 1046209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1047209ff23fSmrg } 1048209ff23fSmrg break; 1049209ff23fSmrg case 2: 1050209ff23fSmrg switch (func) { 1051209ff23fSmrg case ATOM_LVDS_SUPPORTED_REFRESH_RATE: 1052209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1053209ff23fSmrg .LVDS_Info_v12->usSupportedRefreshRate); 1054209ff23fSmrg break; 1055209ff23fSmrg case ATOM_LVDS_OFF_DELAY: 1056209ff23fSmrg *val = le16_to_cpu(atomDataPtr->LVDS_Info 1057209ff23fSmrg .LVDS_Info_v12->usOffDelayInMs); 1058209ff23fSmrg break; 1059209ff23fSmrg case ATOM_LVDS_SEQ_DIG_ONTO_DE: 1060209ff23fSmrg *val = atomDataPtr->LVDS_Info 1061209ff23fSmrg .LVDS_Info_v12->ucPowerSequenceDigOntoDEin10Ms * 10; 1062209ff23fSmrg break; 1063209ff23fSmrg case ATOM_LVDS_SEQ_DE_TO_BL: 1064209ff23fSmrg *val = atomDataPtr->LVDS_Info 1065209ff23fSmrg .LVDS_Info_v12->ucPowerSequenceDEtoBLOnin10Ms * 10; 1066209ff23fSmrg break; 1067209ff23fSmrg case ATOM_LVDS_DITHER: 1068209ff23fSmrg *val = atomDataPtr->LVDS_Info 1069209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x40; 1070209ff23fSmrg break; 1071209ff23fSmrg case ATOM_LVDS_DUALLINK: 1072209ff23fSmrg *val = atomDataPtr->LVDS_Info 1073209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x01; 1074209ff23fSmrg break; 1075209ff23fSmrg case ATOM_LVDS_24BIT: 1076209ff23fSmrg *val = atomDataPtr->LVDS_Info 1077209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x02; 1078209ff23fSmrg break; 1079209ff23fSmrg case ATOM_LVDS_GREYLVL: 1080209ff23fSmrg *val = atomDataPtr->LVDS_Info 1081209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc & 0x0C; 1082209ff23fSmrg break; 1083209ff23fSmrg case ATOM_LVDS_FPDI: 1084209ff23fSmrg *val = atomDataPtr->LVDS_Info 1085209ff23fSmrg .LVDS_Info_v12->ucLVDS_Misc * 0x10; 1086209ff23fSmrg break; 1087209ff23fSmrg default: 1088209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1089209ff23fSmrg } 1090209ff23fSmrg break; 1091209ff23fSmrg default: 1092209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1093209ff23fSmrg } 1094209ff23fSmrg 1095209ff23fSmrg return ATOM_SUCCESS; 1096209ff23fSmrg} 1097209ff23fSmrg 1098209ff23fSmrgstatic AtomBiosResult 1099209ff23fSmrgrhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, 1100209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1101209ff23fSmrg{ 1102209ff23fSmrg atomDataTablesPtr atomDataPtr; 1103209ff23fSmrg uint8_t crev, frev; 1104209ff23fSmrg uint32_t *val = &data->val; 1105209ff23fSmrg 1106209ff23fSmrg //RHDFUNC(handle); 1107209ff23fSmrg 1108209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1109209ff23fSmrg 1110209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1111209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->CompassionateData), 1112209ff23fSmrg &frev,&crev,NULL)) { 1113209ff23fSmrg return ATOM_FAILED; 1114209ff23fSmrg } 1115209ff23fSmrg 1116209ff23fSmrg switch (func) { 1117209ff23fSmrg case ATOM_DAC1_BG_ADJ: 1118209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1119209ff23fSmrg ucDAC1_BG_Adjustment; 1120209ff23fSmrg break; 1121209ff23fSmrg case ATOM_DAC1_DAC_ADJ: 1122209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1123209ff23fSmrg ucDAC1_DAC_Adjustment; 1124209ff23fSmrg break; 1125209ff23fSmrg case ATOM_DAC1_FORCE: 1126209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1127209ff23fSmrg usDAC1_FORCE_Data; 1128209ff23fSmrg break; 1129209ff23fSmrg case ATOM_DAC2_CRTC2_BG_ADJ: 1130209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1131209ff23fSmrg ucDAC2_CRT2_BG_Adjustment; 1132209ff23fSmrg break; 1133209ff23fSmrg case ATOM_DAC2_CRTC2_DAC_ADJ: 1134209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1135209ff23fSmrg ucDAC2_CRT2_DAC_Adjustment; 1136209ff23fSmrg break; 1137209ff23fSmrg case ATOM_DAC2_CRTC2_FORCE: 1138209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1139209ff23fSmrg usDAC2_CRT2_FORCE_Data; 1140209ff23fSmrg break; 1141209ff23fSmrg case ATOM_DAC2_CRTC2_MUX_REG_IND: 1142209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1143209ff23fSmrg usDAC2_CRT2_MUX_RegisterIndex; 1144209ff23fSmrg break; 1145209ff23fSmrg case ATOM_DAC2_CRTC2_MUX_REG_INFO: 1146209ff23fSmrg *val = atomDataPtr->CompassionateData-> 1147209ff23fSmrg ucDAC2_CRT2_MUX_RegisterInfo; 1148209ff23fSmrg break; 1149209ff23fSmrg default: 1150209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1151209ff23fSmrg } 1152209ff23fSmrg return ATOM_SUCCESS; 1153209ff23fSmrg} 1154209ff23fSmrg 1155209ff23fSmrgstatic AtomBiosResult 1156209ff23fSmrgrhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, 1157209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1158209ff23fSmrg{ 1159209ff23fSmrg atomDataTablesPtr atomDataPtr; 1160209ff23fSmrg uint8_t crev, frev; 1161209ff23fSmrg uint32_t *val = &data->val; 1162209ff23fSmrg unsigned short size; 1163209ff23fSmrg 1164209ff23fSmrg //RHDFUNC(handle); 1165209ff23fSmrg 1166209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1167209ff23fSmrg 1168209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1169209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->GPIO_I2C_Info), 1170209ff23fSmrg &frev,&crev,&size)) { 1171209ff23fSmrg return ATOM_FAILED; 1172209ff23fSmrg } 1173209ff23fSmrg 1174209ff23fSmrg switch (func) { 1175209ff23fSmrg case ATOM_GPIO_I2C_CLK_MASK: 1176209ff23fSmrg if ((sizeof(ATOM_COMMON_TABLE_HEADER) 1177209ff23fSmrg + (*val * sizeof(ATOM_GPIO_I2C_ASSIGMENT))) > size) { 1178209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: GPIO_I2C Device " 1179209ff23fSmrg "num %lu exeeds table size %u\n",__func__, 1180209ff23fSmrg (unsigned long)val, 1181209ff23fSmrg size); 1182209ff23fSmrg return ATOM_FAILED; 1183209ff23fSmrg } 1184209ff23fSmrg 1185209ff23fSmrg *val = le16_to_cpu(atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] 1186209ff23fSmrg .usClkMaskRegisterIndex); 1187209ff23fSmrg break; 1188209ff23fSmrg 1189209ff23fSmrg default: 1190209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1191209ff23fSmrg } 1192209ff23fSmrg return ATOM_SUCCESS; 1193209ff23fSmrg} 1194209ff23fSmrg 1195209ff23fSmrgstatic AtomBiosResult 1196209ff23fSmrgrhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, 1197209ff23fSmrg AtomBiosRequestID func, AtomBiosArgPtr data) 1198209ff23fSmrg{ 1199209ff23fSmrg atomDataTablesPtr atomDataPtr; 1200209ff23fSmrg uint8_t crev, frev; 1201209ff23fSmrg uint32_t *val = &data->val; 1202209ff23fSmrg 1203209ff23fSmrg //RHDFUNC(handle); 1204209ff23fSmrg 1205209ff23fSmrg atomDataPtr = handle->atomDataPtr; 1206209ff23fSmrg 1207209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1208209ff23fSmrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), 1209209ff23fSmrg &crev,&frev,NULL)) { 1210209ff23fSmrg return ATOM_FAILED; 1211209ff23fSmrg } 1212209ff23fSmrg 1213209ff23fSmrg switch (crev) { 1214209ff23fSmrg case 1: 1215209ff23fSmrg switch (func) { 1216209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1217209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1218209ff23fSmrg .FirmwareInfo->ulDefaultEngineClock) * 10; 1219209ff23fSmrg break; 1220209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1221209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1222209ff23fSmrg .FirmwareInfo->ulDefaultMemoryClock) * 10; 1223209ff23fSmrg break; 1224209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1225209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1226209ff23fSmrg .FirmwareInfo->ulMaxPixelClockPLL_Output) * 10; 1227209ff23fSmrg break; 1228209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1229209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1230209ff23fSmrg .FirmwareInfo->usMinPixelClockPLL_Output) * 10; 1231209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1232209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1233209ff23fSmrg .FirmwareInfo->usMaxPixelClockPLL_Input) * 10; 1234209ff23fSmrg break; 1235209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1236209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1237209ff23fSmrg .FirmwareInfo->usMinPixelClockPLL_Input) * 10; 1238209ff23fSmrg break; 1239209ff23fSmrg case GET_MAX_PIXEL_CLK: 1240209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1241209ff23fSmrg .FirmwareInfo->usMaxPixelClock) * 10; 1242209ff23fSmrg break; 1243209ff23fSmrg case GET_REF_CLOCK: 1244209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1245209ff23fSmrg .FirmwareInfo->usReferenceClock) * 10; 1246209ff23fSmrg break; 1247209ff23fSmrg default: 1248209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1249209ff23fSmrg } 1250209ff23fSmrg case 2: 1251209ff23fSmrg switch (func) { 1252209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1253209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1254209ff23fSmrg .FirmwareInfo_V_1_2->ulDefaultEngineClock) * 10; 1255209ff23fSmrg break; 1256209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1257209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1258209ff23fSmrg .FirmwareInfo_V_1_2->ulDefaultMemoryClock) * 10; 1259209ff23fSmrg break; 1260209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1261209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1262209ff23fSmrg .FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output) * 10; 1263209ff23fSmrg break; 1264209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1265209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1266209ff23fSmrg .FirmwareInfo_V_1_2->usMinPixelClockPLL_Output) * 10; 1267209ff23fSmrg break; 1268209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1269209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1270209ff23fSmrg .FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input) * 10; 1271209ff23fSmrg break; 1272209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1273209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1274209ff23fSmrg .FirmwareInfo_V_1_2->usMinPixelClockPLL_Input) * 10; 1275209ff23fSmrg break; 1276209ff23fSmrg case GET_MAX_PIXEL_CLK: 1277209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1278209ff23fSmrg .FirmwareInfo_V_1_2->usMaxPixelClock) * 10; 1279209ff23fSmrg break; 1280209ff23fSmrg case GET_REF_CLOCK: 1281209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1282209ff23fSmrg .FirmwareInfo_V_1_2->usReferenceClock) * 10; 1283209ff23fSmrg break; 1284209ff23fSmrg default: 1285209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1286209ff23fSmrg } 1287209ff23fSmrg break; 1288209ff23fSmrg case 3: 1289209ff23fSmrg switch (func) { 1290209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1291209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1292209ff23fSmrg .FirmwareInfo_V_1_3->ulDefaultEngineClock) * 10; 1293209ff23fSmrg break; 1294209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1295209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1296209ff23fSmrg .FirmwareInfo_V_1_3->ulDefaultMemoryClock) * 10; 1297209ff23fSmrg break; 1298209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1299209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1300209ff23fSmrg .FirmwareInfo_V_1_3->ulMaxPixelClockPLL_Output) * 10; 1301209ff23fSmrg break; 1302209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1303209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1304209ff23fSmrg .FirmwareInfo_V_1_3->usMinPixelClockPLL_Output) * 10; 1305209ff23fSmrg break; 1306209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1307209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1308209ff23fSmrg .FirmwareInfo_V_1_3->usMaxPixelClockPLL_Input) * 10; 1309209ff23fSmrg break; 1310209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1311209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1312209ff23fSmrg .FirmwareInfo_V_1_3->usMinPixelClockPLL_Input) * 10; 1313209ff23fSmrg break; 1314209ff23fSmrg case GET_MAX_PIXEL_CLK: 1315209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1316209ff23fSmrg .FirmwareInfo_V_1_3->usMaxPixelClock) * 10; 1317209ff23fSmrg break; 1318209ff23fSmrg case GET_REF_CLOCK: 1319209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1320209ff23fSmrg .FirmwareInfo_V_1_3->usReferenceClock) * 10; 1321209ff23fSmrg break; 1322209ff23fSmrg default: 1323209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1324209ff23fSmrg } 1325209ff23fSmrg break; 1326209ff23fSmrg case 4: 1327209ff23fSmrg switch (func) { 1328209ff23fSmrg case GET_DEFAULT_ENGINE_CLOCK: 1329209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1330209ff23fSmrg .FirmwareInfo_V_1_4->ulDefaultEngineClock) * 10; 1331209ff23fSmrg break; 1332209ff23fSmrg case GET_DEFAULT_MEMORY_CLOCK: 1333209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1334209ff23fSmrg .FirmwareInfo_V_1_4->ulDefaultMemoryClock) * 10; 1335209ff23fSmrg break; 1336209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1337209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1338209ff23fSmrg .FirmwareInfo_V_1_4->usMaxPixelClockPLL_Input) * 10; 1339209ff23fSmrg break; 1340209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1341209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1342209ff23fSmrg .FirmwareInfo_V_1_4->usMinPixelClockPLL_Input) * 10; 1343209ff23fSmrg break; 1344209ff23fSmrg case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1345209ff23fSmrg *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1346209ff23fSmrg .FirmwareInfo_V_1_4->ulMaxPixelClockPLL_Output) * 10; 1347209ff23fSmrg break; 1348209ff23fSmrg case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1349209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1350209ff23fSmrg .FirmwareInfo_V_1_4->usMinPixelClockPLL_Output) * 10; 1351209ff23fSmrg break; 1352209ff23fSmrg case GET_MAX_PIXEL_CLK: 1353209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1354209ff23fSmrg .FirmwareInfo_V_1_4->usMaxPixelClock) * 10; 1355209ff23fSmrg break; 1356209ff23fSmrg case GET_REF_CLOCK: 1357209ff23fSmrg *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1358209ff23fSmrg .FirmwareInfo_V_1_4->usReferenceClock) * 10; 1359209ff23fSmrg break; 1360209ff23fSmrg default: 1361209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1362209ff23fSmrg } 1363209ff23fSmrg break; 1364209ff23fSmrg default: 1365209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 1366209ff23fSmrg } 1367209ff23fSmrg return ATOM_SUCCESS; 1368209ff23fSmrg} 1369209ff23fSmrg 1370209ff23fSmrgconst int object_connector_convert[] = 1371209ff23fSmrg { CONNECTOR_NONE, 1372209ff23fSmrg CONNECTOR_DVI_I, 1373209ff23fSmrg CONNECTOR_DVI_I, 1374209ff23fSmrg CONNECTOR_DVI_D, 1375209ff23fSmrg CONNECTOR_DVI_D, 1376209ff23fSmrg CONNECTOR_VGA, 1377209ff23fSmrg CONNECTOR_CTV, 1378209ff23fSmrg CONNECTOR_STV, 1379209ff23fSmrg CONNECTOR_NONE, 1380c503f109Smrg CONNECTOR_NONE, 1381209ff23fSmrg CONNECTOR_DIN, 1382209ff23fSmrg CONNECTOR_SCART, 1383209ff23fSmrg CONNECTOR_HDMI_TYPE_A, 1384209ff23fSmrg CONNECTOR_HDMI_TYPE_B, 1385209ff23fSmrg CONNECTOR_LVDS, 1386209ff23fSmrg CONNECTOR_DIN, 1387209ff23fSmrg CONNECTOR_NONE, 1388209ff23fSmrg CONNECTOR_NONE, 1389209ff23fSmrg CONNECTOR_NONE, 1390209ff23fSmrg CONNECTOR_DISPLAY_PORT, 1391209ff23fSmrg }; 1392209ff23fSmrg 1393b7e1c893Smrgxf86MonPtr radeon_atom_get_edid(xf86OutputPtr output) 1394209ff23fSmrg{ 1395b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1396b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1397b7e1c893Smrg READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION edid_data; 1398b7e1c893Smrg AtomBiosArgRec data; 1399b7e1c893Smrg unsigned char *space; 1400b7e1c893Smrg int i2c_clock = 50; 1401b7e1c893Smrg int engine_clk = (int)info->sclk * 100; 1402b7e1c893Smrg int prescale; 1403b7e1c893Smrg unsigned char *edid; 1404b7e1c893Smrg xf86MonPtr mon = NULL; 1405b7e1c893Smrg 1406b7e1c893Smrg if (!radeon_output->ddc_i2c.hw_capable) 1407b7e1c893Smrg return mon; 1408b7e1c893Smrg 1409b7e1c893Smrg if (info->atomBIOS->fbBase) 1410b7e1c893Smrg edid = (unsigned char *)info->FB + info->atomBIOS->fbBase; 1411b7e1c893Smrg else if (info->atomBIOS->scratchBase) 1412b7e1c893Smrg edid = (unsigned char *)info->atomBIOS->scratchBase; 1413b7e1c893Smrg else 1414b7e1c893Smrg return mon; 1415b7e1c893Smrg 1416b7e1c893Smrg memset(edid, 0, ATOM_EDID_RAW_DATASIZE); 1417b7e1c893Smrg 1418b7e1c893Smrg if (info->ChipFamily == CHIP_FAMILY_R520) 1419b7e1c893Smrg prescale = (127 << 8) + (engine_clk * 10) / (4 * 127 * i2c_clock); 1420b7e1c893Smrg else if (info->ChipFamily < CHIP_FAMILY_R600) 1421b7e1c893Smrg prescale = (((engine_clk * 10)/(4 * 128 * 100) + 1) << 8) + 128; 1422b7e1c893Smrg else 1423b7e1c893Smrg prescale = (info->pll.reference_freq * 10) / i2c_clock; 1424b7e1c893Smrg 1425b7e1c893Smrg edid_data.usPrescale = prescale; 1426b7e1c893Smrg edid_data.usVRAMAddress = 0; 1427b7e1c893Smrg edid_data.ucSlaveAddr = 0xa0; 1428b7e1c893Smrg edid_data.ucLineNumber = radeon_output->ddc_i2c.hw_line; 1429b7e1c893Smrg 1430b7e1c893Smrg data.exec.index = GetIndexIntoMasterTable(COMMAND, ReadEDIDFromHWAssistedI2C); 1431b7e1c893Smrg data.exec.dataSpace = (void *)&space; 1432b7e1c893Smrg data.exec.pspace = &edid_data; 1433b7e1c893Smrg 1434b7e1c893Smrg if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) 1435b7e1c893Smrg ErrorF("Atom Get EDID success\n"); 1436b7e1c893Smrg else 1437b7e1c893Smrg ErrorF("Atom Get EDID failed\n"); 1438b7e1c893Smrg 1439b7e1c893Smrg if (edid[1] == 0xff) 1440b7e1c893Smrg mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); 1441b7e1c893Smrg 1442b7e1c893Smrg return mon; 1443b7e1c893Smrg 1444209ff23fSmrg} 1445209ff23fSmrg 1446209ff23fSmrgstatic RADEONI2CBusRec 1447209ff23fSmrgRADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id) 1448209ff23fSmrg{ 1449209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1450209ff23fSmrg atomDataTablesPtr atomDataPtr; 1451209ff23fSmrg ATOM_GPIO_I2C_ASSIGMENT gpio; 1452209ff23fSmrg RADEONI2CBusRec i2c; 1453209ff23fSmrg uint8_t crev, frev; 1454209ff23fSmrg 1455209ff23fSmrg memset(&i2c, 0, sizeof(RADEONI2CBusRec)); 1456209ff23fSmrg i2c.valid = FALSE; 1457209ff23fSmrg 1458209ff23fSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 1459209ff23fSmrg 1460209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 1461209ff23fSmrg &(atomDataPtr->GPIO_I2C_Info->sHeader), 1462209ff23fSmrg &crev,&frev,NULL)) { 1463209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No GPIO Info Table found!\n"); 1464209ff23fSmrg return i2c; 1465209ff23fSmrg } 1466209ff23fSmrg 1467209ff23fSmrg gpio = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[id]; 1468209ff23fSmrg i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4; 1469209ff23fSmrg i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4; 1470209ff23fSmrg i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4; 1471209ff23fSmrg i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4; 1472209ff23fSmrg i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4; 1473209ff23fSmrg i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4; 1474b7e1c893Smrg i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4; 1475b7e1c893Smrg i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4; 1476209ff23fSmrg i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift); 1477209ff23fSmrg i2c.mask_data_mask = (1 << gpio.ucDataMaskShift); 1478209ff23fSmrg i2c.put_clk_mask = (1 << gpio.ucClkEnShift); 1479209ff23fSmrg i2c.put_data_mask = (1 << gpio.ucDataEnShift); 1480209ff23fSmrg i2c.get_clk_mask = (1 << gpio.ucClkY_Shift); 1481209ff23fSmrg i2c.get_data_mask = (1 << gpio.ucDataY_Shift); 1482b7e1c893Smrg i2c.a_clk_mask = (1 << gpio.ucClkA_Shift); 1483b7e1c893Smrg i2c.a_data_mask = (1 << gpio.ucDataA_Shift); 1484b7e1c893Smrg i2c.hw_line = gpio.sucI2cId.sbfAccess.bfI2C_LineMux; 1485b7e1c893Smrg i2c.hw_capable = gpio.sucI2cId.sbfAccess.bfHW_Capable; 1486209ff23fSmrg i2c.valid = TRUE; 1487209ff23fSmrg 1488209ff23fSmrg#if 0 1489b7e1c893Smrg ErrorF("id: %d\n", id); 1490b7e1c893Smrg ErrorF("hw capable: %d\n", gpio.sucI2cId.sbfAccess.bfHW_Capable); 1491b7e1c893Smrg ErrorF("hw engine id: %d\n", gpio.sucI2cId.sbfAccess.bfHW_EngineID); 1492b7e1c893Smrg ErrorF("line mux %d\n", gpio.sucI2cId.sbfAccess.bfI2C_LineMux); 1493209ff23fSmrg ErrorF("mask_clk_reg: 0x%x\n", gpio.usClkMaskRegisterIndex * 4); 1494209ff23fSmrg ErrorF("mask_data_reg: 0x%x\n", gpio.usDataMaskRegisterIndex * 4); 1495209ff23fSmrg ErrorF("put_clk_reg: 0x%x\n", gpio.usClkEnRegisterIndex * 4); 1496209ff23fSmrg ErrorF("put_data_reg: 0x%x\n", gpio.usDataEnRegisterIndex * 4); 1497209ff23fSmrg ErrorF("get_clk_reg: 0x%x\n", gpio.usClkY_RegisterIndex * 4); 1498209ff23fSmrg ErrorF("get_data_reg: 0x%x\n", gpio.usDataY_RegisterIndex * 4); 1499b7e1c893Smrg ErrorF("a_clk_reg: 0x%x\n", gpio.usClkA_RegisterIndex * 4); 1500b7e1c893Smrg ErrorF("a_data_reg: 0x%x\n", gpio.usDataA_RegisterIndex * 4); 1501209ff23fSmrg ErrorF("mask_clk_mask: %d\n", gpio.ucClkMaskShift); 1502209ff23fSmrg ErrorF("mask_data_mask: %d\n", gpio.ucDataMaskShift); 1503209ff23fSmrg ErrorF("put_clk_mask: %d\n", gpio.ucClkEnShift); 1504209ff23fSmrg ErrorF("put_data_mask: %d\n", gpio.ucDataEnShift); 1505209ff23fSmrg ErrorF("get_clk_mask: %d\n", gpio.ucClkY_Shift); 1506209ff23fSmrg ErrorF("get_data_mask: %d\n", gpio.ucDataY_Shift); 1507b7e1c893Smrg ErrorF("a_clk_mask: %d\n", gpio.ucClkA_Shift); 1508b7e1c893Smrg ErrorF("a_data_mask: %d\n", gpio.ucDataA_Shift); 1509209ff23fSmrg#endif 1510209ff23fSmrg 1511209ff23fSmrg return i2c; 1512209ff23fSmrg} 1513209ff23fSmrg 1514b7e1c893Smrgstatic RADEONI2CBusRec 1515b7e1c893SmrgrhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, 1516b7e1c893Smrg ATOM_I2C_RECORD *Record, int i) 1517b7e1c893Smrg{ 1518b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1519b7e1c893Smrg 1520b7e1c893Smrg info->BiosConnector[i].i2c_line_mux = Record->sucI2cId.bfI2C_LineMux; 1521b7e1c893Smrg return RADEONLookupGPIOLineForDDC(pScrn, Record->sucI2cId.bfI2C_LineMux); 1522b7e1c893Smrg} 1523b7e1c893Smrg 1524b7e1c893Smrgstatic void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index) 1525b7e1c893Smrg{ 1526b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1527b7e1c893Smrg 1528b7e1c893Smrg /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ 1529b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RS690_791E) && 1530b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1531b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x826d)) { 1532b7e1c893Smrg if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1533b7e1c893Smrg (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1534b7e1c893Smrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1535b7e1c893Smrg } 1536b7e1c893Smrg } 1537c503f109Smrg 1538b7e1c893Smrg /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ 1539b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RS600_7941) && 1540b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x147b) && 1541b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2412)) { 1542b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) 1543b7e1c893Smrg info->BiosConnector[index].valid = FALSE; 1544b7e1c893Smrg } 1545b7e1c893Smrg 1546b7e1c893Smrg /* Falcon NW laptop lists vga ddc line for LVDS */ 1547b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV410_5653) && 1548b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1462) && 1549b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0291)) { 1550b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_LVDS) { 1551b7e1c893Smrg info->BiosConnector[index].ddc_i2c.valid = FALSE; 1552b7e1c893Smrg } 1553b7e1c893Smrg } 1554b7e1c893Smrg 1555b7e1c893Smrg /* Funky macbooks */ 1556b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1557b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1558b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1559b7e1c893Smrg if ((index == ATOM_DEVICE_CRT1_INDEX) || 1560b7e1c893Smrg (index == ATOM_DEVICE_CRT2_INDEX) || 1561b7e1c893Smrg (index == ATOM_DEVICE_DFP2_INDEX)) 1562b7e1c893Smrg info->BiosConnector[index].valid = FALSE; 1563b7e1c893Smrg 1564b7e1c893Smrg if (index == ATOM_DEVICE_DFP1_INDEX) { 1565b7e1c893Smrg info->BiosConnector[index].devices |= ATOM_DEVICE_CRT2_SUPPORT; 1566b7e1c893Smrg } 1567b7e1c893Smrg } 1568b7e1c893Smrg 1569b7e1c893Smrg /* ASUS HD 3600 XT board lists the DVI port as HDMI */ 1570b7e1c893Smrg if ((info->Chipset == PCI_CHIP_RV635_9598) && 1571b7e1c893Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1572b7e1c893Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) { 1573b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_B) 1574b7e1c893Smrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1575b7e1c893Smrg } 1576b7e1c893Smrg 1577c503f109Smrg /* ASUS HD 3450 board lists the DVI port as HDMI */ 1578c503f109Smrg if ((info->Chipset == PCI_CHIP_RV620_95C5) && 1579c503f109Smrg (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1580c503f109Smrg (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) { 1581c503f109Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_B) 1582c503f109Smrg info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1583c503f109Smrg } 1584c503f109Smrg 1585c503f109Smrg /* some BIOSes seem to report DAC on HDMI - usually this is a board with 1586c503f109Smrg * HDMI + VGA reporting as HDMI 1587c503f109Smrg */ 1588c503f109Smrg if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) || 1589c503f109Smrg (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_B)) { 1590c503f109Smrg if (info->BiosConnector[index].devices & (ATOM_DEVICE_CRT_SUPPORT)) { 1591c503f109Smrg info->BiosConnector[index].devices &= ~(ATOM_DEVICE_DFP_SUPPORT); 1592c503f109Smrg info->BiosConnector[index].ConnectorType = CONNECTOR_VGA; 1593c503f109Smrg info->BiosConnector[index].connector_object = 0; 1594c503f109Smrg } else 1595c503f109Smrg info->BiosConnector[index].devices &= ~(ATOM_DEVICE_CRT_SUPPORT); 1596c503f109Smrg } 1597b7e1c893Smrg 1598b7e1c893Smrg} 1599b7e1c893Smrg 1600b7e1c893Smrguint32_t 1601b7e1c893Smrgradeon_get_device_index(uint32_t device_support) 1602b7e1c893Smrg{ 1603b7e1c893Smrg uint32_t device_index = 0; 1604b7e1c893Smrg 1605b7e1c893Smrg if (device_support == 0) 1606b7e1c893Smrg return 0; 1607b7e1c893Smrg 1608b7e1c893Smrg while ((device_support & 1) == 0) { 1609b7e1c893Smrg device_support >>= 1; 1610b7e1c893Smrg device_index++; 1611b7e1c893Smrg } 1612b7e1c893Smrg return device_index; 1613b7e1c893Smrg} 1614b7e1c893Smrg 1615b7e1c893Smrgradeon_encoder_ptr 1616b7e1c893Smrgradeon_get_encoder(xf86OutputPtr output) 1617b7e1c893Smrg{ 1618b7e1c893Smrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1619b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(output->scrn); 1620b7e1c893Smrg 1621b7e1c893Smrg if (radeon_output->active_device) 1622b7e1c893Smrg return info->encoders[radeon_get_device_index(radeon_output->active_device)]; 1623b7e1c893Smrg else 1624b7e1c893Smrg return NULL; 1625b7e1c893Smrg} 1626b7e1c893Smrg 1627b7e1c893SmrgBool 1628b7e1c893Smrgradeon_add_encoder(ScrnInfoPtr pScrn, uint32_t encoder_id, uint32_t device_support) 1629b7e1c893Smrg{ 1630b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1631b7e1c893Smrg uint32_t device_index = radeon_get_device_index(device_support); 1632b7e1c893Smrg int i; 1633b7e1c893Smrg 1634b7e1c893Smrg if (device_support == 0) { 1635b7e1c893Smrg ErrorF("device support == 0\n"); 1636b7e1c893Smrg return FALSE; 1637b7e1c893Smrg } 1638b7e1c893Smrg 1639b7e1c893Smrg if (info->encoders[device_index] != NULL) 1640b7e1c893Smrg return TRUE; 1641b7e1c893Smrg else { 1642b7e1c893Smrg /* look for the encoder */ 1643b7e1c893Smrg for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { 1644b7e1c893Smrg if ((info->encoders[i] != NULL) && (info->encoders[i]->encoder_id == encoder_id)) { 1645b7e1c893Smrg info->encoders[device_index] = info->encoders[i]; 1646b7e1c893Smrg switch (encoder_id) { 1647b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1648b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1649b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1650b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1651b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1652b7e1c893Smrg if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1653b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1654b7e1c893Smrg info->encoders[device_index]->dev_priv = 1655b7e1c893Smrg (radeon_lvds_ptr)xcalloc(1,sizeof(radeon_lvds_rec)); 1656b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1657b7e1c893Smrg ErrorF("xalloc failed\n"); 1658b7e1c893Smrg return FALSE; 1659b7e1c893Smrg } else 1660b7e1c893Smrg RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1661b7e1c893Smrg } 1662b7e1c893Smrg } 1663b7e1c893Smrg break; 1664b7e1c893Smrg } 1665b7e1c893Smrg return TRUE; 1666b7e1c893Smrg } 1667b7e1c893Smrg } 1668b7e1c893Smrg 1669b7e1c893Smrg info->encoders[device_index] = (radeon_encoder_ptr)xcalloc(1,sizeof(radeon_encoder_rec)); 1670b7e1c893Smrg if (info->encoders[device_index] != NULL) { 1671b7e1c893Smrg info->encoders[device_index]->encoder_id = encoder_id; 1672b7e1c893Smrg info->encoders[device_index]->devices = 0; 1673b7e1c893Smrg info->encoders[device_index]->dev_priv = NULL; 1674b7e1c893Smrg // add dev_priv stuff 1675b7e1c893Smrg switch (encoder_id) { 1676b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1677b7e1c893Smrg info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)xcalloc(1,sizeof(radeon_lvds_rec)); 1678b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1679b7e1c893Smrg ErrorF("xalloc failed\n"); 1680b7e1c893Smrg return FALSE; 1681b7e1c893Smrg } else { 1682b7e1c893Smrg if (info->IsAtomBios) 1683b7e1c893Smrg RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1684b7e1c893Smrg else 1685b7e1c893Smrg RADEONGetLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1686b7e1c893Smrg } 1687b7e1c893Smrg break; 1688b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1689b7e1c893Smrg if (!IS_AVIVO_VARIANT) { 1690b7e1c893Smrg info->encoders[device_index]->dev_priv = (radeon_tvdac_ptr)xcalloc(1,sizeof(radeon_tvdac_rec)); 1691b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1692b7e1c893Smrg ErrorF("xalloc failed\n"); 1693b7e1c893Smrg return FALSE; 1694b7e1c893Smrg } else 1695b7e1c893Smrg RADEONGetTVDacAdjInfo(pScrn, (radeon_tvdac_ptr)info->encoders[device_index]->dev_priv); 1696b7e1c893Smrg } 1697b7e1c893Smrg break; 1698b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1699b7e1c893Smrg if (!IS_AVIVO_VARIANT) { 1700b7e1c893Smrg info->encoders[device_index]->dev_priv = (radeon_tmds_ptr)xcalloc(1,sizeof(radeon_tmds_rec)); 1701b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1702b7e1c893Smrg ErrorF("xalloc failed\n"); 1703b7e1c893Smrg return FALSE; 1704b7e1c893Smrg } else 1705b7e1c893Smrg RADEONGetTMDSInfo(pScrn, (radeon_tmds_ptr)info->encoders[device_index]->dev_priv); 1706b7e1c893Smrg } 1707b7e1c893Smrg break; 1708b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1709b7e1c893Smrg if (!IS_AVIVO_VARIANT) { 1710b7e1c893Smrg info->encoders[device_index]->dev_priv = (radeon_dvo_ptr)xcalloc(1,sizeof(radeon_dvo_rec)); 1711b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1712b7e1c893Smrg ErrorF("xalloc failed\n"); 1713b7e1c893Smrg return FALSE; 1714b7e1c893Smrg } else 1715b7e1c893Smrg RADEONGetExtTMDSInfo(pScrn, (radeon_dvo_ptr)info->encoders[device_index]->dev_priv); 1716b7e1c893Smrg } 1717b7e1c893Smrg break; 1718b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1719b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1720b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1721b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1722b7e1c893Smrg case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1723b7e1c893Smrg if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1724b7e1c893Smrg info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)xcalloc(1,sizeof(radeon_lvds_rec)); 1725b7e1c893Smrg if (info->encoders[device_index]->dev_priv == NULL) { 1726b7e1c893Smrg ErrorF("xalloc failed\n"); 1727b7e1c893Smrg return FALSE; 1728b7e1c893Smrg } else 1729b7e1c893Smrg RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1730b7e1c893Smrg } 1731b7e1c893Smrg break; 1732b7e1c893Smrg } 1733b7e1c893Smrg return TRUE; 1734b7e1c893Smrg } else { 1735b7e1c893Smrg ErrorF("xalloc failed\n"); 1736b7e1c893Smrg return FALSE; 1737b7e1c893Smrg } 1738b7e1c893Smrg } 1739b7e1c893Smrg 1740b7e1c893Smrg} 1741b7e1c893Smrg 1742209ff23fSmrgBool 1743209ff23fSmrgRADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn) 1744209ff23fSmrg{ 1745209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1746209ff23fSmrg uint8_t crev, frev; 1747209ff23fSmrg unsigned short size; 1748209ff23fSmrg atomDataTablesPtr atomDataPtr; 1749209ff23fSmrg ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 1750b7e1c893Smrg ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 1751209ff23fSmrg ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj = NULL; 1752b7e1c893Smrg int i, j, path_size, device_support; 1753b7e1c893Smrg Bool enable_tv = FALSE; 1754b7e1c893Smrg 1755b7e1c893Smrg if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 1756b7e1c893Smrg enable_tv = TRUE; 1757209ff23fSmrg 1758209ff23fSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 1759209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->Object_Header), &crev, &frev, &size)) 1760209ff23fSmrg return FALSE; 1761209ff23fSmrg 1762209ff23fSmrg if (crev < 2) 1763209ff23fSmrg return FALSE; 1764209ff23fSmrg 1765b7e1c893Smrg path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) 1766b7e1c893Smrg ((char *)&atomDataPtr->Object_Header->sHeader + 1767b7e1c893Smrg le16_to_cpu(atomDataPtr->Object_Header->usDisplayPathTableOffset)); 1768209ff23fSmrg con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) 1769209ff23fSmrg ((char *)&atomDataPtr->Object_Header->sHeader + 1770209ff23fSmrg le16_to_cpu(atomDataPtr->Object_Header->usConnectorObjectTableOffset)); 1771b7e1c893Smrg device_support = le16_to_cpu(atomDataPtr->Object_Header->usDeviceSupport); 1772b7e1c893Smrg 1773b7e1c893Smrg path_size = 0; 1774b7e1c893Smrg for (i = 0; i < path_obj->ucNumOfDispPath; i++) { 1775b7e1c893Smrg uint8_t *addr = (uint8_t *)path_obj->asDispPath; 1776b7e1c893Smrg ATOM_DISPLAY_OBJECT_PATH *path; 1777b7e1c893Smrg addr += path_size; 1778b7e1c893Smrg path = (ATOM_DISPLAY_OBJECT_PATH *)addr; 1779c503f109Smrg path_size += le16_to_cpu(path->usSize); 1780b7e1c893Smrg 1781c503f109Smrg if (device_support & le16_to_cpu(path->usDeviceTag)) { 1782b7e1c893Smrg uint8_t con_obj_id, con_obj_num, con_obj_type; 1783b7e1c893Smrg 1784c503f109Smrg con_obj_id = (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1785c503f109Smrg con_obj_num = (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1786c503f109Smrg con_obj_type = (le16_to_cpu(path->usConnObjectId) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 1787b7e1c893Smrg 1788c503f109Smrg if ((le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV1_SUPPORT) || 1789c503f109Smrg (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV2_SUPPORT)) { 1790b7e1c893Smrg if (!enable_tv) { 1791b7e1c893Smrg info->BiosConnector[i].valid = FALSE; 1792b7e1c893Smrg continue; 1793b7e1c893Smrg } 1794b7e1c893Smrg } 1795209ff23fSmrg 1796b7e1c893Smrg /* don't support CV yet */ 1797c503f109Smrg if (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_CV_SUPPORT) { 1798b7e1c893Smrg info->BiosConnector[i].valid = FALSE; 1799b7e1c893Smrg continue; 1800b7e1c893Smrg } 1801209ff23fSmrg 1802b7e1c893Smrg if (info->IsIGP && 1803b7e1c893Smrg (con_obj_id == CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { 1804b7e1c893Smrg uint32_t slot_config, ct; 1805209ff23fSmrg 1806b7e1c893Smrg igp_obj = info->atomBIOS->atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2; 1807209ff23fSmrg 1808b7e1c893Smrg if (!igp_obj) 1809b7e1c893Smrg info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1810b7e1c893Smrg else { 1811b7e1c893Smrg if (con_obj_num == 1) 1812b7e1c893Smrg slot_config = igp_obj->ulDDISlot1Config; 1813b7e1c893Smrg else 1814b7e1c893Smrg slot_config = igp_obj->ulDDISlot2Config; 1815209ff23fSmrg 1816b7e1c893Smrg ct = (slot_config >> 16) & 0xff; 1817b7e1c893Smrg info->BiosConnector[i].ConnectorType = object_connector_convert[ct]; 1818b7e1c893Smrg info->BiosConnector[i].igp_lane_info = slot_config & 0xffff; 1819b7e1c893Smrg } 1820b7e1c893Smrg } else 1821b7e1c893Smrg info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1822b7e1c893Smrg 1823b7e1c893Smrg if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 1824b7e1c893Smrg info->BiosConnector[i].valid = FALSE; 1825b7e1c893Smrg continue; 1826b7e1c893Smrg } else 1827b7e1c893Smrg info->BiosConnector[i].valid = TRUE; 1828c503f109Smrg info->BiosConnector[i].devices = le16_to_cpu(path->usDeviceTag); 1829c503f109Smrg info->BiosConnector[i].connector_object = le16_to_cpu(path->usConnObjectId); 1830b7e1c893Smrg 1831c503f109Smrg for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { 1832b7e1c893Smrg uint8_t enc_obj_id, enc_obj_num, enc_obj_type; 1833b7e1c893Smrg 1834c503f109Smrg enc_obj_id = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1835c503f109Smrg enc_obj_num = (le16_to_cpu(path->usGraphicObjIds[j]) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1836c503f109Smrg enc_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 1837b7e1c893Smrg 1838b7e1c893Smrg if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { 1839b7e1c893Smrg if (enc_obj_num == 2) 1840b7e1c893Smrg info->BiosConnector[i].linkb = TRUE; 1841b7e1c893Smrg else 1842b7e1c893Smrg info->BiosConnector[i].linkb = FALSE; 1843b7e1c893Smrg 1844c503f109Smrg if (!radeon_add_encoder(pScrn, enc_obj_id, le16_to_cpu(path->usDeviceTag))) 1845b7e1c893Smrg return FALSE; 1846b7e1c893Smrg } 1847209ff23fSmrg } 1848209ff23fSmrg 1849b7e1c893Smrg /* look up gpio for ddc */ 1850c503f109Smrg if ((le16_to_cpu(path->usDeviceTag) & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { 1851b7e1c893Smrg for (j = 0; j < con_obj->ucNumberOfObjects; j++) { 1852c503f109Smrg if (le16_to_cpu(path->usConnObjectId) == le16_to_cpu(con_obj->asObjects[j].usObjectID)) { 1853b7e1c893Smrg ATOM_COMMON_RECORD_HEADER *Record = (ATOM_COMMON_RECORD_HEADER *) 1854b7e1c893Smrg ((char *)&atomDataPtr->Object_Header->sHeader 1855b7e1c893Smrg + le16_to_cpu(con_obj->asObjects[j].usRecordOffset)); 1856b7e1c893Smrg 1857b7e1c893Smrg while (Record->ucRecordType > 0 1858b7e1c893Smrg && Record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER ) { 1859b7e1c893Smrg 1860b7e1c893Smrg /*ErrorF("record type %d\n", Record->ucRecordType);*/ 1861b7e1c893Smrg switch (Record->ucRecordType) { 1862b7e1c893Smrg case ATOM_I2C_RECORD_TYPE: 1863b7e1c893Smrg info->BiosConnector[i].ddc_i2c = 1864b7e1c893Smrg rhdAtomParseI2CRecord(pScrn, info->atomBIOS, 1865b7e1c893Smrg (ATOM_I2C_RECORD *)Record, j); 1866b7e1c893Smrg break; 1867b7e1c893Smrg case ATOM_HPD_INT_RECORD_TYPE: 1868b7e1c893Smrg break; 1869b7e1c893Smrg case ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE: 1870b7e1c893Smrg break; 1871b7e1c893Smrg } 1872b7e1c893Smrg 1873b7e1c893Smrg Record = (ATOM_COMMON_RECORD_HEADER*) 1874b7e1c893Smrg ((char *)Record + Record->ucRecordSize); 1875b7e1c893Smrg } 1876b7e1c893Smrg break; 1877b7e1c893Smrg } 1878b7e1c893Smrg } 1879b7e1c893Smrg } 1880b7e1c893Smrg } 1881b7e1c893Smrg RADEONApplyATOMQuirks(pScrn, i); 1882b7e1c893Smrg } 1883209ff23fSmrg 1884b7e1c893Smrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 1885b7e1c893Smrg if (info->BiosConnector[i].valid) { 1886b7e1c893Smrg /* shared connectors */ 1887b7e1c893Smrg for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 1888b7e1c893Smrg if (info->BiosConnector[j].valid && (i != j) ) { 1889b7e1c893Smrg if (info->BiosConnector[i].connector_object == info->BiosConnector[j].connector_object) { 1890b7e1c893Smrg info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 1891b7e1c893Smrg info->BiosConnector[j].valid = FALSE; 1892b7e1c893Smrg } 1893b7e1c893Smrg } 1894b7e1c893Smrg } 1895b7e1c893Smrg /* shared ddc */ 1896b7e1c893Smrg for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 1897b7e1c893Smrg if (info->BiosConnector[j].valid && (i != j) ) { 1898b7e1c893Smrg if (info->BiosConnector[i].i2c_line_mux == info->BiosConnector[j].i2c_line_mux) { 1899b7e1c893Smrg ErrorF("Shared DDC line: %d %d\n", i, j); 1900b7e1c893Smrg info->BiosConnector[i].shared_ddc = TRUE; 1901b7e1c893Smrg info->BiosConnector[j].shared_ddc = TRUE; 1902b7e1c893Smrg } 1903b7e1c893Smrg } 1904209ff23fSmrg } 1905209ff23fSmrg } 1906b7e1c893Smrg } 1907209ff23fSmrg 1908b7e1c893Smrg return TRUE; 1909b7e1c893Smrg} 1910209ff23fSmrg 1911b7e1c893Smrgstatic void 1912b7e1c893SmrgRADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 1913b7e1c893Smrg{ 1914b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1915b7e1c893Smrg radeon_native_mode_ptr native_mode = &lvds->native_mode; 1916b7e1c893Smrg atomDataTablesPtr atomDataPtr; 1917b7e1c893Smrg uint8_t crev, frev; 1918209ff23fSmrg 1919b7e1c893Smrg atomDataPtr = info->atomBIOS->atomDataPtr; 1920209ff23fSmrg 1921b7e1c893Smrg if (!rhdAtomGetTableRevisionAndSize( 1922b7e1c893Smrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 1923b7e1c893Smrg &frev,&crev,NULL)) { 1924b7e1c893Smrg return; 1925b7e1c893Smrg } 1926209ff23fSmrg 1927b7e1c893Smrg switch (crev) { 1928b7e1c893Smrg case 1: 1929b7e1c893Smrg native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHActive); 1930b7e1c893Smrg native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVActive); 1931b7e1c893Smrg native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usPixClk) * 10; 1932b7e1c893Smrg native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHBlanking_Time); 1933b7e1c893Smrg native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncOffset); 1934b7e1c893Smrg native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncWidth); 1935b7e1c893Smrg native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVBlanking_Time); 1936b7e1c893Smrg native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncOffset); 1937b7e1c893Smrg native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncWidth); 1938b7e1c893Smrg lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->usOffDelayInMs); 1939b7e1c893Smrg lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info->ucLVDS_Misc; 1940b7e1c893Smrg lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info->ucSS_Id; 1941b7e1c893Smrg break; 1942b7e1c893Smrg case 2: 1943b7e1c893Smrg native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHActive); 1944b7e1c893Smrg native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVActive); 1945b7e1c893Smrg native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usPixClk) * 10; 1946b7e1c893Smrg native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHBlanking_Time); 1947b7e1c893Smrg native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncOffset); 1948b7e1c893Smrg native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncWidth); 1949b7e1c893Smrg native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVBlanking_Time); 1950b7e1c893Smrg native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncOffset); 1951b7e1c893Smrg native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncWidth); 1952b7e1c893Smrg lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->usOffDelayInMs); 1953b7e1c893Smrg lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucLVDS_Misc; 1954b7e1c893Smrg lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucSS_Id; 1955b7e1c893Smrg break; 1956209ff23fSmrg } 1957b7e1c893Smrg native_mode->Flags = 0; 1958b7e1c893Smrg 1959b7e1c893Smrg if (lvds->PanelPwrDly > 2000 || lvds->PanelPwrDly < 0) 1960b7e1c893Smrg lvds->PanelPwrDly = 2000; 1961b7e1c893Smrg 1962b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1963b7e1c893Smrg "LVDS Info:\n" 1964b7e1c893Smrg "XRes: %d, YRes: %d, DotClock: %d\n" 1965b7e1c893Smrg "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" 1966b7e1c893Smrg "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", 1967b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes, native_mode->DotClock, 1968b7e1c893Smrg native_mode->HBlank, native_mode->HOverPlus, native_mode->HSyncWidth, 1969b7e1c893Smrg native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth); 1970209ff23fSmrg} 1971209ff23fSmrg 1972209ff23fSmrgBool 1973209ff23fSmrgRADEONGetATOMTVInfo(xf86OutputPtr output) 1974209ff23fSmrg{ 1975209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1976209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1977209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 1978b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 1979209ff23fSmrg ATOM_ANALOG_TV_INFO *tv_info; 1980209ff23fSmrg 1981b7e1c893Smrg tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info.AnalogTV_Info; 1982209ff23fSmrg 1983209ff23fSmrg if (!tv_info) 1984209ff23fSmrg return FALSE; 1985209ff23fSmrg 1986209ff23fSmrg switch(tv_info->ucTV_BootUpDefaultStandard) { 1987209ff23fSmrg case NTSCJ_SUPPORT: 1988b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC_J; 1989209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); 1990209ff23fSmrg break; 1991209ff23fSmrg case PAL_SUPPORT: 1992b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL; 1993209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); 1994209ff23fSmrg break; 1995209ff23fSmrg case PALM_SUPPORT: 1996b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_M; 1997209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); 1998209ff23fSmrg break; 1999209ff23fSmrg case PAL60_SUPPORT: 2000b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_60; 2001209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); 2002209ff23fSmrg break; 2003b7e1c893Smrg default: 2004b7e1c893Smrg case NTSC_SUPPORT: 2005b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC; 2006b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); 2007b7e1c893Smrg break; 2008209ff23fSmrg } 2009209ff23fSmrg 2010b7e1c893Smrg tvout->tvStd = tvout->default_tvStd; 2011209ff23fSmrg 2012209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); 2013b7e1c893Smrg tvout->SupportedTVStds = tvout->default_tvStd; 2014209ff23fSmrg if (tv_info->ucTV_SupportedStandard & NTSC_SUPPORT) { 2015209ff23fSmrg ErrorF("NTSC "); 2016b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC; 2017209ff23fSmrg } 2018209ff23fSmrg if (tv_info->ucTV_SupportedStandard & NTSCJ_SUPPORT) { 2019209ff23fSmrg ErrorF("NTSC-J "); 2020b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC_J; 2021209ff23fSmrg } 2022209ff23fSmrg if (tv_info->ucTV_SupportedStandard & PAL_SUPPORT) { 2023209ff23fSmrg ErrorF("PAL "); 2024b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL; 2025209ff23fSmrg } 2026209ff23fSmrg if (tv_info->ucTV_SupportedStandard & PALM_SUPPORT) { 2027209ff23fSmrg ErrorF("PAL-M "); 2028b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_M; 2029209ff23fSmrg } 2030209ff23fSmrg if (tv_info->ucTV_SupportedStandard & PAL60_SUPPORT) { 2031209ff23fSmrg ErrorF("PAL-60 "); 2032b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_60; 2033209ff23fSmrg } 2034209ff23fSmrg ErrorF("\n"); 2035209ff23fSmrg 2036209ff23fSmrg if (tv_info->ucExt_TV_ASIC_ID) { 2037209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown external TV ASIC\n"); 2038209ff23fSmrg return FALSE; 2039209ff23fSmrg } 2040209ff23fSmrg 2041209ff23fSmrg return TRUE; 2042209ff23fSmrg} 2043209ff23fSmrg 2044209ff23fSmrgBool 2045209ff23fSmrgRADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, int32_t *pixel_clock) 2046209ff23fSmrg{ 2047209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2048209ff23fSmrg ATOM_ANALOG_TV_INFO *tv_info; 2049b7e1c893Smrg ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; 2050b7e1c893Smrg ATOM_DTD_FORMAT *dtd_timings; 2051b7e1c893Smrg atomDataTablesPtr atomDataPtr; 2052b7e1c893Smrg uint8_t crev, frev; 2053209ff23fSmrg 2054b7e1c893Smrg atomDataPtr = info->atomBIOS->atomDataPtr; 2055b7e1c893Smrg if (!rhdAtomGetTableRevisionAndSize( 2056b7e1c893Smrg (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info.base), 2057b7e1c893Smrg &crev,&frev,NULL)) { 2058209ff23fSmrg return FALSE; 2059b7e1c893Smrg } 2060209ff23fSmrg 2061b7e1c893Smrg switch(crev) { 2062b7e1c893Smrg case 1: 2063b7e1c893Smrg tv_info = atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2064b7e1c893Smrg 2065b7e1c893Smrg if (index > MAX_SUPPORTED_TV_TIMING) 2066b7e1c893Smrg return FALSE; 2067b7e1c893Smrg 2068b7e1c893Smrg crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); 2069b7e1c893Smrg crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); 2070b7e1c893Smrg crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); 2071b7e1c893Smrg crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); 2072b7e1c893Smrg 2073b7e1c893Smrg crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); 2074b7e1c893Smrg crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); 2075b7e1c893Smrg crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); 2076b7e1c893Smrg crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); 2077b7e1c893Smrg 2078b7e1c893Smrg crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo; 2079b7e1c893Smrg 2080b7e1c893Smrg crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight); 2081b7e1c893Smrg crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft); 2082b7e1c893Smrg crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom); 2083b7e1c893Smrg crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop); 2084b7e1c893Smrg *pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; 2085b7e1c893Smrg 2086b7e1c893Smrg if (index == 1) { 2087b7e1c893Smrg /* PAL timings appear to have wrong values for totals */ 2088b7e1c893Smrg crtc_timing->usH_Total -= 1; 2089b7e1c893Smrg crtc_timing->usV_Total -= 1; 2090b7e1c893Smrg } 2091b7e1c893Smrg break; 2092b7e1c893Smrg case 2: 2093b7e1c893Smrg tv_info_v1_2 = atomDataPtr->AnalogTV_Info.AnalogTV_Info_v1_2; 2094b7e1c893Smrg if (index > MAX_SUPPORTED_TV_TIMING_V1_2) 2095b7e1c893Smrg return FALSE; 2096209ff23fSmrg 2097b7e1c893Smrg dtd_timings = &tv_info_v1_2->aModeTimings[index]; 2098b7e1c893Smrg crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time); 2099b7e1c893Smrg crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive); 2100b7e1c893Smrg crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset); 2101b7e1c893Smrg crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth); 2102209ff23fSmrg 2103b7e1c893Smrg crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time); 2104b7e1c893Smrg crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive); 2105b7e1c893Smrg crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset); 2106b7e1c893Smrg crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth); 2107209ff23fSmrg 2108b7e1c893Smrg crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); 2109b7e1c893Smrg *pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10; 2110b7e1c893Smrg break; 2111b7e1c893Smrg } 2112209ff23fSmrg 2113209ff23fSmrg return TRUE; 2114209ff23fSmrg} 2115209ff23fSmrg 2116b7e1c893Smrguint32_t 2117b7e1c893Smrgradeon_get_encoder_id_from_supported_device(ScrnInfoPtr pScrn, uint32_t supported_device, int dac) 2118209ff23fSmrg{ 2119209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 2120b7e1c893Smrg uint32_t ret = 0; 2121b7e1c893Smrg 2122b7e1c893Smrg switch (supported_device) { 2123b7e1c893Smrg case ATOM_DEVICE_CRT1_SUPPORT: 2124b7e1c893Smrg case ATOM_DEVICE_TV1_SUPPORT: 2125b7e1c893Smrg case ATOM_DEVICE_TV2_SUPPORT: 2126b7e1c893Smrg case ATOM_DEVICE_CRT2_SUPPORT: 2127b7e1c893Smrg case ATOM_DEVICE_CV_SUPPORT: 2128b7e1c893Smrg switch (dac) { 2129b7e1c893Smrg // primary dac 2130b7e1c893Smrg case 1: 2131b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2132b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS400) || 2133b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) 2134b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2135b7e1c893Smrg else if (IS_AVIVO_VARIANT) 2136b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 2137b7e1c893Smrg else 2138b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 2139b7e1c893Smrg break; 2140b7e1c893Smrg // secondary dac 2141b7e1c893Smrg case 2: 2142b7e1c893Smrg if (IS_AVIVO_VARIANT) 2143b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 2144b7e1c893Smrg else { 2145b7e1c893Smrg /*if (info->ChipFamily == CHIP_FAMILY_R200) 2146b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2147b7e1c893Smrg else*/ 2148b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2149b7e1c893Smrg } 2150b7e1c893Smrg break; 2151b7e1c893Smrg // external dac 2152b7e1c893Smrg case 3: 2153b7e1c893Smrg if (IS_AVIVO_VARIANT) 2154b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2155b7e1c893Smrg else 2156b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2157b7e1c893Smrg break; 2158209ff23fSmrg } 2159b7e1c893Smrg break; 2160b7e1c893Smrg case ATOM_DEVICE_LCD1_SUPPORT: 2161b7e1c893Smrg if (IS_AVIVO_VARIANT) 2162b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2163b7e1c893Smrg else 2164b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 2165b7e1c893Smrg break; 2166b7e1c893Smrg case ATOM_DEVICE_DFP1_SUPPORT: 2167b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2168b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS400) || 2169b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS480)) 2170b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2171b7e1c893Smrg else if (IS_AVIVO_VARIANT) 2172b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 2173b7e1c893Smrg else 2174b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 2175b7e1c893Smrg break; 2176b7e1c893Smrg case ATOM_DEVICE_LCD2_SUPPORT: 2177b7e1c893Smrg case ATOM_DEVICE_DFP2_SUPPORT: 2178b7e1c893Smrg if ((info->ChipFamily == CHIP_FAMILY_RS600) || 2179b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS690) || 2180b7e1c893Smrg (info->ChipFamily == CHIP_FAMILY_RS740)) 2181b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 2182b7e1c893Smrg else if (IS_AVIVO_VARIANT) 2183b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2184b7e1c893Smrg else 2185b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2186b7e1c893Smrg break; 2187b7e1c893Smrg case ATOM_DEVICE_DFP3_SUPPORT: 2188b7e1c893Smrg ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2189b7e1c893Smrg break; 2190209ff23fSmrg } 2191209ff23fSmrg 2192b7e1c893Smrg return ret; 2193209ff23fSmrg} 2194209ff23fSmrg 2195209ff23fSmrgBool 2196209ff23fSmrgRADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn) 2197209ff23fSmrg{ 2198209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 2199209ff23fSmrg atomDataTablesPtr atomDataPtr; 2200209ff23fSmrg uint8_t crev, frev; 2201209ff23fSmrg int i, j; 2202b7e1c893Smrg Bool enable_tv = FALSE; 2203b7e1c893Smrg 2204b7e1c893Smrg if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 2205b7e1c893Smrg enable_tv = TRUE; 2206209ff23fSmrg 2207209ff23fSmrg atomDataPtr = info->atomBIOS->atomDataPtr; 2208209ff23fSmrg 2209209ff23fSmrg if (!rhdAtomGetTableRevisionAndSize( 2210209ff23fSmrg &(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader), 2211209ff23fSmrg &crev,&frev,NULL)) { 2212209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); 2213209ff23fSmrg return FALSE; 2214209ff23fSmrg } 2215209ff23fSmrg 2216209ff23fSmrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2217209ff23fSmrg ATOM_CONNECTOR_INFO_I2C ci 2218209ff23fSmrg = atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[i]; 2219209ff23fSmrg 2220209ff23fSmrg if (!(le16_to_cpu(atomDataPtr->SupportedDevicesInfo 2221209ff23fSmrg .SupportedDevicesInfo->usDeviceSupport) & (1 << i))) { 2222209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2223209ff23fSmrg continue; 2224209ff23fSmrg } 2225209ff23fSmrg 2226b7e1c893Smrg /* don't support CV yet */ 2227209ff23fSmrg if (i == ATOM_DEVICE_CV_INDEX) { 2228209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping Component Video\n"); 2229209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2230209ff23fSmrg continue; 2231209ff23fSmrg } 2232b7e1c893Smrg 2233b7e1c893Smrg if (!enable_tv && (i == ATOM_DEVICE_TV1_INDEX)) { 2234209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping TV-Out\n"); 2235209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2236209ff23fSmrg continue; 2237209ff23fSmrg } 2238209ff23fSmrg 2239209ff23fSmrg info->BiosConnector[i].valid = TRUE; 2240b7e1c893Smrg info->BiosConnector[i].load_detection = TRUE; 2241b7e1c893Smrg info->BiosConnector[i].shared_ddc = FALSE; 2242209ff23fSmrg info->BiosConnector[i].output_id = ci.sucI2cId.sbfAccess.bfI2C_LineMux; 2243209ff23fSmrg info->BiosConnector[i].devices = (1 << i); 2244209ff23fSmrg info->BiosConnector[i].ConnectorType = ci.sucConnectorInfo.sbfAccess.bfConnectorType; 2245209ff23fSmrg 2246209ff23fSmrg if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 2247209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2248209ff23fSmrg continue; 2249209ff23fSmrg } 2250209ff23fSmrg 2251209ff23fSmrg /* don't assign a gpio for tv */ 2252209ff23fSmrg if ((i == ATOM_DEVICE_TV1_INDEX) || 2253209ff23fSmrg (i == ATOM_DEVICE_TV2_INDEX) || 2254209ff23fSmrg (i == ATOM_DEVICE_CV_INDEX)) 2255209ff23fSmrg info->BiosConnector[i].ddc_i2c.valid = FALSE; 2256b7e1c893Smrg else if ((info->ChipFamily == CHIP_FAMILY_RS690) || 2257209ff23fSmrg (info->ChipFamily == CHIP_FAMILY_RS740)) { 2258c503f109Smrg /* IGP DFP ports sometimes use non-standard gpio entries */ 2259c503f109Smrg if ((i == ATOM_DEVICE_DFP2_INDEX) && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2)) 2260c503f109Smrg info->BiosConnector[i].ddc_i2c = 2261c503f109Smrg RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1); 2262c503f109Smrg else if ((i == ATOM_DEVICE_DFP3_INDEX) && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1)) 2263209ff23fSmrg info->BiosConnector[i].ddc_i2c = 2264209ff23fSmrg RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1); 2265209ff23fSmrg else 2266209ff23fSmrg info->BiosConnector[i].ddc_i2c = 2267209ff23fSmrg RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.sbfAccess.bfI2C_LineMux); 2268209ff23fSmrg } else 2269209ff23fSmrg info->BiosConnector[i].ddc_i2c = 2270209ff23fSmrg RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.sbfAccess.bfI2C_LineMux); 2271209ff23fSmrg 2272b7e1c893Smrg if (!radeon_add_encoder(pScrn, 2273b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, (1 << i), 2274b7e1c893Smrg ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC), 2275b7e1c893Smrg (1 << i))) 2276b7e1c893Smrg return FALSE; 2277209ff23fSmrg 2278209ff23fSmrg /* Always set the connector type to VGA for CRT1/CRT2. if they are 2279209ff23fSmrg * shared with a DVI port, we'll pick up the DVI connector below when we 2280209ff23fSmrg * merge the outputs 2281209ff23fSmrg */ 2282209ff23fSmrg if ((i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) && 2283209ff23fSmrg (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I || 2284209ff23fSmrg info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D || 2285209ff23fSmrg info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A)) { 2286209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; 2287209ff23fSmrg } 2288209ff23fSmrg 2289209ff23fSmrg if (crev > 1) { 2290209ff23fSmrg ATOM_CONNECTOR_INC_SRC_BITMAP isb 2291209ff23fSmrg = atomDataPtr->SupportedDevicesInfo 2292209ff23fSmrg .SupportedDevicesInfo_HD->asIntSrcInfo[i]; 2293209ff23fSmrg 2294209ff23fSmrg switch (isb.ucIntSrcBitmap) { 2295209ff23fSmrg case 0x4: 2296209ff23fSmrg info->BiosConnector[i].hpd_mask = 0x00000001; 2297209ff23fSmrg break; 2298209ff23fSmrg case 0xa: 2299209ff23fSmrg info->BiosConnector[i].hpd_mask = 0x00000100; 2300209ff23fSmrg break; 2301209ff23fSmrg default: 2302209ff23fSmrg info->BiosConnector[i].hpd_mask = 0; 2303209ff23fSmrg break; 2304209ff23fSmrg } 2305b7e1c893Smrg } else 2306209ff23fSmrg info->BiosConnector[i].hpd_mask = 0; 2307209ff23fSmrg 2308209ff23fSmrg RADEONApplyATOMQuirks(pScrn, i); 2309209ff23fSmrg 2310209ff23fSmrg } 2311209ff23fSmrg 2312209ff23fSmrg /* CRTs/DFPs may share a port */ 2313209ff23fSmrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2314209ff23fSmrg if (info->BiosConnector[i].valid) { 2315209ff23fSmrg for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2316209ff23fSmrg if (info->BiosConnector[j].valid && (i != j) ) { 2317209ff23fSmrg if (info->BiosConnector[i].output_id == info->BiosConnector[j].output_id) { 2318209ff23fSmrg if (((i == ATOM_DEVICE_DFP1_INDEX) || 2319209ff23fSmrg (i == ATOM_DEVICE_DFP2_INDEX) || 2320209ff23fSmrg (i == ATOM_DEVICE_DFP3_INDEX)) && 2321b7e1c893Smrg ((j == ATOM_DEVICE_CRT1_INDEX) || 2322b7e1c893Smrg (j == ATOM_DEVICE_CRT2_INDEX))) { 2323209ff23fSmrg info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2324c503f109Smrg if (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) 2325c503f109Smrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; 2326209ff23fSmrg info->BiosConnector[j].valid = FALSE; 2327209ff23fSmrg } else if (((j == ATOM_DEVICE_DFP1_INDEX) || 2328b7e1c893Smrg (j == ATOM_DEVICE_DFP2_INDEX) || 2329b7e1c893Smrg (j == ATOM_DEVICE_DFP3_INDEX)) && 2330b7e1c893Smrg ((i == ATOM_DEVICE_CRT1_INDEX) || 2331b7e1c893Smrg (i == ATOM_DEVICE_CRT2_INDEX))) { 2332209ff23fSmrg info->BiosConnector[j].devices |= info->BiosConnector[i].devices; 2333c503f109Smrg if (info->BiosConnector[j].ConnectorType == CONNECTOR_DVI_D) 2334c503f109Smrg info->BiosConnector[j].ConnectorType = CONNECTOR_DVI_I; 2335209ff23fSmrg info->BiosConnector[i].valid = FALSE; 2336b7e1c893Smrg } else { 2337b7e1c893Smrg info->BiosConnector[i].shared_ddc = TRUE; 2338b7e1c893Smrg info->BiosConnector[j].shared_ddc = TRUE; 2339209ff23fSmrg } 2340209ff23fSmrg /* other possible combos? */ 2341209ff23fSmrg } 2342209ff23fSmrg } 2343209ff23fSmrg } 2344209ff23fSmrg } 2345209ff23fSmrg } 2346209ff23fSmrg 2347209ff23fSmrg for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2348b7e1c893Smrg if (info->encoders[i] != NULL) { 2349b7e1c893Smrg ErrorF("encoder: 0x%x\n", info->encoders[i]->encoder_id); 2350209ff23fSmrg } 2351209ff23fSmrg } 2352209ff23fSmrg 2353209ff23fSmrg return TRUE; 2354209ff23fSmrg} 2355209ff23fSmrg 2356209ff23fSmrg# ifdef ATOM_BIOS_PARSER 2357209ff23fSmrgstatic AtomBiosResult 2358209ff23fSmrgrhdAtomExec (atomBiosHandlePtr handle, 2359209ff23fSmrg AtomBiosRequestID unused, AtomBiosArgPtr data) 2360209ff23fSmrg{ 2361209ff23fSmrg RADEONInfoPtr info = RADEONPTR (xf86Screens[handle->scrnIndex]); 2362209ff23fSmrg Bool ret = FALSE; 2363209ff23fSmrg char *msg; 2364209ff23fSmrg int idx = data->exec.index; 2365209ff23fSmrg void *pspace = data->exec.pspace; 2366209ff23fSmrg pointer *dataSpace = data->exec.dataSpace; 2367209ff23fSmrg 2368209ff23fSmrg //RHDFUNCI(handle->scrnIndex); 2369209ff23fSmrg 2370209ff23fSmrg if (dataSpace) { 2371209ff23fSmrg if (!handle->fbBase && !handle->scratchBase) 2372209ff23fSmrg return ATOM_FAILED; 2373209ff23fSmrg if (handle->fbBase) { 2374209ff23fSmrg if (!info->FB) { 2375209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: " 2376209ff23fSmrg "Cannot exec AtomBIOS: framebuffer not mapped\n", 2377209ff23fSmrg __func__); 2378209ff23fSmrg return ATOM_FAILED; 2379209ff23fSmrg } 2380209ff23fSmrg *dataSpace = (uint8_t*)info->FB + handle->fbBase; 2381209ff23fSmrg } else 2382209ff23fSmrg *dataSpace = (uint8_t*)handle->scratchBase; 2383209ff23fSmrg } 2384209ff23fSmrg ret = ParseTableWrapper(pspace, idx, handle, 2385209ff23fSmrg handle->BIOSBase, 2386209ff23fSmrg &msg); 2387209ff23fSmrg if (!ret) 2388209ff23fSmrg xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s\n",msg); 2389209ff23fSmrg else 2390209ff23fSmrg xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 5, "%s\n",msg); 2391209ff23fSmrg 2392209ff23fSmrg return (ret) ? ATOM_SUCCESS : ATOM_FAILED; 2393209ff23fSmrg} 2394209ff23fSmrg# endif 2395209ff23fSmrg 2396209ff23fSmrgAtomBiosResult 2397209ff23fSmrgRHDAtomBiosFunc(int scrnIndex, atomBiosHandlePtr handle, 2398209ff23fSmrg AtomBiosRequestID id, AtomBiosArgPtr data) 2399209ff23fSmrg{ 2400209ff23fSmrg AtomBiosResult ret = ATOM_FAILED; 2401209ff23fSmrg int i; 2402209ff23fSmrg char *msg = NULL; 2403209ff23fSmrg enum msgDataFormat msg_f = MSG_FORMAT_NONE; 2404209ff23fSmrg AtomBiosRequestFunc req_func = NULL; 2405209ff23fSmrg 2406209ff23fSmrg //RHDFUNCI(scrnIndex); 2407209ff23fSmrg 2408209ff23fSmrg for (i = 0; AtomBiosRequestList[i].id != FUNC_END; i++) { 2409209ff23fSmrg if (id == AtomBiosRequestList[i].id) { 2410209ff23fSmrg req_func = AtomBiosRequestList[i].request; 2411209ff23fSmrg msg = AtomBiosRequestList[i].message; 2412209ff23fSmrg msg_f = AtomBiosRequestList[i].message_format; 2413209ff23fSmrg break; 2414209ff23fSmrg } 2415209ff23fSmrg } 2416209ff23fSmrg 2417209ff23fSmrg if (req_func == NULL) { 2418209ff23fSmrg xf86DrvMsg(scrnIndex, X_ERROR, "Unknown AtomBIOS request: %i\n",id); 2419209ff23fSmrg return ATOM_NOT_IMPLEMENTED; 2420209ff23fSmrg } 2421209ff23fSmrg /* Hack for now */ 2422209ff23fSmrg if (id == ATOMBIOS_INIT) 2423209ff23fSmrg data->val = scrnIndex; 2424209ff23fSmrg 2425209ff23fSmrg if (id == ATOMBIOS_INIT || handle) 2426209ff23fSmrg ret = req_func(handle, id, data); 2427209ff23fSmrg 2428209ff23fSmrg if (ret == ATOM_SUCCESS) { 2429209ff23fSmrg 2430209ff23fSmrg switch (msg_f) { 2431209ff23fSmrg case MSG_FORMAT_DEC: 2432209ff23fSmrg xf86DrvMsg(scrnIndex,X_INFO,"%s: %li\n", msg, 2433209ff23fSmrg (unsigned long) data->val); 2434209ff23fSmrg break; 2435209ff23fSmrg case MSG_FORMAT_HEX: 2436209ff23fSmrg xf86DrvMsg(scrnIndex,X_INFO,"%s: 0x%lx\n",msg , 2437209ff23fSmrg (unsigned long) data->val); 2438209ff23fSmrg break; 2439209ff23fSmrg case MSG_FORMAT_NONE: 2440209ff23fSmrg xf86DrvMsgVerb(scrnIndex, 7, X_INFO, 2441209ff23fSmrg "Call to %s succeeded\n", msg); 2442209ff23fSmrg break; 2443209ff23fSmrg } 2444209ff23fSmrg 2445209ff23fSmrg } else { 2446209ff23fSmrg 2447209ff23fSmrg char *result = (ret == ATOM_FAILED) ? "failed" 2448209ff23fSmrg : "not implemented"; 2449209ff23fSmrg switch (msg_f) { 2450209ff23fSmrg case MSG_FORMAT_DEC: 2451209ff23fSmrg case MSG_FORMAT_HEX: 2452209ff23fSmrg xf86DrvMsgVerb(scrnIndex, 1, X_WARNING, 2453209ff23fSmrg "Call to %s %s\n", msg, result); 2454209ff23fSmrg break; 2455209ff23fSmrg case MSG_FORMAT_NONE: 2456209ff23fSmrg xf86DrvMsg(scrnIndex,X_INFO,"Query for %s: %s\n", msg, result); 2457209ff23fSmrg break; 2458209ff23fSmrg } 2459209ff23fSmrg } 2460209ff23fSmrg return ret; 2461209ff23fSmrg} 2462209ff23fSmrg 2463209ff23fSmrg# ifdef ATOM_BIOS_PARSER 2464209ff23fSmrgVOID* 2465209ff23fSmrgCailAllocateMemory(VOID *CAIL,UINT16 size) 2466209ff23fSmrg{ 2467b7e1c893Smrg void *ret; 2468209ff23fSmrg CAILFUNC(CAIL); 2469209ff23fSmrg 2470b7e1c893Smrg ret = malloc(size); 2471b7e1c893Smrg memset(ret, 0, size); 2472b7e1c893Smrg return ret; 2473209ff23fSmrg} 2474209ff23fSmrg 2475209ff23fSmrgVOID 2476209ff23fSmrgCailReleaseMemory(VOID *CAIL, VOID *addr) 2477209ff23fSmrg{ 2478209ff23fSmrg CAILFUNC(CAIL); 2479209ff23fSmrg 2480209ff23fSmrg free(addr); 2481209ff23fSmrg} 2482209ff23fSmrg 2483209ff23fSmrgVOID 2484209ff23fSmrgCailDelayMicroSeconds(VOID *CAIL, UINT32 delay) 2485209ff23fSmrg{ 2486209ff23fSmrg CAILFUNC(CAIL); 2487209ff23fSmrg 2488209ff23fSmrg usleep(delay); 2489209ff23fSmrg 2490209ff23fSmrg /*DEBUGP(xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_INFO,"Delay %i usec\n",delay));*/ 2491209ff23fSmrg} 2492209ff23fSmrg 2493209ff23fSmrgUINT32 2494209ff23fSmrgCailReadATIRegister(VOID* CAIL, UINT32 idx) 2495209ff23fSmrg{ 2496209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2497209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2498209ff23fSmrg unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2499209ff23fSmrg UINT32 ret; 2500209ff23fSmrg CAILFUNC(CAIL); 2501209ff23fSmrg 2502209ff23fSmrg ret = INREG(idx << 2); 2503209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret));*/ 2504209ff23fSmrg return ret; 2505209ff23fSmrg} 2506209ff23fSmrg 2507209ff23fSmrgVOID 2508209ff23fSmrgCailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data) 2509209ff23fSmrg{ 2510209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2511209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2512209ff23fSmrg unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2513209ff23fSmrg CAILFUNC(CAIL); 2514209ff23fSmrg 2515209ff23fSmrg OUTREG(idx << 2,data); 2516209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx << 2,data));*/ 2517209ff23fSmrg} 2518209ff23fSmrg 2519209ff23fSmrgUINT32 2520209ff23fSmrgCailReadFBData(VOID* CAIL, UINT32 idx) 2521209ff23fSmrg{ 2522209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2523209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 2524209ff23fSmrg UINT32 ret; 2525209ff23fSmrg 2526209ff23fSmrg CAILFUNC(CAIL); 2527209ff23fSmrg 2528209ff23fSmrg if (((atomBiosHandlePtr)CAIL)->fbBase) { 2529209ff23fSmrg uint8_t *FBBase = (uint8_t*)info->FB; 2530209ff23fSmrg ret = *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)); 2531209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2532209ff23fSmrg } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2533209ff23fSmrg ret = *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx); 2534209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2535209ff23fSmrg } else { 2536209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2537209ff23fSmrg "%s: no fbbase set\n",__func__); 2538209ff23fSmrg return 0; 2539209ff23fSmrg } 2540209ff23fSmrg return ret; 2541209ff23fSmrg} 2542209ff23fSmrg 2543209ff23fSmrgVOID 2544209ff23fSmrgCailWriteFBData(VOID *CAIL, UINT32 idx, UINT32 data) 2545209ff23fSmrg{ 2546209ff23fSmrg CAILFUNC(CAIL); 2547209ff23fSmrg 2548209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,data));*/ 2549209ff23fSmrg if (((atomBiosHandlePtr)CAIL)->fbBase) { 2550209ff23fSmrg uint8_t *FBBase = (uint8_t*) 2551209ff23fSmrg RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->FB; 2552209ff23fSmrg *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)) = data; 2553209ff23fSmrg } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2554209ff23fSmrg *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx) = data; 2555209ff23fSmrg } else 2556209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2557209ff23fSmrg "%s: no fbbase set\n",__func__); 2558209ff23fSmrg} 2559209ff23fSmrg 2560209ff23fSmrgULONG 2561209ff23fSmrgCailReadMC(VOID *CAIL, ULONG Address) 2562209ff23fSmrg{ 2563209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2564209ff23fSmrg ULONG ret; 2565209ff23fSmrg 2566209ff23fSmrg CAILFUNC(CAIL); 2567209ff23fSmrg 2568209ff23fSmrg ret = INMC(pScrn, Address); 2569209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2570209ff23fSmrg return ret; 2571209ff23fSmrg} 2572209ff23fSmrg 2573209ff23fSmrgVOID 2574209ff23fSmrgCailWriteMC(VOID *CAIL, ULONG Address, ULONG data) 2575209ff23fSmrg{ 2576209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2577209ff23fSmrg 2578209ff23fSmrg CAILFUNC(CAIL); 2579209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,data));*/ 2580209ff23fSmrg OUTMC(pScrn, Address, data); 2581209ff23fSmrg} 2582209ff23fSmrg 2583209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 2584209ff23fSmrg 2585209ff23fSmrgVOID 2586209ff23fSmrgCailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2587209ff23fSmrg{ 2588209ff23fSmrg pci_device_cfg_read(RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->PciInfo, 2589209ff23fSmrg ret,idx << 2 , size >> 3, NULL); 2590209ff23fSmrg} 2591209ff23fSmrg 2592209ff23fSmrgVOID 2593209ff23fSmrgCailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2594209ff23fSmrg{ 2595209ff23fSmrg pci_device_cfg_write(RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->PciInfo, 2596209ff23fSmrg src, idx << 2, size >> 3, NULL); 2597209ff23fSmrg} 2598209ff23fSmrg 2599209ff23fSmrg#else 2600209ff23fSmrg 2601209ff23fSmrgVOID 2602209ff23fSmrgCailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2603209ff23fSmrg{ 2604209ff23fSmrg PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2605209ff23fSmrg 2606209ff23fSmrg CAILFUNC(CAIL); 2607209ff23fSmrg 2608209ff23fSmrg switch (size) { 2609209ff23fSmrg case 8: 2610209ff23fSmrg *(uint8_t*)ret = pciReadByte(tag,idx << 2); 2611209ff23fSmrg break; 2612209ff23fSmrg case 16: 2613209ff23fSmrg *(uint16_t*)ret = pciReadWord(tag,idx << 2); 2614209ff23fSmrg break; 2615209ff23fSmrg case 32: 2616209ff23fSmrg *(uint32_t*)ret = pciReadLong(tag,idx << 2); 2617209ff23fSmrg break; 2618209ff23fSmrg default: 2619209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex, 2620209ff23fSmrg X_ERROR,"%s: Unsupported size: %i\n", 2621209ff23fSmrg __func__,(int)size); 2622209ff23fSmrg return; 2623209ff23fSmrg break; 2624209ff23fSmrg } 2625209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,*(unsigned int*)ret));*/ 2626209ff23fSmrg 2627209ff23fSmrg} 2628209ff23fSmrg 2629209ff23fSmrgVOID 2630209ff23fSmrgCailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2631209ff23fSmrg{ 2632209ff23fSmrg PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2633209ff23fSmrg 2634209ff23fSmrg CAILFUNC(CAIL); 2635209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,(*(unsigned int*)src)));*/ 2636209ff23fSmrg switch (size) { 2637209ff23fSmrg case 8: 2638209ff23fSmrg pciWriteByte(tag,idx << 2,*(uint8_t*)src); 2639209ff23fSmrg break; 2640209ff23fSmrg case 16: 2641209ff23fSmrg pciWriteWord(tag,idx << 2,*(uint16_t*)src); 2642209ff23fSmrg break; 2643209ff23fSmrg case 32: 2644209ff23fSmrg pciWriteLong(tag,idx << 2,*(uint32_t*)src); 2645209ff23fSmrg break; 2646209ff23fSmrg default: 2647209ff23fSmrg xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2648209ff23fSmrg "%s: Unsupported size: %i\n",__func__,(int)size); 2649209ff23fSmrg break; 2650209ff23fSmrg } 2651209ff23fSmrg} 2652209ff23fSmrg#endif 2653209ff23fSmrg 2654209ff23fSmrgULONG 2655209ff23fSmrgCailReadPLL(VOID *CAIL, ULONG Address) 2656209ff23fSmrg{ 2657209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2658209ff23fSmrg ULONG ret; 2659209ff23fSmrg 2660209ff23fSmrg CAILFUNC(CAIL); 2661209ff23fSmrg 2662209ff23fSmrg ret = RADEONINPLL(pScrn, Address); 2663209ff23fSmrg /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2664209ff23fSmrg return ret; 2665209ff23fSmrg} 2666209ff23fSmrg 2667209ff23fSmrgVOID 2668209ff23fSmrgCailWritePLL(VOID *CAIL, ULONG Address,ULONG Data) 2669209ff23fSmrg{ 2670209ff23fSmrg ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2671209ff23fSmrg CAILFUNC(CAIL); 2672209ff23fSmrg 2673209ff23fSmrg /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,Data));*/ 2674209ff23fSmrg RADEONOUTPLL(pScrn, Address, Data); 2675209ff23fSmrg} 2676209ff23fSmrg 2677209ff23fSmrgvoid 2678209ff23fSmrgatombios_get_command_table_version(atomBiosHandlePtr atomBIOS, int index, int *major, int *minor) 2679209ff23fSmrg{ 2680209ff23fSmrg ATOM_MASTER_COMMAND_TABLE *cmd_table = (void *)(atomBIOS->BIOSBase + atomBIOS->cmd_offset); 2681209ff23fSmrg ATOM_MASTER_LIST_OF_COMMAND_TABLES *table_start; 2682209ff23fSmrg ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *table_hdr; 2683209ff23fSmrg 2684209ff23fSmrg //unsigned short *ptr; 2685209ff23fSmrg unsigned short offset; 2686209ff23fSmrg 2687209ff23fSmrg table_start = &cmd_table->ListOfCommandTables; 2688209ff23fSmrg 2689209ff23fSmrg offset = *(((unsigned short *)table_start) + index); 2690209ff23fSmrg 2691209ff23fSmrg offset = le16_to_cpu(offset); 2692209ff23fSmrg table_hdr = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)(atomBIOS->BIOSBase + offset); 2693209ff23fSmrg 2694209ff23fSmrg *major = table_hdr->CommonHeader.ucTableFormatRevision; 2695209ff23fSmrg *minor = table_hdr->CommonHeader.ucTableContentRevision; 2696209ff23fSmrg} 2697209ff23fSmrg 2698209ff23fSmrg 2699b7e1c893SmrgUINT16 ATOM_BSWAP16(UINT16 x) 2700b7e1c893Smrg{ 2701b7e1c893Smrg return bswap_16(x); 2702b7e1c893Smrg} 2703b7e1c893Smrg 2704b7e1c893SmrgUINT32 ATOM_BSWAP32(UINT32 x) 2705b7e1c893Smrg{ 2706b7e1c893Smrg return bswap_32(x); 2707b7e1c893Smrg} 2708b7e1c893Smrg 2709b7e1c893Smrg 2710209ff23fSmrg#endif /* ATOM_BIOS */ 2711