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