radeon_atombios.c revision ad43ddac
1/* 2 * Copyright 2007 Egbert Eich <eich@novell.com> 3 * Copyright 2007 Luc Verhaegen <lverhaegen@novell.com> 4 * Copyright 2007 Matthias Hopf <mhopf@novell.com> 5 * Copyright 2007 Advanced Micro Devices, Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26#ifdef HAVE_CONFIG_H 27# include "config.h" 28#endif 29#include "xf86.h" 30#include "xf86_OSproc.h" 31 32#include "radeon.h" 33#include "radeon_reg.h" 34#include "radeon_atombios.h" 35#include "radeon_atomwrapper.h" 36#include "radeon_probe.h" 37#include "radeon_macros.h" 38 39#include "ati_pciids_gen.h" 40 41#include "xorg-server.h" 42 43/* only for testing now */ 44#include "xf86DDC.h" 45 46typedef AtomBiosResult (*AtomBiosRequestFunc)(atomBiosHandlePtr handle, 47 AtomBiosRequestID unused, AtomBiosArgPtr data); 48typedef struct rhdConnectorInfo *rhdConnectorInfoPtr; 49 50static AtomBiosResult rhdAtomInit(atomBiosHandlePtr unused1, 51 AtomBiosRequestID unused2, AtomBiosArgPtr data); 52static AtomBiosResult rhdAtomTearDown(atomBiosHandlePtr handle, 53 AtomBiosRequestID unused1, AtomBiosArgPtr unused2); 54static AtomBiosResult rhdAtomVramInfoQuery(atomBiosHandlePtr handle, 55 AtomBiosRequestID func, AtomBiosArgPtr data); 56static AtomBiosResult rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, 57 AtomBiosRequestID func, AtomBiosArgPtr data); 58static AtomBiosResult rhdAtomAllocateFbScratch(atomBiosHandlePtr handle, 59 AtomBiosRequestID func, AtomBiosArgPtr data); 60static AtomBiosResult rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, 61 AtomBiosRequestID unused, AtomBiosArgPtr data); 62static AtomBiosResult rhdAtomCVGetTimings(atomBiosHandlePtr handle, 63 AtomBiosRequestID unused, AtomBiosArgPtr data); 64static AtomBiosResult rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, 65 AtomBiosRequestID func, AtomBiosArgPtr data); 66static AtomBiosResult rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, 67 AtomBiosRequestID func, AtomBiosArgPtr data); 68static AtomBiosResult rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, 69 AtomBiosRequestID func, AtomBiosArgPtr data); 70/*static AtomBiosResult rhdAtomConnectorInfo(atomBiosHandlePtr handle, 71 AtomBiosRequestID unused, AtomBiosArgPtr data);*/ 72# ifdef ATOM_BIOS_PARSER 73static AtomBiosResult rhdAtomExec(atomBiosHandlePtr handle, 74 AtomBiosRequestID unused, AtomBiosArgPtr data); 75# endif 76static AtomBiosResult 77rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, 78 AtomBiosRequestID func, AtomBiosArgPtr data); 79 80 81static void 82RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds); 83 84 85enum msgDataFormat { 86 MSG_FORMAT_NONE, 87 MSG_FORMAT_HEX, 88 MSG_FORMAT_DEC 89}; 90 91struct atomBIOSRequests { 92 AtomBiosRequestID id; 93 AtomBiosRequestFunc request; 94 char *message; 95 enum msgDataFormat message_format; 96} AtomBiosRequestList [] = { 97 {ATOMBIOS_INIT, rhdAtomInit, 98 "AtomBIOS Init", MSG_FORMAT_NONE}, 99 {ATOMBIOS_TEARDOWN, rhdAtomTearDown, 100 "AtomBIOS Teardown", MSG_FORMAT_NONE}, 101# ifdef ATOM_BIOS_PARSER 102 {ATOMBIOS_EXEC, rhdAtomExec, 103 "AtomBIOS Exec", MSG_FORMAT_NONE}, 104#endif 105 {ATOMBIOS_ALLOCATE_FB_SCRATCH, rhdAtomAllocateFbScratch, 106 "AtomBIOS Set FB Space", MSG_FORMAT_NONE}, 107 /*{ATOMBIOS_GET_CONNECTORS, rhdAtomConnectorInfo, 108 "AtomBIOS Get Connectors", MSG_FORMAT_NONE},*/ 109 {ATOMBIOS_GET_PANEL_MODE, rhdAtomLvdsGetTimings, 110 "AtomBIOS Get Panel Mode", MSG_FORMAT_NONE}, 111 {ATOMBIOS_GET_PANEL_EDID, rhdAtomLvdsGetTimings, 112 "AtomBIOS Get Panel EDID", MSG_FORMAT_NONE}, 113 {GET_DEFAULT_ENGINE_CLOCK, rhdAtomFirmwareInfoQuery, 114 "Default Engine Clock", MSG_FORMAT_DEC}, 115 {GET_DEFAULT_MEMORY_CLOCK, rhdAtomFirmwareInfoQuery, 116 "Default Memory Clock", MSG_FORMAT_DEC}, 117 {GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, 118 "Maximum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, 119 {GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, 120 "Minimum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, 121 {GET_MAX_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, 122 "Maximum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, 123 {GET_MIN_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, 124 "Minimum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, 125 {GET_MAX_PIXEL_CLK, rhdAtomFirmwareInfoQuery, 126 "Maximum Pixel Clock", MSG_FORMAT_DEC}, 127 {GET_REF_CLOCK, rhdAtomFirmwareInfoQuery, 128 "Reference Clock", MSG_FORMAT_DEC}, 129 {GET_FW_FB_START, rhdAtomVramInfoQuery, 130 "Start of VRAM area used by Firmware", MSG_FORMAT_HEX}, 131 {GET_FW_FB_SIZE, rhdAtomVramInfoQuery, 132 "Framebuffer space used by Firmware (kb)", MSG_FORMAT_DEC}, 133 {ATOM_TMDS_FREQUENCY, rhdAtomTmdsInfoQuery, 134 "TMDS Frequency", MSG_FORMAT_DEC}, 135 {ATOM_TMDS_PLL_CHARGE_PUMP, rhdAtomTmdsInfoQuery, 136 "TMDS PLL ChargePump", MSG_FORMAT_DEC}, 137 {ATOM_TMDS_PLL_DUTY_CYCLE, rhdAtomTmdsInfoQuery, 138 "TMDS PLL DutyCycle", MSG_FORMAT_DEC}, 139 {ATOM_TMDS_PLL_VCO_GAIN, rhdAtomTmdsInfoQuery, 140 "TMDS PLL VCO Gain", MSG_FORMAT_DEC}, 141 {ATOM_TMDS_PLL_VOLTAGE_SWING, rhdAtomTmdsInfoQuery, 142 "TMDS PLL VoltageSwing", MSG_FORMAT_DEC}, 143 {ATOM_LVDS_SUPPORTED_REFRESH_RATE, rhdAtomLvdsInfoQuery, 144 "LVDS Supported Refresh Rate", MSG_FORMAT_DEC}, 145 {ATOM_LVDS_OFF_DELAY, rhdAtomLvdsInfoQuery, 146 "LVDS Off Delay", MSG_FORMAT_DEC}, 147 {ATOM_LVDS_SEQ_DIG_ONTO_DE, rhdAtomLvdsInfoQuery, 148 "LVDS SEQ Dig onto DE", MSG_FORMAT_DEC}, 149 {ATOM_LVDS_SEQ_DE_TO_BL, rhdAtomLvdsInfoQuery, 150 "LVDS SEQ DE to BL", MSG_FORMAT_DEC}, 151 {ATOM_LVDS_DITHER, rhdAtomLvdsInfoQuery, 152 "LVDS Ditherc", MSG_FORMAT_HEX}, 153 {ATOM_LVDS_DUALLINK, rhdAtomLvdsInfoQuery, 154 "LVDS Duallink", MSG_FORMAT_HEX}, 155 {ATOM_LVDS_GREYLVL, rhdAtomLvdsInfoQuery, 156 "LVDS Grey Level", MSG_FORMAT_HEX}, 157 {ATOM_LVDS_FPDI, rhdAtomLvdsInfoQuery, 158 "LVDS FPDI", MSG_FORMAT_HEX}, 159 {ATOM_LVDS_24BIT, rhdAtomLvdsInfoQuery, 160 "LVDS 24Bit", MSG_FORMAT_HEX}, 161 {ATOM_GPIO_I2C_CLK_MASK, rhdAtomGPIOI2CInfoQuery, 162 "GPIO_I2C_Clk_Mask", MSG_FORMAT_HEX}, 163 {ATOM_DAC1_BG_ADJ, rhdAtomCompassionateDataQuery, 164 "DAC1 BG Adjustment", MSG_FORMAT_HEX}, 165 {ATOM_DAC1_DAC_ADJ, rhdAtomCompassionateDataQuery, 166 "DAC1 DAC Adjustment", MSG_FORMAT_HEX}, 167 {ATOM_DAC1_FORCE, rhdAtomCompassionateDataQuery, 168 "DAC1 Force Data", MSG_FORMAT_HEX}, 169 {ATOM_DAC2_CRTC2_BG_ADJ, rhdAtomCompassionateDataQuery, 170 "DAC2_CRTC2 BG Adjustment", MSG_FORMAT_HEX}, 171 {ATOM_DAC2_CRTC2_DAC_ADJ, rhdAtomCompassionateDataQuery, 172 "DAC2_CRTC2 DAC Adjustment", MSG_FORMAT_HEX}, 173 {ATOM_DAC2_CRTC2_FORCE, rhdAtomCompassionateDataQuery, 174 "DAC2_CRTC2 Force", MSG_FORMAT_HEX}, 175 {ATOM_DAC2_CRTC2_MUX_REG_IND,rhdAtomCompassionateDataQuery, 176 "DAC2_CRTC2 Mux Register Index", MSG_FORMAT_HEX}, 177 {ATOM_DAC2_CRTC2_MUX_REG_INFO,rhdAtomCompassionateDataQuery, 178 "DAC2_CRTC2 Mux Register Info", MSG_FORMAT_HEX}, 179 {ATOMBIOS_GET_CV_MODES, rhdAtomCVGetTimings, 180 "AtomBIOS Get CV Mode", MSG_FORMAT_NONE}, 181 {FUNC_END, NULL, 182 NULL, MSG_FORMAT_NONE} 183}; 184 185enum { 186 legacyBIOSLocation = 0xC0000, 187 legacyBIOSMax = 0x10000 188}; 189 190#define DEBUGP(x) {x;} 191#define LOG_DEBUG 7 192 193# ifdef ATOM_BIOS_PARSER 194 195# define LOG_CAIL LOG_DEBUG + 1 196 197#if 0 198 199static void 200RHDDebug(int scrnIndex, const char *format, ...) 201{ 202 va_list ap; 203 204 va_start(ap, format); 205 xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_DEBUG, format, ap); 206 va_end(ap); 207} 208 209static void 210RHDDebugCont(const char *format, ...) 211{ 212 va_list ap; 213 214 va_start(ap, format); 215 xf86VDrvMsgVerb(-1, X_NONE, LOG_DEBUG, format, ap); 216 va_end(ap); 217} 218 219#endif 220 221static void 222CailDebug(int scrnIndex, const char *format, ...) 223{ 224 va_list ap; 225 226 va_start(ap, format); 227 xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_CAIL, format, ap); 228 va_end(ap); 229} 230# define CAILFUNC(ptr) \ 231 CailDebug(((atomBiosHandlePtr)(ptr))->scrnIndex, "CAIL: %s\n", __func__) 232 233# endif 234 235static int 236rhdAtomAnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr) 237{ 238 if (le16_to_cpu(hdr->usStructureSize) == 0xaa55) 239 return FALSE; 240 241 return TRUE; 242} 243 244static int 245rhdAtomAnalyzeRomHdr(unsigned char *rombase, 246 ATOM_ROM_HEADER *hdr, 247 unsigned int *data_offset, 248 unsigned int *command_offset) 249{ 250 if (!rhdAtomAnalyzeCommonHdr(&hdr->sHeader)) { 251 return FALSE; 252 } 253 xf86DrvMsg(-1,X_NONE,"\tSubsystemVendorID: 0x%4.4x SubsystemID: 0x%4.4x\n", 254 le16_to_cpu(hdr->usSubsystemVendorID),le16_to_cpu(hdr->usSubsystemID)); 255 xf86DrvMsg(-1,X_NONE,"\tIOBaseAddress: 0x%4.4x\n",le16_to_cpu(hdr->usIoBaseAddress)); 256 xf86DrvMsgVerb(-1,X_NONE,3,"\tFilename: %s\n",rombase + le16_to_cpu(hdr->usConfigFilenameOffset)); 257 xf86DrvMsgVerb(-1,X_NONE,3,"\tBIOS Bootup Message: %s\n", 258 rombase + le16_to_cpu(hdr->usBIOS_BootupMessageOffset)); 259 260 *data_offset = le16_to_cpu(hdr->usMasterDataTableOffset); 261 *command_offset = le16_to_cpu(hdr->usMasterCommandTableOffset); 262 263 return TRUE; 264} 265 266static int 267rhdAtomAnalyzeRomDataTable(unsigned char *base, uint16_t offset, 268 void *ptr,unsigned short *size) 269{ 270 ATOM_COMMON_TABLE_HEADER *table = (ATOM_COMMON_TABLE_HEADER *) 271 (base + le16_to_cpu(offset)); 272 273 if (!*size || !rhdAtomAnalyzeCommonHdr(table)) { 274 if (*size) *size -= 2; 275 *(void **)ptr = NULL; 276 return FALSE; 277 } 278 *size -= 2; 279 *(void **)ptr = (void *)(table); 280 return TRUE; 281} 282 283Bool 284rhdAtomGetTableRevisionAndSize(ATOM_COMMON_TABLE_HEADER *hdr, 285 uint8_t *contentRev, 286 uint8_t *formatRev, 287 unsigned short *size) 288{ 289 if (!hdr) 290 return FALSE; 291 292 if (contentRev) *contentRev = hdr->ucTableContentRevision; 293 if (formatRev) *formatRev = hdr->ucTableFormatRevision; 294 if (size) *size = (short)le16_to_cpu(hdr->usStructureSize) 295 - sizeof(ATOM_COMMON_TABLE_HEADER); 296 return TRUE; 297} 298 299static Bool 300rhdAtomAnalyzeMasterDataTable(unsigned char *base, 301 ATOM_MASTER_DATA_TABLE *table, 302 atomDataTablesPtr data) 303{ 304 ATOM_MASTER_LIST_OF_DATA_TABLES *data_table = 305 &table->ListOfDataTables; 306 unsigned short size; 307 308 if (!rhdAtomAnalyzeCommonHdr(&table->sHeader)) 309 return FALSE; 310 if (!rhdAtomGetTableRevisionAndSize(&table->sHeader,NULL,NULL, 311 &size)) 312 return FALSE; 313# define SET_DATA_TABLE(x) {\ 314 rhdAtomAnalyzeRomDataTable(base,data_table->x,(void *)(&(data->x)),&size); \ 315 } 316 317# define SET_DATA_TABLE_VERS(x) {\ 318 rhdAtomAnalyzeRomDataTable(base,data_table->x,&(data->x.base),&size); \ 319 } 320 321 SET_DATA_TABLE(UtilityPipeLine); 322 SET_DATA_TABLE(MultimediaCapabilityInfo); 323 SET_DATA_TABLE(MultimediaConfigInfo); 324 SET_DATA_TABLE(StandardVESA_Timing); 325 SET_DATA_TABLE_VERS(FirmwareInfo); 326 SET_DATA_TABLE(DAC_Info); 327 SET_DATA_TABLE_VERS(LVDS_Info); 328 SET_DATA_TABLE(TMDS_Info); 329 SET_DATA_TABLE_VERS(AnalogTV_Info); 330 SET_DATA_TABLE_VERS(SupportedDevicesInfo); 331 SET_DATA_TABLE(GPIO_I2C_Info); 332 SET_DATA_TABLE(VRAM_UsageByFirmware); 333 SET_DATA_TABLE(GPIO_Pin_LUT); 334 SET_DATA_TABLE(VESA_ToInternalModeLUT); 335 SET_DATA_TABLE_VERS(ComponentVideoInfo); 336 SET_DATA_TABLE(PowerPlayInfo); 337 SET_DATA_TABLE(CompassionateData); 338 SET_DATA_TABLE(SaveRestoreInfo); 339 SET_DATA_TABLE(PPLL_SS_Info); 340 SET_DATA_TABLE(OemInfo); 341 SET_DATA_TABLE(XTMDS_Info); 342 SET_DATA_TABLE(MclkSS_Info); 343 SET_DATA_TABLE(Object_Header); 344 SET_DATA_TABLE(IndirectIOAccess); 345 SET_DATA_TABLE(MC_InitParameter); 346 SET_DATA_TABLE(ASIC_VDDC_Info); 347 SET_DATA_TABLE(ASIC_InternalSS_Info); 348 SET_DATA_TABLE(TV_VideoMode); 349 SET_DATA_TABLE_VERS(VRAM_Info); 350 SET_DATA_TABLE(MemoryTrainingInfo); 351 SET_DATA_TABLE_VERS(IntegratedSystemInfo); 352 SET_DATA_TABLE(ASIC_ProfilingInfo); 353 SET_DATA_TABLE(VoltageObjectInfo); 354 SET_DATA_TABLE(PowerSourceInfo); 355# undef SET_DATA_TABLE 356 357 return TRUE; 358} 359 360static Bool 361rhdAtomGetDataTable(int scrnIndex, 362 unsigned char *base, 363 atomDataTables *atomDataPtr, 364 unsigned int *cmd_offset, 365 unsigned int BIOSImageSize) 366{ 367 unsigned int data_offset; 368 unsigned int atom_romhdr_off = le16_to_cpu(*(unsigned short*) 369 (base + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); 370 ATOM_ROM_HEADER *atom_rom_hdr = 371 (ATOM_ROM_HEADER *)(base + atom_romhdr_off); 372 373 //RHDFUNCI(scrnIndex); 374 375 if (atom_romhdr_off + sizeof(ATOM_ROM_HEADER) > BIOSImageSize) { 376 xf86DrvMsg(scrnIndex,X_ERROR, 377 "%s: AtomROM header extends beyond BIOS image\n",__func__); 378 return FALSE; 379 } 380 381 if (memcmp("ATOM",&atom_rom_hdr->uaFirmWareSignature,4)) { 382 xf86DrvMsg(scrnIndex,X_ERROR,"%s: No AtomBios signature found\n", 383 __func__); 384 return FALSE; 385 } 386 xf86DrvMsg(scrnIndex, X_INFO, "ATOM BIOS Rom: \n"); 387 if (!rhdAtomAnalyzeRomHdr(base, atom_rom_hdr, &data_offset, cmd_offset)) { 388 xf86DrvMsg(scrnIndex, X_ERROR, "RomHeader invalid\n"); 389 return FALSE; 390 } 391 392 if (data_offset + sizeof (ATOM_MASTER_DATA_TABLE) > BIOSImageSize) { 393 xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom data table outside of BIOS\n", 394 __func__); 395 } 396 397 if (*cmd_offset + sizeof (ATOM_MASTER_COMMAND_TABLE) > BIOSImageSize) { 398 xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom command table outside of BIOS\n", 399 __func__); 400 } 401 402 if (!rhdAtomAnalyzeMasterDataTable(base, (ATOM_MASTER_DATA_TABLE *) 403 (base + data_offset), 404 atomDataPtr)) { 405 xf86DrvMsg(scrnIndex, X_ERROR, "%s: ROM Master Table invalid\n", 406 __func__); 407 return FALSE; 408 } 409 return TRUE; 410} 411 412static Bool 413rhdAtomGetFbBaseAndSize(atomBiosHandlePtr handle, unsigned int *base, 414 unsigned int *size) 415{ 416 AtomBiosArgRec data; 417 if (RHDAtomBiosFunc(handle->scrnIndex, handle, GET_FW_FB_SIZE, &data) 418 == ATOM_SUCCESS) { 419 if (data.val == 0) { 420 xf86DrvMsg(handle->scrnIndex, X_WARNING, "%s: AtomBIOS specified VRAM " 421 "scratch space size invalid\n", __func__); 422 return FALSE; 423 } 424 if (size) 425 *size = (int)data.val; 426 } else 427 return FALSE; 428 if (RHDAtomBiosFunc(handle->scrnIndex, handle, GET_FW_FB_START, &data) 429 == ATOM_SUCCESS) { 430 if (data.val == 0) 431 return FALSE; 432 if (base) 433 *base = (int)data.val; 434 } 435 return TRUE; 436} 437 438/* 439 * Uses videoRam form ScrnInfoRec. 440 */ 441static AtomBiosResult 442rhdAtomAllocateFbScratch(atomBiosHandlePtr handle, 443 AtomBiosRequestID func, AtomBiosArgPtr data) 444{ 445 unsigned int fb_base = 0; 446 unsigned int fb_size = 0; 447 unsigned int start = data->fb.start; 448 unsigned int size = data->fb.size; 449 handle->scratchBase = NULL; 450 handle->fbBase = 0; 451 452 if (rhdAtomGetFbBaseAndSize(handle, &fb_base, &fb_size)) { 453 xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS requests %ikB" 454 " of VRAM scratch space\n",fb_size); 455 fb_size *= 1024; /* convert to bytes */ 456 xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS VRAM scratch base: 0x%x\n", 457 fb_base); 458 } else { 459 fb_size = 20 * 1024; 460 xf86DrvMsg(handle->scrnIndex, X_INFO, " default to: %i\n",fb_size); 461 } 462 if (fb_base && fb_size && size) { 463 /* 4k align */ 464 fb_size = (fb_size & ~(uint32_t)0xfff) + ((fb_size & 0xfff) ? 1 : 0); 465 if ((fb_base + fb_size) > (start + size)) { 466 xf86DrvMsg(handle->scrnIndex, X_WARNING, 467 "%s: FW FB scratch area %i (size: %i)" 468 " extends beyond available framebuffer size %i\n", 469 __func__, fb_base, fb_size, size); 470 } else if ((fb_base + fb_size) < (start + size)) { 471 xf86DrvMsg(handle->scrnIndex, X_WARNING, 472 "%s: FW FB scratch area not located " 473 "at the end of VRAM. Scratch End: " 474 "0x%x VRAM End: 0x%x\n", __func__, 475 (unsigned int)(fb_base + fb_size), 476 size); 477 } else if (fb_base < start) { 478 xf86DrvMsg(handle->scrnIndex, X_WARNING, 479 "%s: FW FB scratch area extends below " 480 "the base of the free VRAM: 0x%x Base: 0x%x\n", 481 __func__, (unsigned int)(fb_base), start); 482 } else { 483 size -= fb_size; 484 handle->fbBase = fb_base; 485 return ATOM_SUCCESS; 486 } 487 } 488 489 if (!handle->fbBase) { 490 xf86DrvMsg(handle->scrnIndex, X_INFO, 491 "Cannot get VRAM scratch space. " 492 "Allocating in main memory instead\n"); 493 handle->scratchBase = xcalloc(fb_size,1); 494 return ATOM_SUCCESS; 495 } 496 return ATOM_FAILED; 497} 498 499# ifdef ATOM_BIOS_PARSER 500Bool 501rhdAtomASICInit(atomBiosHandlePtr handle) 502{ 503 ASIC_INIT_PS_ALLOCATION asicInit; 504 AtomBiosArgRec data; 505 506 RHDAtomBiosFunc(handle->scrnIndex, handle, 507 GET_DEFAULT_ENGINE_CLOCK, 508 &data); 509 asicInit.sASICInitClocks.ulDefaultEngineClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 510 RHDAtomBiosFunc(handle->scrnIndex, handle, 511 GET_DEFAULT_MEMORY_CLOCK, 512 &data); 513 asicInit.sASICInitClocks.ulDefaultMemoryClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 514 data.exec.dataSpace = NULL; 515 data.exec.index = 0x0; 516 data.exec.pspace = &asicInit; 517 xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling ASIC Init\n"); 518 if (RHDAtomBiosFunc(handle->scrnIndex, handle, 519 ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 520 xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Successful\n"); 521 return TRUE; 522 } 523 xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Failed\n"); 524 return FALSE; 525} 526 527int 528atombios_clk_gating_setup(ScrnInfoPtr pScrn, Bool enable) 529{ 530 RADEONInfoPtr info = RADEONPTR(pScrn); 531 DYNAMIC_CLOCK_GATING_PS_ALLOCATION dynclk_data; 532 AtomBiosArgRec data; 533 unsigned char *space; 534 535 dynclk_data.ucEnable = enable; 536 537 data.exec.index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); 538 data.exec.dataSpace = (void *)&space; 539 data.exec.pspace = &dynclk_data; 540 541 if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 542 ErrorF("Dynamic clock gating %s success\n", enable? "enable" : "disable"); 543 return ATOM_SUCCESS; 544 } 545 546 ErrorF("Dynamic clock gating %s failure\n", enable? "enable" : "disable"); 547 return ATOM_NOT_IMPLEMENTED; 548 549} 550 551int 552atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, Bool enable) 553{ 554 RADEONInfoPtr info = RADEONPTR(pScrn); 555 ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION pwrmgt_data; 556 AtomBiosArgRec data; 557 unsigned char *space; 558 559 /* disabling static power management causes hangs on some r4xx chips */ 560 if (((info->ChipFamily == CHIP_FAMILY_R420) || 561 (info->ChipFamily == CHIP_FAMILY_RV410)) && 562 !enable) 563 return ATOM_NOT_IMPLEMENTED; 564 565 pwrmgt_data.ucEnable = enable; 566 567 data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt); 568 data.exec.dataSpace = (void *)&space; 569 data.exec.pspace = &pwrmgt_data; 570 571 if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 572 ErrorF("Static power management %s success\n", enable? "enable" : "disable"); 573 return ATOM_SUCCESS; 574 } 575 576 ErrorF("Static power management %s failure\n", enable? "enable" : "disable"); 577 return ATOM_NOT_IMPLEMENTED; 578 579} 580 581int 582atombios_set_engine_clock(ScrnInfoPtr pScrn, uint32_t engclock) 583{ 584 RADEONInfoPtr info = RADEONPTR(pScrn); 585 SET_ENGINE_CLOCK_PS_ALLOCATION eng_clock_ps; 586 AtomBiosArgRec data; 587 unsigned char *space; 588 589 RADEONWaitForIdleMMIO(pScrn); 590 591 eng_clock_ps.ulTargetEngineClock = engclock; /* 10 khz */ 592 593 /*ErrorF("Attempting to set engine clock to: %d\n", engclock);*/ 594 data.exec.index = GetIndexIntoMasterTable(COMMAND, SetEngineClock); 595 data.exec.dataSpace = (void *)&space; 596 data.exec.pspace = &eng_clock_ps; 597 598 if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 599 /* ErrorF("Set engine clock success\n"); */ 600 return ATOM_SUCCESS; 601 } 602 /* ErrorF("Set engine clock failed\n"); */ 603 return ATOM_NOT_IMPLEMENTED; 604} 605 606int 607atombios_set_memory_clock(ScrnInfoPtr pScrn, uint32_t memclock) 608{ 609 RADEONInfoPtr info = RADEONPTR(pScrn); 610 SET_MEMORY_CLOCK_PS_ALLOCATION mem_clock_ps; 611 AtomBiosArgRec data; 612 unsigned char *space; 613 614 if (info->IsIGP) 615 return ATOM_SUCCESS; 616 617 RADEONWaitForIdleMMIO(pScrn); 618 619 mem_clock_ps.ulTargetMemoryClock = memclock; /* 10 khz */ 620 621 /* ErrorF("Attempting to set mem clock to: %d\n", memclock); */ 622 data.exec.index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock); 623 data.exec.dataSpace = (void *)&space; 624 data.exec.pspace = &mem_clock_ps; 625 626 if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 627 /* ErrorF("Set memory clock success\n"); */ 628 return ATOM_SUCCESS; 629 } 630 /* ErrorF("Set memory clock failed\n"); */ 631 return ATOM_NOT_IMPLEMENTED; 632} 633 634# endif 635 636static AtomBiosResult 637rhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2, 638 AtomBiosArgPtr data) 639{ 640 int scrnIndex = data->val; 641 RADEONInfoPtr info = RADEONPTR(xf86Screens[scrnIndex]); 642 atomDataTablesPtr atomDataPtr; 643 unsigned int cmd_offset; 644 atomBiosHandlePtr handle = NULL; 645 unsigned int BIOSImageSize = 0; 646 data->atomhandle = NULL; 647 648#ifdef XSERVER_LIBPCIACCESS 649 BIOSImageSize = info->PciInfo->rom_size > RADEON_VBIOS_SIZE ? info->PciInfo->rom_size : RADEON_VBIOS_SIZE; 650#else 651 BIOSImageSize = RADEON_VBIOS_SIZE; 652#endif 653 654 if (!(atomDataPtr = xcalloc(1, sizeof(atomDataTables)))) { 655 xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory for " 656 "ATOM BIOS data tabes\n"); 657 goto error; 658 } 659 if (!rhdAtomGetDataTable(scrnIndex, info->VBIOS, atomDataPtr, &cmd_offset, BIOSImageSize)) 660 goto error1; 661 if (!(handle = xcalloc(1, sizeof(atomBiosHandleRec)))) { 662 xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory\n"); 663 goto error1; 664 } 665 handle->BIOSBase = info->VBIOS; 666 handle->atomDataPtr = atomDataPtr; 667 handle->cmd_offset = cmd_offset; 668 handle->scrnIndex = scrnIndex; 669#if XSERVER_LIBPCIACCESS 670 handle->device = info->PciInfo; 671#else 672 handle->PciTag = info->PciTag; 673#endif 674 handle->BIOSImageSize = BIOSImageSize; 675 676 data->atomhandle = handle; 677 return ATOM_SUCCESS; 678 679 error1: 680 xfree(atomDataPtr); 681 error: 682 return ATOM_FAILED; 683} 684 685static AtomBiosResult 686rhdAtomTearDown(atomBiosHandlePtr handle, 687 AtomBiosRequestID unused1, AtomBiosArgPtr unused2) 688{ 689 //RHDFUNC(handle); 690 691 xfree(handle->BIOSBase); 692 xfree(handle->atomDataPtr); 693 if (handle->scratchBase) xfree(handle->scratchBase); 694 xfree(handle); 695 return ATOM_SUCCESS; 696} 697 698static AtomBiosResult 699rhdAtomVramInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func, 700 AtomBiosArgPtr data) 701{ 702 atomDataTablesPtr atomDataPtr; 703 uint32_t *val = &data->val; 704 //RHDFUNC(handle); 705 706 atomDataPtr = handle->atomDataPtr; 707 708 switch (func) { 709 case GET_FW_FB_START: 710 if (atomDataPtr->VRAM_UsageByFirmware) 711 *val = le32_to_cpu(atomDataPtr->VRAM_UsageByFirmware 712 ->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware); 713 else 714 return ATOM_NOT_IMPLEMENTED; 715 break; 716 case GET_FW_FB_SIZE: 717 if (atomDataPtr->VRAM_UsageByFirmware) 718 *val = le16_to_cpu(atomDataPtr->VRAM_UsageByFirmware 719 ->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); 720 else 721 return ATOM_NOT_IMPLEMENTED; 722 break; 723 default: 724 return ATOM_NOT_IMPLEMENTED; 725 } 726 return ATOM_SUCCESS; 727} 728 729static AtomBiosResult 730rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, 731 AtomBiosRequestID func, AtomBiosArgPtr data) 732{ 733 atomDataTablesPtr atomDataPtr; 734 uint32_t *val = &data->val; 735 int idx = *val; 736 737 atomDataPtr = handle->atomDataPtr; 738 if (!rhdAtomGetTableRevisionAndSize( 739 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->TMDS_Info), 740 NULL,NULL,NULL)) { 741 return ATOM_FAILED; 742 } 743 744 //RHDFUNC(handle); 745 746 switch (func) { 747 case ATOM_TMDS_FREQUENCY: 748 *val = le16_to_cpu(atomDataPtr->TMDS_Info->asMiscInfo[idx].usFrequency); 749 break; 750 case ATOM_TMDS_PLL_CHARGE_PUMP: 751 *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_ChargePump; 752 break; 753 case ATOM_TMDS_PLL_DUTY_CYCLE: 754 *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_DutyCycle; 755 break; 756 case ATOM_TMDS_PLL_VCO_GAIN: 757 *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_VCO_Gain; 758 break; 759 case ATOM_TMDS_PLL_VOLTAGE_SWING: 760 *val = atomDataPtr->TMDS_Info->asMiscInfo[idx].ucPLL_VoltageSwing; 761 break; 762 default: 763 return ATOM_NOT_IMPLEMENTED; 764 } 765 return ATOM_SUCCESS; 766} 767 768static DisplayModePtr 769rhdAtomDTDTimings(atomBiosHandlePtr handle, ATOM_DTD_FORMAT *dtd) 770{ 771 DisplayModePtr mode; 772#define NAME_LEN 16 773 char name[NAME_LEN]; 774 775 //RHDFUNC(handle); 776 777 if (!dtd->usHActive || !dtd->usVActive) 778 return NULL; 779 780 if (!(mode = (DisplayModePtr)xcalloc(1,sizeof(DisplayModeRec)))) 781 return NULL; 782 783 mode->CrtcHDisplay = mode->HDisplay = le16_to_cpu(dtd->usHActive); 784 mode->CrtcVDisplay = mode->VDisplay = le16_to_cpu(dtd->usVActive); 785 mode->CrtcHBlankStart = dtd->usHActive + dtd->ucHBorder; 786 mode->CrtcHBlankEnd = mode->CrtcHBlankStart + le16_to_cpu(dtd->usHBlanking_Time); 787 mode->CrtcHTotal = mode->HTotal = mode->CrtcHBlankEnd + dtd->ucHBorder; 788 mode->CrtcVBlankStart = dtd->usVActive + dtd->ucVBorder; 789 mode->CrtcVBlankEnd = mode->CrtcVBlankStart + le16_to_cpu(dtd->usVBlanking_Time); 790 mode->CrtcVTotal = mode->VTotal = mode->CrtcVBlankEnd + dtd->ucVBorder; 791 mode->CrtcHSyncStart = mode->HSyncStart = dtd->usHActive + le16_to_cpu(dtd->usHSyncOffset); 792 mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + le16_to_cpu(dtd->usHSyncWidth); 793 mode->CrtcVSyncStart = mode->VSyncStart = dtd->usVActive + le16_to_cpu(dtd->usVSyncOffset); 794 mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + le16_to_cpu(dtd->usVSyncWidth); 795 796 mode->SynthClock = mode->Clock = le16_to_cpu(dtd->usPixClk) * 10; 797 798 mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal); 799 mode->VRefresh = (1000.0 * ((float) mode->Clock)) 800 / ((float)(((float)mode->HTotal) * ((float)mode->VTotal))); 801 802 if (dtd->susModeMiscInfo.sbfAccess.CompositeSync) 803 mode->Flags |= V_CSYNC; 804 if (dtd->susModeMiscInfo.sbfAccess.Interlace) 805 mode->Flags |= V_INTERLACE; 806 if (dtd->susModeMiscInfo.sbfAccess.DoubleClock) 807 mode->Flags |= V_DBLSCAN; 808 if (dtd->susModeMiscInfo.sbfAccess.VSyncPolarity) 809 mode->Flags |= V_NVSYNC; 810 if (dtd->susModeMiscInfo.sbfAccess.HSyncPolarity) 811 mode->Flags |= V_NHSYNC; 812 813 snprintf(name, NAME_LEN, "%dx%d", 814 mode->HDisplay, mode->VDisplay); 815 mode->name = xstrdup(name); 816 817 ErrorF("DTD Modeline: %s " 818 "%2.d %i (%i) %i %i (%i) %i %i (%i) %i %i (%i) %i flags: 0x%x\n", 819 mode->name, mode->Clock, 820 mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd, 821 mode->CrtcHBlankEnd, mode->HTotal, 822 mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd, 823 mode->CrtcVBlankEnd, mode->VTotal, mode->Flags); 824 825 return mode; 826} 827 828static unsigned char* 829rhdAtomLvdsDDC(atomBiosHandlePtr handle, uint32_t offset, unsigned char *record) 830{ 831 unsigned char *EDIDBlock; 832 833 //RHDFUNC(handle); 834 835 while (*record != ATOM_RECORD_END_TYPE) { 836 837 switch (*record) { 838 case LCD_MODE_PATCH_RECORD_MODE_TYPE: 839 offset += sizeof(ATOM_PATCH_RECORD_MODE); 840 if (offset > handle->BIOSImageSize) break; 841 record += sizeof(ATOM_PATCH_RECORD_MODE); 842 break; 843 844 case LCD_RTS_RECORD_TYPE: 845 offset += sizeof(ATOM_LCD_RTS_RECORD); 846 if (offset > handle->BIOSImageSize) break; 847 record += sizeof(ATOM_LCD_RTS_RECORD); 848 break; 849 850 case LCD_CAP_RECORD_TYPE: 851 offset += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 852 if (offset > handle->BIOSImageSize) break; 853 record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 854 break; 855 856 case LCD_FAKE_EDID_PATCH_RECORD_TYPE: 857 offset += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); 858 /* check if the structure still fully lives in the BIOS image */ 859 if (offset > handle->BIOSImageSize) break; 860 offset += ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength 861 - sizeof(UCHAR); 862 if (offset > handle->BIOSImageSize) break; 863 /* dup string as we free it later */ 864 if (!(EDIDBlock = (unsigned char *)xalloc( 865 ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength))) 866 return NULL; 867 memcpy(EDIDBlock,&((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDString, 868 ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength); 869 870 /* for testing */ 871 { 872 xf86MonPtr mon = xf86InterpretEDID(handle->scrnIndex,EDIDBlock); 873 xf86PrintEDID(mon); 874 xfree(mon); 875 } 876 return EDIDBlock; 877 878 case LCD_PANEL_RESOLUTION_RECORD_TYPE: 879 offset += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 880 if (offset > handle->BIOSImageSize) break; 881 record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 882 break; 883 884 default: 885 xf86DrvMsg(handle->scrnIndex, X_ERROR, 886 "%s: unknown record type: %x\n",__func__,*record); 887 return NULL; 888 } 889 } 890 891 return NULL; 892} 893 894static AtomBiosResult 895rhdAtomCVGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, 896 AtomBiosArgPtr data) 897{ 898 atomDataTablesPtr atomDataPtr; 899 uint8_t crev, frev; 900 DisplayModePtr last = NULL; 901 DisplayModePtr new = NULL; 902 DisplayModePtr first = NULL; 903 int i; 904 uint16_t size; 905 906 data->modes = NULL; 907 908 atomDataPtr = handle->atomDataPtr; 909 910 if (!rhdAtomGetTableRevisionAndSize( 911 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->ComponentVideoInfo.base), 912 &crev,&frev,&size)) { 913 return ATOM_FAILED; 914 } 915 916 switch (frev) { 917 case 1: 918 switch (func) { 919 case ATOMBIOS_GET_CV_MODES: 920 for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { 921 new = rhdAtomDTDTimings(handle, 922 &atomDataPtr->ComponentVideoInfo 923 .ComponentVideoInfo->aModeTimings[i]); 924 925 if (!new) 926 continue; 927 928 new->type |= M_T_DRIVER; 929 new->next = NULL; 930 new->prev = last; 931 932 if (last) last->next = new; 933 last = new; 934 if (!first) first = new; 935 } 936 if (last) { 937 last->next = NULL; //first; 938 first->prev = NULL; //last; 939 data->modes = first; 940 } 941 if (data->modes) 942 return ATOM_SUCCESS; 943 default: 944 return ATOM_FAILED; 945 } 946 case 2: 947 switch (func) { 948 case ATOMBIOS_GET_CV_MODES: 949 for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { 950 /* my rv730 table has only room for one mode */ 951 if ((void *)&atomDataPtr->ComponentVideoInfo.ComponentVideoInfo_v21->aModeTimings[i] - 952 atomDataPtr->ComponentVideoInfo.base > size) 953 break; 954 955 new = rhdAtomDTDTimings(handle, 956 &atomDataPtr->ComponentVideoInfo 957 .ComponentVideoInfo_v21->aModeTimings[i]); 958 959 if (!new) 960 continue; 961 962 new->type |= M_T_DRIVER; 963 new->next = NULL; 964 new->prev = last; 965 966 if (last) last->next = new; 967 last = new; 968 if (!first) first = new; 969 970 } 971 if (last) { 972 last->next = NULL; //first; 973 first->prev = NULL; //last; 974 data->modes = first; 975 } 976 if (data->modes) 977 return ATOM_SUCCESS; 978 return ATOM_FAILED; 979 980 default: 981 return ATOM_FAILED; 982 } 983 default: 984 return ATOM_NOT_IMPLEMENTED; 985 } 986/*NOTREACHED*/ 987} 988 989static AtomBiosResult 990rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, 991 AtomBiosArgPtr data) 992{ 993 atomDataTablesPtr atomDataPtr; 994 uint8_t crev, frev; 995 unsigned long offset; 996 997 //RHDFUNC(handle); 998 999 atomDataPtr = handle->atomDataPtr; 1000 1001 if (!rhdAtomGetTableRevisionAndSize( 1002 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 1003 &frev,&crev,NULL)) { 1004 return ATOM_FAILED; 1005 } 1006 1007 switch (crev) { 1008 1009 case 1: 1010 switch (func) { 1011 case ATOMBIOS_GET_PANEL_MODE: 1012 data->modes = rhdAtomDTDTimings(handle, 1013 &atomDataPtr->LVDS_Info 1014 .LVDS_Info->sLCDTiming); 1015 if (data->modes) 1016 return ATOM_SUCCESS; 1017 default: 1018 return ATOM_FAILED; 1019 } 1020 case 2: 1021 switch (func) { 1022 case ATOMBIOS_GET_PANEL_MODE: 1023 data->modes = rhdAtomDTDTimings(handle, 1024 &atomDataPtr->LVDS_Info 1025 .LVDS_Info_v12->sLCDTiming); 1026 if (data->modes) 1027 return ATOM_SUCCESS; 1028 return ATOM_FAILED; 1029 1030 case ATOMBIOS_GET_PANEL_EDID: 1031 offset = (unsigned long)&atomDataPtr->LVDS_Info.base 1032 - (unsigned long)handle->BIOSBase 1033 + le16_to_cpu(atomDataPtr->LVDS_Info 1034 .LVDS_Info_v12->usExtInfoTableOffset); 1035 1036 data->EDIDBlock 1037 = rhdAtomLvdsDDC(handle, offset, 1038 (unsigned char *) 1039 &atomDataPtr->LVDS_Info.base 1040 + le16_to_cpu(atomDataPtr->LVDS_Info 1041 .LVDS_Info_v12->usExtInfoTableOffset)); 1042 if (data->EDIDBlock) 1043 return ATOM_SUCCESS; 1044 default: 1045 return ATOM_FAILED; 1046 } 1047 default: 1048 return ATOM_NOT_IMPLEMENTED; 1049 } 1050/*NOTREACHED*/ 1051} 1052 1053static AtomBiosResult 1054rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, 1055 AtomBiosRequestID func, AtomBiosArgPtr data) 1056{ 1057 atomDataTablesPtr atomDataPtr; 1058 uint8_t crev, frev; 1059 uint32_t *val = &data->val; 1060 1061 //RHDFUNC(handle); 1062 1063 atomDataPtr = handle->atomDataPtr; 1064 1065 if (!rhdAtomGetTableRevisionAndSize( 1066 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 1067 &frev,&crev,NULL)) { 1068 return ATOM_FAILED; 1069 } 1070 1071 switch (crev) { 1072 case 1: 1073 switch (func) { 1074 case ATOM_LVDS_SUPPORTED_REFRESH_RATE: 1075 *val = le16_to_cpu(atomDataPtr->LVDS_Info 1076 .LVDS_Info->usSupportedRefreshRate); 1077 break; 1078 case ATOM_LVDS_OFF_DELAY: 1079 *val = le16_to_cpu(atomDataPtr->LVDS_Info 1080 .LVDS_Info->usOffDelayInMs); 1081 break; 1082 case ATOM_LVDS_SEQ_DIG_ONTO_DE: 1083 *val = atomDataPtr->LVDS_Info 1084 .LVDS_Info->ucPowerSequenceDigOntoDEin10Ms * 10; 1085 break; 1086 case ATOM_LVDS_SEQ_DE_TO_BL: 1087 *val = atomDataPtr->LVDS_Info 1088 .LVDS_Info->ucPowerSequenceDEtoBLOnin10Ms * 10; 1089 break; 1090 case ATOM_LVDS_DITHER: 1091 *val = atomDataPtr->LVDS_Info 1092 .LVDS_Info->ucLVDS_Misc & 0x40; 1093 break; 1094 case ATOM_LVDS_DUALLINK: 1095 *val = atomDataPtr->LVDS_Info 1096 .LVDS_Info->ucLVDS_Misc & 0x01; 1097 break; 1098 case ATOM_LVDS_24BIT: 1099 *val = atomDataPtr->LVDS_Info 1100 .LVDS_Info->ucLVDS_Misc & 0x02; 1101 break; 1102 case ATOM_LVDS_GREYLVL: 1103 *val = atomDataPtr->LVDS_Info 1104 .LVDS_Info->ucLVDS_Misc & 0x0C; 1105 break; 1106 case ATOM_LVDS_FPDI: 1107 *val = atomDataPtr->LVDS_Info 1108 .LVDS_Info->ucLVDS_Misc * 0x10; 1109 break; 1110 default: 1111 return ATOM_NOT_IMPLEMENTED; 1112 } 1113 break; 1114 case 2: 1115 switch (func) { 1116 case ATOM_LVDS_SUPPORTED_REFRESH_RATE: 1117 *val = le16_to_cpu(atomDataPtr->LVDS_Info 1118 .LVDS_Info_v12->usSupportedRefreshRate); 1119 break; 1120 case ATOM_LVDS_OFF_DELAY: 1121 *val = le16_to_cpu(atomDataPtr->LVDS_Info 1122 .LVDS_Info_v12->usOffDelayInMs); 1123 break; 1124 case ATOM_LVDS_SEQ_DIG_ONTO_DE: 1125 *val = atomDataPtr->LVDS_Info 1126 .LVDS_Info_v12->ucPowerSequenceDigOntoDEin10Ms * 10; 1127 break; 1128 case ATOM_LVDS_SEQ_DE_TO_BL: 1129 *val = atomDataPtr->LVDS_Info 1130 .LVDS_Info_v12->ucPowerSequenceDEtoBLOnin10Ms * 10; 1131 break; 1132 case ATOM_LVDS_DITHER: 1133 *val = atomDataPtr->LVDS_Info 1134 .LVDS_Info_v12->ucLVDS_Misc & 0x40; 1135 break; 1136 case ATOM_LVDS_DUALLINK: 1137 *val = atomDataPtr->LVDS_Info 1138 .LVDS_Info_v12->ucLVDS_Misc & 0x01; 1139 break; 1140 case ATOM_LVDS_24BIT: 1141 *val = atomDataPtr->LVDS_Info 1142 .LVDS_Info_v12->ucLVDS_Misc & 0x02; 1143 break; 1144 case ATOM_LVDS_GREYLVL: 1145 *val = atomDataPtr->LVDS_Info 1146 .LVDS_Info_v12->ucLVDS_Misc & 0x0C; 1147 break; 1148 case ATOM_LVDS_FPDI: 1149 *val = atomDataPtr->LVDS_Info 1150 .LVDS_Info_v12->ucLVDS_Misc * 0x10; 1151 break; 1152 default: 1153 return ATOM_NOT_IMPLEMENTED; 1154 } 1155 break; 1156 default: 1157 return ATOM_NOT_IMPLEMENTED; 1158 } 1159 1160 return ATOM_SUCCESS; 1161} 1162 1163static AtomBiosResult 1164rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, 1165 AtomBiosRequestID func, AtomBiosArgPtr data) 1166{ 1167 atomDataTablesPtr atomDataPtr; 1168 uint8_t crev, frev; 1169 uint32_t *val = &data->val; 1170 1171 //RHDFUNC(handle); 1172 1173 atomDataPtr = handle->atomDataPtr; 1174 1175 if (!rhdAtomGetTableRevisionAndSize( 1176 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->CompassionateData), 1177 &frev,&crev,NULL)) { 1178 return ATOM_FAILED; 1179 } 1180 1181 switch (func) { 1182 case ATOM_DAC1_BG_ADJ: 1183 *val = atomDataPtr->CompassionateData-> 1184 ucDAC1_BG_Adjustment; 1185 break; 1186 case ATOM_DAC1_DAC_ADJ: 1187 *val = atomDataPtr->CompassionateData-> 1188 ucDAC1_DAC_Adjustment; 1189 break; 1190 case ATOM_DAC1_FORCE: 1191 *val = atomDataPtr->CompassionateData-> 1192 usDAC1_FORCE_Data; 1193 break; 1194 case ATOM_DAC2_CRTC2_BG_ADJ: 1195 *val = atomDataPtr->CompassionateData-> 1196 ucDAC2_CRT2_BG_Adjustment; 1197 break; 1198 case ATOM_DAC2_CRTC2_DAC_ADJ: 1199 *val = atomDataPtr->CompassionateData-> 1200 ucDAC2_CRT2_DAC_Adjustment; 1201 break; 1202 case ATOM_DAC2_CRTC2_FORCE: 1203 *val = atomDataPtr->CompassionateData-> 1204 usDAC2_CRT2_FORCE_Data; 1205 break; 1206 case ATOM_DAC2_CRTC2_MUX_REG_IND: 1207 *val = atomDataPtr->CompassionateData-> 1208 usDAC2_CRT2_MUX_RegisterIndex; 1209 break; 1210 case ATOM_DAC2_CRTC2_MUX_REG_INFO: 1211 *val = atomDataPtr->CompassionateData-> 1212 ucDAC2_CRT2_MUX_RegisterInfo; 1213 break; 1214 default: 1215 return ATOM_NOT_IMPLEMENTED; 1216 } 1217 return ATOM_SUCCESS; 1218} 1219 1220static AtomBiosResult 1221rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, 1222 AtomBiosRequestID func, AtomBiosArgPtr data) 1223{ 1224 atomDataTablesPtr atomDataPtr; 1225 uint8_t crev, frev; 1226 uint32_t *val = &data->val; 1227 unsigned short size; 1228 1229 //RHDFUNC(handle); 1230 1231 atomDataPtr = handle->atomDataPtr; 1232 1233 if (!rhdAtomGetTableRevisionAndSize( 1234 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->GPIO_I2C_Info), 1235 &frev,&crev,&size)) { 1236 return ATOM_FAILED; 1237 } 1238 1239 switch (func) { 1240 case ATOM_GPIO_I2C_CLK_MASK: 1241 if ((sizeof(ATOM_COMMON_TABLE_HEADER) 1242 + (*val * sizeof(ATOM_GPIO_I2C_ASSIGMENT))) > size) { 1243 xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: GPIO_I2C Device " 1244 "num %lu exeeds table size %u\n",__func__, 1245 (unsigned long)val, 1246 size); 1247 return ATOM_FAILED; 1248 } 1249 1250 *val = le16_to_cpu(atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] 1251 .usClkMaskRegisterIndex); 1252 break; 1253 1254 default: 1255 return ATOM_NOT_IMPLEMENTED; 1256 } 1257 return ATOM_SUCCESS; 1258} 1259 1260static AtomBiosResult 1261rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, 1262 AtomBiosRequestID func, AtomBiosArgPtr data) 1263{ 1264 atomDataTablesPtr atomDataPtr; 1265 uint8_t crev, frev; 1266 uint32_t *val = &data->val; 1267 1268 //RHDFUNC(handle); 1269 1270 atomDataPtr = handle->atomDataPtr; 1271 1272 if (!rhdAtomGetTableRevisionAndSize( 1273 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), 1274 &crev,&frev,NULL)) { 1275 return ATOM_FAILED; 1276 } 1277 1278 switch (crev) { 1279 case 1: 1280 switch (func) { 1281 case GET_DEFAULT_ENGINE_CLOCK: 1282 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1283 .FirmwareInfo->ulDefaultEngineClock) * 10; 1284 break; 1285 case GET_DEFAULT_MEMORY_CLOCK: 1286 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1287 .FirmwareInfo->ulDefaultMemoryClock) * 10; 1288 break; 1289 case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1290 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1291 .FirmwareInfo->ulMaxPixelClockPLL_Output) * 10; 1292 break; 1293 case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1294 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1295 .FirmwareInfo->usMinPixelClockPLL_Output) * 10; 1296 case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1297 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1298 .FirmwareInfo->usMaxPixelClockPLL_Input) * 10; 1299 break; 1300 case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1301 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1302 .FirmwareInfo->usMinPixelClockPLL_Input) * 10; 1303 break; 1304 case GET_MAX_PIXEL_CLK: 1305 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1306 .FirmwareInfo->usMaxPixelClock) * 10; 1307 break; 1308 case GET_REF_CLOCK: 1309 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1310 .FirmwareInfo->usReferenceClock) * 10; 1311 break; 1312 default: 1313 return ATOM_NOT_IMPLEMENTED; 1314 } 1315 case 2: 1316 switch (func) { 1317 case GET_DEFAULT_ENGINE_CLOCK: 1318 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1319 .FirmwareInfo_V_1_2->ulDefaultEngineClock) * 10; 1320 break; 1321 case GET_DEFAULT_MEMORY_CLOCK: 1322 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1323 .FirmwareInfo_V_1_2->ulDefaultMemoryClock) * 10; 1324 break; 1325 case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1326 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1327 .FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output) * 10; 1328 break; 1329 case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1330 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1331 .FirmwareInfo_V_1_2->usMinPixelClockPLL_Output) * 10; 1332 break; 1333 case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1334 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1335 .FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input) * 10; 1336 break; 1337 case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1338 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1339 .FirmwareInfo_V_1_2->usMinPixelClockPLL_Input) * 10; 1340 break; 1341 case GET_MAX_PIXEL_CLK: 1342 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1343 .FirmwareInfo_V_1_2->usMaxPixelClock) * 10; 1344 break; 1345 case GET_REF_CLOCK: 1346 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1347 .FirmwareInfo_V_1_2->usReferenceClock) * 10; 1348 break; 1349 default: 1350 return ATOM_NOT_IMPLEMENTED; 1351 } 1352 break; 1353 case 3: 1354 switch (func) { 1355 case GET_DEFAULT_ENGINE_CLOCK: 1356 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1357 .FirmwareInfo_V_1_3->ulDefaultEngineClock) * 10; 1358 break; 1359 case GET_DEFAULT_MEMORY_CLOCK: 1360 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1361 .FirmwareInfo_V_1_3->ulDefaultMemoryClock) * 10; 1362 break; 1363 case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1364 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1365 .FirmwareInfo_V_1_3->ulMaxPixelClockPLL_Output) * 10; 1366 break; 1367 case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1368 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1369 .FirmwareInfo_V_1_3->usMinPixelClockPLL_Output) * 10; 1370 break; 1371 case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1372 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1373 .FirmwareInfo_V_1_3->usMaxPixelClockPLL_Input) * 10; 1374 break; 1375 case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1376 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1377 .FirmwareInfo_V_1_3->usMinPixelClockPLL_Input) * 10; 1378 break; 1379 case GET_MAX_PIXEL_CLK: 1380 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1381 .FirmwareInfo_V_1_3->usMaxPixelClock) * 10; 1382 break; 1383 case GET_REF_CLOCK: 1384 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1385 .FirmwareInfo_V_1_3->usReferenceClock) * 10; 1386 break; 1387 default: 1388 return ATOM_NOT_IMPLEMENTED; 1389 } 1390 break; 1391 case 4: 1392 switch (func) { 1393 case GET_DEFAULT_ENGINE_CLOCK: 1394 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1395 .FirmwareInfo_V_1_4->ulDefaultEngineClock) * 10; 1396 break; 1397 case GET_DEFAULT_MEMORY_CLOCK: 1398 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1399 .FirmwareInfo_V_1_4->ulDefaultMemoryClock) * 10; 1400 break; 1401 case GET_MAX_PIXEL_CLOCK_PLL_INPUT: 1402 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1403 .FirmwareInfo_V_1_4->usMaxPixelClockPLL_Input) * 10; 1404 break; 1405 case GET_MIN_PIXEL_CLOCK_PLL_INPUT: 1406 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1407 .FirmwareInfo_V_1_4->usMinPixelClockPLL_Input) * 10; 1408 break; 1409 case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: 1410 *val = le32_to_cpu(atomDataPtr->FirmwareInfo 1411 .FirmwareInfo_V_1_4->ulMaxPixelClockPLL_Output) * 10; 1412 break; 1413 case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: 1414 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1415 .FirmwareInfo_V_1_4->usMinPixelClockPLL_Output) * 10; 1416 break; 1417 case GET_MAX_PIXEL_CLK: 1418 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1419 .FirmwareInfo_V_1_4->usMaxPixelClock) * 10; 1420 break; 1421 case GET_REF_CLOCK: 1422 *val = le16_to_cpu(atomDataPtr->FirmwareInfo 1423 .FirmwareInfo_V_1_4->usReferenceClock) * 10; 1424 break; 1425 default: 1426 return ATOM_NOT_IMPLEMENTED; 1427 } 1428 break; 1429 default: 1430 return ATOM_NOT_IMPLEMENTED; 1431 } 1432 return ATOM_SUCCESS; 1433} 1434 1435const int object_connector_convert[] = 1436 { CONNECTOR_NONE, 1437 CONNECTOR_DVI_I, 1438 CONNECTOR_DVI_I, 1439 CONNECTOR_DVI_D, 1440 CONNECTOR_DVI_D, 1441 CONNECTOR_VGA, 1442 CONNECTOR_CTV, 1443 CONNECTOR_STV, 1444 CONNECTOR_NONE, 1445 CONNECTOR_NONE, 1446 CONNECTOR_DIN, 1447 CONNECTOR_SCART, 1448 CONNECTOR_HDMI_TYPE_A, 1449 CONNECTOR_HDMI_TYPE_B, 1450 CONNECTOR_LVDS, 1451 CONNECTOR_DIN, 1452 CONNECTOR_NONE, 1453 CONNECTOR_NONE, 1454 CONNECTOR_NONE, 1455 CONNECTOR_DISPLAY_PORT, 1456 CONNECTOR_EDP, 1457 CONNECTOR_NONE, 1458 }; 1459 1460xf86MonPtr radeon_atom_get_edid(xf86OutputPtr output) 1461{ 1462 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1463 RADEONInfoPtr info = RADEONPTR(output->scrn); 1464 READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION edid_data; 1465 AtomBiosArgRec data; 1466 unsigned char *space; 1467 int i2c_clock = 50; 1468 int engine_clk = (int)info->sclk * 100; 1469 int prescale; 1470 unsigned char *edid; 1471 xf86MonPtr mon = NULL; 1472 1473 if (!radeon_output->ddc_i2c.hw_capable) 1474 return mon; 1475 1476 if (info->atomBIOS->fbBase) 1477 edid = (unsigned char *)info->FB + info->atomBIOS->fbBase; 1478 else if (info->atomBIOS->scratchBase) 1479 edid = (unsigned char *)info->atomBIOS->scratchBase; 1480 else 1481 return mon; 1482 1483 memset(edid, 0, ATOM_EDID_RAW_DATASIZE); 1484 1485 if (info->ChipFamily == CHIP_FAMILY_R520) 1486 prescale = (127 << 8) + (engine_clk * 10) / (4 * 127 * i2c_clock); 1487 else if (info->ChipFamily < CHIP_FAMILY_R600) 1488 prescale = (((engine_clk * 10)/(4 * 128 * 100) + 1) << 8) + 128; 1489 else 1490 prescale = (info->pll.reference_freq * 10) / i2c_clock; 1491 1492 edid_data.usPrescale = prescale; 1493 edid_data.usVRAMAddress = 0; 1494 edid_data.ucSlaveAddr = 0xa0; 1495 edid_data.ucLineNumber = radeon_output->ddc_i2c.hw_line; 1496 1497 data.exec.index = GetIndexIntoMasterTable(COMMAND, ReadEDIDFromHWAssistedI2C); 1498 data.exec.dataSpace = (void *)&space; 1499 data.exec.pspace = &edid_data; 1500 1501 if (RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) 1502 ErrorF("Atom Get EDID success\n"); 1503 else 1504 ErrorF("Atom Get EDID failed\n"); 1505 1506 if (edid[1] == 0xff) 1507 mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); 1508 1509 return mon; 1510 1511} 1512 1513static RADEONI2CBusRec 1514RADEONLookupGPIOLineForDDC(ScrnInfoPtr pScrn, uint8_t id) 1515{ 1516 RADEONInfoPtr info = RADEONPTR (pScrn); 1517 atomDataTablesPtr atomDataPtr; 1518 ATOM_GPIO_I2C_ASSIGMENT *gpio; 1519 RADEONI2CBusRec i2c; 1520 uint8_t crev, frev; 1521 unsigned short size; 1522 int i, num_indices; 1523 1524 memset(&i2c, 0, sizeof(RADEONI2CBusRec)); 1525 i2c.valid = FALSE; 1526 1527 atomDataPtr = info->atomBIOS->atomDataPtr; 1528 1529 if (!rhdAtomGetTableRevisionAndSize( 1530 &(atomDataPtr->GPIO_I2C_Info->sHeader), 1531 &crev,&frev,&size)) { 1532 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No GPIO Info Table found!\n"); 1533 return i2c; 1534 } 1535 1536 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / 1537 sizeof(ATOM_GPIO_I2C_ASSIGMENT); 1538 1539 for (i = 0; i < num_indices; i++) { 1540 gpio = &atomDataPtr->GPIO_I2C_Info->asGPIO_Info[i]; 1541 if (gpio->sucI2cId.ucAccess == id) { 1542 i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; 1543 i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; 1544 i2c.put_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; 1545 i2c.put_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; 1546 i2c.get_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; 1547 i2c.get_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; 1548 i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; 1549 i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; 1550 i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); 1551 i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); 1552 i2c.put_clk_mask = (1 << gpio->ucClkEnShift); 1553 i2c.put_data_mask = (1 << gpio->ucDataEnShift); 1554 i2c.get_clk_mask = (1 << gpio->ucClkY_Shift); 1555 i2c.get_data_mask = (1 << gpio->ucDataY_Shift); 1556 i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); 1557 i2c.a_data_mask = (1 << gpio->ucDataA_Shift); 1558 i2c.hw_line = gpio->sucI2cId.ucAccess; 1559 i2c.hw_capable = gpio->sucI2cId.sbfAccess.bfHW_Capable; 1560 i2c.valid = TRUE; 1561 break; 1562 } 1563 } 1564 1565#if 0 1566 ErrorF("id: %d\n", id); 1567 ErrorF("hw capable: %d\n", gpio->sucI2cId.sbfAccess.bfHW_Capable); 1568 ErrorF("hw engine id: %d\n", gpio->sucI2cId.sbfAccess.bfHW_EngineID); 1569 ErrorF("line mux %d\n", gpio->sucI2cId.sbfAccess.bfI2C_LineMux); 1570 ErrorF("mask_clk_reg: 0x%x\n", gpio->usClkMaskRegisterIndex * 4); 1571 ErrorF("mask_data_reg: 0x%x\n", gpio->usDataMaskRegisterIndex * 4); 1572 ErrorF("put_clk_reg: 0x%x\n", gpio->usClkEnRegisterIndex * 4); 1573 ErrorF("put_data_reg: 0x%x\n", gpio->usDataEnRegisterIndex * 4); 1574 ErrorF("get_clk_reg: 0x%x\n", gpio->usClkY_RegisterIndex * 4); 1575 ErrorF("get_data_reg: 0x%x\n", gpio->usDataY_RegisterIndex * 4); 1576 ErrorF("a_clk_reg: 0x%x\n", gpio->usClkA_RegisterIndex * 4); 1577 ErrorF("a_data_reg: 0x%x\n", gpio->usDataA_RegisterIndex * 4); 1578 ErrorF("mask_clk_mask: %d\n", gpio->ucClkMaskShift); 1579 ErrorF("mask_data_mask: %d\n", gpio->ucDataMaskShift); 1580 ErrorF("put_clk_mask: %d\n", gpio->ucClkEnShift); 1581 ErrorF("put_data_mask: %d\n", gpio->ucDataEnShift); 1582 ErrorF("get_clk_mask: %d\n", gpio->ucClkY_Shift); 1583 ErrorF("get_data_mask: %d\n", gpio->ucDataY_Shift); 1584 ErrorF("a_clk_mask: %d\n", gpio->ucClkA_Shift); 1585 ErrorF("a_data_mask: %d\n", gpio->ucDataA_Shift); 1586#endif 1587 1588 return i2c; 1589} 1590 1591static RADEONI2CBusRec 1592rhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, 1593 ATOM_I2C_RECORD *Record, int i) 1594{ 1595 RADEONInfoPtr info = RADEONPTR (pScrn); 1596 uint8_t *temp = &Record->sucI2cId; 1597 1598 info->BiosConnector[i].i2c_line_mux = *temp; 1599 info->BiosConnector[i].ucI2cId = *temp; 1600 return RADEONLookupGPIOLineForDDC(pScrn, *temp); 1601} 1602 1603static uint8_t 1604radeon_lookup_hpd_id(ScrnInfoPtr pScrn, ATOM_HPD_INT_RECORD *record) 1605{ 1606 RADEONInfoPtr info = RADEONPTR (pScrn); 1607 unsigned short size; 1608 uint8_t hpd = 0; 1609 int i, num_indices; 1610 struct _ATOM_GPIO_PIN_LUT *gpio_info; 1611 ATOM_GPIO_PIN_ASSIGNMENT *pin; 1612 atomDataTablesPtr atomDataPtr; 1613 uint8_t crev, frev; 1614 uint32_t reg; 1615 1616 atomDataPtr = info->atomBIOS->atomDataPtr; 1617 1618 if (!rhdAtomGetTableRevisionAndSize( 1619 &(atomDataPtr->GPIO_Pin_LUT->sHeader), 1620 &crev,&frev,&size)) { 1621 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No GPIO Pin Table found!\n"); 1622 return hpd; 1623 } 1624 1625 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 1626 1627 if (IS_DCE4_VARIANT) 1628 reg = EVERGREEN_DC_GPIO_HPD_A; 1629 else 1630 reg = AVIVO_DC_GPIO_HPD_A; 1631 1632 gpio_info = atomDataPtr->GPIO_Pin_LUT; 1633 for (i = 0; i < num_indices; i++) { 1634 pin = &gpio_info->asGPIO_Pin[i]; 1635 if (record->ucHPDIntGPIOID == pin->ucGPIO_ID) { 1636 if ((pin->usGpioPin_AIndex * 4) == reg) { 1637 switch (pin->ucGpioPinBitShift) { 1638 case 0: 1639 default: 1640 hpd = 0; 1641 break; 1642 case 8: 1643 hpd = 1; 1644 break; 1645 case 16: 1646 hpd = 2; 1647 break; 1648 case 24: 1649 hpd = 3; 1650 break; 1651 case 26: 1652 hpd = 4; 1653 break; 1654 case 28: 1655 hpd = 5; 1656 break; 1657 } 1658 break; 1659 } 1660 } 1661 } 1662 1663 return hpd; 1664} 1665 1666static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index) 1667{ 1668 RADEONInfoPtr info = RADEONPTR (pScrn); 1669 1670 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ 1671 if ((info->Chipset == PCI_CHIP_RS690_791E) && 1672 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1673 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x826d)) { 1674 if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1675 (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1676 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1677 } 1678 } 1679 1680 /* RS600 board lists the DVI port as HDMI */ 1681 if ((info->Chipset == PCI_CHIP_RS600_7941) && 1682 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1849) && 1683 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x7941)) { 1684 if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1685 (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1686 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1687 } 1688 } 1689 1690 /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ 1691 if ((info->Chipset == PCI_CHIP_RS600_7941) && 1692 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x147b) && 1693 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2412)) { 1694 if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) 1695 info->BiosConnector[index].valid = FALSE; 1696 } 1697 1698 /* Falcon NW laptop lists vga ddc line for LVDS */ 1699 if ((info->Chipset == PCI_CHIP_RV410_5653) && 1700 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1462) && 1701 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0291)) { 1702 if (info->BiosConnector[index].ConnectorType == CONNECTOR_LVDS) { 1703 info->BiosConnector[index].ddc_i2c.valid = FALSE; 1704 } 1705 } 1706 1707 /* Funky macbooks */ 1708 if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1709 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1710 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1711 if ((index == ATOM_DEVICE_CRT1_INDEX) || 1712 (index == ATOM_DEVICE_CRT2_INDEX) || 1713 (index == ATOM_DEVICE_DFP2_INDEX)) 1714 info->BiosConnector[index].valid = FALSE; 1715 1716 if (index == ATOM_DEVICE_DFP1_INDEX) { 1717 info->BiosConnector[index].devices |= ATOM_DEVICE_CRT2_SUPPORT; 1718 } 1719 } 1720 1721 /* ASUS HD 3600 XT board lists the DVI port as HDMI */ 1722 if ((info->Chipset == PCI_CHIP_RV635_9598) && 1723 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1724 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) { 1725 if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) 1726 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I; 1727 } 1728 1729 /* ASUS HD 3450 board lists the DVI port as HDMI */ 1730 if ((info->Chipset == PCI_CHIP_RV620_95C5) && 1731 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1732 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) { 1733 if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) 1734 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I; 1735 } 1736 1737 /* some BIOSes seem to report DAC on HDMI - usually this is a board with 1738 * HDMI + VGA reporting as HDMI 1739 */ 1740 if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) { 1741 if (info->BiosConnector[index].devices & (ATOM_DEVICE_CRT_SUPPORT)) { 1742 info->BiosConnector[index].devices &= ~(ATOM_DEVICE_DFP_SUPPORT); 1743 info->BiosConnector[index].ConnectorType = CONNECTOR_VGA; 1744 info->BiosConnector[index].connector_object = 0; 1745 } 1746 } 1747 1748} 1749 1750uint32_t 1751radeon_get_device_index(uint32_t device_support) 1752{ 1753 uint32_t device_index = 0; 1754 1755 if (device_support == 0) 1756 return 0; 1757 1758 while ((device_support & 1) == 0) { 1759 device_support >>= 1; 1760 device_index++; 1761 } 1762 return device_index; 1763} 1764 1765radeon_encoder_ptr 1766radeon_get_encoder(xf86OutputPtr output) 1767{ 1768 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1769 RADEONInfoPtr info = RADEONPTR(output->scrn); 1770 1771 if (radeon_output->active_device) 1772 return info->encoders[radeon_get_device_index(radeon_output->active_device)]; 1773 else 1774 return NULL; 1775} 1776 1777Bool 1778radeon_add_encoder(ScrnInfoPtr pScrn, uint32_t encoder_id, uint32_t device_support) 1779{ 1780 RADEONInfoPtr info = RADEONPTR (pScrn); 1781 uint32_t device_index = radeon_get_device_index(device_support); 1782 int i; 1783 1784 if (device_support == 0) { 1785 ErrorF("device support == 0\n"); 1786 return FALSE; 1787 } 1788 1789 if (info->encoders[device_index] != NULL) 1790 return TRUE; 1791 else { 1792 /* look for the encoder */ 1793 for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { 1794 if ((info->encoders[i] != NULL) && (info->encoders[i]->encoder_id == encoder_id)) { 1795 info->encoders[device_index] = info->encoders[i]; 1796 switch (encoder_id) { 1797 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1798 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1799 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1800 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1801 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1802 if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1803 if (info->encoders[device_index]->dev_priv == NULL) { 1804 info->encoders[device_index]->dev_priv = 1805 (radeon_lvds_ptr)xcalloc(1,sizeof(radeon_lvds_rec)); 1806 if (info->encoders[device_index]->dev_priv == NULL) { 1807 ErrorF("xalloc failed\n"); 1808 return FALSE; 1809 } else 1810 RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1811 } 1812 } 1813 break; 1814 } 1815 return TRUE; 1816 } 1817 } 1818 1819 info->encoders[device_index] = (radeon_encoder_ptr)xcalloc(1,sizeof(radeon_encoder_rec)); 1820 if (info->encoders[device_index] != NULL) { 1821 info->encoders[device_index]->encoder_id = encoder_id; 1822 info->encoders[device_index]->devices = 0; 1823 info->encoders[device_index]->dev_priv = NULL; 1824 // add dev_priv stuff 1825 switch (encoder_id) { 1826 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1827 info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)xcalloc(1,sizeof(radeon_lvds_rec)); 1828 if (info->encoders[device_index]->dev_priv == NULL) { 1829 ErrorF("xalloc failed\n"); 1830 return FALSE; 1831 } else { 1832 if (info->IsAtomBios) 1833 RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1834 else 1835 RADEONGetLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1836 } 1837 break; 1838 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1839 if (!IS_AVIVO_VARIANT) { 1840 info->encoders[device_index]->dev_priv = (radeon_tvdac_ptr)xcalloc(1,sizeof(radeon_tvdac_rec)); 1841 if (info->encoders[device_index]->dev_priv == NULL) { 1842 ErrorF("xalloc failed\n"); 1843 return FALSE; 1844 } else 1845 RADEONGetTVDacAdjInfo(pScrn, (radeon_tvdac_ptr)info->encoders[device_index]->dev_priv); 1846 } 1847 break; 1848 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1849 if (!IS_AVIVO_VARIANT) { 1850 info->encoders[device_index]->dev_priv = (radeon_tmds_ptr)xcalloc(1,sizeof(radeon_tmds_rec)); 1851 if (info->encoders[device_index]->dev_priv == NULL) { 1852 ErrorF("xalloc failed\n"); 1853 return FALSE; 1854 } else 1855 RADEONGetTMDSInfo(pScrn, (radeon_tmds_ptr)info->encoders[device_index]->dev_priv); 1856 } 1857 break; 1858 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1859 if (!IS_AVIVO_VARIANT) { 1860 info->encoders[device_index]->dev_priv = (radeon_dvo_ptr)xcalloc(1,sizeof(radeon_dvo_rec)); 1861 if (info->encoders[device_index]->dev_priv == NULL) { 1862 ErrorF("xalloc failed\n"); 1863 return FALSE; 1864 } else 1865 RADEONGetExtTMDSInfo(pScrn, (radeon_dvo_ptr)info->encoders[device_index]->dev_priv); 1866 } 1867 break; 1868 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1869 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1870 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1871 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1872 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1873 if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1874 info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)xcalloc(1,sizeof(radeon_lvds_rec)); 1875 if (info->encoders[device_index]->dev_priv == NULL) { 1876 ErrorF("xalloc failed\n"); 1877 return FALSE; 1878 } else 1879 RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1880 } 1881 break; 1882 } 1883 return TRUE; 1884 } else { 1885 ErrorF("xalloc failed\n"); 1886 return FALSE; 1887 } 1888 } 1889 1890} 1891 1892Bool 1893RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn) 1894{ 1895 RADEONInfoPtr info = RADEONPTR (pScrn); 1896 uint8_t crev, frev; 1897 unsigned short size; 1898 atomDataTablesPtr atomDataPtr; 1899 ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 1900 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 1901 ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj = NULL; 1902 int i, j, path_size, device_support; 1903 Bool enable_tv = FALSE; 1904 1905 if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 1906 enable_tv = TRUE; 1907 1908 atomDataPtr = info->atomBIOS->atomDataPtr; 1909 if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->Object_Header), &crev, &frev, &size)) 1910 return FALSE; 1911 1912 if (crev < 2) 1913 return FALSE; 1914 1915 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) 1916 ((char *)&atomDataPtr->Object_Header->sHeader + 1917 le16_to_cpu(atomDataPtr->Object_Header->usDisplayPathTableOffset)); 1918 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) 1919 ((char *)&atomDataPtr->Object_Header->sHeader + 1920 le16_to_cpu(atomDataPtr->Object_Header->usConnectorObjectTableOffset)); 1921 device_support = le16_to_cpu(atomDataPtr->Object_Header->usDeviceSupport); 1922 1923 path_size = 0; 1924 for (i = 0; i < path_obj->ucNumOfDispPath; i++) { 1925 uint8_t *addr = (uint8_t *)path_obj->asDispPath; 1926 ATOM_DISPLAY_OBJECT_PATH *path; 1927 addr += path_size; 1928 path = (ATOM_DISPLAY_OBJECT_PATH *)addr; 1929 path_size += le16_to_cpu(path->usSize); 1930 1931 if (device_support & le16_to_cpu(path->usDeviceTag)) { 1932 uint8_t con_obj_id, con_obj_num, con_obj_type; 1933 1934 con_obj_id = (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1935 con_obj_num = (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1936 con_obj_type = (le16_to_cpu(path->usConnObjectId) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 1937 1938 if ((le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV1_SUPPORT) || 1939 (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV2_SUPPORT)) { 1940 if (!enable_tv) { 1941 info->BiosConnector[i].valid = FALSE; 1942 continue; 1943 } 1944 } 1945 1946 /* don't support CV yet */ 1947 if (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_CV_SUPPORT) { 1948 info->BiosConnector[i].valid = FALSE; 1949 continue; 1950 } 1951 1952 if (info->IsIGP && 1953 (con_obj_id == CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { 1954 uint32_t slot_config, ct; 1955 1956 igp_obj = info->atomBIOS->atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2; 1957 1958 if (!igp_obj) 1959 info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1960 else { 1961 if (con_obj_num == 1) 1962 slot_config = igp_obj->ulDDISlot1Config; 1963 else 1964 slot_config = igp_obj->ulDDISlot2Config; 1965 1966 ct = (slot_config >> 16) & 0xff; 1967 info->BiosConnector[i].ConnectorType = object_connector_convert[ct]; 1968 info->BiosConnector[i].connector_object_id = ct; 1969 info->BiosConnector[i].igp_lane_info = slot_config & 0xffff; 1970 } 1971 } else { 1972 info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1973 info->BiosConnector[i].connector_object_id = con_obj_id; 1974 } 1975 1976 if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 1977 info->BiosConnector[i].valid = FALSE; 1978 continue; 1979 } else 1980 info->BiosConnector[i].valid = TRUE; 1981 info->BiosConnector[i].devices = le16_to_cpu(path->usDeviceTag); 1982 info->BiosConnector[i].connector_object = le16_to_cpu(path->usConnObjectId); 1983 1984 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { 1985 uint8_t enc_obj_id, enc_obj_num, enc_obj_type; 1986 1987 enc_obj_id = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1988 enc_obj_num = (le16_to_cpu(path->usGraphicObjIds[j]) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1989 enc_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 1990 1991 if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { 1992 if (enc_obj_num == 2) 1993 info->BiosConnector[i].linkb = TRUE; 1994 else 1995 info->BiosConnector[i].linkb = FALSE; 1996 1997 if (!radeon_add_encoder(pScrn, enc_obj_id, le16_to_cpu(path->usDeviceTag))) 1998 return FALSE; 1999 } 2000 } 2001 2002 /* look up gpio for ddc */ 2003 if ((le16_to_cpu(path->usDeviceTag) & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { 2004 for (j = 0; j < con_obj->ucNumberOfObjects; j++) { 2005 if (le16_to_cpu(path->usConnObjectId) == le16_to_cpu(con_obj->asObjects[j].usObjectID)) { 2006 ATOM_COMMON_RECORD_HEADER *Record = (ATOM_COMMON_RECORD_HEADER *) 2007 ((char *)&atomDataPtr->Object_Header->sHeader 2008 + le16_to_cpu(con_obj->asObjects[j].usRecordOffset)); 2009 2010 while (Record->ucRecordType > 0 2011 && Record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER ) { 2012 2013 /*ErrorF("record type %d\n", Record->ucRecordType);*/ 2014 switch (Record->ucRecordType) { 2015 case ATOM_I2C_RECORD_TYPE: 2016 info->BiosConnector[i].ddc_i2c = 2017 rhdAtomParseI2CRecord(pScrn, info->atomBIOS, 2018 (ATOM_I2C_RECORD *)Record, j); 2019 break; 2020 case ATOM_HPD_INT_RECORD_TYPE: 2021 info->BiosConnector[i].hpd_id = 2022 radeon_lookup_hpd_id(pScrn, 2023 (ATOM_HPD_INT_RECORD *)Record); 2024 break; 2025 case ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE: 2026 break; 2027 } 2028 2029 Record = (ATOM_COMMON_RECORD_HEADER*) 2030 ((char *)Record + Record->ucRecordSize); 2031 } 2032 break; 2033 } 2034 } 2035 } 2036 } 2037 RADEONApplyATOMQuirks(pScrn, i); 2038 } 2039 2040 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2041 if (info->BiosConnector[i].valid) { 2042 /* shared connectors */ 2043 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2044 if (info->BiosConnector[j].valid && (i != j) ) { 2045 if (info->BiosConnector[i].connector_object == info->BiosConnector[j].connector_object) { 2046 info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2047 info->BiosConnector[j].valid = FALSE; 2048 } 2049 } 2050 } 2051 /* shared ddc */ 2052 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2053 if (info->BiosConnector[j].valid && (i != j) ) { 2054 if (info->BiosConnector[i].i2c_line_mux == info->BiosConnector[j].i2c_line_mux) { 2055 info->BiosConnector[i].shared_ddc = TRUE; 2056 info->BiosConnector[j].shared_ddc = TRUE; 2057 } 2058 } 2059 } 2060 } 2061 } 2062 2063 return TRUE; 2064} 2065 2066static void 2067RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 2068{ 2069 RADEONInfoPtr info = RADEONPTR(pScrn); 2070 radeon_native_mode_ptr native_mode = &lvds->native_mode; 2071 atomDataTablesPtr atomDataPtr; 2072 uint8_t crev, frev; 2073 uint16_t misc; 2074 2075 atomDataPtr = info->atomBIOS->atomDataPtr; 2076 2077 if (!rhdAtomGetTableRevisionAndSize( 2078 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 2079 &frev,&crev,NULL)) { 2080 return; 2081 } 2082 2083 switch (crev) { 2084 case 1: 2085 native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHActive); 2086 native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVActive); 2087 native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usPixClk) * 10; 2088 native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHBlanking_Time); 2089 native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncOffset); 2090 native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncWidth); 2091 native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVBlanking_Time); 2092 native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncOffset); 2093 native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncWidth); 2094 misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.susModeMiscInfo.usAccess); 2095 if (misc & ATOM_VSYNC_POLARITY) 2096 native_mode->Flags |= V_NVSYNC; 2097 if (misc & ATOM_HSYNC_POLARITY) 2098 native_mode->Flags |= V_NHSYNC; 2099 if (misc & ATOM_COMPOSITESYNC) 2100 native_mode->Flags |= V_CSYNC; 2101 if (misc & ATOM_INTERLACE) 2102 native_mode->Flags |= V_INTERLACE; 2103 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2104 native_mode->Flags |= V_DBLSCAN; 2105 lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->usOffDelayInMs); 2106 lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info->ucLVDS_Misc; 2107 lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info->ucSS_Id; 2108 break; 2109 case 2: 2110 native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHActive); 2111 native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVActive); 2112 native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usPixClk) * 10; 2113 native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHBlanking_Time); 2114 native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncOffset); 2115 native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncWidth); 2116 native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVBlanking_Time); 2117 native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncOffset); 2118 native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncWidth); 2119 misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.susModeMiscInfo.usAccess); 2120 if (misc & ATOM_VSYNC_POLARITY) 2121 native_mode->Flags |= V_NVSYNC; 2122 if (misc & ATOM_HSYNC_POLARITY) 2123 native_mode->Flags |= V_NHSYNC; 2124 if (misc & ATOM_COMPOSITESYNC) 2125 native_mode->Flags |= V_CSYNC; 2126 if (misc & ATOM_INTERLACE) 2127 native_mode->Flags |= V_INTERLACE; 2128 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2129 native_mode->Flags |= V_DBLSCAN; 2130 lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->usOffDelayInMs); 2131 lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucLVDS_Misc; 2132 lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucSS_Id; 2133 break; 2134 } 2135 native_mode->Flags = 0; 2136 2137 if (lvds->PanelPwrDly > 2000 || lvds->PanelPwrDly < 0) 2138 lvds->PanelPwrDly = 2000; 2139 2140 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2141 "LVDS Info:\n" 2142 "XRes: %d, YRes: %d, DotClock: %d\n" 2143 "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" 2144 "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", 2145 native_mode->PanelXRes, native_mode->PanelYRes, native_mode->DotClock, 2146 native_mode->HBlank, native_mode->HOverPlus, native_mode->HSyncWidth, 2147 native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth); 2148} 2149 2150void 2151RADEONATOMGetIGPInfo(ScrnInfoPtr pScrn) 2152{ 2153 RADEONInfoPtr info = RADEONPTR(pScrn); 2154 atomDataTablesPtr atomDataPtr; 2155 unsigned short size; 2156 uint8_t crev, frev; 2157 2158 atomDataPtr = info->atomBIOS->atomDataPtr; 2159 2160 if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base), &frev, &crev, &size)) 2161 return; 2162 2163 switch (crev) { 2164 case 1: 2165 info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ulBootUpMemoryClock / 100.0; 2166 info->igp_system_mclk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usK8MemoryClock); 2167 info->igp_ht_link_clk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usFSBClock); 2168 info->igp_ht_link_width = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ucHTLinkWidth; 2169 break; 2170 case 2: 2171 info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpSidePortClock / 100.0; 2172 info->igp_system_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpUMAClock / 100.0; 2173 info->igp_ht_link_clk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulHTLinkFreq / 100.0; 2174 info->igp_ht_link_width = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->usMinHTLinkWidth); 2175 break; 2176 } 2177} 2178 2179Bool 2180RADEONGetATOMTVInfo(xf86OutputPtr output) 2181{ 2182 ScrnInfoPtr pScrn = output->scrn; 2183 RADEONInfoPtr info = RADEONPTR(pScrn); 2184 RADEONOutputPrivatePtr radeon_output = output->driver_private; 2185 radeon_tvout_ptr tvout = &radeon_output->tvout; 2186 ATOM_ANALOG_TV_INFO *tv_info; 2187 2188 tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2189 2190 if (!tv_info) 2191 return FALSE; 2192 2193 switch(tv_info->ucTV_BootUpDefaultStandard) { 2194 case NTSCJ_SUPPORT: 2195 tvout->default_tvStd = TV_STD_NTSC_J; 2196 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); 2197 break; 2198 case PAL_SUPPORT: 2199 tvout->default_tvStd = TV_STD_PAL; 2200 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); 2201 break; 2202 case PALM_SUPPORT: 2203 tvout->default_tvStd = TV_STD_PAL_M; 2204 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); 2205 break; 2206 case PAL60_SUPPORT: 2207 tvout->default_tvStd = TV_STD_PAL_60; 2208 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); 2209 break; 2210 default: 2211 case NTSC_SUPPORT: 2212 tvout->default_tvStd = TV_STD_NTSC; 2213 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); 2214 break; 2215 } 2216 2217 tvout->tvStd = tvout->default_tvStd; 2218 2219 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); 2220 tvout->SupportedTVStds = tvout->default_tvStd; 2221 if (tv_info->ucTV_SupportedStandard & NTSC_SUPPORT) { 2222 ErrorF("NTSC "); 2223 tvout->SupportedTVStds |= TV_STD_NTSC; 2224 } 2225 if (tv_info->ucTV_SupportedStandard & NTSCJ_SUPPORT) { 2226 ErrorF("NTSC-J "); 2227 tvout->SupportedTVStds |= TV_STD_NTSC_J; 2228 } 2229 if (tv_info->ucTV_SupportedStandard & PAL_SUPPORT) { 2230 ErrorF("PAL "); 2231 tvout->SupportedTVStds |= TV_STD_PAL; 2232 } 2233 if (tv_info->ucTV_SupportedStandard & PALM_SUPPORT) { 2234 ErrorF("PAL-M "); 2235 tvout->SupportedTVStds |= TV_STD_PAL_M; 2236 } 2237 if (tv_info->ucTV_SupportedStandard & PAL60_SUPPORT) { 2238 ErrorF("PAL-60 "); 2239 tvout->SupportedTVStds |= TV_STD_PAL_60; 2240 } 2241 ErrorF("\n"); 2242 2243 if (tv_info->ucExt_TV_ASIC_ID) { 2244 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown external TV ASIC\n"); 2245 return FALSE; 2246 } 2247 2248 return TRUE; 2249} 2250 2251Bool 2252RADEONGetATOMClockInfo(ScrnInfoPtr pScrn) 2253{ 2254 RADEONInfoPtr info = RADEONPTR (pScrn); 2255 RADEONPLLPtr pll = &info->pll; 2256 atomDataTablesPtr atomDataPtr; 2257 uint8_t crev, frev; 2258 2259 atomDataPtr = info->atomBIOS->atomDataPtr; 2260 if (!rhdAtomGetTableRevisionAndSize( 2261 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), 2262 &crev,&frev,NULL)) { 2263 return FALSE; 2264 } 2265 2266 switch(crev) { 2267 case 1: 2268 info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultEngineClock) / 100.0; 2269 info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultMemoryClock) / 100.0; 2270 pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClock); 2271 pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Input); 2272 pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClockPLL_Input); 2273 pll->pll_out_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Output); 2274 pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulMaxPixelClockPLL_Output); 2275 pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usReferenceClock); 2276 break; 2277 case 2: 2278 case 3: 2279 case 4: 2280 default: 2281 info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultEngineClock) / 100.0; 2282 info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultMemoryClock) / 100.0; 2283 pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClock); 2284 pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMinPixelClockPLL_Input); 2285 pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input); 2286 pll->pll_out_min = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMinPixelClockPLL_Output); 2287 pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output); 2288 pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usReferenceClock); 2289 break; 2290 } 2291 pll->reference_div = 0; 2292 if (pll->pll_out_min == 0) 2293 pll->pll_out_min = 64800; 2294 2295 2296 /* limiting the range is a good thing in most cases 2297 * as it limits the number of matching pll combinations, 2298 * however, some duallink DVI monitors seem to prefer combinations that 2299 * would be limited by this. This may need to be revisited 2300 * per chip family. 2301 */ 2302 if (!xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) { 2303 if (pll->pll_out_min > 64800) 2304 pll->pll_out_min = 64800; 2305 } 2306 2307 return TRUE; 2308} 2309 2310Bool 2311RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode) 2312{ 2313 RADEONInfoPtr info = RADEONPTR(pScrn); 2314 ATOM_ANALOG_TV_INFO *tv_info; 2315 ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; 2316 ATOM_DTD_FORMAT *dtd_timings; 2317 atomDataTablesPtr atomDataPtr; 2318 uint8_t crev, frev; 2319 uint16_t misc; 2320 2321 atomDataPtr = info->atomBIOS->atomDataPtr; 2322 if (!rhdAtomGetTableRevisionAndSize( 2323 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info.base), 2324 &crev,&frev,NULL)) { 2325 return FALSE; 2326 } 2327 2328 switch(crev) { 2329 case 1: 2330 tv_info = atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2331 2332 if (index > MAX_SUPPORTED_TV_TIMING) 2333 return FALSE; 2334 2335 mode->CrtcHTotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); 2336 mode->CrtcHDisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); 2337 mode->CrtcHSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); 2338 mode->CrtcHSyncEnd = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) + 2339 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); 2340 2341 mode->CrtcVTotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); 2342 mode->CrtcVDisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); 2343 mode->CrtcVSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); 2344 mode->CrtcVSyncEnd = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) + 2345 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); 2346 2347 mode->Flags = 0; 2348 misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess); 2349 if (misc & ATOM_VSYNC_POLARITY) 2350 mode->Flags |= V_NVSYNC; 2351 if (misc & ATOM_HSYNC_POLARITY) 2352 mode->Flags |= V_NHSYNC; 2353 if (misc & ATOM_COMPOSITESYNC) 2354 mode->Flags |= V_CSYNC; 2355 if (misc & ATOM_INTERLACE) 2356 mode->Flags |= V_INTERLACE; 2357 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2358 mode->Flags |= V_DBLSCAN; 2359 2360 mode->Clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; 2361 2362 if (index == 1) { 2363 /* PAL timings appear to have wrong values for totals */ 2364 mode->CrtcHTotal -= 1; 2365 mode->CrtcVTotal -= 1; 2366 } 2367 break; 2368 case 2: 2369 tv_info_v1_2 = atomDataPtr->AnalogTV_Info.AnalogTV_Info_v1_2; 2370 if (index > MAX_SUPPORTED_TV_TIMING_V1_2) 2371 return FALSE; 2372 2373 dtd_timings = &tv_info_v1_2->aModeTimings[index]; 2374 mode->CrtcHTotal = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time); 2375 mode->CrtcHDisplay = le16_to_cpu(dtd_timings->usHActive); 2376 mode->CrtcHSyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset); 2377 mode->CrtcHSyncEnd = mode->CrtcHSyncStart + le16_to_cpu(dtd_timings->usHSyncWidth); 2378 2379 mode->CrtcVTotal = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time); 2380 mode->CrtcVDisplay = le16_to_cpu(dtd_timings->usVActive); 2381 mode->CrtcVSyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset); 2382 mode->CrtcVSyncEnd = mode->CrtcVSyncStart + le16_to_cpu(dtd_timings->usVSyncWidth); 2383 2384 mode->Flags = 0; 2385 misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); 2386 if (misc & ATOM_VSYNC_POLARITY) 2387 mode->Flags |= V_NVSYNC; 2388 if (misc & ATOM_HSYNC_POLARITY) 2389 mode->Flags |= V_NHSYNC; 2390 if (misc & ATOM_COMPOSITESYNC) 2391 mode->Flags |= V_CSYNC; 2392 if (misc & ATOM_INTERLACE) 2393 mode->Flags |= V_INTERLACE; 2394 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2395 mode->Flags |= V_DBLSCAN; 2396 2397 mode->Clock = le16_to_cpu(dtd_timings->usPixClk) * 10; 2398 2399 break; 2400 } 2401 2402 return TRUE; 2403} 2404 2405uint32_t 2406radeon_get_encoder_id_from_supported_device(ScrnInfoPtr pScrn, uint32_t supported_device, int dac) 2407{ 2408 RADEONInfoPtr info = RADEONPTR (pScrn); 2409 uint32_t ret = 0; 2410 2411 switch (supported_device) { 2412 case ATOM_DEVICE_CRT1_SUPPORT: 2413 case ATOM_DEVICE_TV1_SUPPORT: 2414 case ATOM_DEVICE_TV2_SUPPORT: 2415 case ATOM_DEVICE_CRT2_SUPPORT: 2416 case ATOM_DEVICE_CV_SUPPORT: 2417 switch (dac) { 2418 // primary dac 2419 case 1: 2420 if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2421 (info->ChipFamily == CHIP_FAMILY_RS400) || 2422 (info->ChipFamily == CHIP_FAMILY_RS480)) 2423 ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2424 else if (IS_AVIVO_VARIANT) 2425 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 2426 else 2427 ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 2428 break; 2429 // secondary dac 2430 case 2: 2431 if (IS_AVIVO_VARIANT) 2432 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 2433 else { 2434 /*if (info->ChipFamily == CHIP_FAMILY_R200) 2435 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2436 else*/ 2437 ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2438 } 2439 break; 2440 // external dac 2441 case 3: 2442 if (IS_AVIVO_VARIANT) 2443 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2444 else 2445 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2446 break; 2447 } 2448 break; 2449 case ATOM_DEVICE_LCD1_SUPPORT: 2450 if (IS_AVIVO_VARIANT) 2451 ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2452 else 2453 ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 2454 break; 2455 case ATOM_DEVICE_DFP1_SUPPORT: 2456 if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2457 (info->ChipFamily == CHIP_FAMILY_RS400) || 2458 (info->ChipFamily == CHIP_FAMILY_RS480)) 2459 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2460 else if (IS_AVIVO_VARIANT) 2461 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 2462 else 2463 ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 2464 break; 2465 case ATOM_DEVICE_LCD2_SUPPORT: 2466 case ATOM_DEVICE_DFP2_SUPPORT: 2467 if ((info->ChipFamily == CHIP_FAMILY_RS600) || 2468 (info->ChipFamily == CHIP_FAMILY_RS690) || 2469 (info->ChipFamily == CHIP_FAMILY_RS740)) 2470 ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 2471 else if (IS_AVIVO_VARIANT) 2472 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2473 else 2474 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2475 break; 2476 case ATOM_DEVICE_DFP3_SUPPORT: 2477 ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2478 break; 2479 } 2480 2481 return ret; 2482} 2483 2484Bool 2485RADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn) 2486{ 2487 RADEONInfoPtr info = RADEONPTR (pScrn); 2488 atomDataTablesPtr atomDataPtr; 2489 uint8_t crev, frev; 2490 int i, j; 2491 Bool enable_tv = FALSE; 2492 2493 if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 2494 enable_tv = TRUE; 2495 2496 atomDataPtr = info->atomBIOS->atomDataPtr; 2497 2498 if (!rhdAtomGetTableRevisionAndSize( 2499 &(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader), 2500 &crev,&frev,NULL)) { 2501 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); 2502 return FALSE; 2503 } 2504 2505 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2506 ATOM_CONNECTOR_INFO_I2C ci 2507 = atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[i]; 2508 2509 if (!(le16_to_cpu(atomDataPtr->SupportedDevicesInfo 2510 .SupportedDevicesInfo->usDeviceSupport) & (1 << i))) { 2511 info->BiosConnector[i].valid = FALSE; 2512 continue; 2513 } 2514 2515 /* don't support CV yet */ 2516 if (i == ATOM_DEVICE_CV_INDEX) { 2517 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping Component Video\n"); 2518 info->BiosConnector[i].valid = FALSE; 2519 continue; 2520 } 2521 2522 if (!enable_tv && (i == ATOM_DEVICE_TV1_INDEX)) { 2523 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping TV-Out\n"); 2524 info->BiosConnector[i].valid = FALSE; 2525 continue; 2526 } 2527 2528 info->BiosConnector[i].valid = TRUE; 2529 info->BiosConnector[i].load_detection = TRUE; 2530 info->BiosConnector[i].shared_ddc = FALSE; 2531 info->BiosConnector[i].output_id = ci.sucI2cId.ucAccess; 2532 info->BiosConnector[i].devices = (1 << i); 2533 info->BiosConnector[i].ConnectorType = ci.sucConnectorInfo.sbfAccess.bfConnectorType; 2534 2535 if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 2536 info->BiosConnector[i].valid = FALSE; 2537 continue; 2538 } 2539 2540 /* don't assign a gpio for tv */ 2541 if ((i == ATOM_DEVICE_TV1_INDEX) || 2542 (i == ATOM_DEVICE_TV2_INDEX) || 2543 (i == ATOM_DEVICE_CV_INDEX)) 2544 info->BiosConnector[i].ddc_i2c.valid = FALSE; 2545 else 2546 info->BiosConnector[i].ddc_i2c = 2547 RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.ucAccess); 2548 2549 if (!radeon_add_encoder(pScrn, 2550 radeon_get_encoder_id_from_supported_device(pScrn, (1 << i), 2551 ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC), 2552 (1 << i))) 2553 return FALSE; 2554 2555 /* Always set the connector type to VGA for CRT1/CRT2. if they are 2556 * shared with a DVI port, we'll pick up the DVI connector below when we 2557 * merge the outputs 2558 */ 2559 if ((i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) && 2560 (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I || 2561 info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D || 2562 info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A)) { 2563 info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; 2564 } 2565 2566 if (crev > 1) { 2567 ATOM_CONNECTOR_INC_SRC_BITMAP isb 2568 = atomDataPtr->SupportedDevicesInfo 2569 .SupportedDevicesInfo_HD->asIntSrcInfo[i]; 2570 2571 switch (isb.ucIntSrcBitmap) { 2572 case 0x4: 2573 info->BiosConnector[i].hpd_mask = 0x00000001; 2574 break; 2575 case 0xa: 2576 info->BiosConnector[i].hpd_mask = 0x00000100; 2577 break; 2578 default: 2579 info->BiosConnector[i].hpd_mask = 0; 2580 break; 2581 } 2582 } else 2583 info->BiosConnector[i].hpd_mask = 0; 2584 2585 RADEONApplyATOMQuirks(pScrn, i); 2586 2587 } 2588 2589 /* CRTs/DFPs may share a port */ 2590 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2591 if (info->BiosConnector[i].valid) { 2592 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2593 if (info->BiosConnector[j].valid && (i != j) ) { 2594 if (info->BiosConnector[i].output_id == info->BiosConnector[j].output_id) { 2595 if (((i == ATOM_DEVICE_DFP1_INDEX) || 2596 (i == ATOM_DEVICE_DFP2_INDEX) || 2597 (i == ATOM_DEVICE_DFP3_INDEX)) && 2598 ((j == ATOM_DEVICE_CRT1_INDEX) || 2599 (j == ATOM_DEVICE_CRT2_INDEX))) { 2600 info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2601 if (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) 2602 info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; 2603 info->BiosConnector[j].valid = FALSE; 2604 } else if (((j == ATOM_DEVICE_DFP1_INDEX) || 2605 (j == ATOM_DEVICE_DFP2_INDEX) || 2606 (j == ATOM_DEVICE_DFP3_INDEX)) && 2607 ((i == ATOM_DEVICE_CRT1_INDEX) || 2608 (i == ATOM_DEVICE_CRT2_INDEX))) { 2609 info->BiosConnector[j].devices |= info->BiosConnector[i].devices; 2610 if (info->BiosConnector[j].ConnectorType == CONNECTOR_DVI_D) 2611 info->BiosConnector[j].ConnectorType = CONNECTOR_DVI_I; 2612 info->BiosConnector[i].valid = FALSE; 2613 } else { 2614 info->BiosConnector[i].shared_ddc = TRUE; 2615 info->BiosConnector[j].shared_ddc = TRUE; 2616 } 2617 /* other possible combos? */ 2618 } 2619 } 2620 } 2621 } 2622 } 2623 2624 return TRUE; 2625} 2626 2627# ifdef ATOM_BIOS_PARSER 2628static AtomBiosResult 2629rhdAtomExec (atomBiosHandlePtr handle, 2630 AtomBiosRequestID unused, AtomBiosArgPtr data) 2631{ 2632 RADEONInfoPtr info = RADEONPTR (xf86Screens[handle->scrnIndex]); 2633 Bool ret = FALSE; 2634 char *msg; 2635 int idx = data->exec.index; 2636 void *pspace = data->exec.pspace; 2637 pointer *dataSpace = data->exec.dataSpace; 2638 2639 //RHDFUNCI(handle->scrnIndex); 2640 2641 if (dataSpace) { 2642 if (!handle->fbBase && !handle->scratchBase) 2643 return ATOM_FAILED; 2644 if (handle->fbBase) { 2645 if (!info->FB) { 2646 xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: " 2647 "Cannot exec AtomBIOS: framebuffer not mapped\n", 2648 __func__); 2649 return ATOM_FAILED; 2650 } 2651 *dataSpace = (uint8_t*)info->FB + handle->fbBase; 2652 } else 2653 *dataSpace = (uint8_t*)handle->scratchBase; 2654 } 2655 ret = ParseTableWrapper(pspace, idx, handle, 2656 handle->BIOSBase, 2657 &msg); 2658 if (!ret) 2659 xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s\n",msg); 2660 else 2661 xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 5, "%s\n",msg); 2662 2663 return (ret) ? ATOM_SUCCESS : ATOM_FAILED; 2664} 2665# endif 2666 2667AtomBiosResult 2668RHDAtomBiosFunc(int scrnIndex, atomBiosHandlePtr handle, 2669 AtomBiosRequestID id, AtomBiosArgPtr data) 2670{ 2671 AtomBiosResult ret = ATOM_FAILED; 2672 int i; 2673 char *msg = NULL; 2674 enum msgDataFormat msg_f = MSG_FORMAT_NONE; 2675 AtomBiosRequestFunc req_func = NULL; 2676 2677 //RHDFUNCI(scrnIndex); 2678 2679 for (i = 0; AtomBiosRequestList[i].id != FUNC_END; i++) { 2680 if (id == AtomBiosRequestList[i].id) { 2681 req_func = AtomBiosRequestList[i].request; 2682 msg = AtomBiosRequestList[i].message; 2683 msg_f = AtomBiosRequestList[i].message_format; 2684 break; 2685 } 2686 } 2687 2688 if (req_func == NULL) { 2689 xf86DrvMsg(scrnIndex, X_ERROR, "Unknown AtomBIOS request: %i\n",id); 2690 return ATOM_NOT_IMPLEMENTED; 2691 } 2692 /* Hack for now */ 2693 if (id == ATOMBIOS_INIT) 2694 data->val = scrnIndex; 2695 2696 if (id == ATOMBIOS_INIT || handle) 2697 ret = req_func(handle, id, data); 2698 2699 if (ret == ATOM_SUCCESS) { 2700 2701 switch (msg_f) { 2702 case MSG_FORMAT_DEC: 2703 xf86DrvMsg(scrnIndex,X_INFO,"%s: %li\n", msg, 2704 (unsigned long) data->val); 2705 break; 2706 case MSG_FORMAT_HEX: 2707 xf86DrvMsg(scrnIndex,X_INFO,"%s: 0x%lx\n",msg , 2708 (unsigned long) data->val); 2709 break; 2710 case MSG_FORMAT_NONE: 2711 xf86DrvMsgVerb(scrnIndex, 7, X_INFO, 2712 "Call to %s succeeded\n", msg); 2713 break; 2714 } 2715 2716 } else { 2717 2718 char *result = (ret == ATOM_FAILED) ? "failed" 2719 : "not implemented"; 2720 switch (msg_f) { 2721 case MSG_FORMAT_DEC: 2722 case MSG_FORMAT_HEX: 2723 xf86DrvMsgVerb(scrnIndex, 1, X_WARNING, 2724 "Call to %s %s\n", msg, result); 2725 break; 2726 case MSG_FORMAT_NONE: 2727 xf86DrvMsg(scrnIndex,X_INFO,"Query for %s: %s\n", msg, result); 2728 break; 2729 } 2730 } 2731 return ret; 2732} 2733 2734# ifdef ATOM_BIOS_PARSER 2735VOID* 2736CailAllocateMemory(VOID *CAIL,UINT16 size) 2737{ 2738 void *ret; 2739 CAILFUNC(CAIL); 2740 2741 ret = malloc(size); 2742 memset(ret, 0, size); 2743 return ret; 2744} 2745 2746VOID 2747CailReleaseMemory(VOID *CAIL, VOID *addr) 2748{ 2749 CAILFUNC(CAIL); 2750 2751 free(addr); 2752} 2753 2754VOID 2755CailDelayMicroSeconds(VOID *CAIL, UINT32 delay) 2756{ 2757 CAILFUNC(CAIL); 2758 2759 usleep(delay); 2760 2761 /*DEBUGP(xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_INFO,"Delay %i usec\n",delay));*/ 2762} 2763 2764UINT32 2765CailReadATIRegister(VOID* CAIL, UINT32 idx) 2766{ 2767 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2768 RADEONInfoPtr info = RADEONPTR(pScrn); 2769 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2770 unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2771 UINT32 ret; 2772 UINT32 mm_reg = idx << 2; 2773 CAILFUNC(CAIL); 2774 2775 if (mm_reg < info->MMIOSize) 2776 ret = INREG(mm_reg); 2777 else { 2778 OUTREG(RADEON_MM_INDEX, mm_reg); 2779 ret = INREG(RADEON_MM_DATA); 2780 } 2781 2782 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret));*/ 2783 return ret; 2784} 2785 2786VOID 2787CailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data) 2788{ 2789 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2790 RADEONInfoPtr info = RADEONPTR(pScrn); 2791 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2792 unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2793 UINT32 mm_reg = idx << 2; 2794 CAILFUNC(CAIL); 2795 2796 if (mm_reg < info->MMIOSize) 2797 OUTREG(mm_reg, data); 2798 else { 2799 OUTREG(RADEON_MM_INDEX, mm_reg); 2800 OUTREG(RADEON_MM_DATA, data); 2801 } 2802 2803 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx << 2,data));*/ 2804} 2805 2806UINT32 2807CailReadFBData(VOID* CAIL, UINT32 idx) 2808{ 2809 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2810 RADEONInfoPtr info = RADEONPTR(pScrn); 2811 UINT32 ret; 2812 2813 CAILFUNC(CAIL); 2814 2815 if (((atomBiosHandlePtr)CAIL)->fbBase) { 2816 uint8_t *FBBase = (uint8_t*)info->FB; 2817 ret = *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)); 2818 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2819 } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2820 ret = *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx); 2821 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2822 } else { 2823 xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2824 "%s: no fbbase set\n",__func__); 2825 return 0; 2826 } 2827 return ret; 2828} 2829 2830VOID 2831CailWriteFBData(VOID *CAIL, UINT32 idx, UINT32 data) 2832{ 2833 CAILFUNC(CAIL); 2834 2835 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,data));*/ 2836 if (((atomBiosHandlePtr)CAIL)->fbBase) { 2837 uint8_t *FBBase = (uint8_t*) 2838 RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->FB; 2839 *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)) = data; 2840 } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2841 *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx) = data; 2842 } else 2843 xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2844 "%s: no fbbase set\n",__func__); 2845} 2846 2847ULONG 2848CailReadMC(VOID *CAIL, ULONG Address) 2849{ 2850 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2851 ULONG ret; 2852 2853 CAILFUNC(CAIL); 2854 2855 ret = INMC(pScrn, Address); 2856 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2857 return ret; 2858} 2859 2860VOID 2861CailWriteMC(VOID *CAIL, ULONG Address, ULONG data) 2862{ 2863 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2864 2865 CAILFUNC(CAIL); 2866 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,data));*/ 2867 OUTMC(pScrn, Address, data); 2868} 2869 2870#ifdef XSERVER_LIBPCIACCESS 2871 2872VOID 2873CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2874{ 2875 pci_device_cfg_read(RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->PciInfo, 2876 ret,idx << 2 , size >> 3, NULL); 2877} 2878 2879VOID 2880CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2881{ 2882 pci_device_cfg_write(RADEONPTR(xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex])->PciInfo, 2883 src, idx << 2, size >> 3, NULL); 2884} 2885 2886#else 2887 2888VOID 2889CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2890{ 2891 PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2892 2893 CAILFUNC(CAIL); 2894 2895 switch (size) { 2896 case 8: 2897 *(uint8_t*)ret = pciReadByte(tag,idx << 2); 2898 break; 2899 case 16: 2900 *(uint16_t*)ret = pciReadWord(tag,idx << 2); 2901 break; 2902 case 32: 2903 *(uint32_t*)ret = pciReadLong(tag,idx << 2); 2904 break; 2905 default: 2906 xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex, 2907 X_ERROR,"%s: Unsupported size: %i\n", 2908 __func__,(int)size); 2909 return; 2910 break; 2911 } 2912 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,*(unsigned int*)ret));*/ 2913 2914} 2915 2916VOID 2917CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2918{ 2919 PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2920 2921 CAILFUNC(CAIL); 2922 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,(*(unsigned int*)src)));*/ 2923 switch (size) { 2924 case 8: 2925 pciWriteByte(tag,idx << 2,*(uint8_t*)src); 2926 break; 2927 case 16: 2928 pciWriteWord(tag,idx << 2,*(uint16_t*)src); 2929 break; 2930 case 32: 2931 pciWriteLong(tag,idx << 2,*(uint32_t*)src); 2932 break; 2933 default: 2934 xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2935 "%s: Unsupported size: %i\n",__func__,(int)size); 2936 break; 2937 } 2938} 2939#endif 2940 2941ULONG 2942CailReadPLL(VOID *CAIL, ULONG Address) 2943{ 2944 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2945 ULONG ret; 2946 2947 CAILFUNC(CAIL); 2948 2949 ret = RADEONINPLL(pScrn, Address); 2950 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2951 return ret; 2952} 2953 2954VOID 2955CailWritePLL(VOID *CAIL, ULONG Address,ULONG Data) 2956{ 2957 ScrnInfoPtr pScrn = xf86Screens[((atomBiosHandlePtr)CAIL)->scrnIndex]; 2958 CAILFUNC(CAIL); 2959 2960 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,Data));*/ 2961 RADEONOUTPLL(pScrn, Address, Data); 2962} 2963 2964void 2965atombios_get_command_table_version(atomBiosHandlePtr atomBIOS, int index, int *major, int *minor) 2966{ 2967 ATOM_MASTER_COMMAND_TABLE *cmd_table = (void *)(atomBIOS->BIOSBase + atomBIOS->cmd_offset); 2968 ATOM_MASTER_LIST_OF_COMMAND_TABLES *table_start; 2969 ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *table_hdr; 2970 2971 //unsigned short *ptr; 2972 unsigned short offset; 2973 2974 table_start = &cmd_table->ListOfCommandTables; 2975 2976 offset = *(((unsigned short *)table_start) + index); 2977 2978 offset = le16_to_cpu(offset); 2979 table_hdr = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)(atomBIOS->BIOSBase + offset); 2980 2981 *major = table_hdr->CommonHeader.ucTableFormatRevision; 2982 *minor = table_hdr->CommonHeader.ucTableContentRevision; 2983} 2984 2985 2986UINT16 ATOM_BSWAP16(UINT16 x) 2987{ 2988 return bswap_16(x); 2989} 2990 2991UINT32 ATOM_BSWAP32(UINT32 x) 2992{ 2993 return bswap_32(x); 2994} 2995 2996 2997#endif /* ATOM_BIOS */ 2998