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))->pScrn->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->pScrn, handle, GET_FW_FB_SIZE, &data) 418 == ATOM_SUCCESS) { 419 if (data.val == 0) { 420 xf86DrvMsg(handle->pScrn->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->pScrn, 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->pScrn->scrnIndex, X_INFO, "AtomBIOS requests %ikB" 454 " of VRAM scratch space\n",fb_size); 455 fb_size *= 1024; /* convert to bytes */ 456 xf86DrvMsg(handle->pScrn->scrnIndex, X_INFO, "AtomBIOS VRAM scratch base: 0x%x\n", 457 fb_base); 458 } else { 459 fb_size = 20 * 1024; 460 xf86DrvMsg(handle->pScrn->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->pScrn->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->pScrn->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->pScrn->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->pScrn->scrnIndex, X_INFO, 491 "Cannot get VRAM scratch space. " 492 "Allocating in main memory instead\n"); 493 handle->scratchBase = calloc(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->pScrn, handle, 507 GET_DEFAULT_ENGINE_CLOCK, 508 &data); 509 asicInit.sASICInitClocks.ulDefaultEngineClock = cpu_to_le32(data.val / 10);/*in 10 Khz*/ 510 RHDAtomBiosFunc(handle->pScrn, 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->pScrn->scrnIndex, X_INFO, "Calling ASIC Init\n"); 518 if (RHDAtomBiosFunc(handle->pScrn, handle, 519 ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { 520 xf86DrvMsg(handle->pScrn->scrnIndex, X_INFO, "ASIC_INIT Successful\n"); 521 return TRUE; 522 } 523 xf86DrvMsg(handle->pScrn->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->pScrn, 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->pScrn, 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->pScrn, 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->pScrn, 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 ScrnInfoPtr pScrn = data->pScrn; 641 RADEONInfoPtr info = RADEONPTR(pScrn); 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 = calloc(1, sizeof(atomDataTables)))) { 655 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Cannot allocate memory for " 656 "ATOM BIOS data tabes\n"); 657 goto error; 658 } 659 if (!rhdAtomGetDataTable(pScrn->scrnIndex, info->VBIOS, atomDataPtr, &cmd_offset, BIOSImageSize)) 660 goto error1; 661 if (!(handle = calloc(1, sizeof(atomBiosHandleRec)))) { 662 xf86DrvMsg(pScrn->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->pScrn = pScrn; 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 free(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 free(handle->BIOSBase); 692 free(handle->atomDataPtr); 693 if (handle->scratchBase) free(handle->scratchBase); 694 free(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)calloc(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 = le16_to_cpu(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 = le16_to_cpu(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 = le16_to_cpu(dtd->usHActive) + le16_to_cpu(dtd->usHSyncOffset); 792 mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + le16_to_cpu(dtd->usHSyncWidth); 793 mode->CrtcVSyncStart = mode->VSyncStart = le16_to_cpu(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 *)malloc( 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->pScrn->scrnIndex,EDIDBlock); 873 xf86PrintEDID(mon); 874 free(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->pScrn->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->pScrn->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->pScrn, 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_GPIO_I2C_ASSIGMENT); 1537 1538 for (i = 0; i < num_indices; i++) { 1539 gpio = &atomDataPtr->GPIO_I2C_Info->asGPIO_Info[i]; 1540 1541 if (IS_DCE4_VARIANT) { 1542 if ((i == 7) && 1543 (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) && 1544 (gpio->sucI2cId.ucAccess == 0)) { 1545 gpio->sucI2cId.ucAccess = 0x97; 1546 gpio->ucDataMaskShift = 8; 1547 gpio->ucDataEnShift = 8; 1548 gpio->ucDataY_Shift = 8; 1549 gpio->ucDataA_Shift = 8; 1550 } 1551 } 1552 1553 if (gpio->sucI2cId.ucAccess == id) { 1554 i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; 1555 i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; 1556 i2c.put_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; 1557 i2c.put_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; 1558 i2c.get_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; 1559 i2c.get_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; 1560 i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; 1561 i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; 1562 i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); 1563 i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); 1564 i2c.put_clk_mask = (1 << gpio->ucClkEnShift); 1565 i2c.put_data_mask = (1 << gpio->ucDataEnShift); 1566 i2c.get_clk_mask = (1 << gpio->ucClkY_Shift); 1567 i2c.get_data_mask = (1 << gpio->ucDataY_Shift); 1568 i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); 1569 i2c.a_data_mask = (1 << gpio->ucDataA_Shift); 1570 i2c.hw_line = gpio->sucI2cId.ucAccess; 1571 i2c.hw_capable = gpio->sucI2cId.sbfAccess.bfHW_Capable; 1572 i2c.valid = TRUE; 1573 break; 1574 } 1575 } 1576 1577#if 0 1578 ErrorF("id: %d\n", id); 1579 ErrorF("hw capable: %d\n", gpio->sucI2cId.sbfAccess.bfHW_Capable); 1580 ErrorF("hw engine id: %d\n", gpio->sucI2cId.sbfAccess.bfHW_EngineID); 1581 ErrorF("line mux %d\n", gpio->sucI2cId.sbfAccess.bfI2C_LineMux); 1582 ErrorF("mask_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4); 1583 ErrorF("mask_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4); 1584 ErrorF("put_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkEnRegisterIndex) * 4); 1585 ErrorF("put_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataEnRegisterIndex) * 4); 1586 ErrorF("get_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkY_RegisterIndex) * 4); 1587 ErrorF("get_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataY_RegisterIndex) * 4); 1588 ErrorF("a_clk_reg: 0x%x\n", le16_to_cpu(gpio->usClkA_RegisterIndex) * 4); 1589 ErrorF("a_data_reg: 0x%x\n", le16_to_cpu(gpio->usDataA_RegisterIndex) * 4); 1590 ErrorF("mask_clk_mask: %d\n", gpio->ucClkMaskShift); 1591 ErrorF("mask_data_mask: %d\n", gpio->ucDataMaskShift); 1592 ErrorF("put_clk_mask: %d\n", gpio->ucClkEnShift); 1593 ErrorF("put_data_mask: %d\n", gpio->ucDataEnShift); 1594 ErrorF("get_clk_mask: %d\n", gpio->ucClkY_Shift); 1595 ErrorF("get_data_mask: %d\n", gpio->ucDataY_Shift); 1596 ErrorF("a_clk_mask: %d\n", gpio->ucClkA_Shift); 1597 ErrorF("a_data_mask: %d\n", gpio->ucDataA_Shift); 1598#endif 1599 1600 return i2c; 1601} 1602 1603static RADEONI2CBusRec 1604rhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, 1605 ATOM_I2C_RECORD *Record, int i) 1606{ 1607 RADEONInfoPtr info = RADEONPTR (pScrn); 1608 uint8_t *temp = (uint8_t *)&Record->sucI2cId; 1609 1610 info->BiosConnector[i].i2c_line_mux = *temp; 1611 info->BiosConnector[i].ucI2cId = *temp; 1612 return RADEONLookupGPIOLineForDDC(pScrn, *temp); 1613} 1614 1615static uint8_t 1616radeon_lookup_hpd_id(ScrnInfoPtr pScrn, ATOM_HPD_INT_RECORD *record) 1617{ 1618 RADEONInfoPtr info = RADEONPTR (pScrn); 1619 unsigned short size; 1620 uint8_t hpd = 0; 1621 int i, num_indices; 1622 struct _ATOM_GPIO_PIN_LUT *gpio_info; 1623 ATOM_GPIO_PIN_ASSIGNMENT *pin; 1624 atomDataTablesPtr atomDataPtr; 1625 uint8_t crev, frev; 1626 uint32_t reg; 1627 1628 atomDataPtr = info->atomBIOS->atomDataPtr; 1629 1630 if (!rhdAtomGetTableRevisionAndSize( 1631 &(atomDataPtr->GPIO_Pin_LUT->sHeader), 1632 &crev,&frev,&size)) { 1633 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No GPIO Pin Table found!\n"); 1634 return hpd; 1635 } 1636 1637 num_indices = size / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 1638 1639 if (IS_DCE4_VARIANT) 1640 reg = EVERGREEN_DC_GPIO_HPD_A; 1641 else 1642 reg = AVIVO_DC_GPIO_HPD_A; 1643 1644 gpio_info = atomDataPtr->GPIO_Pin_LUT; 1645 for (i = 0; i < num_indices; i++) { 1646 pin = &gpio_info->asGPIO_Pin[i]; 1647 if (record->ucHPDIntGPIOID == pin->ucGPIO_ID) { 1648 if ((le16_to_cpu(pin->usGpioPin_AIndex) * 4) == reg) { 1649 switch (pin->ucGpioPinBitShift) { 1650 case 0: 1651 default: 1652 hpd = 0; 1653 break; 1654 case 8: 1655 hpd = 1; 1656 break; 1657 case 16: 1658 hpd = 2; 1659 break; 1660 case 24: 1661 hpd = 3; 1662 break; 1663 case 26: 1664 hpd = 4; 1665 break; 1666 case 28: 1667 hpd = 5; 1668 break; 1669 } 1670 break; 1671 } 1672 } 1673 } 1674 1675 return hpd; 1676} 1677 1678static void RADEONApplyATOMQuirks(ScrnInfoPtr pScrn, int index) 1679{ 1680 RADEONInfoPtr info = RADEONPTR (pScrn); 1681 1682 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ 1683 if ((info->Chipset == PCI_CHIP_RS690_791E) && 1684 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1685 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x826d)) { 1686 if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1687 (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1688 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1689 } 1690 } 1691 1692 /* RS600 board lists the DVI port as HDMI */ 1693 if ((info->Chipset == PCI_CHIP_RS600_7941) && 1694 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1849) && 1695 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x7941)) { 1696 if ((info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) && 1697 (info->BiosConnector[index].devices & ATOM_DEVICE_DFP3_SUPPORT)) { 1698 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_D; 1699 } 1700 } 1701 1702 /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ 1703 if ((info->Chipset == PCI_CHIP_RS600_7941) && 1704 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x147b) && 1705 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x2412)) { 1706 if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) 1707 info->BiosConnector[index].valid = FALSE; 1708 } 1709 1710 /* Falcon NW laptop lists vga ddc line for LVDS */ 1711 if ((info->Chipset == PCI_CHIP_RV410_5653) && 1712 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1462) && 1713 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0291)) { 1714 if (info->BiosConnector[index].ConnectorType == CONNECTOR_LVDS) { 1715 info->BiosConnector[index].ddc_i2c.valid = FALSE; 1716 } 1717 } 1718 1719 /* Funky macbooks */ 1720 if ((info->Chipset == PCI_CHIP_RV530_71C5) && 1721 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x106b) && 1722 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x0080)) { 1723 if ((index == ATOM_DEVICE_CRT1_INDEX) || 1724 (index == ATOM_DEVICE_CRT2_INDEX) || 1725 (index == ATOM_DEVICE_DFP2_INDEX)) 1726 info->BiosConnector[index].valid = FALSE; 1727 1728 if (index == ATOM_DEVICE_DFP1_INDEX) { 1729 info->BiosConnector[index].devices |= ATOM_DEVICE_CRT2_SUPPORT; 1730 } 1731 } 1732 1733 /* ASUS HD 3600 XT board lists the DVI port as HDMI */ 1734 if ((info->Chipset == PCI_CHIP_RV635_9598) && 1735 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1736 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01da)) { 1737 if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) 1738 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I; 1739 } 1740 1741 /* ASUS HD 3450 board lists the DVI port as HDMI */ 1742 if ((info->Chipset == PCI_CHIP_RV620_95C5) && 1743 (PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1043) && 1744 (PCI_SUB_DEVICE_ID(info->PciInfo) == 0x01e2)) { 1745 if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) 1746 info->BiosConnector[index].ConnectorType = CONNECTOR_DVI_I; 1747 } 1748 1749 /* some BIOSes seem to report DAC on HDMI - usually this is a board with 1750 * HDMI + VGA reporting as HDMI 1751 */ 1752 if (info->BiosConnector[index].ConnectorType == CONNECTOR_HDMI_TYPE_A) { 1753 if (info->BiosConnector[index].devices & (ATOM_DEVICE_CRT_SUPPORT)) { 1754 info->BiosConnector[index].devices &= ~(ATOM_DEVICE_DFP_SUPPORT); 1755 info->BiosConnector[index].ConnectorType = CONNECTOR_VGA; 1756 info->BiosConnector[index].connector_object = 0; 1757 } 1758 } 1759 1760} 1761 1762uint32_t 1763radeon_get_device_index(uint32_t device_support) 1764{ 1765 uint32_t device_index = 0; 1766 1767 if (device_support == 0) 1768 return 0; 1769 1770 while ((device_support & 1) == 0) { 1771 device_support >>= 1; 1772 device_index++; 1773 } 1774 return device_index; 1775} 1776 1777radeon_encoder_ptr 1778radeon_get_encoder(xf86OutputPtr output) 1779{ 1780 RADEONOutputPrivatePtr radeon_output = output->driver_private; 1781 RADEONInfoPtr info = RADEONPTR(output->scrn); 1782 1783 if (radeon_output->active_device) 1784 return info->encoders[radeon_get_device_index(radeon_output->active_device)]; 1785 else 1786 return NULL; 1787} 1788 1789Bool 1790radeon_add_encoder(ScrnInfoPtr pScrn, uint32_t encoder_id, uint32_t device_support) 1791{ 1792 RADEONInfoPtr info = RADEONPTR (pScrn); 1793 uint32_t device_index = radeon_get_device_index(device_support); 1794 int i; 1795 1796 if (device_support == 0) { 1797 ErrorF("device support == 0\n"); 1798 return FALSE; 1799 } 1800 1801 if (info->encoders[device_index] != NULL) 1802 return TRUE; 1803 else { 1804 /* look for the encoder */ 1805 for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { 1806 if ((info->encoders[i] != NULL) && (info->encoders[i]->encoder_id == encoder_id)) { 1807 info->encoders[device_index] = info->encoders[i]; 1808 switch (encoder_id) { 1809 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1810 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1811 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1812 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1813 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1814 if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1815 if (info->encoders[device_index]->dev_priv == NULL) { 1816 info->encoders[device_index]->dev_priv = 1817 (radeon_lvds_ptr)calloc(1,sizeof(radeon_lvds_rec)); 1818 if (info->encoders[device_index]->dev_priv == NULL) { 1819 ErrorF("calloc failed\n"); 1820 return FALSE; 1821 } else 1822 RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1823 } 1824 } 1825 break; 1826 } 1827 return TRUE; 1828 } 1829 } 1830 1831 info->encoders[device_index] = (radeon_encoder_ptr)calloc(1,sizeof(radeon_encoder_rec)); 1832 if (info->encoders[device_index] != NULL) { 1833 info->encoders[device_index]->encoder_id = encoder_id; 1834 info->encoders[device_index]->devices = 0; 1835 info->encoders[device_index]->dev_priv = NULL; 1836 // add dev_priv stuff 1837 switch (encoder_id) { 1838 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1839 info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)calloc(1,sizeof(radeon_lvds_rec)); 1840 if (info->encoders[device_index]->dev_priv == NULL) { 1841 ErrorF("calloc failed\n"); 1842 return FALSE; 1843 } else { 1844 if (info->IsAtomBios) 1845 RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1846 else 1847 RADEONGetLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1848 } 1849 break; 1850 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1851 if (!IS_AVIVO_VARIANT) { 1852 info->encoders[device_index]->dev_priv = (radeon_tvdac_ptr)calloc(1,sizeof(radeon_tvdac_rec)); 1853 if (info->encoders[device_index]->dev_priv == NULL) { 1854 ErrorF("calloc failed\n"); 1855 return FALSE; 1856 } else 1857 RADEONGetTVDacAdjInfo(pScrn, (radeon_tvdac_ptr)info->encoders[device_index]->dev_priv); 1858 } 1859 break; 1860 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1861 if (!IS_AVIVO_VARIANT) { 1862 info->encoders[device_index]->dev_priv = (radeon_tmds_ptr)calloc(1,sizeof(radeon_tmds_rec)); 1863 if (info->encoders[device_index]->dev_priv == NULL) { 1864 ErrorF("calloc failed\n"); 1865 return FALSE; 1866 } else 1867 RADEONGetTMDSInfo(pScrn, (radeon_tmds_ptr)info->encoders[device_index]->dev_priv); 1868 } 1869 break; 1870 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1871 if (!IS_AVIVO_VARIANT) { 1872 info->encoders[device_index]->dev_priv = (radeon_dvo_ptr)calloc(1,sizeof(radeon_dvo_rec)); 1873 if (info->encoders[device_index]->dev_priv == NULL) { 1874 ErrorF("calloc failed\n"); 1875 return FALSE; 1876 } else 1877 RADEONGetExtTMDSInfo(pScrn, (radeon_dvo_ptr)info->encoders[device_index]->dev_priv); 1878 } 1879 break; 1880 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1881 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1882 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1883 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1884 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1885 if (device_support & ATOM_DEVICE_LCD1_SUPPORT) { 1886 info->encoders[device_index]->dev_priv = (radeon_lvds_ptr)calloc(1,sizeof(radeon_lvds_rec)); 1887 if (info->encoders[device_index]->dev_priv == NULL) { 1888 ErrorF("calloc failed\n"); 1889 return FALSE; 1890 } else 1891 RADEONGetATOMLVDSInfo(pScrn, (radeon_lvds_ptr)info->encoders[device_index]->dev_priv); 1892 } 1893 break; 1894 } 1895 return TRUE; 1896 } else { 1897 ErrorF("calloc failed\n"); 1898 return FALSE; 1899 } 1900 } 1901 1902} 1903 1904Bool 1905RADEONGetATOMConnectorInfoFromBIOSObject (ScrnInfoPtr pScrn) 1906{ 1907 RADEONInfoPtr info = RADEONPTR (pScrn); 1908 uint8_t crev, frev; 1909 unsigned short size; 1910 atomDataTablesPtr atomDataPtr; 1911 ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 1912 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 1913 ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj = NULL; 1914 int i, j, path_size, device_support; 1915 Bool enable_tv = FALSE; 1916 1917 if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 1918 enable_tv = TRUE; 1919 1920 atomDataPtr = info->atomBIOS->atomDataPtr; 1921 if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->Object_Header), &crev, &frev, &size)) 1922 return FALSE; 1923 1924 if (crev < 2) 1925 return FALSE; 1926 1927 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) 1928 ((char *)&atomDataPtr->Object_Header->sHeader + 1929 le16_to_cpu(atomDataPtr->Object_Header->usDisplayPathTableOffset)); 1930 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) 1931 ((char *)&atomDataPtr->Object_Header->sHeader + 1932 le16_to_cpu(atomDataPtr->Object_Header->usConnectorObjectTableOffset)); 1933 device_support = le16_to_cpu(atomDataPtr->Object_Header->usDeviceSupport); 1934 1935 path_size = 0; 1936 for (i = 0; i < path_obj->ucNumOfDispPath; i++) { 1937 uint8_t *addr = (uint8_t *)path_obj->asDispPath; 1938 ATOM_DISPLAY_OBJECT_PATH *path; 1939 addr += path_size; 1940 path = (ATOM_DISPLAY_OBJECT_PATH *)addr; 1941 path_size += le16_to_cpu(path->usSize); 1942 1943 if (device_support & le16_to_cpu(path->usDeviceTag)) { 1944 uint8_t con_obj_id, con_obj_num, con_obj_type; 1945 1946 con_obj_id = (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 1947 con_obj_num = (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 1948 con_obj_type = (le16_to_cpu(path->usConnObjectId) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 1949 1950 if ((le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV1_SUPPORT) || 1951 (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_TV2_SUPPORT)) { 1952 if (!enable_tv) { 1953 info->BiosConnector[i].valid = FALSE; 1954 continue; 1955 } 1956 } 1957 1958 /* don't support CV yet */ 1959 if (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_CV_SUPPORT) { 1960 info->BiosConnector[i].valid = FALSE; 1961 continue; 1962 } 1963 1964 if (info->IsIGP && 1965 (con_obj_id == CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { 1966 uint32_t slot_config, ct; 1967 1968 igp_obj = info->atomBIOS->atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2; 1969 1970 if (!igp_obj) 1971 info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1972 else { 1973 if (con_obj_num == 1) 1974 slot_config = igp_obj->ulDDISlot1Config; 1975 else 1976 slot_config = igp_obj->ulDDISlot2Config; 1977 1978 ct = (slot_config >> 16) & 0xff; 1979 info->BiosConnector[i].ConnectorType = object_connector_convert[ct]; 1980 info->BiosConnector[i].connector_object_id = ct; 1981 info->BiosConnector[i].igp_lane_info = slot_config & 0xffff; 1982 } 1983 } else { 1984 info->BiosConnector[i].ConnectorType = object_connector_convert[con_obj_id]; 1985 info->BiosConnector[i].connector_object_id = con_obj_id; 1986 } 1987 1988 if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 1989 info->BiosConnector[i].valid = FALSE; 1990 continue; 1991 } else 1992 info->BiosConnector[i].valid = TRUE; 1993 info->BiosConnector[i].devices = le16_to_cpu(path->usDeviceTag); 1994 info->BiosConnector[i].connector_object = le16_to_cpu(path->usConnObjectId); 1995 1996 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { 1997 uint8_t enc_obj_id, enc_obj_num, enc_obj_type; 1998 1999 enc_obj_id = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 2000 enc_obj_num = (le16_to_cpu(path->usGraphicObjIds[j]) & ENUM_ID_MASK) >> ENUM_ID_SHIFT; 2001 enc_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 2002 2003 if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { 2004 if (enc_obj_num == 2) 2005 info->BiosConnector[i].linkb = TRUE; 2006 else 2007 info->BiosConnector[i].linkb = FALSE; 2008 2009 if (!radeon_add_encoder(pScrn, enc_obj_id, le16_to_cpu(path->usDeviceTag))) 2010 return FALSE; 2011 } 2012 } 2013 2014 /* look up gpio for ddc */ 2015 if ((le16_to_cpu(path->usDeviceTag) & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) { 2016 for (j = 0; j < con_obj->ucNumberOfObjects; j++) { 2017 if (le16_to_cpu(path->usConnObjectId) == le16_to_cpu(con_obj->asObjects[j].usObjectID)) { 2018 ATOM_COMMON_RECORD_HEADER *Record = (ATOM_COMMON_RECORD_HEADER *) 2019 ((char *)&atomDataPtr->Object_Header->sHeader 2020 + le16_to_cpu(con_obj->asObjects[j].usRecordOffset)); 2021 2022 while (Record->ucRecordType > 0 2023 && Record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER ) { 2024 2025 /*ErrorF("record type %d\n", Record->ucRecordType);*/ 2026 switch (Record->ucRecordType) { 2027 case ATOM_I2C_RECORD_TYPE: 2028 info->BiosConnector[i].ddc_i2c = 2029 rhdAtomParseI2CRecord(pScrn, info->atomBIOS, 2030 (ATOM_I2C_RECORD *)Record, j); 2031 break; 2032 case ATOM_HPD_INT_RECORD_TYPE: 2033 info->BiosConnector[i].hpd_id = 2034 radeon_lookup_hpd_id(pScrn, 2035 (ATOM_HPD_INT_RECORD *)Record); 2036 break; 2037 case ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE: 2038 break; 2039 } 2040 2041 Record = (ATOM_COMMON_RECORD_HEADER*) 2042 ((char *)Record + Record->ucRecordSize); 2043 } 2044 break; 2045 } 2046 } 2047 } 2048 } 2049 RADEONApplyATOMQuirks(pScrn, i); 2050 } 2051 2052 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2053 if (info->BiosConnector[i].valid) { 2054 /* shared connectors */ 2055 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2056 if (info->BiosConnector[j].valid && (i != j) ) { 2057 if (info->BiosConnector[i].connector_object == info->BiosConnector[j].connector_object) { 2058 info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2059 info->BiosConnector[j].valid = FALSE; 2060 } 2061 } 2062 } 2063 /* shared ddc */ 2064 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2065 if (info->BiosConnector[j].valid && (i != j) ) { 2066 if (info->BiosConnector[i].i2c_line_mux == info->BiosConnector[j].i2c_line_mux) { 2067 info->BiosConnector[i].shared_ddc = TRUE; 2068 info->BiosConnector[j].shared_ddc = TRUE; 2069 } 2070 } 2071 } 2072 } 2073 } 2074 2075 return TRUE; 2076} 2077 2078static void 2079RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 2080{ 2081 RADEONInfoPtr info = RADEONPTR(pScrn); 2082 radeon_native_mode_ptr native_mode = &lvds->native_mode; 2083 atomDataTablesPtr atomDataPtr; 2084 uint8_t crev, frev; 2085 uint16_t misc; 2086 2087 atomDataPtr = info->atomBIOS->atomDataPtr; 2088 2089 if (!rhdAtomGetTableRevisionAndSize( 2090 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), 2091 &frev,&crev,NULL)) { 2092 return; 2093 } 2094 2095 switch (crev) { 2096 case 1: 2097 native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHActive); 2098 native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVActive); 2099 native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usPixClk) * 10; 2100 native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHBlanking_Time); 2101 native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncOffset); 2102 native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usHSyncWidth); 2103 native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVBlanking_Time); 2104 native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncOffset); 2105 native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncWidth); 2106 misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.susModeMiscInfo.usAccess); 2107 if (misc & ATOM_VSYNC_POLARITY) 2108 native_mode->Flags |= V_NVSYNC; 2109 if (misc & ATOM_HSYNC_POLARITY) 2110 native_mode->Flags |= V_NHSYNC; 2111 if (misc & ATOM_COMPOSITESYNC) 2112 native_mode->Flags |= V_CSYNC; 2113 if (misc & ATOM_INTERLACE) 2114 native_mode->Flags |= V_INTERLACE; 2115 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2116 native_mode->Flags |= V_DBLSCAN; 2117 lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->usOffDelayInMs); 2118 lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info->ucLVDS_Misc; 2119 lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info->ucSS_Id; 2120 break; 2121 case 2: 2122 native_mode->PanelXRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHActive); 2123 native_mode->PanelYRes = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVActive); 2124 native_mode->DotClock = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usPixClk) * 10; 2125 native_mode->HBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHBlanking_Time); 2126 native_mode->HOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncOffset); 2127 native_mode->HSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usHSyncWidth); 2128 native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVBlanking_Time); 2129 native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncOffset); 2130 native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncWidth); 2131 misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.susModeMiscInfo.usAccess); 2132 if (misc & ATOM_VSYNC_POLARITY) 2133 native_mode->Flags |= V_NVSYNC; 2134 if (misc & ATOM_HSYNC_POLARITY) 2135 native_mode->Flags |= V_NHSYNC; 2136 if (misc & ATOM_COMPOSITESYNC) 2137 native_mode->Flags |= V_CSYNC; 2138 if (misc & ATOM_INTERLACE) 2139 native_mode->Flags |= V_INTERLACE; 2140 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2141 native_mode->Flags |= V_DBLSCAN; 2142 lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->usOffDelayInMs); 2143 lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucLVDS_Misc; 2144 lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucSS_Id; 2145 break; 2146 } 2147 native_mode->Flags = 0; 2148 2149 if (lvds->PanelPwrDly > 2000 || lvds->PanelPwrDly < 0) 2150 lvds->PanelPwrDly = 2000; 2151 2152 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2153 "LVDS Info:\n" 2154 "XRes: %d, YRes: %d, DotClock: %d\n" 2155 "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" 2156 "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", 2157 native_mode->PanelXRes, native_mode->PanelYRes, native_mode->DotClock, 2158 native_mode->HBlank, native_mode->HOverPlus, native_mode->HSyncWidth, 2159 native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth); 2160} 2161 2162void 2163RADEONATOMGetIGPInfo(ScrnInfoPtr pScrn) 2164{ 2165 RADEONInfoPtr info = RADEONPTR(pScrn); 2166 atomDataTablesPtr atomDataPtr; 2167 unsigned short size; 2168 uint8_t crev, frev; 2169 2170 atomDataPtr = info->atomBIOS->atomDataPtr; 2171 2172 if (!rhdAtomGetTableRevisionAndSize((ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base), &frev, &crev, &size)) 2173 return; 2174 2175 switch (crev) { 2176 case 1: 2177 info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ulBootUpMemoryClock / 100.0; 2178 info->igp_system_mclk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usK8MemoryClock); 2179 info->igp_ht_link_clk = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usFSBClock); 2180 info->igp_ht_link_width = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->ucHTLinkWidth; 2181 break; 2182 case 2: 2183 info->igp_sideport_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpSidePortClock / 100.0; 2184 info->igp_system_mclk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulBootUpUMAClock / 100.0; 2185 info->igp_ht_link_clk = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulHTLinkFreq / 100.0; 2186 info->igp_ht_link_width = le16_to_cpu(atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->usMinHTLinkWidth); 2187 break; 2188 } 2189} 2190 2191Bool 2192RADEONGetATOMTVInfo(xf86OutputPtr output) 2193{ 2194 ScrnInfoPtr pScrn = output->scrn; 2195 RADEONInfoPtr info = RADEONPTR(pScrn); 2196 RADEONOutputPrivatePtr radeon_output = output->driver_private; 2197 radeon_tvout_ptr tvout = &radeon_output->tvout; 2198 ATOM_ANALOG_TV_INFO *tv_info; 2199 2200 tv_info = info->atomBIOS->atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2201 2202 if (!tv_info) 2203 return FALSE; 2204 2205 switch(tv_info->ucTV_BootUpDefaultStandard) { 2206 case NTSCJ_SUPPORT: 2207 tvout->default_tvStd = TV_STD_NTSC_J; 2208 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); 2209 break; 2210 case PAL_SUPPORT: 2211 tvout->default_tvStd = TV_STD_PAL; 2212 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); 2213 break; 2214 case PALM_SUPPORT: 2215 tvout->default_tvStd = TV_STD_PAL_M; 2216 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); 2217 break; 2218 case PAL60_SUPPORT: 2219 tvout->default_tvStd = TV_STD_PAL_60; 2220 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); 2221 break; 2222 default: 2223 case NTSC_SUPPORT: 2224 tvout->default_tvStd = TV_STD_NTSC; 2225 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); 2226 break; 2227 } 2228 2229 tvout->tvStd = tvout->default_tvStd; 2230 2231 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); 2232 tvout->SupportedTVStds = tvout->default_tvStd; 2233 if (tv_info->ucTV_SupportedStandard & NTSC_SUPPORT) { 2234 ErrorF("NTSC "); 2235 tvout->SupportedTVStds |= TV_STD_NTSC; 2236 } 2237 if (tv_info->ucTV_SupportedStandard & NTSCJ_SUPPORT) { 2238 ErrorF("NTSC-J "); 2239 tvout->SupportedTVStds |= TV_STD_NTSC_J; 2240 } 2241 if (tv_info->ucTV_SupportedStandard & PAL_SUPPORT) { 2242 ErrorF("PAL "); 2243 tvout->SupportedTVStds |= TV_STD_PAL; 2244 } 2245 if (tv_info->ucTV_SupportedStandard & PALM_SUPPORT) { 2246 ErrorF("PAL-M "); 2247 tvout->SupportedTVStds |= TV_STD_PAL_M; 2248 } 2249 if (tv_info->ucTV_SupportedStandard & PAL60_SUPPORT) { 2250 ErrorF("PAL-60 "); 2251 tvout->SupportedTVStds |= TV_STD_PAL_60; 2252 } 2253 ErrorF("\n"); 2254 2255 if (tv_info->ucExt_TV_ASIC_ID) { 2256 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown external TV ASIC\n"); 2257 return FALSE; 2258 } 2259 2260 return TRUE; 2261} 2262 2263Bool 2264RADEONGetATOMClockInfo(ScrnInfoPtr pScrn) 2265{ 2266 RADEONInfoPtr info = RADEONPTR (pScrn); 2267 RADEONPLLPtr pll = &info->pll; 2268 atomDataTablesPtr atomDataPtr; 2269 uint8_t crev, frev; 2270 2271 atomDataPtr = info->atomBIOS->atomDataPtr; 2272 if (!rhdAtomGetTableRevisionAndSize( 2273 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), 2274 &crev,&frev,NULL)) { 2275 return FALSE; 2276 } 2277 2278 switch(crev) { 2279 case 1: 2280 info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultEngineClock) / 100.0; 2281 info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulDefaultMemoryClock) / 100.0; 2282 pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClock); 2283 pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Input); 2284 pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMaxPixelClockPLL_Input); 2285 pll->pll_out_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usMinPixelClockPLL_Output); 2286 pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->ulMaxPixelClockPLL_Output); 2287 pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo->usReferenceClock); 2288 break; 2289 case 2: 2290 case 3: 2291 case 4: 2292 default: 2293 info->sclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultEngineClock) / 100.0; 2294 info->mclk = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulDefaultMemoryClock) / 100.0; 2295 pll->xclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClock); 2296 pll->pll_in_min = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMinPixelClockPLL_Input); 2297 pll->pll_in_max = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input); 2298 pll->pll_out_min = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMinPixelClockPLL_Output); 2299 pll->pll_out_max = le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output); 2300 pll->reference_freq = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_1_2->usReferenceClock); 2301 break; 2302 } 2303 pll->reference_div = 0; 2304 if (pll->pll_out_min == 0) { 2305 if (IS_AVIVO_VARIANT) 2306 pll->pll_out_min = 64800; 2307 else 2308 pll->pll_out_min = 20000; 2309 } 2310 2311 /* limiting the range is a good thing in most cases 2312 * as it limits the number of matching pll combinations, 2313 * however, some duallink DVI monitors seem to prefer combinations that 2314 * would be limited by this. This may need to be revisited 2315 * per chip family. 2316 */ 2317 if (!xf86ReturnOptValBool(info->Options, OPTION_NEW_PLL, TRUE)) { 2318 if (pll->pll_out_min > 64800) 2319 pll->pll_out_min = 64800; 2320 } 2321 2322 if (IS_DCE4_VARIANT) { 2323 info->default_dispclk = 2324 le32_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_2_1->ulDefaultDispEngineClkFreq); 2325 if (info->default_dispclk == 0) 2326 info->default_dispclk = 60000; 2327 info->dp_extclk = le16_to_cpu(atomDataPtr->FirmwareInfo.FirmwareInfo_V_2_1->usUniphyDPModeExtClkFreq); 2328 } 2329 return TRUE; 2330} 2331 2332Bool 2333RADEONATOMGetTVTimings(ScrnInfoPtr pScrn, int index, DisplayModePtr mode) 2334{ 2335 RADEONInfoPtr info = RADEONPTR(pScrn); 2336 ATOM_ANALOG_TV_INFO *tv_info; 2337 ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; 2338 ATOM_DTD_FORMAT *dtd_timings; 2339 atomDataTablesPtr atomDataPtr; 2340 uint8_t crev, frev; 2341 uint16_t misc; 2342 2343 atomDataPtr = info->atomBIOS->atomDataPtr; 2344 if (!rhdAtomGetTableRevisionAndSize( 2345 (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info.base), 2346 &crev,&frev,NULL)) { 2347 return FALSE; 2348 } 2349 2350 switch(crev) { 2351 case 1: 2352 tv_info = atomDataPtr->AnalogTV_Info.AnalogTV_Info; 2353 2354 if (index > MAX_SUPPORTED_TV_TIMING) 2355 return FALSE; 2356 2357 mode->CrtcHTotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); 2358 mode->CrtcHDisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); 2359 mode->CrtcHSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); 2360 mode->CrtcHSyncEnd = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) + 2361 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); 2362 2363 mode->CrtcVTotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); 2364 mode->CrtcVDisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); 2365 mode->CrtcVSyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); 2366 mode->CrtcVSyncEnd = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) + 2367 le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); 2368 2369 mode->Flags = 0; 2370 misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess); 2371 if (misc & ATOM_VSYNC_POLARITY) 2372 mode->Flags |= V_NVSYNC; 2373 if (misc & ATOM_HSYNC_POLARITY) 2374 mode->Flags |= V_NHSYNC; 2375 if (misc & ATOM_COMPOSITESYNC) 2376 mode->Flags |= V_CSYNC; 2377 if (misc & ATOM_INTERLACE) 2378 mode->Flags |= V_INTERLACE; 2379 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2380 mode->Flags |= V_DBLSCAN; 2381 2382 mode->Clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; 2383 2384 if (index == 1) { 2385 /* PAL timings appear to have wrong values for totals */ 2386 mode->CrtcHTotal -= 1; 2387 mode->CrtcVTotal -= 1; 2388 } 2389 break; 2390 case 2: 2391 tv_info_v1_2 = atomDataPtr->AnalogTV_Info.AnalogTV_Info_v1_2; 2392 if (index > MAX_SUPPORTED_TV_TIMING_V1_2) 2393 return FALSE; 2394 2395 dtd_timings = &tv_info_v1_2->aModeTimings[index]; 2396 mode->CrtcHTotal = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time); 2397 mode->CrtcHDisplay = le16_to_cpu(dtd_timings->usHActive); 2398 mode->CrtcHSyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset); 2399 mode->CrtcHSyncEnd = mode->CrtcHSyncStart + le16_to_cpu(dtd_timings->usHSyncWidth); 2400 2401 mode->CrtcVTotal = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time); 2402 mode->CrtcVDisplay = le16_to_cpu(dtd_timings->usVActive); 2403 mode->CrtcVSyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset); 2404 mode->CrtcVSyncEnd = mode->CrtcVSyncStart + le16_to_cpu(dtd_timings->usVSyncWidth); 2405 2406 mode->Flags = 0; 2407 misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); 2408 if (misc & ATOM_VSYNC_POLARITY) 2409 mode->Flags |= V_NVSYNC; 2410 if (misc & ATOM_HSYNC_POLARITY) 2411 mode->Flags |= V_NHSYNC; 2412 if (misc & ATOM_COMPOSITESYNC) 2413 mode->Flags |= V_CSYNC; 2414 if (misc & ATOM_INTERLACE) 2415 mode->Flags |= V_INTERLACE; 2416 if (misc & ATOM_DOUBLE_CLOCK_MODE) 2417 mode->Flags |= V_DBLSCAN; 2418 2419 mode->Clock = le16_to_cpu(dtd_timings->usPixClk) * 10; 2420 2421 break; 2422 } 2423 2424 return TRUE; 2425} 2426 2427uint32_t 2428radeon_get_encoder_id_from_supported_device(ScrnInfoPtr pScrn, uint32_t supported_device, int dac) 2429{ 2430 RADEONInfoPtr info = RADEONPTR (pScrn); 2431 uint32_t ret = 0; 2432 2433 switch (supported_device) { 2434 case ATOM_DEVICE_CRT1_SUPPORT: 2435 case ATOM_DEVICE_TV1_SUPPORT: 2436 case ATOM_DEVICE_TV2_SUPPORT: 2437 case ATOM_DEVICE_CRT2_SUPPORT: 2438 case ATOM_DEVICE_CV_SUPPORT: 2439 switch (dac) { 2440 // primary dac 2441 case 1: 2442 if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2443 (info->ChipFamily == CHIP_FAMILY_RS400) || 2444 (info->ChipFamily == CHIP_FAMILY_RS480)) 2445 ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2446 else if (IS_AVIVO_VARIANT) 2447 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; 2448 else 2449 ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; 2450 break; 2451 // secondary dac 2452 case 2: 2453 if (IS_AVIVO_VARIANT) 2454 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; 2455 else { 2456 /*if (info->ChipFamily == CHIP_FAMILY_R200) 2457 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2458 else*/ 2459 ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; 2460 } 2461 break; 2462 // external dac 2463 case 3: 2464 if (IS_AVIVO_VARIANT) 2465 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2466 else 2467 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2468 break; 2469 } 2470 break; 2471 case ATOM_DEVICE_LCD1_SUPPORT: 2472 if (IS_AVIVO_VARIANT) 2473 ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2474 else 2475 ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; 2476 break; 2477 case ATOM_DEVICE_DFP1_SUPPORT: 2478 if ((info->ChipFamily == CHIP_FAMILY_RS300) || 2479 (info->ChipFamily == CHIP_FAMILY_RS400) || 2480 (info->ChipFamily == CHIP_FAMILY_RS480)) 2481 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2482 else if (IS_AVIVO_VARIANT) 2483 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; 2484 else 2485 ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; 2486 break; 2487 case ATOM_DEVICE_LCD2_SUPPORT: 2488 case ATOM_DEVICE_DFP2_SUPPORT: 2489 if ((info->ChipFamily == CHIP_FAMILY_RS600) || 2490 (info->ChipFamily == CHIP_FAMILY_RS690) || 2491 (info->ChipFamily == CHIP_FAMILY_RS740)) 2492 ret = ENCODER_OBJECT_ID_INTERNAL_DDI; 2493 else if (IS_AVIVO_VARIANT) 2494 ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; 2495 else 2496 ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; 2497 break; 2498 case ATOM_DEVICE_DFP3_SUPPORT: 2499 ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; 2500 break; 2501 } 2502 2503 return ret; 2504} 2505 2506Bool 2507RADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn) 2508{ 2509 RADEONInfoPtr info = RADEONPTR (pScrn); 2510 atomDataTablesPtr atomDataPtr; 2511 uint8_t crev, frev; 2512 int i, j; 2513 Bool enable_tv = FALSE; 2514 2515 if (xf86ReturnOptValBool(info->Options, OPTION_ATOM_TVOUT, FALSE)) 2516 enable_tv = TRUE; 2517 2518 atomDataPtr = info->atomBIOS->atomDataPtr; 2519 2520 if (!rhdAtomGetTableRevisionAndSize( 2521 &(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader), 2522 &crev,&frev,NULL)) { 2523 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); 2524 return FALSE; 2525 } 2526 2527 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2528 ATOM_CONNECTOR_INFO_I2C ci 2529 = atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[i]; 2530 2531 if (!(le16_to_cpu(atomDataPtr->SupportedDevicesInfo 2532 .SupportedDevicesInfo->usDeviceSupport) & (1 << i))) { 2533 info->BiosConnector[i].valid = FALSE; 2534 continue; 2535 } 2536 2537 /* don't support CV yet */ 2538 if (i == ATOM_DEVICE_CV_INDEX) { 2539 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping Component Video\n"); 2540 info->BiosConnector[i].valid = FALSE; 2541 continue; 2542 } 2543 2544 if (!enable_tv && (i == ATOM_DEVICE_TV1_INDEX)) { 2545 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Skipping TV-Out\n"); 2546 info->BiosConnector[i].valid = FALSE; 2547 continue; 2548 } 2549 2550 info->BiosConnector[i].valid = TRUE; 2551 info->BiosConnector[i].load_detection = TRUE; 2552 info->BiosConnector[i].shared_ddc = FALSE; 2553 info->BiosConnector[i].output_id = ci.sucI2cId.ucAccess; 2554 info->BiosConnector[i].devices = (1 << i); 2555 info->BiosConnector[i].ConnectorType = ci.sucConnectorInfo.sbfAccess.bfConnectorType; 2556 2557 if (info->BiosConnector[i].ConnectorType == CONNECTOR_NONE) { 2558 info->BiosConnector[i].valid = FALSE; 2559 continue; 2560 } 2561 2562 /* don't assign a gpio for tv */ 2563 if ((i == ATOM_DEVICE_TV1_INDEX) || 2564 (i == ATOM_DEVICE_TV2_INDEX) || 2565 (i == ATOM_DEVICE_CV_INDEX)) 2566 info->BiosConnector[i].ddc_i2c.valid = FALSE; 2567 else 2568 info->BiosConnector[i].ddc_i2c = 2569 RADEONLookupGPIOLineForDDC(pScrn, ci.sucI2cId.ucAccess); 2570 2571 if (!radeon_add_encoder(pScrn, 2572 radeon_get_encoder_id_from_supported_device(pScrn, (1 << i), 2573 ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC), 2574 (1 << i))) 2575 return FALSE; 2576 2577 /* Always set the connector type to VGA for CRT1/CRT2. if they are 2578 * shared with a DVI port, we'll pick up the DVI connector below when we 2579 * merge the outputs 2580 */ 2581 if ((i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) && 2582 (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I || 2583 info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D || 2584 info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A)) { 2585 info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; 2586 } 2587 2588 if (crev > 1) { 2589 ATOM_CONNECTOR_INC_SRC_BITMAP isb 2590 = atomDataPtr->SupportedDevicesInfo 2591 .SupportedDevicesInfo_HD->asIntSrcInfo[i]; 2592 2593 switch (isb.ucIntSrcBitmap) { 2594 case 0x4: 2595 info->BiosConnector[i].hpd_mask = 0x00000001; 2596 break; 2597 case 0xa: 2598 info->BiosConnector[i].hpd_mask = 0x00000100; 2599 break; 2600 default: 2601 info->BiosConnector[i].hpd_mask = 0; 2602 break; 2603 } 2604 } else 2605 info->BiosConnector[i].hpd_mask = 0; 2606 2607 RADEONApplyATOMQuirks(pScrn, i); 2608 2609 } 2610 2611 /* CRTs/DFPs may share a port */ 2612 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 2613 if (info->BiosConnector[i].valid) { 2614 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 2615 if (info->BiosConnector[j].valid && (i != j) ) { 2616 if (info->BiosConnector[i].output_id == info->BiosConnector[j].output_id) { 2617 if (((i == ATOM_DEVICE_DFP1_INDEX) || 2618 (i == ATOM_DEVICE_DFP2_INDEX) || 2619 (i == ATOM_DEVICE_DFP3_INDEX)) && 2620 ((j == ATOM_DEVICE_CRT1_INDEX) || 2621 (j == ATOM_DEVICE_CRT2_INDEX))) { 2622 info->BiosConnector[i].devices |= info->BiosConnector[j].devices; 2623 if (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) 2624 info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; 2625 info->BiosConnector[j].valid = FALSE; 2626 } else if (((j == ATOM_DEVICE_DFP1_INDEX) || 2627 (j == ATOM_DEVICE_DFP2_INDEX) || 2628 (j == ATOM_DEVICE_DFP3_INDEX)) && 2629 ((i == ATOM_DEVICE_CRT1_INDEX) || 2630 (i == ATOM_DEVICE_CRT2_INDEX))) { 2631 info->BiosConnector[j].devices |= info->BiosConnector[i].devices; 2632 if (info->BiosConnector[j].ConnectorType == CONNECTOR_DVI_D) 2633 info->BiosConnector[j].ConnectorType = CONNECTOR_DVI_I; 2634 info->BiosConnector[i].valid = FALSE; 2635 } else { 2636 info->BiosConnector[i].shared_ddc = TRUE; 2637 info->BiosConnector[j].shared_ddc = TRUE; 2638 } 2639 /* other possible combos? */ 2640 } 2641 } 2642 } 2643 } 2644 } 2645 2646 return TRUE; 2647} 2648 2649# ifdef ATOM_BIOS_PARSER 2650static AtomBiosResult 2651rhdAtomExec (atomBiosHandlePtr handle, 2652 AtomBiosRequestID unused, AtomBiosArgPtr data) 2653{ 2654 RADEONInfoPtr info = RADEONPTR (handle->pScrn); 2655 Bool ret = FALSE; 2656 char *msg; 2657 int idx = data->exec.index; 2658 void *pspace = data->exec.pspace; 2659 pointer *dataSpace = data->exec.dataSpace; 2660 2661 //RHDFUNCI(handle->scrnIndex); 2662 2663 if (dataSpace) { 2664 if (!handle->fbBase && !handle->scratchBase) 2665 return ATOM_FAILED; 2666 if (handle->fbBase) { 2667 if (!info->FB) { 2668 xf86DrvMsg(handle->pScrn->scrnIndex, X_ERROR, "%s: " 2669 "Cannot exec AtomBIOS: framebuffer not mapped\n", 2670 __func__); 2671 return ATOM_FAILED; 2672 } 2673 *dataSpace = (uint8_t*)info->FB + handle->fbBase; 2674 } else 2675 *dataSpace = (uint8_t*)handle->scratchBase; 2676 } 2677 ret = ParseTableWrapper(pspace, idx, handle, 2678 handle->BIOSBase, 2679 &msg); 2680 if (!ret) 2681 xf86DrvMsg(handle->pScrn->scrnIndex, X_ERROR, "%s\n",msg); 2682 else 2683 xf86DrvMsgVerb(handle->pScrn->scrnIndex, X_INFO, 5, "%s\n",msg); 2684 2685 return (ret) ? ATOM_SUCCESS : ATOM_FAILED; 2686} 2687# endif 2688 2689AtomBiosResult 2690RHDAtomBiosFunc(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, 2691 AtomBiosRequestID id, AtomBiosArgPtr data) 2692{ 2693 AtomBiosResult ret = ATOM_FAILED; 2694 int i; 2695 char *msg = NULL; 2696 enum msgDataFormat msg_f = MSG_FORMAT_NONE; 2697 AtomBiosRequestFunc req_func = NULL; 2698 2699 //RHDFUNCI(scrnIndex); 2700 2701 for (i = 0; AtomBiosRequestList[i].id != FUNC_END; i++) { 2702 if (id == AtomBiosRequestList[i].id) { 2703 req_func = AtomBiosRequestList[i].request; 2704 msg = AtomBiosRequestList[i].message; 2705 msg_f = AtomBiosRequestList[i].message_format; 2706 break; 2707 } 2708 } 2709 2710 if (req_func == NULL) { 2711 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unknown AtomBIOS request: %i\n",id); 2712 return ATOM_NOT_IMPLEMENTED; 2713 } 2714 /* Hack for now */ 2715 if (id == ATOMBIOS_INIT) 2716 data->pScrn = pScrn; 2717 2718 if (id == ATOMBIOS_INIT || handle) 2719 ret = req_func(handle, id, data); 2720 2721 if (ret == ATOM_SUCCESS) { 2722 2723 switch (msg_f) { 2724 case MSG_FORMAT_DEC: 2725 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"%s: %li\n", msg, 2726 (unsigned long) data->val); 2727 break; 2728 case MSG_FORMAT_HEX: 2729 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"%s: 0x%lx\n",msg , 2730 (unsigned long) data->val); 2731 break; 2732 case MSG_FORMAT_NONE: 2733 xf86DrvMsgVerb(pScrn->scrnIndex, 7, X_INFO, 2734 "Call to %s succeeded\n", msg); 2735 break; 2736 } 2737 2738 } else { 2739 2740 char *result = (ret == ATOM_FAILED) ? "failed" 2741 : "not implemented"; 2742 switch (msg_f) { 2743 case MSG_FORMAT_DEC: 2744 case MSG_FORMAT_HEX: 2745 xf86DrvMsgVerb(pScrn->scrnIndex, 1, X_WARNING, 2746 "Call to %s %s\n", msg, result); 2747 break; 2748 case MSG_FORMAT_NONE: 2749 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Query for %s: %s\n", msg, result); 2750 break; 2751 } 2752 } 2753 return ret; 2754} 2755 2756# ifdef ATOM_BIOS_PARSER 2757VOID* 2758CailAllocateMemory(VOID *CAIL,UINT16 size) 2759{ 2760 void *ret; 2761 CAILFUNC(CAIL); 2762 2763 ret = malloc(size); 2764 memset(ret, 0, size); 2765 return ret; 2766} 2767 2768VOID 2769CailReleaseMemory(VOID *CAIL, VOID *addr) 2770{ 2771 CAILFUNC(CAIL); 2772 2773 free(addr); 2774} 2775 2776VOID 2777CailDelayMicroSeconds(VOID *CAIL, UINT32 delay) 2778{ 2779 CAILFUNC(CAIL); 2780 2781 usleep(delay); 2782 2783 /*DEBUGP(xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_INFO,"Delay %i usec\n",delay));*/ 2784} 2785 2786UINT32 2787CailReadATIRegister(VOID* CAIL, UINT32 idx) 2788{ 2789 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2790 RADEONInfoPtr info = RADEONPTR(pScrn); 2791 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2792 unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2793 UINT32 ret; 2794 UINT32 mm_reg = idx << 2; 2795 CAILFUNC(CAIL); 2796 2797 if (mm_reg < info->MMIOSize) 2798 ret = INREG(mm_reg); 2799 else { 2800 OUTREG(RADEON_MM_INDEX, mm_reg); 2801 ret = INREG(RADEON_MM_DATA); 2802 } 2803 2804 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret));*/ 2805 return ret; 2806} 2807 2808VOID 2809CailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data) 2810{ 2811 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2812 RADEONInfoPtr info = RADEONPTR(pScrn); 2813 RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 2814 unsigned char *RADEONMMIO = pRADEONEnt->MMIO; 2815 UINT32 mm_reg = idx << 2; 2816 CAILFUNC(CAIL); 2817 2818 if (mm_reg < info->MMIOSize) 2819 OUTREG(mm_reg, data); 2820 else { 2821 OUTREG(RADEON_MM_INDEX, mm_reg); 2822 OUTREG(RADEON_MM_DATA, data); 2823 } 2824 2825 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx << 2,data));*/ 2826} 2827 2828UINT32 2829CailReadFBData(VOID* CAIL, UINT32 idx) 2830{ 2831 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2832 RADEONInfoPtr info = RADEONPTR(pScrn); 2833 UINT32 ret; 2834 2835 CAILFUNC(CAIL); 2836 2837 if (((atomBiosHandlePtr)CAIL)->fbBase) { 2838 uint8_t *FBBase = (uint8_t*)info->FB; 2839 ret = *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)); 2840 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2841 } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2842 ret = *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx); 2843 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,ret));*/ 2844 } else { 2845 xf86DrvMsg(pScrn->scrnIndex,X_ERROR, 2846 "%s: no fbbase set\n",__func__); 2847 return 0; 2848 } 2849 return ret; 2850} 2851 2852VOID 2853CailWriteFBData(VOID *CAIL, UINT32 idx, UINT32 data) 2854{ 2855 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2856 CAILFUNC(CAIL); 2857 2858 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,data));*/ 2859 if (((atomBiosHandlePtr)CAIL)->fbBase) { 2860 uint8_t *FBBase = (uint8_t*) 2861 RADEONPTR(pScrn)->FB; 2862 *((uint32_t*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)) = data; 2863 } else if (((atomBiosHandlePtr)CAIL)->scratchBase) { 2864 *(uint32_t*)((uint8_t*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx) = data; 2865 } else 2866 xf86DrvMsg(pScrn->scrnIndex,X_ERROR, 2867 "%s: no fbbase set\n",__func__); 2868} 2869 2870ULONG 2871CailReadMC(VOID *CAIL, ULONG Address) 2872{ 2873 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2874 ULONG ret; 2875 2876 CAILFUNC(CAIL); 2877 2878 ret = INMC(pScrn, Address); 2879 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2880 return ret; 2881} 2882 2883VOID 2884CailWriteMC(VOID *CAIL, ULONG Address, ULONG data) 2885{ 2886 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2887 2888 CAILFUNC(CAIL); 2889 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,data));*/ 2890 OUTMC(pScrn, Address, data); 2891} 2892 2893#ifdef XSERVER_LIBPCIACCESS 2894 2895VOID 2896CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2897{ 2898 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2899 pci_device_cfg_read(RADEONPTR(pScrn)->PciInfo, 2900 ret,idx << 2 , size >> 3, NULL); 2901} 2902 2903VOID 2904CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2905{ 2906 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2907 pci_device_cfg_write(RADEONPTR(pScrn)->PciInfo, 2908 src, idx << 2, size >> 3, NULL); 2909} 2910 2911#else 2912 2913VOID 2914CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) 2915{ 2916 PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2917 2918 CAILFUNC(CAIL); 2919 2920 switch (size) { 2921 case 8: 2922 *(uint8_t*)ret = pciReadByte(tag,idx << 2); 2923 break; 2924 case 16: 2925 *(uint16_t*)ret = pciReadWord(tag,idx << 2); 2926 break; 2927 case 32: 2928 *(uint32_t*)ret = pciReadLong(tag,idx << 2); 2929 break; 2930 default: 2931 xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex, 2932 X_ERROR,"%s: Unsupported size: %i\n", 2933 __func__,(int)size); 2934 return; 2935 break; 2936 } 2937 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx,*(unsigned int*)ret));*/ 2938 2939} 2940 2941VOID 2942CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) 2943{ 2944 PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; 2945 2946 CAILFUNC(CAIL); 2947 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,idx,(*(unsigned int*)src)));*/ 2948 switch (size) { 2949 case 8: 2950 pciWriteByte(tag,idx << 2,*(uint8_t*)src); 2951 break; 2952 case 16: 2953 pciWriteWord(tag,idx << 2,*(uint16_t*)src); 2954 break; 2955 case 32: 2956 pciWriteLong(tag,idx << 2,*(uint32_t*)src); 2957 break; 2958 default: 2959 xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, 2960 "%s: Unsupported size: %i\n",__func__,(int)size); 2961 break; 2962 } 2963} 2964#endif 2965 2966ULONG 2967CailReadPLL(VOID *CAIL, ULONG Address) 2968{ 2969 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2970 ULONG ret; 2971 2972 CAILFUNC(CAIL); 2973 2974 ret = RADEONINPLL(pScrn, Address); 2975 /*DEBUGP(ErrorF("%s(%x) = %x\n",__func__,Address,ret));*/ 2976 return ret; 2977} 2978 2979VOID 2980CailWritePLL(VOID *CAIL, ULONG Address,ULONG Data) 2981{ 2982 ScrnInfoPtr pScrn = ((atomBiosHandlePtr)CAIL)->pScrn; 2983 CAILFUNC(CAIL); 2984 2985 /*DEBUGP(ErrorF("%s(%x,%x)\n",__func__,Address,Data));*/ 2986 RADEONOUTPLL(pScrn, Address, Data); 2987} 2988 2989void 2990atombios_get_command_table_version(atomBiosHandlePtr atomBIOS, int index, int *major, int *minor) 2991{ 2992 ATOM_MASTER_COMMAND_TABLE *cmd_table = (void *)(atomBIOS->BIOSBase + atomBIOS->cmd_offset); 2993 ATOM_MASTER_LIST_OF_COMMAND_TABLES *table_start; 2994 ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *table_hdr; 2995 2996 //unsigned short *ptr; 2997 unsigned short offset; 2998 2999 table_start = &cmd_table->ListOfCommandTables; 3000 3001 offset = *(((unsigned short *)table_start) + index); 3002 3003 offset = le16_to_cpu(offset); 3004 table_hdr = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)(atomBIOS->BIOSBase + offset); 3005 3006 *major = table_hdr->CommonHeader.ucTableFormatRevision; 3007 *minor = table_hdr->CommonHeader.ucTableContentRevision; 3008} 3009 3010 3011UINT16 ATOM_BSWAP16(UINT16 x) 3012{ 3013 return bswap_16(x); 3014} 3015 3016UINT32 ATOM_BSWAP32(UINT32 x) 3017{ 3018 return bswap_32(x); 3019} 3020 3021 3022#endif /* ATOM_BIOS */ 3023