Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2007  Egbert Eich   <eich (at) novell.com>
      3  * Copyright 2007  Luc Verhaegen <lverhaegen (at) novell.com>
      4  * Copyright 2007  Matthias Hopf <mhopf (at) 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 
     46 typedef AtomBiosResult (*AtomBiosRequestFunc)(atomBiosHandlePtr handle,
     47 					  AtomBiosRequestID unused, AtomBiosArgPtr data);
     48 typedef struct rhdConnectorInfo *rhdConnectorInfoPtr;
     49 
     50 static AtomBiosResult rhdAtomInit(atomBiosHandlePtr unused1,
     51 				      AtomBiosRequestID unused2, AtomBiosArgPtr data);
     52 static AtomBiosResult rhdAtomTearDown(atomBiosHandlePtr handle,
     53 					  AtomBiosRequestID unused1, AtomBiosArgPtr unused2);
     54 static AtomBiosResult rhdAtomVramInfoQuery(atomBiosHandlePtr handle,
     55 					       AtomBiosRequestID func, AtomBiosArgPtr data);
     56 static AtomBiosResult rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle,
     57 					       AtomBiosRequestID func, AtomBiosArgPtr data);
     58 static AtomBiosResult rhdAtomAllocateFbScratch(atomBiosHandlePtr handle,
     59 						   AtomBiosRequestID func, AtomBiosArgPtr data);
     60 static AtomBiosResult rhdAtomLvdsGetTimings(atomBiosHandlePtr handle,
     61 					AtomBiosRequestID unused, AtomBiosArgPtr data);
     62 static AtomBiosResult rhdAtomCVGetTimings(atomBiosHandlePtr handle,
     63 					  AtomBiosRequestID unused, AtomBiosArgPtr data);
     64 static AtomBiosResult rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle,
     65 					       AtomBiosRequestID func,  AtomBiosArgPtr data);
     66 static AtomBiosResult rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle,
     67 						  AtomBiosRequestID func, AtomBiosArgPtr data);
     68 static 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
     73 static AtomBiosResult rhdAtomExec(atomBiosHandlePtr handle,
     74 				   AtomBiosRequestID unused, AtomBiosArgPtr data);
     75 # endif
     76 static AtomBiosResult
     77 rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle,
     78 			      AtomBiosRequestID func, AtomBiosArgPtr data);
     79 
     80 
     81 static void
     82 RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds);
     83 
     84 
     85 enum msgDataFormat {
     86     MSG_FORMAT_NONE,
     87     MSG_FORMAT_HEX,
     88     MSG_FORMAT_DEC
     89 };
     90 
     91 struct 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 
    185 enum {
    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 
    199 static void
    200 RHDDebug(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 
    209 static void
    210 RHDDebugCont(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 
    221 static void
    222 CailDebug(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 
    235 static int
    236 rhdAtomAnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr)
    237 {
    238     if (le16_to_cpu(hdr->usStructureSize) == 0xaa55)
    239         return FALSE;
    240 
    241     return TRUE;
    242 }
    243 
    244 static int
    245 rhdAtomAnalyzeRomHdr(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 
    266 static int
    267 rhdAtomAnalyzeRomDataTable(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 
    283 Bool
    284 rhdAtomGetTableRevisionAndSize(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 
    299 static Bool
    300 rhdAtomAnalyzeMasterDataTable(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 
    360 static Bool
    361 rhdAtomGetDataTable(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 
    412 static Bool
    413 rhdAtomGetFbBaseAndSize(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  */
    441 static AtomBiosResult
    442 rhdAtomAllocateFbScratch(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
    500 Bool
    501 rhdAtomASICInit(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 
    527 int
    528 atombios_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 
    551 int
    552 atombios_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 
    581 int
    582 atombios_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 
    606 int
    607 atombios_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 
    636 static AtomBiosResult
    637 rhdAtomInit(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 
    685 static AtomBiosResult
    686 rhdAtomTearDown(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 
    698 static AtomBiosResult
    699 rhdAtomVramInfoQuery(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 
    729 static AtomBiosResult
    730 rhdAtomTmdsInfoQuery(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 
    768 static DisplayModePtr
    769 rhdAtomDTDTimings(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 
    828 static unsigned char*
    829 rhdAtomLvdsDDC(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 
    894 static AtomBiosResult
    895 rhdAtomCVGetTimings(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 
    989 static AtomBiosResult
    990 rhdAtomLvdsGetTimings(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 
   1053 static AtomBiosResult
   1054 rhdAtomLvdsInfoQuery(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 
   1163 static AtomBiosResult
   1164 rhdAtomCompassionateDataQuery(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 
   1220 static AtomBiosResult
   1221 rhdAtomGPIOI2CInfoQuery(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 
   1260 static AtomBiosResult
   1261 rhdAtomFirmwareInfoQuery(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 
   1435 const 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 
   1460 xf86MonPtr 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 
   1513 static RADEONI2CBusRec
   1514 RADEONLookupGPIOLineForDDC(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 
   1603 static RADEONI2CBusRec
   1604 rhdAtomParseI2CRecord(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 
   1615 static uint8_t
   1616 radeon_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 
   1678 static 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 
   1762 uint32_t
   1763 radeon_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 
   1777 radeon_encoder_ptr
   1778 radeon_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 
   1789 Bool
   1790 radeon_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 
   1904 Bool
   1905 RADEONGetATOMConnectorInfoFromBIOSObject (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 
   2078 static void
   2079 RADEONGetATOMLVDSInfo(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 
   2162 void
   2163 RADEONATOMGetIGPInfo(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 
   2191 Bool
   2192 RADEONGetATOMTVInfo(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 
   2263 Bool
   2264 RADEONGetATOMClockInfo(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 
   2332 Bool
   2333 RADEONATOMGetTVTimings(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 
   2427 uint32_t
   2428 radeon_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 
   2506 Bool
   2507 RADEONGetATOMConnectorInfoFromBIOSConnectorTable (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
   2650 static AtomBiosResult
   2651 rhdAtomExec (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 
   2689 AtomBiosResult
   2690 RHDAtomBiosFunc(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
   2757 VOID*
   2758 CailAllocateMemory(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 
   2768 VOID
   2769 CailReleaseMemory(VOID *CAIL, VOID *addr)
   2770 {
   2771     CAILFUNC(CAIL);
   2772 
   2773     free(addr);
   2774 }
   2775 
   2776 VOID
   2777 CailDelayMicroSeconds(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 
   2786 UINT32
   2787 CailReadATIRegister(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 
   2808 VOID
   2809 CailWriteATIRegister(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 
   2828 UINT32
   2829 CailReadFBData(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 
   2852 VOID
   2853 CailWriteFBData(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 
   2870 ULONG
   2871 CailReadMC(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 
   2883 VOID
   2884 CailWriteMC(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 
   2895 VOID
   2896 CailReadPCIConfigData(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 
   2903 VOID
   2904 CailWritePCIConfigData(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 
   2913 VOID
   2914 CailReadPCIConfigData(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 
   2941 VOID
   2942 CailWritePCIConfigData(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 
   2966 ULONG
   2967 CailReadPLL(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 
   2979 VOID
   2980 CailWritePLL(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 
   2989 void
   2990 atombios_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 
   3011 UINT16 ATOM_BSWAP16(UINT16 x)
   3012 {
   3013     return bswap_16(x);
   3014 }
   3015 
   3016 UINT32 ATOM_BSWAP32(UINT32 x)
   3017 {
   3018     return bswap_32(x);
   3019 }
   3020 
   3021 
   3022 #endif /* ATOM_BIOS */
   3023