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