Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1029 serge 1
/*
2
 * Copyright 2007, 2008  Egbert Eich   
3
 * Copyright 2007, 2008  Luc Verhaegen 
4
 * Copyright 2007, 2008  Matthias Hopf 
5
 * Copyright 2007, 2008  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
/* #define RHD_DEBUG */
26
 
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
#include "xf86.h"
31
 
32
 
33
/* only for testing now */
34
 
35
#include "rhd.h"
36
#include "edid.h"
37
#include "rhd_atombios.h"
38
#include "rhd_connector.h"
39
#include "rhd_output.h"
40
#include "rhd_biosscratch.h"
41
#include "rhd_monitor.h"
42
#include "rhd_card.h"
43
#include "rhd_regs.h"
44
 
45
#ifdef ATOM_BIOS
46
# include "rhd_atomwrapper.h"
47
//# include "xf86int10.h"
48
# ifdef ATOM_BIOS_PARSER
49
#  define INT8 INT8
50
#  define INT16 INT16
51
#  define INT32 INT32
52
#  include "AtomBios/includes/CD_Common_Types.h"
53
# else
54
#  ifndef ULONG
55
typedef unsigned int ULONG;
56
#   define ULONG ULONG
57
#  endif
58
#  ifndef UCHAR
59
typedef unsigned char UCHAR;
60
#   define UCHAR UCHAR
61
#  endif
62
#  ifndef USHORT
63
typedef unsigned short USHORT;
64
#   define USHORT USHORT
65
#  endif
66
# endif
67
 
68
# include "atomBios/includes/atombios.h"
69
# include "atomBios/includes/ObjectID.h"
70
 
71
typedef AtomBiosResult (*AtomBiosRequestFunc)(atomBiosHandlePtr handle,
72
					  AtomBiosRequestID unused, AtomBiosArgPtr data);
73
typedef struct rhdConnectorInfo *rhdConnectorInfoPtr;
74
 
75
static AtomBiosResult rhdAtomInit(atomBiosHandlePtr unused1,
76
				      AtomBiosRequestID unused2, AtomBiosArgPtr data);
77
static AtomBiosResult rhdAtomTearDown(atomBiosHandlePtr handle,
78
					  AtomBiosRequestID unused1, AtomBiosArgPtr unused2);
79
static AtomBiosResult rhdAtomGetDataInCodeTable(atomBiosHandlePtr handle,
80
						AtomBiosRequestID unused, AtomBiosArgPtr data);
81
static AtomBiosResult rhdAtomVramInfoQuery(atomBiosHandlePtr handle,
82
					       AtomBiosRequestID func, AtomBiosArgPtr data);
83
static AtomBiosResult rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle,
84
					       AtomBiosRequestID func, AtomBiosArgPtr data);
85
static AtomBiosResult rhdAtomAllocateFbScratch(atomBiosHandlePtr handle,
86
						   AtomBiosRequestID func, AtomBiosArgPtr data);
87
static AtomBiosResult rhdAtomLvdsGetTimings(atomBiosHandlePtr handle,
88
					AtomBiosRequestID unused, AtomBiosArgPtr data);
89
static AtomBiosResult rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle,
90
					       AtomBiosRequestID func,  AtomBiosArgPtr data);
91
static AtomBiosResult rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle,
92
						  AtomBiosRequestID func, AtomBiosArgPtr data);
93
static AtomBiosResult rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle,
94
						   AtomBiosRequestID func, AtomBiosArgPtr data);
95
static AtomBiosResult rhdAtomConnectorInfo(atomBiosHandlePtr handle,
96
             AtomBiosRequestID unused, AtomBiosArgPtr data);
97
static AtomBiosResult rhdAtomOutputDeviceList(atomBiosHandlePtr handle,
98
					   AtomBiosRequestID unused, AtomBiosArgPtr data);
99
static AtomBiosResult
100
rhdAtomAnalogTVInfoQuery(atomBiosHandlePtr handle,
101
			 AtomBiosRequestID func, AtomBiosArgPtr data);
102
static AtomBiosResult
103
rhdAtomGetConditionalGoldenSetting(atomBiosHandlePtr handle,
104
				   AtomBiosRequestID func, AtomBiosArgPtr data);
105
 
106
# ifdef ATOM_BIOS_PARSER
107
static AtomBiosResult rhdAtomExec(atomBiosHandlePtr handle,
108
				   AtomBiosRequestID unused, AtomBiosArgPtr data);
109
# endif
110
static AtomBiosResult
111
rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle,
112
			      AtomBiosRequestID func, AtomBiosArgPtr data);
113
static AtomBiosResult
114
rhdAtomIntegratedSystemInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data);
115
static AtomBiosResult
116
atomSetRegisterListLocation(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data);
117
static AtomBiosResult
118
atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data);
119
 
120
 
121
enum msgDataFormat {
122
    MSG_FORMAT_NONE,
123
    MSG_FORMAT_HEX,
124
    MSG_FORMAT_DEC
125
};
126
 
127
enum atomRegisterType {
128
    atomRegisterMMIO,
129
    atomRegisterMC,
130
    atomRegisterPLL,
131
    atomRegisterPCICFG
132
};
133
 
134
struct atomBIOSRequests {
135
    AtomBiosRequestID id;
136
    AtomBiosRequestFunc request;
137
    char *message;
138
    enum msgDataFormat message_format;
139
} AtomBiosRequestList [] = {
140
    {ATOMBIOS_INIT,			rhdAtomInit,
141
     "AtomBIOS Init",				MSG_FORMAT_NONE},
142
    {ATOMBIOS_TEARDOWN,			rhdAtomTearDown,
143
     "AtomBIOS Teardown",			MSG_FORMAT_NONE},
144
# ifdef ATOM_BIOS_PARSER
145
    {ATOMBIOS_EXEC,			rhdAtomExec,
146
     "AtomBIOS Exec",				MSG_FORMAT_NONE},
147
#endif
148
    {ATOMBIOS_ALLOCATE_FB_SCRATCH,	rhdAtomAllocateFbScratch,
149
     "AtomBIOS Set FB Space",			MSG_FORMAT_NONE},
150
    {ATOMBIOS_GET_CONNECTORS,		rhdAtomConnectorInfo,
151
     "AtomBIOS Get Connectors",			MSG_FORMAT_NONE},
152
    {ATOMBIOS_GET_OUTPUT_DEVICE_LIST,	rhdAtomOutputDeviceList,
153
     "AtomBIOS Get Output Info",		MSG_FORMAT_NONE},
154
    {ATOMBIOS_GET_PANEL_MODE,		rhdAtomLvdsGetTimings,
155
     "AtomBIOS Get Panel Mode",			MSG_FORMAT_NONE},
156
    {ATOMBIOS_GET_PANEL_EDID,		rhdAtomLvdsGetTimings,
157
     "AtomBIOS Get Panel EDID",			MSG_FORMAT_NONE},
158
    {ATOMBIOS_GET_CODE_DATA_TABLE,	rhdAtomGetDataInCodeTable,
159
     "AtomBIOS Get Datatable from Codetable",   MSG_FORMAT_NONE},
160
    {GET_DEFAULT_ENGINE_CLOCK,		rhdAtomFirmwareInfoQuery,
161
     "Default Engine Clock",			MSG_FORMAT_DEC},
162
    {GET_DEFAULT_MEMORY_CLOCK,		rhdAtomFirmwareInfoQuery,
163
     "Default Memory Clock",			MSG_FORMAT_DEC},
164
    {GET_MAX_PIXEL_CLOCK_PLL_OUTPUT,	rhdAtomFirmwareInfoQuery,
165
     "Maximum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC},
166
    {GET_MIN_PIXEL_CLOCK_PLL_OUTPUT,	rhdAtomFirmwareInfoQuery,
167
     "Minimum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC},
168
    {GET_MAX_PIXEL_CLOCK_PLL_INPUT,	rhdAtomFirmwareInfoQuery,
169
     "Maximum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC},
170
    {GET_MIN_PIXEL_CLOCK_PLL_INPUT,	rhdAtomFirmwareInfoQuery,
171
     "Minimum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC},
172
    {GET_MAX_PIXEL_CLK,			rhdAtomFirmwareInfoQuery,
173
     "Maximum Pixel Clock",			MSG_FORMAT_DEC},
174
    {GET_REF_CLOCK,			rhdAtomFirmwareInfoQuery,
175
     "Reference Clock",				MSG_FORMAT_DEC},
176
    {GET_FW_FB_START,			rhdAtomVramInfoQuery,
177
      "Start of VRAM area used by Firmware",	MSG_FORMAT_HEX},
178
    {GET_FW_FB_SIZE,			rhdAtomVramInfoQuery,
179
      "Framebuffer space used by Firmware (kb)", MSG_FORMAT_DEC},
180
    {ATOM_TMDS_MAX_FREQUENCY,		rhdAtomTmdsInfoQuery,
181
     "TMDS Max Frequency",			MSG_FORMAT_DEC},
182
    {ATOM_TMDS_PLL_CHARGE_PUMP,		rhdAtomTmdsInfoQuery,
183
     "TMDS PLL ChargePump",			MSG_FORMAT_DEC},
184
    {ATOM_TMDS_PLL_DUTY_CYCLE,		rhdAtomTmdsInfoQuery,
185
     "TMDS PLL DutyCycle",			MSG_FORMAT_DEC},
186
    {ATOM_TMDS_PLL_VCO_GAIN,		rhdAtomTmdsInfoQuery,
187
     "TMDS PLL VCO Gain",			MSG_FORMAT_DEC},
188
    {ATOM_TMDS_PLL_VOLTAGE_SWING,	rhdAtomTmdsInfoQuery,
189
     "TMDS PLL VoltageSwing",			MSG_FORMAT_DEC},
190
    {ATOM_LVDS_SUPPORTED_REFRESH_RATE,	rhdAtomLvdsInfoQuery,
191
     "LVDS Supported Refresh Rate",		MSG_FORMAT_DEC},
192
    {ATOM_LVDS_OFF_DELAY,		rhdAtomLvdsInfoQuery,
193
     "LVDS Off Delay",				MSG_FORMAT_DEC},
194
    {ATOM_LVDS_SEQ_DIG_ONTO_DE,		rhdAtomLvdsInfoQuery,
195
     "LVDS SEQ Dig onto DE",			MSG_FORMAT_DEC},
196
    {ATOM_LVDS_SEQ_DE_TO_BL,		rhdAtomLvdsInfoQuery,
197
     "LVDS SEQ DE to BL",			MSG_FORMAT_DEC},
198
    {ATOM_LVDS_TEMPORAL_DITHER,	        rhdAtomLvdsInfoQuery,
199
     "LVDS Temporal Dither ",			MSG_FORMAT_HEX},
200
    {ATOM_LVDS_SPATIAL_DITHER,	        rhdAtomLvdsInfoQuery,
201
     "LVDS Spatial Dither ",			MSG_FORMAT_HEX},
202
    {ATOM_LVDS_DUALLINK,		rhdAtomLvdsInfoQuery,
203
     "LVDS Duallink",				MSG_FORMAT_HEX},
204
    {ATOM_LVDS_GREYLVL,			rhdAtomLvdsInfoQuery,
205
     "LVDS Grey Level",				MSG_FORMAT_HEX},
206
    {ATOM_LVDS_FPDI,			rhdAtomLvdsInfoQuery,
207
     "LVDS FPDI",				MSG_FORMAT_HEX},
208
    {ATOM_LVDS_24BIT,			rhdAtomLvdsInfoQuery,
209
     "LVDS 24Bit",				MSG_FORMAT_HEX},
210
    {ATOM_GPIO_I2C_CLK_MASK,		rhdAtomGPIOI2CInfoQuery,
211
     "GPIO_I2C_Clk_Mask",			MSG_FORMAT_HEX},
212
    {ATOM_GPIO_I2C_CLK_MASK_SHIFT,	rhdAtomGPIOI2CInfoQuery,
213
     "GPIO_I2C_Clk_Mask_Shift",			MSG_FORMAT_HEX},
214
    {ATOM_GPIO_I2C_DATA_MASK,		rhdAtomGPIOI2CInfoQuery,
215
     "GPIO_I2C_Data_Mask",			MSG_FORMAT_HEX},
216
    {ATOM_GPIO_I2C_DATA_MASK_SHIFT,	rhdAtomGPIOI2CInfoQuery,
217
     "GPIO_I2C_Data_Mask_Shift",		MSG_FORMAT_HEX},
218
    {ATOM_DAC1_BG_ADJ,		rhdAtomCompassionateDataQuery,
219
     "DAC1 BG Adjustment",			MSG_FORMAT_HEX},
220
    {ATOM_DAC1_DAC_ADJ,		rhdAtomCompassionateDataQuery,
221
     "DAC1 DAC Adjustment",			MSG_FORMAT_HEX},
222
    {ATOM_DAC1_FORCE,		rhdAtomCompassionateDataQuery,
223
     "DAC1 Force Data",				MSG_FORMAT_HEX},
224
    {ATOM_DAC2_CRTC2_BG_ADJ,	rhdAtomCompassionateDataQuery,
225
     "DAC2_CRTC2 BG Adjustment",		MSG_FORMAT_HEX},
226
    {ATOM_DAC2_NTSC_BG_ADJ,	rhdAtomCompassionateDataQuery,
227
     "DAC2_NTSC BG Adjustment",			MSG_FORMAT_HEX},
228
    {ATOM_DAC2_PAL_BG_ADJ,	rhdAtomCompassionateDataQuery,
229
     "DAC2_PAL BG Adjustment",			MSG_FORMAT_HEX},
230
    {ATOM_DAC2_CV_BG_ADJ,	rhdAtomCompassionateDataQuery,
231
     "DAC2_CV BG Adjustment",			MSG_FORMAT_HEX},
232
    {ATOM_DAC2_CRTC2_DAC_ADJ,	rhdAtomCompassionateDataQuery,
233
     "DAC2_CRTC2 DAC Adjustment",		MSG_FORMAT_HEX},
234
    {ATOM_DAC2_NTSC_DAC_ADJ,	rhdAtomCompassionateDataQuery,
235
     "DAC2_NTSC DAC Adjustment",		MSG_FORMAT_HEX},
236
    {ATOM_DAC2_PAL_DAC_ADJ,	rhdAtomCompassionateDataQuery,
237
     "DAC2_PAL DAC Adjustment",			MSG_FORMAT_HEX},
238
    {ATOM_DAC2_CV_DAC_ADJ,	rhdAtomCompassionateDataQuery,
239
     "DAC2_CV DAC Adjustment",			MSG_FORMAT_HEX},
240
    {ATOM_DAC2_CRTC2_FORCE,	rhdAtomCompassionateDataQuery,
241
     "DAC2_CRTC2 Force",			MSG_FORMAT_HEX},
242
    {ATOM_DAC2_CRTC2_MUX_REG_IND,rhdAtomCompassionateDataQuery,
243
     "DAC2_CRTC2 Mux Register Index",		MSG_FORMAT_HEX},
244
    {ATOM_DAC2_CRTC2_MUX_REG_INFO,rhdAtomCompassionateDataQuery,
245
     "DAC2_CRTC2 Mux Register Info",		MSG_FORMAT_HEX},
246
    {ATOM_ANALOG_TV_MODE, rhdAtomAnalogTVInfoQuery,
247
     "Analog TV Mode",				MSG_FORMAT_NONE},
248
    {ATOM_ANALOG_TV_DEFAULT_MODE, rhdAtomAnalogTVInfoQuery,
249
     "Analog TV Default Mode",			MSG_FORMAT_DEC},
250
    {ATOM_ANALOG_TV_SUPPORTED_MODES, rhdAtomAnalogTVInfoQuery,
251
     "Analog TV Supported Modes",		MSG_FORMAT_HEX},
252
    {ATOM_GET_CONDITIONAL_GOLDEN_SETTINGS, rhdAtomGetConditionalGoldenSetting,
253
     "Conditional Golden Setting",		MSG_FORMAT_NONE},
254
    {ATOM_GET_PCIENB_CFG_REG7, rhdAtomIntegratedSystemInfoQuery,
255
     "PCIE NB Cfg7Reg",				MSG_FORMAT_HEX},
256
    {ATOM_GET_CAPABILITY_FLAG, rhdAtomIntegratedSystemInfoQuery,
257
     "CapabilityFlag",				MSG_FORMAT_HEX},
258
    {ATOM_GET_PCIE_LANES, rhdAtomIntegratedSystemInfoQuery,
259
     "PCI Lanes",				MSG_FORMAT_NONE},
260
    {ATOM_SET_REGISTER_LIST_LOCATION, atomSetRegisterListLocation,
261
     "Register List Location",			MSG_FORMAT_NONE},
262
    {ATOM_RESTORE_REGISTERS, atomRestoreRegisters,
263
     "Restore Registers",			MSG_FORMAT_NONE},
264
    {FUNC_END,					NULL,
265
     NULL,					MSG_FORMAT_NONE}
266
};
267
 
268
/*
269
 * This works around a bug in atombios.h where
270
 * ATOM_MAX_SUPPORTED_DEVICE_INFO is specified incorrectly.
271
 */
272
 
273
#define ATOM_MAX_SUPPORTED_DEVICE_INFO_HD (ATOM_DEVICE_RESERVEDF_INDEX+1)
274
typedef struct _ATOM_SUPPORTED_DEVICES_INFO_HD
275
{
276
    ATOM_COMMON_TABLE_HEADER      sHeader;
277
    USHORT                        usDeviceSupport;
278
    ATOM_CONNECTOR_INFO_I2C       asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_HD];
279
    ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_HD];
280
} ATOM_SUPPORTED_DEVICES_INFO_HD;
281
 
282
typedef struct _atomDataTables
283
{
284
    unsigned char                       *UtilityPipeLine;
285
    ATOM_MULTIMEDIA_CAPABILITY_INFO     *MultimediaCapabilityInfo;
286
    ATOM_MULTIMEDIA_CONFIG_INFO         *MultimediaConfigInfo;
287
    ATOM_STANDARD_VESA_TIMING           *StandardVESA_Timing;
288
    union {
289
        void                            *base;
290
        ATOM_FIRMWARE_INFO              *FirmwareInfo;
291
        ATOM_FIRMWARE_INFO_V1_2         *FirmwareInfo_V_1_2;
292
        ATOM_FIRMWARE_INFO_V1_3         *FirmwareInfo_V_1_3;
293
        ATOM_FIRMWARE_INFO_V1_4         *FirmwareInfo_V_1_4;
294
    } FirmwareInfo;
295
    ATOM_DAC_INFO                       *DAC_Info;
296
    union {
297
        void                            *base;
298
        ATOM_LVDS_INFO                  *LVDS_Info;
299
        ATOM_LVDS_INFO_V12              *LVDS_Info_v12;
300
    } LVDS_Info;
301
    ATOM_TMDS_INFO                      *TMDS_Info;
302
    ATOM_ANALOG_TV_INFO                 *AnalogTV_Info;
303
    union {
304
        void                            *base;
305
        ATOM_SUPPORTED_DEVICES_INFO     *SupportedDevicesInfo;
306
        ATOM_SUPPORTED_DEVICES_INFO_2   *SupportedDevicesInfo_2;
307
        ATOM_SUPPORTED_DEVICES_INFO_2d1 *SupportedDevicesInfo_2d1;
308
        ATOM_SUPPORTED_DEVICES_INFO_HD  *SupportedDevicesInfo_HD;
309
    } SupportedDevicesInfo;
310
    ATOM_GPIO_I2C_INFO                  *GPIO_I2C_Info;
311
    ATOM_VRAM_USAGE_BY_FIRMWARE         *VRAM_UsageByFirmware;
312
    ATOM_GPIO_PIN_LUT                   *GPIO_Pin_LUT;
313
    ATOM_VESA_TO_INTENAL_MODE_LUT       *VESA_ToInternalModeLUT;
314
    union {
315
        void                            *base;
316
        ATOM_COMPONENT_VIDEO_INFO       *ComponentVideoInfo;
317
        ATOM_COMPONENT_VIDEO_INFO_V21   *ComponentVideoInfo_v21;
318
    } ComponentVideoInfo;
319
/**/unsigned char                       *PowerPlayInfo;
320
    COMPASSIONATE_DATA                  *CompassionateData;
321
    ATOM_DISPLAY_DEVICE_PRIORITY_INFO   *SaveRestoreInfo;
322
/**/unsigned char                       *PPLL_SS_Info;
323
    ATOM_OEM_INFO                       *OemInfo;
324
    ATOM_XTMDS_INFO                     *XTMDS_Info;
325
    ATOM_ASIC_MVDD_INFO                 *MclkSS_Info;
326
    ATOM_OBJECT_HEADER                  *Object_Header;
327
    INDIRECT_IO_ACCESS                  *IndirectIOAccess;
328
    ATOM_MC_INIT_PARAM_TABLE            *MC_InitParameter;
329
/**/unsigned char                       *ASIC_VDDC_Info;
330
    ATOM_ASIC_INTERNAL_SS_INFO          *ASIC_InternalSS_Info;
331
/**/unsigned char                       *TV_VideoMode;
332
    union {
333
        void                            *base;
334
        ATOM_VRAM_INFO_V2               *VRAM_Info_v2;
335
        ATOM_VRAM_INFO_V3               *VRAM_Info_v3;
336
    } VRAM_Info;
337
    ATOM_MEMORY_TRAINING_INFO           *MemoryTrainingInfo;
338
    union {
339
        void                            *base;
340
        ATOM_INTEGRATED_SYSTEM_INFO     *IntegratedSystemInfo;
341
        ATOM_INTEGRATED_SYSTEM_INFO_V2  *IntegratedSystemInfo_v2;
342
    } IntegratedSystemInfo;
343
    ATOM_ASIC_PROFILING_INFO            *ASIC_ProfilingInfo;
344
    ATOM_VOLTAGE_OBJECT_INFO            *VoltageObjectInfo;
345
    ATOM_POWER_SOURCE_INFO              *PowerSourceInfo;
346
} atomDataTables, *atomDataTablesPtr;
347
 
348
struct atomSaveListRecord
349
{
350
    /* header */
351
    int Length;
352
    int Last;
353
    struct atomRegisterList{
354
	enum atomRegisterType Type;
355
	CARD32 Address;
356
	CARD32 Value;
357
    } RegisterList[1];
358
};
359
 
360
struct atomSaveListObject
361
{
362
    struct atomSaveListObject *next;
363
    struct atomSaveListRecord **SaveList;
364
};
365
 
366
typedef struct _atomBiosHandle {
367
    int scrnIndex;
368
    RHDPtr rhdPtr;
369
    unsigned char *BIOSBase;
370
    atomDataTablesPtr atomDataPtr;
371
    pointer *scratchBase;
372
    CARD32 fbBase;
373
    PCITAG PciTag;
374
    unsigned int BIOSImageSize;
375
    unsigned char *codeTable;
376
    struct atomSaveListRecord **SaveList;
377
    struct atomSaveListObject *SaveListObjects;
378
} atomBiosHandleRec;
379
 
380
enum {
381
    legacyBIOSLocation = 0xC0000,
382
    legacyBIOSMax = 0x10000
383
};
384
 
385
struct atomConnectorInfoPrivate {
386
    enum atomDevice *Devices;
387
};
388
 
389
#  ifdef ATOM_BIOS_PARSER
390
 
391
#   define LOG_CAIL LOG_DEBUG + 1
392
 
393
static void
394
atomDebugPrintPspace(atomBiosHandlePtr handle, AtomBiosArgPtr data, int size)
395
{
396
    CARD32 *pspace = (CARD32 *)data->exec.pspace;
397
    int i = 0;
398
 
399
    size >>= 2;
400
 
401
    while (i++,size--)
402
	RHDDebug(handle->scrnIndex, " Pspace[%2.2i]: 0x%8.8x\n", i, *(pspace++));
403
}
404
 
405
/*
406
#define va_start(v,l) __builtin_va_start(v,l)
407
#define va_end(v)	__builtin_va_end(v)
408
#define va_arg(v,l)	__builtin_va_arg(v,l)
409
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
410
#define va_copy(d,s)	__builtin_va_copy(d,s)
411
#endif
412
#define __va_copy(d,s)	__builtin_va_copy(d,s)
413
 
414
typedef __builtin_va_list __gnuc_va_list;
415
typedef __gnuc_va_list va_list;
416
 
417
#define arg(x) va_arg (ap, u32_t)
418
 
419
static void
420
CailDebug(int scrnIndex, const char *format, ...)
421
{
422
    va_list ap;
423
 
424
    va_start(ap, format);
425
    xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_CAIL, format, ap);
426
    va_end(ap);
427
}
428
#   define CAILFUNC(ptr) \
429
  CailDebug(((atomBiosHandlePtr)(ptr))->scrnIndex, "CAIL: %s\n", __func__)
430
*/
431
 
432
#  endif
433
 
434
#  define DEBUG_VERSION(index, handle, version) \
435
    xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 3, "%s returned version %i for index 0x%x\n" ,__func__,version.cref,index)
436
#  define DEBUG_VERSION_NAME(index, handle, name, version)		\
437
    xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 3, "%s(%s) returned version %i for index 0x%x\n",\
438
		   __func__,name,version.cref,index)
439
 
440
static int
441
rhdAtomAnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr)
442
{
443
  if (hdr->usStructureSize == 0xaa55)
444
    return FALSE;
445
 
446
  return TRUE;
447
}
448
 
449
static int
450
rhdAtomAnalyzeRomHdr(unsigned char *rombase,
451
              ATOM_ROM_HEADER *hdr,
452
		     unsigned int *data_offset, unsigned int *code_table)
453
{
454
    if (!rhdAtomAnalyzeCommonHdr(&hdr->sHeader)) {
455
     return FALSE;
456
  }
457
    xf86DrvMsg(-1,X_NONE,"\tSubsystemVendorID: 0x%4.4x SubsystemID: 0x%4.4x\n",
458
               hdr->usSubsystemVendorID,hdr->usSubsystemID);
459
    xf86DrvMsg(-1,X_NONE,"\tIOBaseAddress: 0x%4.4x\n",hdr->usIoBaseAddress);
460
    xf86DrvMsgVerb(-1,X_NONE,3,"\tFilename: %s\n",rombase + hdr->usConfigFilenameOffset);
461
    xf86DrvMsgVerb(-1,X_NONE,3,"\tBIOS Bootup Message: %s\n",
462
		   rombase + hdr->usBIOS_BootupMessageOffset);
463
 
464
  *data_offset = hdr->usMasterDataTableOffset;
465
    *code_table = hdr->usMasterCommandTableOffset;
466
 
467
  return TRUE;
468
}
469
 
470
static int
471
rhdAtomAnalyzeRomDataTable(unsigned char *base, int offset,
472
                    void *ptr,unsigned short *size)
473
{
474
    ATOM_COMMON_TABLE_HEADER *table = (ATOM_COMMON_TABLE_HEADER *)
475
        (base + offset);
476
 
477
   if (!*size || !rhdAtomAnalyzeCommonHdr(table)) {
478
    if (*size) *size -= 2;
479
    *(void **)ptr = NULL;
480
    return FALSE;
481
  }
482
  *size -= 2;
483
  *(void **)ptr = (void *)(table);
484
  return TRUE;
485
}
486
 
487
static Bool
488
rhdAtomGetTableRevisionAndSize(ATOM_COMMON_TABLE_HEADER *hdr,
489
			       CARD8 *contentRev,
490
			       CARD8 *formatRev,
491
			       unsigned short *size)
492
{
493
    if (!hdr)
494
        return FALSE;
495
 
496
    if (contentRev) *contentRev = hdr->ucTableContentRevision;
497
    if (formatRev) *formatRev = hdr->ucTableFormatRevision;
498
    if (size) *size = (short)hdr->usStructureSize
499
                   - sizeof(ATOM_COMMON_TABLE_HEADER);
500
 
501
    return TRUE;
502
}
503
 
504
static Bool
505
rhdAtomGetCommandTableRevisionSize(atomBiosHandlePtr handle, int index,
506
				   CARD8 *contentRev, CARD8 *formatRev, unsigned short *size)
507
{
508
    unsigned short offset = ((USHORT *)&(((ATOM_MASTER_COMMAND_TABLE *)handle->codeTable)
509
					 ->ListOfCommandTables))[index];
510
    ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *hdr = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)(handle->BIOSBase + offset);
511
    ATOM_COMMON_TABLE_HEADER hdr1 = hdr->CommonHeader;
512
 
513
    if (!offset) {
514
	*contentRev = *formatRev = 0;
515
	return FALSE;
516
    }
517
    return rhdAtomGetTableRevisionAndSize(&hdr1, contentRev, formatRev, size);
518
}
519
 
520
static Bool
521
rhdAtomAnalyzeMasterDataTable(unsigned char *base,
522
			      ATOM_MASTER_DATA_TABLE *table,
523
			      atomDataTablesPtr data)
524
{
525
    ATOM_MASTER_LIST_OF_DATA_TABLES *data_table =
526
        &table->ListOfDataTables;
527
    unsigned short size;
528
 
529
    if (!rhdAtomAnalyzeCommonHdr(&table->sHeader))
530
        return FALSE;
531
    if (!rhdAtomGetTableRevisionAndSize(&table->sHeader,NULL,NULL,
532
					&size))
533
        return FALSE;
534
# define SET_DATA_TABLE(x) {\
535
   rhdAtomAnalyzeRomDataTable(base,data_table->x,(void *)(&(data->x)),&size); \
536
    }
537
 
538
# define SET_DATA_TABLE_VERS(x) {\
539
   rhdAtomAnalyzeRomDataTable(base,data_table->x,&(data->x.base),&size); \
540
    }
541
 
542
    SET_DATA_TABLE(UtilityPipeLine);
543
    SET_DATA_TABLE(MultimediaCapabilityInfo);
544
    SET_DATA_TABLE(MultimediaConfigInfo);
545
    SET_DATA_TABLE(StandardVESA_Timing);
546
    SET_DATA_TABLE_VERS(FirmwareInfo);
547
    SET_DATA_TABLE(DAC_Info);
548
    SET_DATA_TABLE_VERS(LVDS_Info);
549
    SET_DATA_TABLE(TMDS_Info);
550
    SET_DATA_TABLE(AnalogTV_Info);
551
    SET_DATA_TABLE_VERS(SupportedDevicesInfo);
552
    SET_DATA_TABLE(GPIO_I2C_Info);
553
    SET_DATA_TABLE(VRAM_UsageByFirmware);
554
    SET_DATA_TABLE(GPIO_Pin_LUT);
555
    SET_DATA_TABLE(VESA_ToInternalModeLUT);
556
    SET_DATA_TABLE_VERS(ComponentVideoInfo);
557
    SET_DATA_TABLE(PowerPlayInfo);
558
    SET_DATA_TABLE(CompassionateData);
559
    SET_DATA_TABLE(SaveRestoreInfo);
560
    SET_DATA_TABLE(PPLL_SS_Info);
561
    SET_DATA_TABLE(OemInfo);
562
    SET_DATA_TABLE(XTMDS_Info);
563
    SET_DATA_TABLE(MclkSS_Info);
564
    SET_DATA_TABLE(Object_Header);
565
    SET_DATA_TABLE(IndirectIOAccess);
566
    SET_DATA_TABLE(MC_InitParameter);
567
    SET_DATA_TABLE(ASIC_VDDC_Info);
568
    SET_DATA_TABLE(ASIC_InternalSS_Info);
569
    SET_DATA_TABLE(TV_VideoMode);
570
    SET_DATA_TABLE_VERS(VRAM_Info);
571
    SET_DATA_TABLE(MemoryTrainingInfo);
572
    SET_DATA_TABLE_VERS(IntegratedSystemInfo);
573
    SET_DATA_TABLE(ASIC_ProfilingInfo);
574
    SET_DATA_TABLE(VoltageObjectInfo);
575
    SET_DATA_TABLE(PowerSourceInfo);
576
# undef SET_DATA_TABLE
577
 
578
    return TRUE;
579
}
580
 
581
static Bool
582
rhdAtomGetTables(RHDPtr rhdPtr, unsigned char *base,
583
		 atomDataTables *atomDataPtr, unsigned char **codeTablePtr,
584
		 unsigned int BIOSImageSize)
585
{
586
  unsigned int  data_offset;
587
    unsigned int  code_offset;
588
    int scrnIndex=0;
589
 
590
  unsigned int atom_romhdr_off =  *(unsigned short*)
591
        (base + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
592
  ATOM_ROM_HEADER *atom_rom_hdr =
593
        (ATOM_ROM_HEADER *)(base + atom_romhdr_off);
594
 
595
    RHDFUNCI(scrnIndex);
596
 
597
    if (atom_romhdr_off + sizeof(ATOM_ROM_HEADER) > BIOSImageSize) {
598
	xf86DrvMsg(scrnIndex,X_ERROR,
599
		   "%s: AtomROM header extends beyond BIOS image\n",__func__);
600
    return FALSE;
601
  }
602
 
603
    if (memcmp("ATOM",&atom_rom_hdr->uaFirmWareSignature,4)) {
604
        xf86DrvMsg(scrnIndex,X_ERROR,"%s: No AtomBios signature found\n",
605
		   __func__);
606
    return FALSE;
607
  }
608
    xf86DrvMsg(scrnIndex, X_INFO, "ATOM BIOS Rom: \n");
609
    if (!rhdAtomAnalyzeRomHdr(base, atom_rom_hdr, &data_offset, &code_offset)) {
610
        xf86DrvMsg(scrnIndex, X_ERROR, "RomHeader invalid\n");
611
     return FALSE;
612
  }
613
 
614
    if (data_offset + sizeof (ATOM_MASTER_DATA_TABLE) > BIOSImageSize) {
615
	xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom data table outside of BIOS\n",
616
		   __func__);
617
	return FALSE;
618
  }
619
 
620
    if (code_offset + sizeof (ATOM_MASTER_COMMAND_TABLE) > BIOSImageSize) {
621
	xf86DrvMsg(scrnIndex, X_ERROR, "%s: Atom command table outside of BIOS\n",
622
		   __func__);
623
	(*codeTablePtr) = NULL;
624
    } else
625
	(*codeTablePtr) = base + code_offset;
626
 
627
  if (!rhdAtomAnalyzeMasterDataTable(base, (ATOM_MASTER_DATA_TABLE *)
628
				       (base + data_offset),
629
				       atomDataPtr)) {
630
        xf86DrvMsg(scrnIndex, X_ERROR, "%s: ROM Master Table invalid\n",
631
		   __func__);
632
    return FALSE;
633
  }
634
 
635
  return TRUE;
636
}
637
 
638
static Bool
639
rhdAtomGetFbBaseAndSize(atomBiosHandlePtr handle, unsigned int *base,
640
			unsigned int *size)
641
{
642
  AtomBiosArgRec data;
643
  if (RHDAtomBiosFunc(handle->rhdPtr, handle, GET_FW_FB_SIZE, &data)
644
	== ATOM_SUCCESS) {
645
	if (data.val == 0) {
646
	    xf86DrvMsg(handle->scrnIndex, X_WARNING, "%s: AtomBIOS specified VRAM "
647
		       "scratch space size invalid\n", __func__);
648
	    return FALSE;
649
	}
650
	if (size)
651
	    *size = (int)data.val;
652
    } else
653
    return FALSE;
654
    if (RHDAtomBiosFunc(handle->rhdPtr, handle, GET_FW_FB_START, &data)
655
	== ATOM_SUCCESS) {
656
    if (data.val == 0)
657
	    return FALSE;
658
    if (base)
659
	    *base = (int)data.val;
660
  }
661
  return TRUE;
662
}
663
 
664
/*
665
 * Uses videoRam form ScrnInfoRec.
666
 */
667
static AtomBiosResult
668
rhdAtomAllocateFbScratch(atomBiosHandlePtr handle,
669
			 AtomBiosRequestID func, AtomBiosArgPtr data)
670
{
671
  unsigned int fb_base = 0;
672
  unsigned int fb_size = 0;
673
  unsigned int start = data->fb.start;
674
  unsigned int size = data->fb.size;
675
  handle->scratchBase = NULL;
676
  handle->fbBase = 0;
677
 
678
    if (rhdAtomGetFbBaseAndSize(handle, &fb_base, &fb_size)) {
679
	xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS requests %ikB"
680
		   " of VRAM scratch space\n",fb_size);
681
    fb_size *= 1024; /* convert to bytes */
682
	xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS VRAM scratch base: 0x%x\n",
683
		   fb_base);
684
    } else {
685
    fb_size = 20 * 1024;
686
	    xf86DrvMsg(handle->scrnIndex, X_INFO, " default to: %i\n",fb_size);
687
  }
688
    if (fb_base && fb_size && size) {
689
	/* 4k align */
690
    fb_size = (fb_size & ~(CARD32)0xfff) + ((fb_size & 0xfff) ? 1 : 0);
691
	if ((fb_base + fb_size) > (start + size)) {
692
	    xf86DrvMsg(handle->scrnIndex, X_WARNING,
693
		       "%s: FW FB scratch area %i (size: %i)"
694
		       " extends beyond available framebuffer size %i\n",
695
		       __func__, fb_base, fb_size, size);
696
	} else if ((fb_base + fb_size) < (start + size)) {
697
	    xf86DrvMsg(handle->scrnIndex, X_WARNING,
698
		       "%s: FW FB scratch area not located "
699
                  "at the end of VRAM. Scratch End: "
700
                  "0x%x VRAM End: 0x%x\n", __func__,
701
		       (unsigned int)(fb_base + fb_size),
702
		       size);
703
	} else if (fb_base < start) {
704
	    xf86DrvMsg(handle->scrnIndex, X_WARNING,
705
		       "%s: FW FB scratch area extends below "
706
                    "the base of the free VRAM: 0x%x Base: 0x%x\n",
707
		       __func__, (unsigned int)(fb_base), start);
708
	} else {
709
          size -= fb_size;
710
          handle->fbBase = fb_base;
711
	    return ATOM_SUCCESS;
712
	}
713
    }
714
 
715
    if (!handle->fbBase) {
716
	xf86DrvMsg(handle->scrnIndex, X_INFO,
717
		   "Cannot get VRAM scratch space. "
718
		   "Allocating in main memory instead\n");
719
	handle->scratchBase = xcalloc(fb_size,1);
720
	return ATOM_SUCCESS;
721
    }
722
    return ATOM_FAILED;
723
}
724
 
725
# ifdef ATOM_BIOS_PARSER
726
static Bool
727
rhdAtomASICInit(atomBiosHandlePtr handle)
728
{
729
    ASIC_INIT_PS_ALLOCATION asicInit;
730
    AtomBiosArgRec data;
731
 
732
    RHDFUNC(handle);
733
 
734
    RHDAtomBiosFunc(handle->rhdPtr, handle,
735
		    GET_DEFAULT_ENGINE_CLOCK,
736
		    &data);
737
    asicInit.sASICInitClocks.ulDefaultEngineClock = data.val / 10;/*in 10 Khz*/
738
    RHDAtomBiosFunc(handle->rhdPtr, handle,
739
		    GET_DEFAULT_MEMORY_CLOCK,
740
		    &data);
741
    asicInit.sASICInitClocks.ulDefaultMemoryClock = data.val / 10;/*in 10 Khz*/
742
    data.exec.dataSpace = NULL;
743
    data.exec.index = GetIndexIntoMasterTable(COMMAND, ASIC_Init);
744
    data.exec.pspace = &asicInit;
745
 
746
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling ASIC Init\n");
747
    atomDebugPrintPspace(handle, &data, sizeof(asicInit));
748
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
749
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
750
	xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Successful\n");
751
	return TRUE;
752
    }
753
    xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Failed\n");
754
    return FALSE;
755
}
756
 
757
/*
758
 *
759
 */
760
struct atomCodeTableVersion
761
rhdAtomASICInitVersion(atomBiosHandlePtr handle)
762
{
763
    struct atomCodeTableVersion version;
764
    int index = GetIndexIntoMasterTable(COMMAND, ASIC_Init);
765
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
766
    return version;
767
}
768
 
769
/*
770
 *
771
 */
772
Bool
773
rhdAtomSetScaler(atomBiosHandlePtr handle, enum atomScaler scalerID, enum atomScaleMode mode)
774
{
775
    ENABLE_SCALER_PARAMETERS scaler;
776
    AtomBiosArgRec data;
777
 
778
    RHDFUNC(handle);
779
 
780
    switch (scalerID) {
781
	case atomScaler1:
782
	    scaler.ucScaler = ATOM_SCALER1;
783
	    break;
784
	case atomScaler2:
785
	    scaler.ucScaler = ATOM_SCALER2;
786
	    break;
787
    }
788
 
789
    switch (mode) {
790
	case atomScaleDisable:
791
	    scaler.ucEnable = ATOM_SCALER_DISABLE;
792
	    break;
793
	case atomScaleCenter:
794
	    scaler.ucEnable = ATOM_SCALER_CENTER;
795
	    break;
796
	case atomScaleExpand:
797
	    scaler.ucEnable = ATOM_SCALER_EXPANSION;
798
	    break;
799
	case atomScaleMulttabExpand:
800
	    scaler.ucEnable = ATOM_SCALER_MULTI_EX;
801
	    break;
802
    }
803
 
804
    data.exec.dataSpace = NULL;
805
    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
806
    data.exec.pspace = &scaler;
807
    atomDebugPrintPspace(handle, &data, sizeof(scaler));
808
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableScaler\n");
809
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
810
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
811
	xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableScaler Successful\n");
812
	return TRUE;
813
    }
814
    xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableScaler Failed\n");
815
    return FALSE;
816
}
817
 
818
/*
819
 *
820
 */
821
struct atomCodeTableVersion
822
rhdAtomSetScalerVersion(atomBiosHandlePtr handle)
823
{
824
    struct atomCodeTableVersion version;
825
    int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
826
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
827
    return version;
828
}
829
 
830
/*
831
 *
832
 */
833
Bool
834
rhdAtomSetTVEncoder(atomBiosHandlePtr handle, Bool enable, int mode)
835
{
836
    TV_ENCODER_CONTROL_PS_ALLOCATION tvEncoder;
837
    AtomBiosArgRec data;
838
 
839
    RHDFUNC(handle);
840
 
841
    tvEncoder.sTVEncoder.ucTvStandard = mode;
842
    tvEncoder.sTVEncoder.ucAction = enable ? 1 :0;
843
 
844
    data.exec.dataSpace = NULL;
845
    data.exec.pspace = &tvEncoder;
846
    data.exec.index =  GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
847
 
848
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetTVEncoder\n");
849
    atomDebugPrintPspace(handle, &data, sizeof(tvEncoder));
850
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
851
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
852
	xf86DrvMsg(handle->scrnIndex, X_INFO, "SetTVEncoder Successful\n");
853
	return TRUE;
854
    }
855
    xf86DrvMsg(handle->scrnIndex, X_INFO, "SetTVEncoder Failed\n");
856
    return FALSE;
857
}
858
 
859
/*
860
 *
861
 */
862
#if (ATOM_TRANSMITTER_CONFIG_COHERENT != ATOM_TRANSMITTER_CONFIG_V2_COHERENT)
863
# error
864
#endif
865
 
866
Bool
867
rhdAtomDigTransmitterControl(atomBiosHandlePtr handle, enum atomTransmitter id,
868
			     enum atomTransmitterAction action, struct atomTransmitterConfig *config)
869
{
870
    DIG_TRANSMITTER_CONTROL_PARAMETERS Transmitter;
871
    AtomBiosArgRec data;
872
    char *name = NULL;
873
    struct atomCodeTableVersion version;
874
 
875
    RHDFUNC(handle);
876
 
877
    switch (action) {
878
	case atomTransDisable:
879
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_DISABLE;
880
	    break;
881
	case atomTransEnable:
882
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE;
883
	    break;
884
	case atomTransEnableOutput:
885
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT;
886
	    break;
887
	case atomTransDisableOutput:
888
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT;
889
	    break;
890
	case atomTransLcdBlOff:
891
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_LCD_BLOFF;
892
	    break;
893
	case atomTransLcdBlOn:
894
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_LCD_BLON;
895
	    break;
896
	case atomTransLcdBlBrightness:
897
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL;
898
	    break;
899
	case atomTransSetup:
900
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_SETUP;
901
	    break;
902
	case atomTransInit:
903
	    Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_INIT;
904
	    break;
905
    }
906
 
907
    Transmitter.ucConfig = 0;
908
 
909
    /* INIT is only called by ASIC_Init, for our actions this is always the PXLCLK */
910
    switch (config->LinkCnt) {
911
	case atomSingleLink:
912
	    Transmitter.usPixelClock = config->PixelClock * 4 / 10;
913
	    break;
914
 
915
	case atomDualLink:
916
	    Transmitter.usPixelClock = config->PixelClock * 2/ 10;
917
	    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
918
	    break;
919
    }
920
 
921
    if (config->Coherent)
922
	Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
923
 
924
    switch (id) {
925
	case atomTransmitterDIG1:
926
	case atomTransmitterUNIPHY:
927
	case atomTransmitterUNIPHY1:
928
	case atomTransmitterUNIPHY2:
929
	case atomTransmitterPCIEPHY:
930
	    data.exec.index =  GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
931
	    name = "UNIPHYTransmitterControl";
932
 
933
	    rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version.cref, &version.fref, NULL);
934
 
935
	    if (version.fref > 1 || version.cref > 2)
936
		return FALSE;
937
 
938
	    switch (version.cref) {
939
		case 1:
940
 
941
	    switch (config->Link) {
942
		case atomTransLinkA:
943
		    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
944
		    break;
945
		case atomTransLinkAB:
946
		    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA_B;
947
		    break;
948
		case atomTransLinkB:
949
		    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
950
		    break;
951
		case atomTransLinkBA:
952
		    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB_A;
953
		    break;
954
	    }
955
	    switch (config->Encoder) {
956
		case atomEncoderDIG1:
957
		    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
958
		    break;
959
 
960
		case atomEncoderDIG2:
961
		    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
962
		    break;
963
		default:
964
		    xf86DrvMsg(handle->scrnIndex, X_ERROR,
965
			       "%s called with invalid encoder %x for DIG transmitter\n",
966
			       __func__, config->Encoder);
967
		    return FALSE;
968
	    }
969
	    if (id == atomTransmitterPCIEPHY) {
970
		switch (config->Lanes) {
971
		    case atomPCIELaneNONE:
972
			Transmitter.ucConfig |= 0;
973
			break;
974
		    case atomPCIELane0_3:
975
			Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
976
			break;
977
		    case atomPCIELane0_7:
978
			Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
979
			break;
980
		    case atomPCIELane4_7:
981
			Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
982
			break;
983
		    case atomPCIELane8_11:
984
			Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
985
			break;
986
		    case atomPCIELane8_15:
987
			Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
988
			break;
989
		    case atomPCIELane12_15:
990
			Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
991
			break;
992
		}
993
		/* According to ATI this is the only one used so far */
994
		Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
995
	    }
996
		    break;
997
		case 2:
998
		    if (id == atomTransmitterPCIEPHY) {
999
			xf86DrvMsg(handle->scrnIndex, X_ERROR,
1000
				   "%s PCIPHY not valid for DCE 3.2\n",
1001
				   __func__);
1002
			return FALSE;
1003
		    }
1004
		    switch (config->Link) {
1005
			case atomTransLinkA:
1006
			case atomTransLinkAB:
1007
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_LINKA;
1008
			    break;
1009
			case atomTransLinkB:
1010
			case atomTransLinkBA:
1011
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_LINKB;
1012
			    break;
1013
			default:
1014
			    xf86DrvMsg(handle->scrnIndex, X_ERROR,
1015
				       "%s called with invalid transmitter link selection %x for DIG transmitter\n",
1016
				       __func__, config->Link);
1017
			    return FALSE;
1018
		    }
1019
		    switch (config->Encoder) {
1020
			case atomEncoderDIG1:
1021
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER;
1022
			    break;
1023
			case atomEncoderDIG2:
1024
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER;
1025
			    break;
1026
			default:
1027
			    xf86DrvMsg(handle->scrnIndex, X_ERROR,
1028
				       "%s called with invalid encoder %x for DIG transmitter\n",
1029
				       __func__, config->Encoder);
1030
			    return FALSE;
1031
		    }
1032
		    switch (id) {
1033
			case atomTransmitterUNIPHY:
1034
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1;
1035
			    break;
1036
			case atomTransmitterUNIPHY1:
1037
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2;
1038
			    break;
1039
			case atomTransmitterUNIPHY2:
1040
			    Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3;
1041
			    break;
1042
			default:
1043
			    break;
1044
		    }
1045
 
1046
		    if (config->Mode == atomDP)
1047
			Transmitter.ucConfig |= ATOM_TRASMITTER_CONFIG_V2_DP_CONNECTOR;
1048
		    break;
1049
	    }
1050
 
1051
	    break;
1052
 
1053
	case atomTransmitterLVTMA:
1054
	case atomTransmitterDIG2:
1055
	    data.exec.index =  GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl);
1056
	    name = "DIG2TransmitterControl";
1057
	    break;
1058
    }
1059
 
1060
    data.exec.dataSpace = NULL;
1061
    data.exec.pspace = &Transmitter;
1062
 
1063
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name);
1064
    atomDebugPrintPspace(handle, &data, sizeof(Transmitter));
1065
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
1066
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1067
	xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name);
1068
	return TRUE;
1069
    }
1070
    xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Failed\n",name);
1071
    return FALSE;
1072
}
1073
 
1074
/*
1075
 *
1076
 */
1077
struct atomCodeTableVersion
1078
rhdAtomDigTransmitterControlVersion(atomBiosHandlePtr handle)
1079
{
1080
    struct atomCodeTableVersion version;
1081
    int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
1082
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
1083
    DEBUG_VERSION(index, handle, version);
1084
    return version;
1085
}
1086
 
1087
/*
1088
 *
1089
 */
1090
Bool
1091
rhdAtomOutputControl(atomBiosHandlePtr handle, enum atomOutput OutputId, enum atomOutputAction Action)
1092
{
1093
    AtomBiosArgRec data;
1094
    CARD8 version;
1095
    char *name;
1096
 
1097
    union
1098
    {
1099
	DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS op;
1100
	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION opa;
1101
    } ps;
1102
 
1103
    RHDFUNC(handle);
1104
 
1105
    switch (Action) {
1106
	case atomOutputEnable:
1107
	    ps.op.ucAction = ATOM_ENABLE;
1108
	    break;
1109
	case atomOutputDisable:
1110
	    ps.op.ucAction = ATOM_DISABLE;
1111
	    break;
1112
	default: /* handle below */
1113
	    if (OutputId != atomLCDOutput)
1114
		return FALSE;
1115
    }
1116
 
1117
    switch (OutputId) {
1118
	case atomDVOOutput:
1119
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1120
	    name = "DVOOutputControl";
1121
	    if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL))
1122
		return FALSE;
1123
	    switch  (version) {
1124
		case 1:
1125
		case 2:
1126
		    break;
1127
		case 3:      /* For now. This needs to be treated like DIGTransmitterControl. @@@ */
1128
		    return FALSE;
1129
	    }
1130
	    break;
1131
	case atomLCDOutput:
1132
	    data.exec.index = GetIndexIntoMasterTable(COMMAND,  LCD1OutputControl);
1133
	    name = "LCD1OutputControl";
1134
	    switch (Action) {
1135
		case atomOutputEnable:
1136
		case atomOutputDisable:
1137
		    break;
1138
		case atomOutputLcdOn:
1139
		    ps.op.ucAction = ATOM_LCD_BLON;
1140
		    break;
1141
		case atomOutputLcdOff:
1142
		    ps.op.ucAction = ATOM_LCD_BLOFF;
1143
		    break;
1144
		case atomOutputLcdBrightnessControl:
1145
		    ps.op.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
1146
		    break;
1147
		case atomOutputLcdSelftestStart:
1148
		    ps.op.ucAction = ATOM_LCD_SELFTEST_START;
1149
		    break;
1150
		case atomOutputLcdSelftestStop:
1151
		    ps.op.ucAction = ATOM_LCD_SELFTEST_STOP;
1152
		    break;
1153
		case atomOutputEncoderInit:
1154
		    ps.op.ucAction = ATOM_ENCODER_INIT;
1155
		    break;
1156
		default:
1157
		    return FALSE;
1158
	    }
1159
	    break;
1160
	case atomCVOutput:
1161
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1162
	    name = "CV1OutputControl";
1163
	    break;
1164
	case atomTVOutput:
1165
	    name = "TV1OutputControl";
1166
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1167
	    break;
1168
	case atomLVTMAOutput:
1169
	    name = "LVTMAOutputControl";
1170
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1171
	    switch (Action) {
1172
		case atomOutputEnable:
1173
		case atomOutputDisable:
1174
		    break;
1175
		case atomOutputLcdOn:
1176
		    ps.op.ucAction = ATOM_LCD_BLON;
1177
		    break;
1178
		case atomOutputLcdOff:
1179
		    ps.op.ucAction = ATOM_LCD_BLOFF;
1180
		    break;
1181
		case atomOutputLcdBrightnessControl:
1182
		    ps.op.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL;
1183
		    break;
1184
		case atomOutputLcdSelftestStart:
1185
		    ps.op.ucAction = ATOM_LCD_SELFTEST_START;
1186
		    break;
1187
		case atomOutputLcdSelftestStop:
1188
		    ps.op.ucAction = ATOM_LCD_SELFTEST_STOP;
1189
		    break;
1190
		case atomOutputEncoderInit:
1191
		    ps.op.ucAction = ATOM_ENCODER_INIT;
1192
		    break;
1193
		default:
1194
		    return FALSE;
1195
	    }
1196
	    break;
1197
	case atomTMDSAOutput:
1198
	    name = "TMDSAOutputControl";
1199
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1200
	    break;
1201
	case atomDAC1Output:
1202
	    name = "DAC1OutputControl";
1203
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1204
	    break;
1205
	case atomDAC2Output:
1206
	    name = "DAC2OutputControl";
1207
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1208
	    break;
1209
	default:
1210
	    return FALSE;
1211
    }
1212
 
1213
    data.exec.dataSpace = NULL;
1214
    data.exec.pspace = &ps;
1215
 
1216
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name);
1217
    atomDebugPrintPspace(handle, &data, sizeof(ps));
1218
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
1219
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1220
	xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name);
1221
	return TRUE;
1222
    }
1223
    xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Failed\n",name);
1224
 
1225
    return FALSE;
1226
}
1227
 
1228
/*
1229
 *
1230
 */
1231
struct atomCodeTableVersion
1232
rhdAtomOutputControlVersion(atomBiosHandlePtr handle, enum atomOutput OutputId)
1233
{
1234
    struct atomCodeTableVersion version = {0 , 0};
1235
    int index;
1236
    char *name;
1237
 
1238
    switch (OutputId) {
1239
	case atomDVOOutput:
1240
	    index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
1241
	    name = "DVOOutputControl";
1242
	    break;
1243
	case atomLCDOutput:
1244
	    index = GetIndexIntoMasterTable(COMMAND,  LCD1OutputControl);
1245
	    name = "LCD1OutputControl";
1246
	    break;
1247
	case atomCVOutput:
1248
	    index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
1249
	    name = "CV1OutputControl";
1250
	    break;
1251
	case atomTVOutput:
1252
	    index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
1253
	    name = "TV1OutputControl";
1254
	    break;
1255
	case atomLVTMAOutput:
1256
	    index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
1257
	    name = "LVTMAOutputControl";
1258
	    break;
1259
	case atomTMDSAOutput:
1260
	    index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
1261
	    name = "TMDSAOutputControl";
1262
	    break;
1263
	case atomDAC1Output:
1264
	    index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1265
	    name = "DAC1OutputControl";
1266
	    break;
1267
	case atomDAC2Output:
1268
	    index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1269
	    name = "DAC2OutputContro";
1270
	    break;
1271
	default:
1272
	    return version;
1273
    }
1274
 
1275
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
1276
    DEBUG_VERSION_NAME(index, handle, name, version);
1277
    return version;
1278
}
1279
 
1280
/*
1281
 *
1282
 */
1283
Bool
1284
AtomDACLoadDetection(atomBiosHandlePtr handle, enum atomDevice Device, enum atomDAC dac)
1285
{
1286
    AtomBiosArgRec data;
1287
    union
1288
    {
1289
	DAC_LOAD_DETECTION_PARAMETERS ld;
1290
	DAC_LOAD_DETECTION_PS_ALLOCATION lda;
1291
    } ps;
1292
 
1293
    RHDFUNC(handle);
1294
 
1295
    data.exec.dataSpace = NULL;
1296
    data.exec.pspace = &ps;
1297
    data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1298
    ps.ld.ucMisc = 0;
1299
 
1300
    switch (Device) {
1301
	case atomCRT1:
1302
	    ps.ld.usDeviceID = ATOM_DEVICE_CRT1_SUPPORT;
1303
	    break;
1304
	case atomCRT2:
1305
	    ps.ld.usDeviceID = ATOM_DEVICE_CRT2_SUPPORT;
1306
	    break;
1307
	case atomTV1:
1308
	    ps.ld.usDeviceID = ATOM_DEVICE_TV1_SUPPORT;
1309
	    ps.ld.ucMisc = DAC_LOAD_MISC_YPrPb;
1310
	    break;
1311
	case atomTV2:
1312
	    ps.ld.usDeviceID = ATOM_DEVICE_TV2_SUPPORT;
1313
	    ps.ld.ucMisc = DAC_LOAD_MISC_YPrPb;
1314
	    break;
1315
	case atomCV:
1316
	    ps.ld.usDeviceID = ATOM_DEVICE_CV_SUPPORT;
1317
	    break;
1318
	case atomLCD1:
1319
	case atomDFP1:
1320
	case atomLCD2:
1321
	case atomDFP2:
1322
	case atomDFP3:
1323
	case atomDFP4:
1324
	case atomDFP5:
1325
	case atomNone:
1326
	    xf86DrvMsg(handle->scrnIndex, X_ERROR, "Unsupported device for load detection.\n");
1327
	    return FALSE;
1328
    }
1329
    switch (dac) {
1330
	case atomDACA:
1331
	    ps.ld.ucDacType = ATOM_DAC_A;
1332
	    break;
1333
	case atomDACB:
1334
	    ps.ld.ucDacType = ATOM_DAC_B;
1335
	    break;
1336
	case atomDACExt:
1337
	    ps.ld.ucDacType = ATOM_EXT_DAC;
1338
	    break;
1339
    }
1340
 
1341
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling DAC_LoadDetection\n");
1342
    atomDebugPrintPspace(handle, &data, sizeof(ps));
1343
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
1344
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1345
	xf86DrvMsg(handle->scrnIndex, X_INFO, "DAC_LoadDetection Successful\n");
1346
	return TRUE;
1347
    }
1348
    xf86DrvMsg(handle->scrnIndex, X_INFO, "DAC_LoadDetection Failed\n");
1349
 
1350
    return FALSE;
1351
}
1352
 
1353
/*
1354
 *
1355
 */
1356
struct atomCodeTableVersion
1357
AtomDACLoadDetectionVersion(atomBiosHandlePtr handle, enum atomDevice id)
1358
{
1359
    struct atomCodeTableVersion version;
1360
    int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
1361
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
1362
 
1363
    DEBUG_VERSION(index, handle, version);
1364
 
1365
    return version;
1366
}
1367
 
1368
/*
1369
 *
1370
 */
1371
Bool
1372
rhdAtomEncoderControl(atomBiosHandlePtr handle, enum atomEncoder EncoderId,
1373
			     enum atomEncoderAction Action, struct atomEncoderConfig *Config)
1374
{
1375
    AtomBiosArgRec data;
1376
    char *name = NULL;
1377
    CARD8 version;
1378
 
1379
    union
1380
    {
1381
	DAC_ENCODER_CONTROL_PARAMETERS dac;
1382
	DAC_ENCODER_CONTROL_PS_ALLOCATION dac_a;
1383
	TV_ENCODER_CONTROL_PARAMETERS tv;
1384
	TV_ENCODER_CONTROL_PS_ALLOCATION tv_a;
1385
	LVDS_ENCODER_CONTROL_PARAMETERS lvds;
1386
	LVDS_ENCODER_CONTROL_PS_ALLOCATION lvds_a;
1387
	DIG_ENCODER_CONTROL_PARAMETERS dig;
1388
	DIG_ENCODER_CONTROL_PS_ALLOCATION dig_a;
1389
	EXTERNAL_ENCODER_CONTROL_PARAMETER ext;
1390
	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION ext_a;
1391
	DVO_ENCODER_CONTROL_PARAMETERS dvo;
1392
	DVO_ENCODER_CONTROL_PS_ALLOCATION dvo_a;
1393
	DVO_ENCODER_CONTROL_PARAMETERS_V3 dvo_v3;
1394
	DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3_a;
1395
	LVDS_ENCODER_CONTROL_PARAMETERS_V2 lvdsv2;
1396
	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 lvds2_a;
1397
	USHORT usPixelClock;
1398
    } ps;
1399
 
1400
    RHDFUNC(handle);
1401
 
1402
    ps.usPixelClock = Config->PixelClock / 10;
1403
 
1404
    switch (EncoderId) {
1405
	case atomEncoderDACA:
1406
	case atomEncoderDACB:
1407
	    if (EncoderId == atomEncoderDACA) {
1408
		name = "DACAEncoderControl";
1409
		data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
1410
	    } else {
1411
		name = "DACBEncoderControl";
1412
		data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
1413
	    }
1414
	    {
1415
		DAC_ENCODER_CONTROL_PARAMETERS *dac = &ps.dac;
1416
		switch (Config->u.dac.DacStandard) {
1417
		    case atomDAC_VGA:
1418
			dac->ucDacStandard = ATOM_DAC1_PS2;
1419
			break;
1420
		    case atomDAC_CV:
1421
			dac->ucDacStandard = ATOM_DAC1_CV;
1422
			break;
1423
		    case atomDAC_NTSC:
1424
			dac->ucDacStandard = ATOM_DAC1_NTSC;
1425
			break;
1426
		    case atomDAC_PAL:
1427
			dac->ucDacStandard = ATOM_DAC1_PAL;
1428
			break;
1429
		}
1430
		switch (Action) {
1431
		    case atomEncoderOn:
1432
			dac->ucAction = ATOM_ENABLE;
1433
			break;
1434
		    case atomEncoderOff:
1435
			dac->ucAction = ATOM_DISABLE;
1436
			break;
1437
		    default:
1438
			xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DAC unknown action\n",__func__);
1439
			return FALSE;
1440
		}
1441
	    }
1442
	    break;
1443
	case atomEncoderTV:
1444
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
1445
	    name = "TVAEncoderControl";
1446
	    {
1447
		TV_ENCODER_CONTROL_PARAMETERS *tv = &ps.tv;
1448
		switch (Config->u.tv.TvStandard) {
1449
		    case RHD_TV_NTSC:
1450
			tv->ucTvStandard = ATOM_TV_NTSC;
1451
			break;
1452
		    case RHD_TV_NTSCJ:
1453
			tv->ucTvStandard = ATOM_TV_NTSCJ;
1454
			break;
1455
		    case RHD_TV_PAL:
1456
			tv->ucTvStandard = ATOM_TV_PAL;
1457
			break;
1458
		    case RHD_TV_PALM:
1459
			tv->ucTvStandard = ATOM_TV_PALM;
1460
			break;
1461
		    case RHD_TV_PALCN:
1462
			tv->ucTvStandard = ATOM_TV_PALCN;
1463
			break;
1464
		    case RHD_TV_PALN:
1465
			tv->ucTvStandard = ATOM_TV_PALN;
1466
			break;
1467
		    case RHD_TV_PAL60:
1468
			tv->ucTvStandard = ATOM_TV_PAL60;
1469
			break;
1470
		    case RHD_TV_SECAM:
1471
			tv->ucTvStandard = ATOM_TV_SECAM;
1472
			break;
1473
		    case RHD_TV_CV:
1474
			tv->ucTvStandard = ATOM_TV_CV;
1475
			break;
1476
		    case RHD_TV_NONE:
1477
			return FALSE;
1478
		}
1479
		switch (Action) {
1480
		    case atomEncoderOn:
1481
			tv->ucAction = ATOM_ENABLE;
1482
			break;
1483
		    case atomEncoderOff:
1484
			tv->ucAction = ATOM_DISABLE;
1485
			break;
1486
		    default:
1487
			xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: TV unknown action\n",__func__);
1488
			return FALSE;
1489
		}
1490
	    }
1491
	    break;
1492
	case atomEncoderTMDS1:
1493
	case atomEncoderTMDS2:
1494
	case atomEncoderLVDS:
1495
	    if (EncoderId == atomEncoderLVDS) {
1496
		name = "LVDSEncoderControl";
1497
		data.exec.index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
1498
	    } else if (EncoderId == atomEncoderTMDS1) {
1499
		name = "TMDSAEncoderControl";
1500
		data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDSAEncoderControl);
1501
	    } else {
1502
		name = "LVTMAEncoderControl";
1503
		data.exec.index = GetIndexIntoMasterTable(COMMAND, LVTMAEncoderControl);
1504
	    }
1505
	    if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL))
1506
		return FALSE;
1507
	    switch  (version) {
1508
		case 1:
1509
		{
1510
		    LVDS_ENCODER_CONTROL_PARAMETERS *lvds = &ps.lvds;
1511
		    lvds->ucMisc = 0;
1512
		    if (Config->u.lvds.LinkCnt == atomDualLink)
1513
			lvds->ucMisc |= 0x1;
1514
		    if (Config->u.lvds.Is24bit)
1515
			lvds->ucMisc |= 0x1 << 1;
1516
 
1517
		    switch (Action) {
1518
			case atomEncoderOn:
1519
			    lvds->ucAction = ATOM_ENABLE;
1520
			    break;
1521
			case atomEncoderOff:
1522
			    lvds->ucAction = ATOM_DISABLE;
1523
			    break;
1524
			default:
1525
			    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: LVDS unknown action\n",__func__);
1526
			    return FALSE;
1527
		    }
1528
		    break;
1529
		}
1530
		case 2:
1531
		case 3:
1532
		{
1533
		    LVDS_ENCODER_CONTROL_PARAMETERS_V2 *lvds = &ps.lvdsv2;
1534
 
1535
		    lvds->ucMisc = 0;
1536
		    if (Config->u.lvds2.LinkCnt == atomDualLink)
1537
			lvds->ucMisc |= PANEL_ENCODER_MISC_DUAL;
1538
		    if (Config->u.lvds2.Coherent)
1539
			lvds->ucMisc |= PANEL_ENCODER_MISC_COHERENT;
1540
		    if (Config->u.lvds2.LinkB)
1541
			lvds->ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
1542
		    if (Config->u.lvds2.Hdmi)
1543
			lvds->ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
1544
		    lvds->ucTruncate = 0;
1545
		    lvds->ucSpatial = 0;
1546
		    lvds->ucTemporal = 0;
1547
		    lvds->ucFRC = 0;
1548
 
1549
		    if (EncoderId == atomEncoderLVDS) {
1550
			if (Config->u.lvds2.Is24bit) {
1551
			    lvds->ucTruncate |= PANEL_ENCODER_TRUNCATE_DEPTH;
1552
			    lvds->ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
1553
			    lvds->ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
1554
			}
1555
			switch (Config->u.lvds2.TemporalGrey) {
1556
			    case atomTemporalDither0:
1557
				break;
1558
			    case atomTemporalDither4:
1559
				lvds->ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
1560
			    case atomTemporalDither2:
1561
				lvds->ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_EN;
1562
				break;
1563
			}
1564
			switch (Config->u.lvds2.SpatialDither)
1565
			    lvds->ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_EN;
1566
		    }
1567
 
1568
		    switch (Action) {
1569
			case atomEncoderOn:
1570
			    lvds->ucAction = ATOM_ENABLE;
1571
			    break;
1572
			case atomEncoderOff:
1573
			    lvds->ucAction = ATOM_DISABLE;
1574
			    break;
1575
			default:
1576
			    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: LVDS2 unknown action\n",__func__);
1577
			    return FALSE;
1578
		    }
1579
		    break;
1580
		}
1581
		default:
1582
		    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: LVDS unknown version\n",__func__);
1583
		    return FALSE;
1584
	    }
1585
	    break;
1586
	case atomEncoderDIG1:
1587
	case atomEncoderDIG2:
1588
	case atomEncoderExternal:
1589
	{
1590
	    DIG_ENCODER_CONTROL_PARAMETERS *dig = &ps.dig;
1591
	    struct atomCodeTableVersion version;
1592
 
1593
	    if (EncoderId == atomEncoderDIG1) {
1594
		name = "DIG1EncoderControl";
1595
		data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
1596
	    } else if (EncoderId == atomEncoderDIG2) {
1597
		name = "DIG2EncoderControl";
1598
		data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
1599
	    } else {
1600
		name = "ExternalEncoderControl";
1601
		data.exec.index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
1602
	    }
1603
	    rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version.cref, &version.fref, NULL);
1604
	    if (version.fref > 1 || version.cref > 2)
1605
		return FALSE;
1606
 
1607
	    dig->ucConfig = 0;
1608
	    switch (version.cref) {
1609
		case 1:
1610
	    switch (Config->u.dig.Link) {
1611
		case atomTransLinkA:
1612
		    dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
1613
		    break;
1614
		case atomTransLinkAB:
1615
		    dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
1616
		    break;
1617
		case atomTransLinkB:
1618
		    dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
1619
		    break;
1620
		case atomTransLinkBA:
1621
		    dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKB_A;
1622
		    break;
1623
	    }
1624
 
1625
	    if (EncoderId != atomEncoderExternal) {
1626
		switch (Config->u.dig.Transmitter) {
1627
		    case atomTransmitterUNIPHY:
1628
		    case atomTransmitterPCIEPHY:
1629
		    case atomTransmitterDIG1:
1630
			dig->ucConfig |= ATOM_ENCODER_CONFIG_UNIPHY;
1631
			break;
1632
		    case atomTransmitterLVTMA:
1633
		    case atomTransmitterDIG2:
1634
			dig->ucConfig |= ATOM_ENCODER_CONFIG_LVTMA;
1635
			break;
1636
			/*
1637
			 * these are not DCE3.0 but we need them here as DIGxEncoderControl tables for
1638
			 * DCE3.2 still report cref 1.
1639
			 */
1640
			    case atomTransmitterUNIPHY1:
1641
				dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
1642
				break;
1643
			    case atomTransmitterUNIPHY2:
1644
				dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
1645
				break;
1646
			    default:
1647
				xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: Invalid Transmitter for DCE3.0: %x\n",
1648
					   __func__, Config->u.dig.Transmitter);
1649
				return FALSE;
1650
			}
1651
		    }
1652
		    break;
1653
 
1654
		case 2:
1655
		    switch (Config->u.dig.Link) {
1656
			case atomTransLinkA:
1657
			case atomTransLinkAB:
1658
			    dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_LINKA;
1659
			    break;
1660
			case atomTransLinkB:
1661
			case atomTransLinkBA:
1662
			    dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_LINKB;
1663
			    break;
1664
		    }
1665
		    switch (Config->u.dig.Transmitter) {
1666
			case atomTransmitterUNIPHY:
1667
			    dig->ucConfig |= ATOM_ENCODER_CONFIG_UNIPHY;
1668
			    break;
1669
			case atomTransmitterUNIPHY1:
1670
			    dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
1671
			    break;
1672
			case atomTransmitterUNIPHY2:
1673
			    dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
1674
			    break;
1675
			default:
1676
			    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: Invalid Encoder for DCE3.2: %x\n",
1677
				       __func__, Config->u.dig.Transmitter);
1678
			    return FALSE;
1679
		}
1680
		    break;
1681
 
1682
		default:
1683
		    return FALSE;
1684
	    }
1685
 
1686
	    switch (Config->u.dig.EncoderMode) {
1687
		case atomDVI:
1688
		    dig->ucEncoderMode = ATOM_ENCODER_MODE_DVI;
1689
		    break;
1690
		case atomDP:
1691
		    dig->ucEncoderMode = ATOM_ENCODER_MODE_DP;
1692
		    break;
1693
		case atomLVDS:
1694
		    dig->ucEncoderMode = ATOM_ENCODER_MODE_LVDS;
1695
		    break;
1696
		case atomHDMI:
1697
		    dig->ucEncoderMode = ATOM_ENCODER_MODE_HDMI;
1698
		    break;
1699
		case atomSDVO:
1700
		    dig->ucEncoderMode = ATOM_ENCODER_MODE_SDVO;
1701
		    break;
1702
		case atomNoEncoder:
1703
		case atomTVComposite:
1704
		case atomTVSVideo:
1705
		case atomTVComponent:
1706
		case atomCRT:
1707
		    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s called with invalid DIG encoder mode %i\n",
1708
			       __func__,Config->u.dig.EncoderMode);
1709
		    return FALSE;
1710
		    break;
1711
	    }
1712
 
1713
	    switch (Action) {
1714
		case atomEncoderOn:
1715
		    dig->ucAction = ATOM_ENABLE;
1716
		    break;
1717
		case atomEncoderOff:
1718
		    dig->ucAction = ATOM_DISABLE;
1719
		    break;
1720
		default:
1721
		    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DIG unknown action\n",__func__);
1722
		    return FALSE;
1723
	    }
1724
 
1725
	    switch (Config->u.dig.LinkCnt) {
1726
		case atomSingleLink:
1727
		    dig->ucLaneNum = 4;
1728
		    break;
1729
		case atomDualLink:
1730
		    dig->ucLaneNum = 8;
1731
		    break;
1732
	    }
1733
	    break;
1734
	case atomEncoderDVO:
1735
	    name = "DVOEncoderControl";
1736
	    data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
1737
	    if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version.cref, NULL, NULL))
1738
		return FALSE;
1739
	    switch  (version.cref) {
1740
		case 1:
1741
		case 2:
1742
		{
1743
		    DVO_ENCODER_CONTROL_PARAMETERS *dvo = &ps.dvo;
1744
		    dvo->usEncoderID = Config->u.dvo.EncoderID;
1745
		    switch (Config->u.dvo.DvoDeviceType) {
1746
			case atomLCD1:
1747
			case atomLCD2:
1748
			    dvo->ucDeviceType = ATOM_DEVICE_LCD1_INDEX;
1749
			    break;
1750
			case atomCRT1:
1751
			case atomCRT2:
1752
			    dvo->ucDeviceType = ATOM_DEVICE_CRT1_INDEX;
1753
			    break;
1754
			case atomDFP1:
1755
			case atomDFP2:
1756
			case atomDFP3:
1757
			case atomDFP4:
1758
			case atomDFP5:
1759
			    dvo->ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
1760
			    break;
1761
			case atomTV1:
1762
			case atomTV2:
1763
			    dvo->ucDeviceType = ATOM_DEVICE_TV1_INDEX;
1764
			    break;
1765
			case atomCV:
1766
			    dvo->ucDeviceType = ATOM_DEVICE_CV_INDEX;
1767
			    break;
1768
			case atomNone:
1769
			    return FALSE;
1770
		    }
1771
		    if (Config->u.dvo.digital) {
1772
			dvo->usDevAttr.sDigAttrib.ucAttribute = 0; /* @@@ What do these attributes mean? */
1773
		    } else {
1774
			switch (Config->u.dvo.u.TVMode) {
1775
			    case RHD_TV_NTSC:
1776
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_NTSC;
1777
				break;
1778
			    case RHD_TV_NTSCJ:
1779
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_NTSCJ;
1780
				break;
1781
			    case RHD_TV_PAL:
1782
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PAL;
1783
				break;
1784
			    case RHD_TV_PALM:
1785
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PALM;
1786
				break;
1787
			    case RHD_TV_PALCN:
1788
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PALCN;
1789
				break;
1790
			    case RHD_TV_PALN:
1791
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PALN;
1792
				break;
1793
			    case RHD_TV_PAL60:
1794
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PAL60;
1795
				break;
1796
			    case RHD_TV_SECAM:
1797
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_SECAM;
1798
				break;
1799
			    case RHD_TV_CV:
1800
				dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_CV;
1801
				break;
1802
			    case RHD_TV_NONE:
1803
				return FALSE;
1804
			}
1805
		    }
1806
		    switch (Action) {
1807
			case atomEncoderOn:
1808
			    dvo->ucAction = ATOM_ENABLE;
1809
			    break;
1810
			case atomEncoderOff:
1811
			    dvo->ucAction = ATOM_DISABLE;
1812
			    break;
1813
			default:
1814
			    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DVO unknown action\n",__func__);
1815
			    return FALSE;
1816
		    }
1817
		break;
1818
		}
1819
		case 3:
1820
		{
1821
		    DVO_ENCODER_CONTROL_PARAMETERS_V3 *dvo = &ps.dvo_v3;
1822
		    dvo->ucDVOConfig = 0;
1823
		    if (Config->u.dvo3.Rate == atomDVO_RateSDR)
1824
			dvo->ucDVOConfig |= DVO_ENCODER_CONFIG_SDR_SPEED;
1825
		    else
1826
			dvo->ucDVOConfig |= DVO_ENCODER_CONFIG_DDR_SPEED;
1827
		    switch (Config->u.dvo3.DvoOutput) {
1828
			case atomDVO_OutputLow12Bit:
1829
			    dvo->ucDVOConfig = DVO_ENCODER_CONFIG_LOW12BIT;
1830
			    break;
1831
			case atomDVO_OutputHigh12Bit:
1832
			    dvo->ucDVOConfig = DVO_ENCODER_CONFIG_UPPER12BIT;
1833
			    break;
1834
			case atomDVO_Output24Bit:
1835
			    dvo->ucDVOConfig = DVO_ENCODER_CONFIG_24BIT;
1836
			    break;
1837
		    }
1838
		    switch (Action) {
1839
			case atomEncoderOn:
1840
			    dvo->ucAction = ATOM_ENABLE;
1841
			    break;
1842
			case atomEncoderOff:
1843
			    dvo->ucAction = ATOM_DISABLE;
1844
			    break;
1845
			default:
1846
			    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DVO3 unknown action\n",__func__);
1847
			    return FALSE;
1848
		    }
1849
		    break;
1850
		}
1851
	    }
1852
	    break;
1853
	}
1854
	case atomEncoderNone:
1855
	    return FALSE;
1856
    }
1857
 
1858
    data.exec.dataSpace = NULL;
1859
    data.exec.pspace = &ps;
1860
 
1861
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name);
1862
    atomDebugPrintPspace(handle, &data, sizeof(ps));
1863
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
1864
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1865
	xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name);
1866
	return TRUE;
1867
    }
1868
    xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Failed\n",name);
1869
    return FALSE;
1870
}
1871
 
1872
/*
1873
 *
1874
 */
1875
struct atomCodeTableVersion
1876
rhdAtomEncoderControlVersion(atomBiosHandlePtr handle, enum atomEncoder EncoderId)
1877
{
1878
    struct atomCodeTableVersion version = { 0, 0 };
1879
    int index;
1880
    char *name;
1881
 
1882
    switch (EncoderId) {
1883
	case atomEncoderDACA:
1884
	    index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
1885
	    name = "DAC1EncoderControl";
1886
	    break;
1887
	case atomEncoderDACB:
1888
	    index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
1889
	    name = "DAC2EncoderControl";
1890
	    break;
1891
	case atomEncoderTV:
1892
	    index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
1893
	    name = "TVEncoderControl";
1894
	    break;
1895
	case atomEncoderTMDS1:
1896
	case atomEncoderTMDS2:
1897
	    index = GetIndexIntoMasterTable(COMMAND, TMDSAEncoderControl);
1898
	    name = "TMDSAEncoderControl";
1899
	    break;
1900
	case atomEncoderLVDS:
1901
	    index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
1902
	    name = " LVDSEncoderControl";
1903
	    break;
1904
	case atomEncoderDIG1:
1905
	    index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
1906
	    name = "DIG1EncoderControl";
1907
	    break;
1908
	case atomEncoderDIG2:
1909
	    index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
1910
	    name = "DIG2EncoderControl";
1911
	    break;
1912
	case atomEncoderExternal:
1913
	    index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl);
1914
	    name = "ExternalEncoderControl";
1915
	    break;
1916
	case atomEncoderDVO:
1917
	    index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
1918
	    name = "DVOEncoderControl";
1919
	    break;
1920
	default:
1921
	    return version;
1922
    }
1923
 
1924
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
1925
 
1926
    DEBUG_VERSION_NAME(index, handle, name, version);
1927
 
1928
    return version;
1929
}
1930
 
1931
/*
1932
 *
1933
 */
1934
Bool
1935
rhdAtomUpdateCRTC_DoubleBufferRegisters(atomBiosHandlePtr handle, enum atomCrtc CrtcId,
1936
					enum atomCrtcAction Action)
1937
{
1938
    AtomBiosArgRec data;
1939
    union
1940
    {
1941
	ENABLE_CRTC_PARAMETERS crtc;
1942
	ENABLE_CRTC_PS_ALLOCATION crtc_a;
1943
    } ps;
1944
 
1945
    RHDFUNC(handle);
1946
 
1947
    switch (CrtcId) {
1948
	case atomCrtc1:
1949
	    ps.crtc.ucCRTC = ATOM_CRTC1;
1950
	    break;
1951
	case atomCrtc2:
1952
	    ps.crtc.ucCRTC = ATOM_CRTC2;
1953
	    break;
1954
    }
1955
 
1956
    switch (Action) {
1957
	case atomCrtcEnable:
1958
	    ps.crtc.ucEnable = ATOM_ENABLE;
1959
	    break;
1960
	case atomCrtcDisable:
1961
	    ps.crtc.ucEnable = ATOM_DISABLE;
1962
	    break;
1963
    }
1964
 
1965
    data.exec.index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
1966
 
1967
    data.exec.dataSpace = NULL;
1968
    data.exec.pspace = &ps;
1969
 
1970
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling UpdateCRTC_DoubleBufferRegisters\n");
1971
    atomDebugPrintPspace(handle, &data, sizeof(ps));
1972
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
1973
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
1974
	xf86DrvMsg(handle->scrnIndex, X_INFO, "UpdateCRTC_DoubleBufferRegisters Successful\n");
1975
	return TRUE;
1976
    }
1977
    xf86DrvMsg(handle->scrnIndex, X_INFO, "UpdateCRTC_DoubleBufferRegisters Failed\n");
1978
    return FALSE;
1979
}
1980
 
1981
/*
1982
 *
1983
 */
1984
struct atomCodeTableVersion
1985
rhdAtomUpdateCRTC_DoubleBufferRegistersVersion(atomBiosHandlePtr handle)
1986
{
1987
    struct atomCodeTableVersion version;
1988
    int index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
1989
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
1990
 
1991
    DEBUG_VERSION(index, handle, version);
1992
 
1993
    return version;
1994
}
1995
 
1996
/*
1997
 *
1998
 */
1999
Bool
2000
rhdAtomEnableCrtc(atomBiosHandlePtr handle, enum atomCrtc CrtcId,
2001
		  enum atomCrtcAction Action)
2002
{
2003
    AtomBiosArgRec data;
2004
    union
2005
    {
2006
	ENABLE_CRTC_PARAMETERS crtc;
2007
	ENABLE_CRTC_PS_ALLOCATION crtc_a;
2008
    } ps;
2009
 
2010
    RHDFUNC(handle);
2011
 
2012
    switch (CrtcId) {
2013
	case atomCrtc1:
2014
	    ps.crtc.ucCRTC = ATOM_CRTC1;
2015
	    break;
2016
	case atomCrtc2:
2017
	    ps.crtc.ucCRTC = ATOM_CRTC2;
2018
	    break;
2019
    }
2020
 
2021
    switch (Action) {
2022
	case atomCrtcEnable:
2023
	    ps.crtc.ucEnable = ATOM_ENABLE;
2024
	    break;
2025
	case atomCrtcDisable:
2026
	    ps.crtc.ucEnable = ATOM_DISABLE;
2027
	    break;
2028
    }
2029
 
2030
    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
2031
 
2032
    data.exec.dataSpace = NULL;
2033
    data.exec.pspace = &ps;
2034
 
2035
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableCRTC\n");
2036
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2037
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2038
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2039
	xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTC Successful\n");
2040
	return TRUE;
2041
    }
2042
    xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTC Failed\n");
2043
    return FALSE;
2044
}
2045
 
2046
/*
2047
 *
2048
 */
2049
struct atomCodeTableVersion
2050
rhdAtomEnableCrtcVersion(atomBiosHandlePtr handle)
2051
{
2052
    struct atomCodeTableVersion version;
2053
    int index = GetIndexIntoMasterTable(COMMAND,  EnableCRTC);
2054
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2055
 
2056
    DEBUG_VERSION(index, handle, version);
2057
 
2058
    return version;
2059
}
2060
 
2061
/*
2062
 *
2063
 */
2064
Bool
2065
rhdAtomEnableCrtcMemReq(atomBiosHandlePtr handle, enum atomCrtc CrtcId,
2066
		  enum atomCrtcAction Action)
2067
{
2068
    AtomBiosArgRec data;
2069
    union
2070
    {
2071
	ENABLE_CRTC_PARAMETERS crtc;
2072
	ENABLE_CRTC_PS_ALLOCATION crtc_a;
2073
    } ps;
2074
 
2075
    RHDFUNC(handle);
2076
 
2077
    switch (CrtcId) {
2078
	case atomCrtc1:
2079
	    ps.crtc.ucCRTC = ATOM_CRTC1;
2080
	    break;
2081
	case atomCrtc2:
2082
	    ps.crtc.ucCRTC = ATOM_CRTC2;
2083
	    break;
2084
    }
2085
 
2086
    switch (Action) {
2087
	case atomCrtcEnable:
2088
	    ps.crtc.ucEnable = ATOM_ENABLE;
2089
	    break;
2090
	case atomCrtcDisable:
2091
	    ps.crtc.ucEnable = ATOM_DISABLE;
2092
	    break;
2093
    }
2094
 
2095
    data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
2096
 
2097
    data.exec.dataSpace = NULL;
2098
    data.exec.pspace = &ps;
2099
 
2100
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableCRTCMemReq\n");
2101
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2102
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2103
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2104
	xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTCMemReq Successful\n");
2105
	return TRUE;
2106
    }
2107
    xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTCMemReq Failed\n");
2108
    return FALSE;
2109
}
2110
 
2111
/*
2112
 *
2113
 */
2114
struct atomCodeTableVersion
2115
rhdAtomEnableCrtcMemReqVersion(atomBiosHandlePtr handle)
2116
{
2117
    struct atomCodeTableVersion version;
2118
    int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
2119
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2120
 
2121
    DEBUG_VERSION(index, handle, version);
2122
 
2123
    return version;
2124
 
2125
}
2126
 
2127
/*
2128
 *
2129
 */
2130
Bool
2131
rhdAtomSetCRTCTimings(atomBiosHandlePtr handle, enum atomCrtc id, DisplayModePtr mode, int depth)
2132
{
2133
    AtomBiosArgRec data;
2134
    union
2135
    {
2136
	SET_CRTC_TIMING_PARAMETERS  crtc;
2137
/* 	SET_CRTC_TIMING_PS_ALLOCATION crtc_a; */
2138
    } ps;
2139
    ATOM_MODE_MISC_INFO_ACCESS* msc = &(ps.crtc.susModeMiscInfo);
2140
 
2141
    RHDFUNC(handle);
2142
 
2143
    ps.crtc.usH_Total = mode->CrtcHTotal;
2144
    ps.crtc.usH_Disp = mode->CrtcHDisplay;
2145
    ps.crtc.usH_SyncStart = mode->CrtcHSyncStart;
2146
    ps.crtc.usH_SyncWidth = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
2147
    ps.crtc.usV_Total = mode->CrtcVTotal;
2148
    ps.crtc.usV_Disp = mode->CrtcVDisplay;
2149
    ps.crtc.usV_SyncStart = mode->CrtcVSyncStart;
2150
    ps.crtc.usV_SyncWidth = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
2151
    ps.crtc.ucOverscanRight = mode->CrtcHBlankStart - mode->CrtcHDisplay;
2152
    ps.crtc.ucOverscanLeft = mode->CrtcVTotal - mode->CrtcVBlankEnd;
2153
    ps.crtc.ucOverscanBottom = mode->CrtcVBlankStart - mode->CrtcVDisplay;
2154
    ps.crtc.ucOverscanTop = mode->CrtcVTotal - mode->CrtcVBlankEnd;
2155
    switch (id) {
2156
	case atomCrtc1:
2157
	    ps.crtc.ucCRTC = ATOM_CRTC1;
2158
	    break;
2159
	case atomCrtc2:
2160
	    ps.crtc.ucCRTC = ATOM_CRTC2;
2161
	    break;
2162
    }
2163
 
2164
    msc->sbfAccess.HorizontalCutOff = 0;
2165
    msc->sbfAccess.HSyncPolarity = (mode->Flags & V_NHSYNC) ? 1 : 0;
2166
    msc->sbfAccess.VSyncPolarity = (mode->Flags & V_NVSYNC) ? 1 : 0;
2167
    msc->sbfAccess.VerticalCutOff = 0;
2168
    msc->sbfAccess.H_ReplicationBy2 = 0;
2169
    msc->sbfAccess.V_ReplicationBy2 = (mode->Flags & V_DBLSCAN) ? 1 : 0;
2170
    msc->sbfAccess.CompositeSync =  (mode->Flags & V_CSYNC);
2171
    msc->sbfAccess.Interlace = (mode->Flags & V_INTERLACE) ? 1 : 0;
2172
    msc->sbfAccess.DoubleClock = (mode->Flags & V_DBLCLK) ? 1 : 0;
2173
    msc->sbfAccess.RGB888 = (depth == 24) ? 1 : 0;
2174
 
2175
    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
2176
 
2177
    data.exec.dataSpace = NULL;
2178
    data.exec.pspace = &ps;
2179
 
2180
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetCRTC_Timing\n");
2181
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2182
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2183
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2184
	xf86DrvMsg(handle->scrnIndex, X_INFO, "SetCRTC_Timing Successful\n");
2185
	return TRUE;
2186
  }
2187
    xf86DrvMsg(handle->scrnIndex, X_INFO, "SetCRTC_Timing Failed\n");
2188
    return FALSE;
2189
}
2190
 
2191
/*
2192
 *
2193
 */
2194
struct atomCodeTableVersion
2195
rhdAtomSetCRTCTimingsVersion(atomBiosHandlePtr handle)
2196
{
2197
    struct atomCodeTableVersion version;
2198
    int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
2199
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2200
 
2201
    DEBUG_VERSION(index, handle, version);
2202
    return version;
2203
 
2204
}
2205
 
2206
/*
2207
 *
2208
 */
2209
Bool
2210
rhdAtomSetCRTCOverscan(atomBiosHandlePtr handle, enum atomCrtc id, struct atomCrtcOverscan *config)
2211
{
2212
    AtomBiosArgRec data;
2213
    union
2214
    {
2215
	SET_CRTC_OVERSCAN_PARAMETERS  ovscn;
2216
	SET_CRTC_OVERSCAN_PS_ALLOCATION ovscn_a;
2217
    } ps;
2218
 
2219
    RHDFUNC(handle);
2220
 
2221
    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
2222
    data.exec.dataSpace = NULL;
2223
    data.exec.pspace = &ps;
2224
 
2225
    switch(id) {
2226
	case atomCrtc1:
2227
	    ps.ovscn.ucCRTC = ATOM_CRTC1;
2228
	    break;
2229
	case atomCrtc2:
2230
	    ps.ovscn.ucCRTC = ATOM_CRTC2;
2231
	    break;
2232
    }
2233
    ps.ovscn.usOverscanRight = config->ovscnRight;
2234
    ps.ovscn.usOverscanLeft = config->ovscnLeft;
2235
    ps.ovscn.usOverscanBottom = config->ovscnBottom;
2236
    ps.ovscn.usOverscanTop = config->ovscnTop;
2237
 
2238
    xf86DrvMsg(handle->scrnIndex, X_INFO, "CallingSetCRTC_OverScan\n");
2239
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2240
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2241
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2242
	xf86DrvMsg(handle->scrnIndex, X_INFO, "Set CRTC_OverScan Successful\n");
2243
	return TRUE;
2244
    }
2245
    xf86DrvMsg(handle->scrnIndex, X_INFO, "SetCRTC_OverScan Failed\n");
2246
    return FALSE;
2247
}
2248
 
2249
/*
2250
 *
2251
 */
2252
struct atomCodeTableVersion
2253
rhdAtomSetCRTCOverscanVersion(atomBiosHandlePtr handle)
2254
{
2255
    struct atomCodeTableVersion version;
2256
    int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
2257
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2258
 
2259
    DEBUG_VERSION(index, handle, version);
2260
    return version;
2261
}
2262
 
2263
/*
2264
 *
2265
 */
2266
Bool
2267
rhdAtomBlankCRTC(atomBiosHandlePtr handle, enum atomCrtc id, struct atomCrtcBlank *config)
2268
{
2269
  AtomBiosArgRec data;
2270
    union
2271
    {
2272
	BLANK_CRTC_PARAMETERS blank;
2273
	BLANK_CRTC_PS_ALLOCATION blank_a;
2274
    } ps;
2275
 
2276
    RHDFUNC(handle);
2277
 
2278
    data.exec.index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
2279
    data.exec.pspace = &ps;
2280
    data.exec.dataSpace = NULL;
2281
 
2282
    switch(id) {
2283
	case atomCrtc1:
2284
	    ps.blank.ucCRTC = ATOM_CRTC1;
2285
	    break;
2286
	case atomCrtc2:
2287
	    ps.blank.ucCRTC = ATOM_CRTC2;
2288
	    break;
2289
    }
2290
 
2291
    switch (config->Action) {
2292
	case atomBlankOn:
2293
	    ps.blank.ucBlanking = ATOM_BLANKING;
2294
	    break;
2295
	case atomBlankOff:
2296
	    ps.blank.ucBlanking = ATOM_BLANKING_OFF;
2297
	    break;
2298
    }
2299
    ps.blank.usBlackColorRCr = config->r;
2300
    ps.blank.usBlackColorGY = config->g;
2301
    ps.blank.usBlackColorBCb = config->b;
2302
 
2303
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling BlankCRTC\n");
2304
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2305
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2306
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2307
	xf86DrvMsg(handle->scrnIndex, X_INFO, "BlankCRTC Successful\n");
2308
	return TRUE;
2309
    }
2310
    xf86DrvMsg(handle->scrnIndex, X_INFO, "BlankCRTC Failed\n");
2311
  return FALSE;
2312
}
2313
 
2314
/*
2315
 *
2316
 */
2317
struct atomCodeTableVersion
2318
rhdAtomBlankCRTCVersion(atomBiosHandlePtr handle)
2319
{
2320
    struct atomCodeTableVersion version;
2321
    int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
2322
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2323
 
2324
    DEBUG_VERSION(index, handle, version);
2325
    return version;
2326
}
2327
 
2328
/*
2329
 *
2330
 */
2331
static int
2332
atomGetDevice(atomBiosHandlePtr handle, enum atomDevice Device)
2333
{
2334
    switch (Device) {
2335
	case atomCRT1:
2336
	    return ATOM_DEVICE_CRT1_INDEX;
2337
	case atomLCD1:
2338
	    return ATOM_DEVICE_LCD1_INDEX;
2339
	case atomTV1:
2340
	    return ATOM_DEVICE_TV1_INDEX;
2341
	case atomDFP1:
2342
	    return ATOM_DEVICE_DFP1_INDEX;
2343
	case atomCRT2:
2344
	    return ATOM_DEVICE_CRT2_INDEX;
2345
	case atomLCD2:
2346
	    return ATOM_DEVICE_LCD2_INDEX;
2347
	case atomTV2:
2348
	    return ATOM_DEVICE_TV2_INDEX;
2349
	case atomDFP2:
2350
	    return ATOM_DEVICE_DFP2_INDEX;
2351
	case atomCV:
2352
	    return ATOM_DEVICE_CV_INDEX;
2353
	case atomDFP3:
2354
	    return ATOM_DEVICE_DFP3_INDEX;
2355
	case atomDFP4:
2356
	    return ATOM_DEVICE_DFP4_INDEX;
2357
	case atomDFP5:
2358
	    return ATOM_DEVICE_DFP5_INDEX;
2359
	case atomNone:
2360
	    xf86DrvMsg(handle->scrnIndex, X_ERROR, "Invalid Device\n");
2361
	    return ATOM_MAX_SUPPORTED_DEVICE;
2362
    }
2363
 
2364
    return ATOM_MAX_SUPPORTED_DEVICE;
2365
}
2366
 
2367
/*
2368
 *
2369
 */
2370
Bool
2371
rhdAtomSetPixelClock(atomBiosHandlePtr handle, enum atomPxclk PCLKId, struct atomPixelClockConfig *Config)
2372
{
2373
    AtomBiosArgRec data;
2374
    CARD8 version;
2375
    Bool NeedMode = FALSE;
2376
    union {
2377
	PIXEL_CLOCK_PARAMETERS  pclk;
2378
	PIXEL_CLOCK_PARAMETERS_V2  pclk_v2;
2379
	PIXEL_CLOCK_PARAMETERS_V3  pclk_v3;
2380
	SET_PIXEL_CLOCK_PS_ALLOCATION pclk_a;
2381
    } ps;
2382
 
2383
    data.exec.index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
2384
 
2385
    if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL))
2386
	return FALSE;
2387
    switch  (version) {
2388
	case 1:
2389
	    if (Config->Enable)
2390
		ps.pclk.usPixelClock = Config->PixelClock / 10;
2391
	    else
2392
		ps.pclk.usPixelClock = 0;
2393
	    ps.pclk.usRefDiv = Config->RefDiv;
2394
	    ps.pclk.usFbDiv = Config->FbDiv;
2395
	    ps.pclk.ucPostDiv = Config->PostDiv;
2396
	    ps.pclk.ucFracFbDiv = Config->FracFbDiv;
2397
	    ps.pclk.ucRefDivSrc = 0; /* What's this? @@@ */
2398
	    switch (PCLKId) {
2399
		case atomPclk1:
2400
		    ps.pclk.ucPpll = ATOM_PPLL1;
2401
		    break;
2402
		case atomPclk2:
2403
		    ps.pclk.ucPpll = ATOM_PPLL2;
2404
		    break;
2405
	    }
2406
	    switch (Config->Crtc) {
2407
		case atomCrtc1:
2408
		    ps.pclk.ucCRTC = ATOM_CRTC1;
2409
		    break;
2410
		case atomCrtc2:
2411
		    ps.pclk.ucCRTC = ATOM_CRTC2;
2412
		    break;
2413
	    }
2414
	    break;
2415
	case 2:
2416
	    if (Config->Enable)
2417
		ps.pclk_v2.usPixelClock = Config->PixelClock / 10;
2418
	    else
2419
		ps.pclk_v2.usPixelClock = 0;
2420
	    ps.pclk_v2.usRefDiv = Config->RefDiv;
2421
	    ps.pclk_v2.usFbDiv = Config->FbDiv;
2422
	    ps.pclk_v2.ucPostDiv = Config->PostDiv;
2423
	    ps.pclk_v2.ucFracFbDiv = Config->FracFbDiv;
2424
	    switch (PCLKId) {
2425
		case atomPclk1:
2426
		    ps.pclk_v2.ucPpll = ATOM_PPLL1;
2427
		    break;
2428
		case atomPclk2:
2429
		    ps.pclk_v2.ucPpll = ATOM_PPLL2;
2430
		    break;
2431
	    }
2432
	    ps.pclk_v2.ucRefDivSrc = 1; /* See above... @@@ */
2433
	    switch (Config->Crtc) {
2434
		case atomCrtc1:
2435
		    ps.pclk_v2.ucCRTC = ATOM_CRTC1;
2436
		    break;
2437
		case atomCrtc2:
2438
		    ps.pclk_v2.ucCRTC = ATOM_CRTC2;
2439
		    break;
2440
	    }
2441
	    ASSERTF((!Config->Enable || Config->u.v2.Device != atomNone), "Invalid Device Id\n");
2442
	    ps.pclk_v2.ucMiscInfo = 0;
2443
	    ps.pclk_v2.ucMiscInfo |= (Config->u.v2.Force ? MISC_FORCE_REPROG_PIXEL_CLOCK : 0);
2444
	    if (Config->u.v2.Device != atomNone)
2445
		ps.pclk_v2.ucMiscInfo |= (atomGetDevice(handle, Config->u.v2.Device)
2446
					  << MISC_DEVICE_INDEX_SHIFT);
2447
	    RHDDebug(handle->scrnIndex,"%s Device: %i PixelClock: %i RefDiv: 0x%x FbDiv: 0x%x PostDiv: 0x%x "
2448
		     "PLL: %i Crtc: %i MiscInfo: 0x%x\n",
2449
		   __func__,
2450
		   Config->u.v2.Device,
2451
		   ps.pclk_v2.usPixelClock,
2452
		   ps.pclk_v2.usRefDiv,
2453
		   ps.pclk_v2.usFbDiv,
2454
		   ps.pclk_v2.ucPostDiv,
2455
		   ps.pclk_v2.ucPpll,
2456
		   ps.pclk_v2.ucCRTC,
2457
		   ps.pclk_v2.ucMiscInfo
2458
		);
2459
	    break;
2460
	case 3:
2461
	    if (Config->Enable)
2462
		ps.pclk_v3.usPixelClock = Config->PixelClock / 10;
2463
	    else
2464
		ps.pclk.usPixelClock = 0;
2465
	    ps.pclk_v3.usRefDiv = Config->RefDiv;
2466
	    ps.pclk_v3.usFbDiv = Config->FbDiv;
2467
	    ps.pclk_v3.ucPostDiv = Config->PostDiv;
2468
	    ps.pclk_v3.ucFracFbDiv = Config->FracFbDiv;
2469
	    switch (PCLKId) {
2470
		case atomPclk1:
2471
		    ps.pclk_v3.ucPpll = ATOM_PPLL1;
2472
		    break;
2473
		case atomPclk2:
2474
		    ps.pclk_v3.ucPpll = ATOM_PPLL2;
2475
		    break;
2476
	    }
2477
	    switch (Config->u.v3.OutputType) {
2478
		case atomOutputKldskpLvtma:
2479
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA;
2480
		    NeedMode = TRUE;
2481
		    break;
2482
		case atomOutputUniphyA:
2483
		case atomOutputUniphyB:
2484
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_UNIPHY;
2485
		    NeedMode = TRUE;
2486
		    break;
2487
		case atomOutputUniphyC:
2488
		case atomOutputUniphyD:
2489
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_UNIPHY1;
2490
		    NeedMode = TRUE;
2491
		    break;
2492
		case atomOutputUniphyE:
2493
		case atomOutputUniphyF:
2494
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_UNIPHY2;
2495
		    NeedMode = TRUE;
2496
		    break;
2497
 
2498
		case atomOutputDacA:
2499
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
2500
		    break;
2501
		case atomOutputDacB:
2502
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
2503
		    break;
2504
		case atomOutputDvo:
2505
		    ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1;
2506
		    NeedMode = TRUE;
2507
		    break;
2508
		case atomOutputTmdsa:
2509
		case atomOutputLvtma:
2510
		case atomOutputNone:
2511
		    return FALSE;
2512
	    }
2513
	    if (NeedMode) {
2514
		switch (Config->u.v3.EncoderMode) {
2515
		    case atomNoEncoder:
2516
			ps.pclk_v3.ucEncoderMode = 0;
2517
		    case atomDVI:
2518
			ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_DVI;
2519
			break;
2520
		    case atomDP:
2521
			ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_DP;
2522
			break;
2523
		    case atomLVDS:
2524
			ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_LVDS;
2525
			break;
2526
		    case atomHDMI:
2527
			ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_HDMI;
2528
			break;
2529
		    case atomSDVO:
2530
			ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_SDVO;
2531
			break;
2532
		    default:
2533
			xf86DrvMsg(handle->scrnIndex, X_ERROR,"%s: invalid encoder type.\n",__func__);
2534
			return FALSE;
2535
		}
2536
	    }
2537
	    ps.pclk_v3.ucMiscInfo = (Config->u.v3.Force ? PIXEL_CLOCK_MISC_FORCE_PROG_PPLL : 0x0)
2538
		| (Config->u.v3.UsePpll ?  PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK : 0x0)
2539
		| ((Config->Crtc == atomCrtc2) ? PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2 : PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1);
2540
 
2541
	    RHDDebug(handle->scrnIndex,"%s PixelClock: %i RefDiv: 0x%x FbDiv: 0x%x PostDiv: 0x%x PLL: %i OutputType: %x "
2542
		   "EncoderMode: %x MiscInfo: 0x%x\n",
2543
		   __func__,
2544
		   ps.pclk_v3.usPixelClock,
2545
		   ps.pclk_v3.usRefDiv,
2546
		   ps.pclk_v3.usFbDiv,
2547
		   ps.pclk_v3.ucPostDiv,
2548
		   ps.pclk_v3.ucPpll,
2549
		   ps.pclk_v3.ucTransmitterId,
2550
		   ps.pclk_v3.ucEncoderMode,
2551
		   ps.pclk_v3.ucMiscInfo
2552
		);
2553
	    break;
2554
	default:
2555
	    return FALSE;
2556
    }
2557
 
2558
    data.exec.dataSpace = NULL;
2559
    data.exec.pspace = &ps;
2560
 
2561
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetPixelClock\n");
2562
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2563
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2564
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2565
	xf86DrvMsg(handle->scrnIndex, X_INFO, "SetPixelClock Successful\n");
2566
	return TRUE;
2567
    }
2568
    xf86DrvMsg(handle->scrnIndex, X_INFO, "SetPixelClock Failed\n");
2569
    return FALSE;
2570
}
2571
 
2572
/*
2573
 *
2574
 */
2575
struct atomCodeTableVersion
2576
rhdAtomSetPixelClockVersion(atomBiosHandlePtr handle)
2577
{
2578
    struct atomCodeTableVersion version;
2579
    int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
2580
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2581
 
2582
    DEBUG_VERSION(index, handle, version);
2583
 
2584
    return version;
2585
 
2586
}
2587
 
2588
/*
2589
 *
2590
 */
2591
Bool
2592
rhdAtomSelectCrtcSource(atomBiosHandlePtr handle, enum atomCrtc CrtcId,
2593
			struct atomCrtcSourceConfig *config)
2594
{
2595
    AtomBiosArgRec data;
2596
    CARD8 version;
2597
    Bool NeedMode = FALSE;
2598
 
2599
    union
2600
    {
2601
	SELECT_CRTC_SOURCE_PARAMETERS crtc;
2602
	SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_a;
2603
	SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc2;
2604
/* 	SELECT_CRTC_SOURCE_PS_ALLOCATION_V2 crtc2_a; */
2605
    } ps;
2606
 
2607
    RHDFUNC(handle);
2608
 
2609
    data.exec.index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
2610
 
2611
    if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL))
2612
	return FALSE;
2613
 
2614
    switch  (version) {
2615
	case 1:
2616
	    switch (CrtcId) {
2617
		case atomCrtc1:
2618
		    ps.crtc.ucCRTC = ATOM_CRTC1;
2619
		    break;
2620
		case atomCrtc2:
2621
		    ps.crtc.ucCRTC = ATOM_CRTC2;
2622
		    break;
2623
	    }
2624
	    switch (config->u.Device) {
2625
		case atomCRT1:
2626
		    ps.crtc.ucDevice = ATOM_DEVICE_CRT1_INDEX;
2627
		    break;
2628
		case atomLCD1:
2629
		    ps.crtc.ucDevice = ATOM_DEVICE_LCD1_INDEX;
2630
	    break;
2631
		case atomTV1:
2632
		    ps.crtc.ucDevice = ATOM_DEVICE_TV1_INDEX;
2633
	    break;
2634
		case atomDFP1:
2635
		    ps.crtc.ucDevice = ATOM_DEVICE_DFP1_INDEX;
2636
	    break;
2637
		case atomCRT2:
2638
		    ps.crtc.ucDevice = ATOM_DEVICE_CRT2_INDEX;
2639
	    break;
2640
		case atomLCD2:
2641
		    ps.crtc.ucDevice = ATOM_DEVICE_LCD2_INDEX;
2642
	    break;
2643
		case atomTV2:
2644
		    ps.crtc.ucDevice = ATOM_DEVICE_TV2_INDEX;
2645
	    break;
2646
		case atomDFP2:
2647
		    ps.crtc.ucDevice = ATOM_DEVICE_DFP2_INDEX;
2648
	    break;
2649
		case atomCV:
2650
		    ps.crtc.ucDevice = ATOM_DEVICE_CV_INDEX;
2651
	    break;
2652
		case atomDFP3:
2653
		    ps.crtc.ucDevice = ATOM_DEVICE_DFP3_INDEX;
2654
	    break;
2655
		case atomDFP4:
2656
		    ps.crtc.ucDevice = ATOM_DEVICE_DFP4_INDEX;
2657
		    break;
2658
		case atomDFP5:
2659
		    ps.crtc.ucDevice = ATOM_DEVICE_DFP5_INDEX;
2660
		    break;
2661
		case atomNone:
2662
		    return FALSE;
2663
    }
2664
	    break;
2665
	case 2:
2666
	    switch (CrtcId) {
2667
		case atomCrtc1:
2668
		    ps.crtc2.ucCRTC = ATOM_CRTC1;
2669
		    break;
2670
		case atomCrtc2:
2671
		    ps.crtc2.ucCRTC = ATOM_CRTC2;
2672
	    break;
2673
    }
2674
	    switch (config->u.crtc2.Encoder) {
2675
		case atomEncoderDACA:
2676
		    ps.crtc2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
2677
		    break;
2678
		case atomEncoderDACB:
2679
		    ps.crtc2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
2680
		    break;
2681
		case atomEncoderTV:
2682
		    ps.crtc2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
2683
		    break;
2684
		case atomEncoderDVO:
2685
		    ps.crtc2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
2686
		    NeedMode = TRUE;
2687
		    break;
2688
		case atomEncoderDIG1:
2689
		    ps.crtc2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
2690
		    NeedMode = TRUE;
2691
		    break;
2692
 
2693
		case atomEncoderDIG2:
2694
		    ps.crtc2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
2695
		    break;
2696
		case atomEncoderExternal:
2697
		    ps.crtc2.ucEncoderID = ASIC_EXT_DIG_ENCODER_ID;
2698
		    break;
2699
		case atomEncoderTMDS1:
2700
		case atomEncoderTMDS2:
2701
		case atomEncoderLVDS:
2702
		case atomEncoderNone:
2703
		    return FALSE;
2704
	    }
2705
	    if (NeedMode) {
2706
		switch (config->u.crtc2.Mode) {
2707
		    case atomDVI:
2708
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_DVI;
2709
			break;
2710
		    case atomDP:
2711
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_DP;
2712
			break;
2713
		    case atomLVDS:
2714
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
2715
			break;
2716
		    case atomHDMI:
2717
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_HDMI;
2718
			break;
2719
		    case atomSDVO:
2720
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_SDVO;
2721
			break;
2722
		    case atomTVComposite:
2723
		    case atomTVSVideo:
2724
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_TV;
2725
			break;
2726
		    case atomTVComponent:
2727
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_CV;
2728
			break;
2729
		    case atomCRT:
2730
			ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
2731
			break;
2732
		    case atomNoEncoder:
2733
			xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: invalid encoder type.\n",__func__);
2734
			return FALSE;
2735
		}
2736
	    }
2737
	    break;
2738
    }
2739
 
2740
    data.exec.dataSpace = NULL;
2741
    data.exec.pspace = &ps;
2742
 
2743
    xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SelectCRTCSource\n");
2744
    atomDebugPrintPspace(handle, &data, sizeof(ps));
2745
    if (RHDAtomBiosFunc(handle->rhdPtr, handle,
2746
			ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) {
2747
	xf86DrvMsg(handle->scrnIndex, X_INFO, "SelectCRTCSource Successful\n");
2748
	return TRUE;
2749
    }
2750
    xf86DrvMsg(handle->scrnIndex, X_INFO, "SelectCRTCSource Failed\n");
2751
    return FALSE;
2752
}
2753
 
2754
/*
2755
 *
2756
 */
2757
struct atomCodeTableVersion
2758
rhdAtomSelectCrtcSourceVersion(atomBiosHandlePtr handle)
2759
{
2760
    struct atomCodeTableVersion version;
2761
    int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
2762
    rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL);
2763
    DEBUG_VERSION(index, handle, version);
2764
    return version;
2765
}
2766
 
2767
 
2768
# endif  /* ATOM_BIOS_PARSER */
2769
 
2770
 
2771
static AtomBiosResult
2772
rhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2,
2773
		    AtomBiosArgPtr data)
2774
{
2775
    int scrnIndex = data->val;
2776
    RHDPtr rhdPtr = data->val;
2777
  unsigned char *ptr;
2778
  atomDataTablesPtr atomDataPtr;
2779
  atomBiosHandlePtr handle = NULL;
2780
  unsigned int BIOSImageSize = 0;
2781
  Bool unposted = FALSE;
2782
    unsigned char* codeTable;
2783
 
2784
  data->atomhandle = NULL;
2785
 
2786
    RHDFUNCI(scrnIndex);
2787
 
2788
    if (rhdPtr->BIOSCopy) {
2789
	xf86DrvMsg(scrnIndex,X_INFO,"Getting BIOS copy from INT10\n");
2790
    ptr = rhdPtr->BIOSCopy;
2791
    rhdPtr->BIOSCopy = NULL;
2792
 
2793
    BIOSImageSize = ptr[2] * 512;
2794
	if (BIOSImageSize > legacyBIOSMax) {
2795
	    xf86DrvMsg(scrnIndex,X_ERROR,"Invalid BIOS length field\n");
2796
	    return ATOM_FAILED;
2797
    }
2798
  }
2799
  else
2800
  {
2801
//    if (!xf86IsEntityPrimary(rhdPtr->entityIndex))
2802
//    {
2803
//      if (!(BIOSImageSize = RHDReadPCIBios(rhdPtr, &ptr)))
2804
//        return ATOM_FAILED;
2805
//      unposted = TRUE;
2806
//    }
2807
//    else
2808
    {
2809
	    int read_len;
2810
	    unsigned char tmp[32];
2811
 
2812
      DBG(dbgprintf("Getting BIOS copy from legacy VBIOS location\n"));
2813
      memcpy(tmp,(char*)(OS_BASE+legacyBIOSLocation), 32);
2814
	    BIOSImageSize = tmp[2] * 512;
2815
	    if (BIOSImageSize > legacyBIOSMax) {
2816
    xf86DrvMsg(0,X_ERROR,"Invalid BIOS length field\n");
2817
        return ATOM_FAILED;
2818
	    }
2819
      if (!(ptr = (char*)KernelAlloc(BIOSImageSize)))
2820
      {
2821
        DBG(dbgprintf("Cannot allocate %i bytes of memory "
2822
                  "for BIOS image\n",BIOSImageSize));
2823
        return ATOM_FAILED;
2824
	    }
2825
      memcpy(ptr,(char*)(OS_BASE+legacyBIOSLocation), BIOSImageSize);
2826
      rhdPtr->BIOSCopy = ptr;
2827
    }
2828
  }
2829
 
2830
    if (!(atomDataPtr = xcalloc(1, sizeof(atomDataTables)))) {
2831
	xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory for "
2832
		   "ATOM BIOS data tabes\n");
2833
    goto error;
2834
  }
2835
    if (!rhdAtomGetTables(rhdPtr, ptr, atomDataPtr, &codeTable, BIOSImageSize))
2836
    goto error1;
2837
    if (!(handle = xcalloc(1, sizeof(atomBiosHandleRec)))) {
2838
	xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory\n");
2839
    goto error1;
2840
  }
2841
  handle->BIOSBase = ptr;
2842
  handle->atomDataPtr = atomDataPtr;
2843
  handle->scrnIndex = scrnIndex;
2844
  handle->rhdPtr = rhdPtr;
2845
  handle->PciTag = rhdPtr->PciTag;
2846
  handle->BIOSImageSize = BIOSImageSize;
2847
    handle->codeTable = codeTable;
2848
    handle->SaveListObjects = NULL;
2849
 
2850
# ifdef ATOM_BIOS_PARSER
2851
    /* Try to find out if BIOS has been posted (either by system or int10 */
2852
    if (unposted) {
2853
	/* run AsicInit */
2854
	if (!rhdAtomASICInit(handle))
2855
	    xf86DrvMsg(scrnIndex, X_WARNING,
2856
		       "%s: AsicInit failed. Won't be able to obtain in VRAM "
2857
		       "FB scratch space\n",__func__);
2858
    }
2859
# endif
2860
 
2861
    data->atomhandle = handle;
2862
    return ATOM_SUCCESS;
2863
 
2864
 error1:
2865
    xfree(atomDataPtr);
2866
 error:
2867
    xfree(ptr);
2868
    return ATOM_FAILED;
2869
}
2870
 
2871
static AtomBiosResult
2872
rhdAtomTearDown(atomBiosHandlePtr handle,
2873
		AtomBiosRequestID unused1, AtomBiosArgPtr unused2)
2874
{
2875
    RHDFUNC(handle);
2876
 
2877
    xfree(handle->BIOSBase);
2878
    xfree(handle->atomDataPtr);
2879
    if (handle->scratchBase) xfree(handle->scratchBase);
2880
    xfree(handle);
2881
    return ATOM_SUCCESS;
2882
}
2883
 
2884
static AtomBiosResult
2885
rhdAtomVramInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func,
2886
		     AtomBiosArgPtr data)
2887
{
2888
    atomDataTablesPtr atomDataPtr;
2889
    CARD32 *val = &data->val;
2890
    RHDFUNC(handle);
2891
 
2892
    atomDataPtr = handle->atomDataPtr;
2893
 
2894
    switch (func) {
2895
      case GET_FW_FB_START:
2896
        *val = atomDataPtr->VRAM_UsageByFirmware
2897
        ->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware;
2898
        break;
2899
     case GET_FW_FB_SIZE:
2900
       *val = atomDataPtr->VRAM_UsageByFirmware
2901
       ->asFirmwareVramReserveInfo[0].usFirmwareUseInKb;
2902
       break;
2903
     default:
2904
       return ATOM_NOT_IMPLEMENTED;
2905
    }
2906
    return ATOM_SUCCESS;
2907
}
2908
 
2909
static AtomBiosResult
2910
rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle,
2911
		     AtomBiosRequestID func, AtomBiosArgPtr data)
2912
{
2913
    atomDataTablesPtr atomDataPtr;
2914
    CARD32 *val = &data->val;
2915
    int i = 0, clock = *val;
2916
 
2917
    atomDataPtr = handle->atomDataPtr;
2918
    if (!rhdAtomGetTableRevisionAndSize(
2919
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->TMDS_Info),
2920
	    NULL,NULL,NULL)) {
2921
	return ATOM_FAILED;
2922
    }
2923
 
2924
    RHDFUNC(handle);
2925
 
2926
    if (func == ATOM_TMDS_MAX_FREQUENCY)
2927
	*val = atomDataPtr->TMDS_Info->usMaxFrequency * 10;
2928
    else {
2929
	if (clock > atomDataPtr->TMDS_Info->usMaxFrequency * 10)
2930
	    return ATOM_FAILED;
2931
 
2932
	for (;i < ATOM_MAX_MISC_INFO; i++) {
2933
	    if (clock < atomDataPtr->TMDS_Info->asMiscInfo[i].usFrequency * 10) {
2934
    switch (func) {
2935
	case ATOM_TMDS_PLL_CHARGE_PUMP:
2936
			*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_ChargePump;
2937
			break;
2938
		    case ATOM_TMDS_PLL_DUTY_CYCLE:
2939
			*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_DutyCycle;
2940
			break;
2941
		    case ATOM_TMDS_PLL_VCO_GAIN:
2942
			*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_VCO_Gain;
2943
			break;
2944
		    case ATOM_TMDS_PLL_VOLTAGE_SWING:
2945
			*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_VoltageSwing;
2946
	    break;
2947
	default:
2948
	    return ATOM_NOT_IMPLEMENTED;
2949
    }
2950
		break;
2951
	    }
2952
	}
2953
    }
2954
 
2955
    if (i > ATOM_MAX_MISC_INFO)
2956
	return ATOM_FAILED;
2957
 
2958
    return ATOM_SUCCESS;
2959
}
2960
 
2961
static DisplayModePtr
2962
rhdAtomLvdsTimings(atomBiosHandlePtr handle, ATOM_DTD_FORMAT *dtd)
2963
{
2964
    DisplayModePtr mode;
2965
#define NAME_LEN 16
2966
    char name[NAME_LEN];
2967
 
2968
    RHDFUNC(handle);
2969
 
2970
    if (!(mode = (DisplayModePtr)xcalloc(1,sizeof(DisplayModeRec))))
2971
	return NULL;
2972
 
2973
    mode->CrtcHDisplay = mode->HDisplay = dtd->usHActive;
2974
    mode->CrtcVDisplay = mode->VDisplay = dtd->usVActive;
2975
    mode->CrtcHBlankStart = dtd->usHActive + dtd->ucHBorder;
2976
    mode->CrtcHBlankEnd = mode->CrtcHBlankStart + dtd->usHBlanking_Time;
2977
    mode->CrtcHTotal = mode->HTotal = mode->CrtcHBlankEnd + dtd->ucHBorder;
2978
    mode->CrtcVBlankStart = dtd->usVActive + dtd->ucVBorder;
2979
    mode->CrtcVBlankEnd = mode->CrtcVBlankStart + dtd->usVBlanking_Time;
2980
    mode->CrtcVTotal = mode->VTotal = mode->CrtcVBlankEnd + dtd->ucVBorder;
2981
    mode->CrtcHSyncStart = mode->HSyncStart = dtd->usHActive + dtd->usHSyncOffset;
2982
    mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + dtd->usHSyncWidth;
2983
    mode->CrtcVSyncStart = mode->VSyncStart = dtd->usVActive + dtd->usVSyncOffset;
2984
    mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + dtd->usVSyncWidth;
2985
 
2986
    mode->SynthClock = mode->Clock  = dtd->usPixClk * 10;
2987
 
2988
    mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal);
2989
    mode->VRefresh = (1000.0 * ((float) mode->Clock))
2990
	/ ((float)(((float)mode->HTotal) * ((float)mode->VTotal)));
2991
 
2992
    snprintf(name, NAME_LEN, "%dx%d",
2993
		 mode->HDisplay, mode->VDisplay);
2994
    mode->name = strdup(name);
2995
 
2996
    RHDDebug(handle->scrnIndex,"%s: LVDS Modeline: %s  "
2997
	     "%2.d  %i (%i) %i %i (%i) %i  %i (%i) %i %i (%i) %i\n",
2998
              __func__, mode->name, mode->Clock,
2999
	     mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd,
3000
	     mode->CrtcHBlankEnd, mode->HTotal,
3001
	     mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd,
3002
	     mode->CrtcVBlankEnd, mode->VTotal);
3003
#undef NAME_LEN
3004
    return mode;
3005
}
3006
 
3007
static unsigned char*
3008
rhdAtomLvdsDDC(atomBiosHandlePtr handle, CARD32 offset, unsigned char *record)
3009
{
3010
    unsigned char *EDIDBlock;
3011
 
3012
    RHDFUNC(handle);
3013
 
3014
    while (*record != ATOM_RECORD_END_TYPE) {
3015
 
3016
	switch (*record) {
3017
	    case LCD_MODE_PATCH_RECORD_MODE_TYPE:
3018
		offset += sizeof(ATOM_PATCH_RECORD_MODE);
3019
		if (offset > handle->BIOSImageSize) break;
3020
		record += sizeof(ATOM_PATCH_RECORD_MODE);
3021
		break;
3022
 
3023
	    case LCD_RTS_RECORD_TYPE:
3024
		offset += sizeof(ATOM_LCD_RTS_RECORD);
3025
		if (offset > handle->BIOSImageSize) break;
3026
		record += sizeof(ATOM_LCD_RTS_RECORD);
3027
		break;
3028
 
3029
	    case LCD_CAP_RECORD_TYPE:
3030
		offset += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
3031
		if (offset > handle->BIOSImageSize) break;
3032
		record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
3033
		break;
3034
 
3035
	    case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
3036
		offset += sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
3037
		/* check if the structure still fully lives in the BIOS image */
3038
		if (offset > handle->BIOSImageSize) break;
3039
		offset += ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength
3040
		    - sizeof(UCHAR);
3041
		if (offset > handle->BIOSImageSize) break;
3042
		/* dup string as we free it later */
3043
		if (!(EDIDBlock = (unsigned char *)xalloc(
3044
			  ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength)))
3045
		    return NULL;
3046
		memcpy(EDIDBlock,&((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDString,
3047
		       ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength);
3048
 
3049
		/* for testing */
3050
		{
3051
  //      xf86MonPtr mon = xf86InterpretEDID(handle->scrnIndex,EDIDBlock);
3052
  //      xf86PrintEDID(mon);
3053
 //       kfree(mon);
3054
		}
3055
		return EDIDBlock;
3056
 
3057
	    case LCD_PANEL_RESOLUTION_RECORD_TYPE:
3058
		offset += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
3059
		if (offset > handle->BIOSImageSize) break;
3060
		record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
3061
		break;
3062
 
3063
	    default:
3064
		xf86DrvMsg(handle->scrnIndex, X_ERROR,
3065
			   "%s: unknown record type: %x\n",__func__,*record);
3066
        return NULL;
3067
	}
3068
    }
3069
 
3070
    return NULL;
3071
}
3072
 
3073
static AtomBiosResult
3074
rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func,
3075
		  AtomBiosArgPtr data)
3076
{
3077
    atomDataTablesPtr atomDataPtr;
3078
    CARD8 crev, frev;
3079
    unsigned long offset;
3080
 
3081
    RHDFUNC(handle);
3082
 
3083
    atomDataPtr = handle->atomDataPtr;
3084
 
3085
    if (!rhdAtomGetTableRevisionAndSize(
3086
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base),
3087
	    &crev,&frev,NULL)) {
3088
	return ATOM_FAILED;
3089
    }
3090
 
3091
    switch (crev) {
3092
 
3093
	case 1:
3094
	    switch (func) {
3095
		case ATOMBIOS_GET_PANEL_MODE:
3096
		    data->mode = rhdAtomLvdsTimings(handle,
3097
						    &atomDataPtr->LVDS_Info
3098
						    .LVDS_Info->sLCDTiming);
3099
		    if (data->mode)
3100
			return ATOM_SUCCESS;
3101
		default:
3102
		    return ATOM_FAILED;
3103
	    }
3104
	case 2:
3105
	    switch (func) {
3106
		case ATOMBIOS_GET_PANEL_MODE:
3107
		    data->mode = rhdAtomLvdsTimings(handle,
3108
						    &atomDataPtr->LVDS_Info
3109
						    .LVDS_Info_v12->sLCDTiming);
3110
		    if (data->mode)
3111
			return ATOM_SUCCESS;
3112
		    return ATOM_FAILED;
3113
 
3114
		case ATOMBIOS_GET_PANEL_EDID:
3115
		    offset = (unsigned long)&atomDataPtr->LVDS_Info.base
3116
			- (unsigned long)handle->BIOSBase
3117
			+ atomDataPtr->LVDS_Info
3118
			.LVDS_Info_v12->usExtInfoTableOffset;
3119
 
3120
		    data->EDIDBlock
3121
			= rhdAtomLvdsDDC(handle, offset,
3122
					 (unsigned char *)
3123
					 &atomDataPtr->LVDS_Info.base
3124
					 + atomDataPtr->LVDS_Info
3125
					 .LVDS_Info_v12->usExtInfoTableOffset);
3126
		    if (data->EDIDBlock)
3127
			return ATOM_SUCCESS;
3128
		default:
3129
		    return ATOM_FAILED;
3130
	    }
3131
	default:
3132
	    return ATOM_NOT_IMPLEMENTED;
3133
    }
3134
/*NOTREACHED*/
3135
}
3136
 
3137
static AtomBiosResult
3138
rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle,
3139
		     AtomBiosRequestID func,  AtomBiosArgPtr data)
3140
{
3141
    atomDataTablesPtr atomDataPtr;
3142
    CARD8 crev, frev;
3143
    CARD32 *val = &data->val;
3144
 
3145
    RHDFUNC(handle);
3146
 
3147
    atomDataPtr = handle->atomDataPtr;
3148
 
3149
    if (!rhdAtomGetTableRevisionAndSize(
3150
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base),
3151
	    &crev,&frev,NULL)) {
3152
	return ATOM_FAILED;
3153
    }
3154
 
3155
    switch (crev) {
3156
	case 1:
3157
	    switch (func) {
3158
		case ATOM_LVDS_SUPPORTED_REFRESH_RATE:
3159
		    *val = atomDataPtr->LVDS_Info
3160
			.LVDS_Info->usSupportedRefreshRate;
3161
		    break;
3162
		case ATOM_LVDS_OFF_DELAY:
3163
		    *val = atomDataPtr->LVDS_Info
3164
			.LVDS_Info->usOffDelayInMs;
3165
		    break;
3166
		case ATOM_LVDS_SEQ_DIG_ONTO_DE:
3167
		    *val = atomDataPtr->LVDS_Info
3168
			.LVDS_Info->ucPowerSequenceDigOntoDEin10Ms * 10;
3169
		    break;
3170
		case ATOM_LVDS_SEQ_DE_TO_BL:
3171
		    *val = atomDataPtr->LVDS_Info
3172
			.LVDS_Info->ucPowerSequenceDEtoBLOnin10Ms * 10;
3173
		    break;
3174
		case     ATOM_LVDS_TEMPORAL_DITHER:
3175
		    *val = (atomDataPtr->LVDS_Info
3176
			    .LVDS_Info->ucLVDS_Misc & 0x40) != 0;
3177
		    break;
3178
		case     ATOM_LVDS_SPATIAL_DITHER:
3179
		    *val = (atomDataPtr->LVDS_Info
3180
			    .LVDS_Info->ucLVDS_Misc & 0x20) != 0;
3181
		    break;
3182
		case     ATOM_LVDS_FPDI:
3183
		    *val = (atomDataPtr->LVDS_Info
3184
			    .LVDS_Info->ucLVDS_Misc & 0x10) != 0;
3185
		    break;
3186
		case     ATOM_LVDS_DUALLINK:
3187
		    *val = (atomDataPtr->LVDS_Info
3188
			    .LVDS_Info->ucLVDS_Misc & 0x01) != 0;
3189
		    break;
3190
		case     ATOM_LVDS_24BIT:
3191
		    *val = (atomDataPtr->LVDS_Info
3192
			    .LVDS_Info->ucLVDS_Misc & 0x02) != 0;
3193
		    break;
3194
		case     ATOM_LVDS_GREYLVL:
3195
		    *val = (atomDataPtr->LVDS_Info
3196
			    .LVDS_Info->ucLVDS_Misc & ATOM_PANEL_MISC_GREY_LEVEL)
3197
			>> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT ;
3198
		    break;
3199
		default:
3200
		    return ATOM_NOT_IMPLEMENTED;
3201
	    }
3202
	    break;
3203
	case 2:
3204
	    switch (func) {
3205
		case ATOM_LVDS_SUPPORTED_REFRESH_RATE:
3206
		    *val = atomDataPtr->LVDS_Info
3207
			.LVDS_Info_v12->usSupportedRefreshRate;
3208
		    break;
3209
		case ATOM_LVDS_OFF_DELAY:
3210
		    *val = atomDataPtr->LVDS_Info
3211
			.LVDS_Info_v12->usOffDelayInMs;
3212
		    break;
3213
		case ATOM_LVDS_SEQ_DIG_ONTO_DE:
3214
		    *val = atomDataPtr->LVDS_Info
3215
			.LVDS_Info_v12->ucPowerSequenceDigOntoDEin10Ms * 10;
3216
		    break;
3217
		case ATOM_LVDS_SEQ_DE_TO_BL:
3218
		    *val = atomDataPtr->LVDS_Info
3219
			.LVDS_Info_v12->ucPowerSequenceDEtoBLOnin10Ms * 10;
3220
		    break;
3221
		case     ATOM_LVDS_FPDI:
3222
		    *val = (atomDataPtr->LVDS_Info
3223
			    .LVDS_Info_v12->ucLVDS_Misc * 0x10) != 0;
3224
		    break;
3225
		case     ATOM_LVDS_SPATIAL_DITHER:
3226
		    *val = (atomDataPtr->LVDS_Info
3227
			    .LVDS_Info_v12->ucLVDS_Misc & 0x20) != 0;
3228
		    break;
3229
		case     ATOM_LVDS_TEMPORAL_DITHER:
3230
		    *val = (atomDataPtr->LVDS_Info
3231
			    .LVDS_Info_v12->ucLVDS_Misc & 0x40) != 0;
3232
		    break;
3233
		case     ATOM_LVDS_DUALLINK:
3234
		    *val = (atomDataPtr->LVDS_Info
3235
			    .LVDS_Info_v12->ucLVDS_Misc & 0x01) != 0;
3236
		    break;
3237
		case     ATOM_LVDS_24BIT:
3238
		    *val = (atomDataPtr->LVDS_Info
3239
			    .LVDS_Info_v12->ucLVDS_Misc & 0x02) != 0;
3240
		    break;
3241
		case     ATOM_LVDS_GREYLVL:
3242
		    *val = (atomDataPtr->LVDS_Info
3243
			    .LVDS_Info_v12->ucLVDS_Misc & 0x0C) >> 2;
3244
		    break;
3245
		default:
3246
		    return ATOM_NOT_IMPLEMENTED;
3247
	    }
3248
	    break;
3249
	default:
3250
	    return ATOM_NOT_IMPLEMENTED;
3251
    }
3252
 
3253
    return ATOM_SUCCESS;
3254
}
3255
 
3256
static AtomBiosResult
3257
rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle,
3258
			AtomBiosRequestID func, AtomBiosArgPtr data)
3259
{
3260
    atomDataTablesPtr atomDataPtr;
3261
    CARD8 crev, frev;
3262
    CARD32 *val = &data->val;
3263
 
3264
    RHDFUNC(handle);
3265
 
3266
    atomDataPtr = handle->atomDataPtr;
3267
 
3268
    if (!rhdAtomGetTableRevisionAndSize(
3269
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->CompassionateData),
3270
	    &crev,&frev,NULL)) {
3271
	return ATOM_FAILED;
3272
    }
3273
 
3274
    switch (func) {
3275
	case ATOM_DAC1_BG_ADJ:
3276
	    *val = atomDataPtr->CompassionateData->
3277
		ucDAC1_BG_Adjustment;
3278
	    break;
3279
	case ATOM_DAC1_DAC_ADJ:
3280
	    *val = atomDataPtr->CompassionateData->
3281
		ucDAC1_DAC_Adjustment;
3282
	    break;
3283
	case ATOM_DAC1_FORCE:
3284
	    *val = atomDataPtr->CompassionateData->
3285
		usDAC1_FORCE_Data;
3286
	    break;
3287
	case ATOM_DAC2_CRTC2_BG_ADJ:
3288
	    *val = atomDataPtr->CompassionateData->
3289
		ucDAC2_CRT2_BG_Adjustment;
3290
	    break;
3291
	case ATOM_DAC2_NTSC_BG_ADJ:
3292
	    *val = atomDataPtr->CompassionateData->
3293
		ucDAC2_NTSC_BG_Adjustment;
3294
	    break;
3295
	case ATOM_DAC2_PAL_BG_ADJ:
3296
	    *val = atomDataPtr->CompassionateData->
3297
		ucDAC2_PAL_BG_Adjustment;
3298
	    break;
3299
	case ATOM_DAC2_CV_BG_ADJ:
3300
	    *val = atomDataPtr->CompassionateData->
3301
		ucDAC2_CV_BG_Adjustment;
3302
	    break;
3303
	case ATOM_DAC2_CRTC2_DAC_ADJ:
3304
	    *val = atomDataPtr->CompassionateData->
3305
		ucDAC2_CRT2_DAC_Adjustment;
3306
	    break;
3307
	case ATOM_DAC2_NTSC_DAC_ADJ:
3308
	    *val = atomDataPtr->CompassionateData->
3309
		ucDAC2_NTSC_DAC_Adjustment;
3310
	    break;
3311
	case ATOM_DAC2_PAL_DAC_ADJ:
3312
	    *val = atomDataPtr->CompassionateData->
3313
		ucDAC2_PAL_DAC_Adjustment;
3314
	    break;
3315
	case ATOM_DAC2_CV_DAC_ADJ:
3316
	    *val = atomDataPtr->CompassionateData->
3317
		ucDAC2_CV_DAC_Adjustment;
3318
	    break;
3319
	case ATOM_DAC2_CRTC2_FORCE:
3320
	    *val = atomDataPtr->CompassionateData->
3321
		usDAC2_CRT2_FORCE_Data;
3322
	    break;
3323
	case ATOM_DAC2_CRTC2_MUX_REG_IND:
3324
	    *val = atomDataPtr->CompassionateData->
3325
		usDAC2_CRT2_MUX_RegisterIndex;
3326
	    break;
3327
	case ATOM_DAC2_CRTC2_MUX_REG_INFO:
3328
	    *val = atomDataPtr->CompassionateData->
3329
		ucDAC2_CRT2_MUX_RegisterInfo;
3330
	    break;
3331
	default:
3332
	    return ATOM_NOT_IMPLEMENTED;
3333
    }
3334
    return ATOM_SUCCESS;
3335
}
3336
 
3337
/*
3338
 *
3339
 */
3340
enum atomPCIELanes atomPCIELanesMap[] = {
3341
    atomPCIELaneNONE,
3342
    atomPCIELane0_3,
3343
    atomPCIELane4_7,
3344
    atomPCIELane0_7,
3345
    atomPCIELane8_11,
3346
    atomPCIELaneNONE,
3347
    atomPCIELaneNONE,
3348
    atomPCIELaneNONE,
3349
    atomPCIELane12_15,
3350
    atomPCIELaneNONE,
3351
    atomPCIELaneNONE,
3352
    atomPCIELaneNONE,
3353
    atomPCIELane8_15,
3354
    atomPCIELaneNONE,
3355
    atomPCIELaneNONE,
3356
    atomPCIELaneNONE,
3357
    atomPCIELaneNONE
3358
};
3359
 
3360
static AtomBiosResult
3361
rhdAtomIntegratedSystemInfoQuery(atomBiosHandlePtr handle,
3362
			AtomBiosRequestID func, AtomBiosArgPtr data)
3363
{
3364
    atomDataTablesPtr atomDataPtr;
3365
    CARD8 crev, frev;
3366
    CARD32 *val = &data->val;
3367
 
3368
    RHDFUNC(handle);
3369
 
3370
    atomDataPtr = handle->atomDataPtr;
3371
 
3372
    if (!rhdAtomGetTableRevisionAndSize(
3373
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base),
3374
	    &crev,&frev,NULL)) {
3375
	return ATOM_FAILED;
3376
    }
3377
 
3378
    switch (crev) {
3379
	case 1:
3380
	    switch (func) {
3381
		case ATOM_GET_PCIENB_CFG_REG7:
3382
		    *val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usPCIENBCfgReg7;
3383
		    break;
3384
		case ATOM_GET_CAPABILITY_FLAG:
3385
		    *val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usCapabilityFlag;
3386
		    break;
3387
		default:
3388
		    return ATOM_NOT_IMPLEMENTED;
3389
	    }
3390
	    break;
3391
	case 2:
3392
	    switch (func) {
3393
		case ATOM_GET_PCIE_LANES:
3394
		{
3395
		    CARD32 n;
3396
		    switch (*val) {
3397
			case 1:
3398
			    n = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot1Config;
3399
			    break;
3400
			case 2:
3401
			    n = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot2Config;
3402
			    break;
3403
		default:
3404
			    return ATOM_FAILED;
3405
	    }
3406
		    data->pcieLanes.Chassis = atomPCIELanesMap[n & 0xf];
3407
		    data->pcieLanes.Docking = atomPCIELanesMap[(n >> 4) & 0xf];
3408
		    RHDDebug(handle->scrnIndex, "AtomBIOS IntegratedSystemInfo PCIELanes: Chassis=%x Docking=%x\n",
3409
			     data->pcieLanes.Chassis, data->pcieLanes.Docking);
3410
		    return ATOM_SUCCESS;
3411
		}
3412
	    break;
3413
		default:
3414
		    return ATOM_NOT_IMPLEMENTED;
3415
    }
3416
	    return ATOM_NOT_IMPLEMENTED;
3417
    }
3418
 
3419
    return ATOM_SUCCESS;
3420
}
3421
 
3422
static DisplayModePtr
3423
rhdAtomAnalogTVTimings(atomBiosHandlePtr handle,
3424
		       ATOM_ANALOG_TV_INFO *tv_info,
3425
		       enum RHD_TV_MODE tvMode)
3426
{
3427
    atomDataTablesPtr atomDataPtr;
3428
    DisplayModePtr mode;
3429
    int mode_n;
3430
    char *name;
3431
    ATOM_MODE_TIMING *amt;
3432
 
3433
    RHDFUNC(handle);
3434
 
3435
    atomDataPtr = handle->atomDataPtr;
3436
 
3437
    switch (tvMode) {
3438
	case NTSC_SUPPORT:
3439
	case NTSCJ_SUPPORT:
3440
	    mode_n = 0;
3441
	    name = "TV_NTSC";
3442
	    break;
3443
	case PAL_SUPPORT:
3444
	case PALM_SUPPORT:
3445
	case PALCN_SUPPORT:
3446
	case PALN_SUPPORT:
3447
	case PAL60_SUPPORT:
3448
	case SECAM_SUPPORT:
3449
	    mode_n = 1;
3450
	    name = "TV_PAL/SECAM";
3451
	    break;
3452
	default:
3453
	    return NULL;
3454
    }
3455
 
3456
 
3457
    if (!(tv_info->ucTV_SupportedStandard & (tvMode)))
3458
	return NULL;
3459
 
3460
    if (!(mode = (DisplayModePtr)xcalloc(1,sizeof(DisplayModeRec))))
3461
	return NULL;
3462
 
3463
    amt = &tv_info->aModeTimings[mode_n];
3464
 
3465
    mode->CrtcHDisplay = mode->HDisplay =  amt->usCRTC_H_Disp;
3466
    mode->CrtcHSyncStart = mode->HSyncStart = amt->usCRTC_H_SyncStart;
3467
    mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + amt->usCRTC_H_SyncWidth;
3468
    mode->CrtcHTotal = mode->HTotal = amt->usCRTC_H_Total;
3469
    mode->CrtcHBlankStart = mode->HDisplay + amt->usCRTC_OverscanRight;
3470
    mode->CrtcHBlankEnd = mode->HTotal - amt->usCRTC_OverscanLeft;
3471
 
3472
    mode->CrtcVDisplay = mode->VDisplay = amt->usCRTC_V_Disp;
3473
    mode->CrtcVSyncStart = mode->VSyncStart = amt->usCRTC_V_SyncStart;
3474
    mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + amt->usCRTC_V_SyncWidth;
3475
    mode->CrtcVTotal = mode->VTotal = amt->usCRTC_V_Total;
3476
    mode->CrtcVBlankStart = mode->VDisplay + amt->usCRTC_OverscanBottom;
3477
    mode->CrtcVBlankEnd = mode->CrtcVTotal - amt->usCRTC_OverscanTop;
3478
 
3479
    mode->SynthClock = mode->Clock  = amt->usPixelClock * 10;
3480
    if (amt->susModeMiscInfo.usAccess & ATOM_HSYNC_POLARITY)
3481
	mode->Flags |= V_NHSYNC;
3482
    else
3483
	mode->Flags |= V_PHSYNC;
3484
    if (amt->susModeMiscInfo.usAccess & ATOM_VSYNC_POLARITY)
3485
	mode->Flags |= V_NVSYNC;
3486
    else
3487
	mode->Flags |= V_PVSYNC;
3488
    if (amt->susModeMiscInfo.usAccess & ATOM_INTERLACE)
3489
	mode->Flags |= V_INTERLACE;
3490
    if (amt->susModeMiscInfo.usAccess & ATOM_COMPOSITESYNC)
3491
	mode->Flags |= V_CSYNC;
3492
    if (amt->susModeMiscInfo.usAccess & ATOM_DOUBLE_CLOCK_MODE)
3493
	mode->Flags |= V_DBLCLK;
3494
 
3495
    mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal);
3496
    mode->VRefresh = (1000.0 * ((float) mode->Clock))
3497
	/ ((float)(((float)mode->HTotal) * ((float)mode->VTotal)));
3498
 
3499
    mode->name = strdup(name);
3500
 
3501
    RHDDebug(handle->scrnIndex,"%s: TV Modeline: %s  "
3502
	     "%2.d  %i (%i) %i %i (%i) %i  %i (%i) %i %i (%i) %i\n",
3503
	     __func__, mode->name, mode->Clock,
3504
	     mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd,
3505
	     mode->CrtcHBlankEnd, mode->HTotal,
3506
	     mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd,
3507
	     mode->CrtcVBlankEnd, mode->VTotal);
3508
 
3509
 
3510
    return mode;
3511
}
3512
 
3513
static AtomBiosResult
3514
rhdAtomAnalogTVInfoQuery(atomBiosHandlePtr handle,
3515
			AtomBiosRequestID func, AtomBiosArgPtr data)
3516
{
3517
    CARD8 crev, frev;
3518
    atomDataTablesPtr atomDataPtr = handle->atomDataPtr;
3519
    int mode = 0, i;
3520
    struct { enum RHD_TV_MODE rhd_mode; int atomMode; }
3521
    tv_modes[] = {
3522
	{ RHD_TV_NTSC,  NTSC_SUPPORT },
3523
	{ RHD_TV_NTSCJ, NTSCJ_SUPPORT},
3524
	{ RHD_TV_PAL,   PAL_SUPPORT  },
3525
	{ RHD_TV_PALM,  PALM_SUPPORT },
3526
	{ RHD_TV_PALCN, PALCN_SUPPORT},
3527
	{ RHD_TV_PALN,  PALN_SUPPORT },
3528
	{ RHD_TV_PAL60, PAL60_SUPPORT},
3529
	{ RHD_TV_SECAM, SECAM_SUPPORT},
3530
	{ RHD_TV_NONE, 0 }
3531
    };
3532
 
3533
 
3534
    RHDFUNC(handle);
3535
 
3536
    if (!rhdAtomGetTableRevisionAndSize(
3537
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info),
3538
	    &crev,&frev,NULL)) {
3539
	return ATOM_FAILED;
3540
    }
3541
    switch (func) {
3542
	case ATOM_ANALOG_TV_MODE:
3543
	    for (i = 0; tv_modes[i].atomMode; i++) {
3544
		if (data->tvMode == tv_modes[i].rhd_mode) {
3545
		    mode = tv_modes[i].atomMode;
3546
		    break;
3547
		}
3548
	    }
3549
	    data->mode = rhdAtomAnalogTVTimings(handle,
3550
						atomDataPtr->AnalogTV_Info,
3551
						mode);
3552
	    if (!data->mode)
3553
		return ATOM_FAILED;
3554
	    return ATOM_SUCCESS;
3555
	case ATOM_ANALOG_TV_DEFAULT_MODE:
3556
	     data->tvMode = tv_modes[atomDataPtr->AnalogTV_Info->ucTV_BootUpDefaultStandard - 1].rhd_mode;
3557
	    break;
3558
	case ATOM_ANALOG_TV_SUPPORTED_MODES:
3559
	    mode = (CARD32)atomDataPtr->AnalogTV_Info->ucTV_SupportedStandard;
3560
	    data->val = 0;
3561
	    for (i = 0; tv_modes[i].atomMode; i++) {
3562
		if (tv_modes[i].atomMode & mode) {
3563
		    data->val |= tv_modes[i].rhd_mode;
3564
		}
3565
	    }
3566
	    break;
3567
	default:
3568
	    return ATOM_NOT_IMPLEMENTED;
3569
    }
3570
 
3571
    return ATOM_SUCCESS;
3572
}
3573
 
3574
static AtomBiosResult
3575
rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle,
3576
			AtomBiosRequestID func, AtomBiosArgPtr data)
3577
{
3578
  atomDataTablesPtr atomDataPtr;
3579
  CARD8 crev, frev;
3580
  CARD32 *val = &data->val;
3581
  unsigned short size;
3582
 
3583
    RHDFUNC(handle);
3584
 
3585
  atomDataPtr = handle->atomDataPtr;
3586
 
3587
  if (!rhdAtomGetTableRevisionAndSize(
3588
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->GPIO_I2C_Info),
3589
	    &crev,&frev,&size)) {
3590
    return ATOM_FAILED;
3591
  }
3592
 
3593
      if ((sizeof(ATOM_COMMON_TABLE_HEADER)
3594
		 + (*val * sizeof(ATOM_GPIO_I2C_ASSIGMENT))) > size) {
3595
		xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: GPIO_I2C Device "
3596
			   "num %lu exeeds table size %u\n",__func__,
3597
			   (unsigned long)val,
3598
			   size);
3599
        return ATOM_FAILED;
3600
	    }
3601
 
3602
    switch (func) {
3603
	case ATOM_GPIO_I2C_DATA_MASK:
3604
	    *val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val]
3605
		.usDataMaskRegisterIndex;
3606
	    break;
3607
 
3608
	case ATOM_GPIO_I2C_DATA_MASK_SHIFT:
3609
	    *val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val]
3610
		.ucDataMaskShift;
3611
	    break;
3612
 
3613
	case ATOM_GPIO_I2C_CLK_MASK:
3614
	    *val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val]
3615
            .usClkMaskRegisterIndex;
3616
	    break;
3617
 
3618
	case ATOM_GPIO_I2C_CLK_MASK_SHIFT:
3619
	    *val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val]
3620
		.ucClkMaskShift;
3621
	    break;
3622
 
3623
    default:
3624
	    return ATOM_NOT_IMPLEMENTED;
3625
  }
3626
  return ATOM_SUCCESS;
3627
}
3628
 
3629
static AtomBiosResult
3630
rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle,
3631
			 AtomBiosRequestID func, AtomBiosArgPtr data)
3632
{
3633
  atomDataTablesPtr atomDataPtr;
3634
  CARD8 crev, frev;
3635
  CARD32 *val = &data->val;
3636
 
3637
    RHDFUNC(handle);
3638
 
3639
  atomDataPtr = handle->atomDataPtr;
3640
 
3641
  if (!rhdAtomGetTableRevisionAndSize(
3642
	    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base),
3643
	    &crev,&frev,NULL)) {
3644
    return ATOM_FAILED;
3645
  }
3646
 
3647
    switch (crev) {
3648
	case 1:
3649
	    switch (func) {
3650
        case GET_DEFAULT_ENGINE_CLOCK:
3651
          *val = atomDataPtr->FirmwareInfo
3652
                 .FirmwareInfo->ulDefaultEngineClock * 10;
3653
          break;
3654
        case GET_DEFAULT_MEMORY_CLOCK:
3655
          *val = atomDataPtr->FirmwareInfo
3656
                 .FirmwareInfo->ulDefaultMemoryClock * 10;
3657
          break;
3658
        case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT:
3659
          *val = atomDataPtr->FirmwareInfo
3660
                 .FirmwareInfo->ulMaxPixelClockPLL_Output * 10;
3661
          break;
3662
        case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT:
3663
          *val = atomDataPtr->FirmwareInfo
3664
                 .FirmwareInfo->usMinPixelClockPLL_Output * 10;
3665
        case GET_MAX_PIXEL_CLOCK_PLL_INPUT:
3666
          *val = atomDataPtr->FirmwareInfo
3667
                 .FirmwareInfo->usMaxPixelClockPLL_Input * 10;
3668
          break;
3669
        case GET_MIN_PIXEL_CLOCK_PLL_INPUT:
3670
          *val = atomDataPtr->FirmwareInfo
3671
                 .FirmwareInfo->usMinPixelClockPLL_Input * 10;
3672
          break;
3673
        case GET_MAX_PIXEL_CLK:
3674
          *val = atomDataPtr->FirmwareInfo
3675
               .FirmwareInfo->usMaxPixelClock * 10;
3676
          break;
3677
        case GET_REF_CLOCK:
3678
          *val = atomDataPtr->FirmwareInfo
3679
               .FirmwareInfo->usReferenceClock * 10;
3680
          break;
3681
        default:
3682
          return ATOM_NOT_IMPLEMENTED;
3683
      }
3684
    case 2:
3685
	    switch (func) {
3686
        case GET_DEFAULT_ENGINE_CLOCK:
3687
          *val = atomDataPtr->FirmwareInfo
3688
                .FirmwareInfo_V_1_2->ulDefaultEngineClock * 10;
3689
          break;
3690
        case GET_DEFAULT_MEMORY_CLOCK:
3691
          *val = atomDataPtr->FirmwareInfo
3692
                 .FirmwareInfo_V_1_2->ulDefaultMemoryClock * 10;
3693
          break;
3694
        case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT:
3695
          *val = atomDataPtr->FirmwareInfo
3696
                 .FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output * 10;
3697
          break;
3698
        case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT:
3699
          *val = atomDataPtr->FirmwareInfo
3700
                 .FirmwareInfo_V_1_2->usMinPixelClockPLL_Output * 10;
3701
          break;
3702
        case GET_MAX_PIXEL_CLOCK_PLL_INPUT:
3703
          *val = atomDataPtr->FirmwareInfo
3704
                .FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input * 10;
3705
          break;
3706
        case GET_MIN_PIXEL_CLOCK_PLL_INPUT:
3707
          *val = atomDataPtr->FirmwareInfo
3708
                .FirmwareInfo_V_1_2->usMinPixelClockPLL_Input * 10;
3709
          break;
3710
        case GET_MAX_PIXEL_CLK:
3711
          *val = atomDataPtr->FirmwareInfo
3712
                .FirmwareInfo_V_1_2->usMaxPixelClock * 10;
3713
          break;
3714
        case GET_REF_CLOCK:
3715
          *val = atomDataPtr->FirmwareInfo
3716
                .FirmwareInfo_V_1_2->usReferenceClock * 10;
3717
          break;
3718
        default:
3719
          return ATOM_NOT_IMPLEMENTED;
3720
	    }
3721
	    break;
3722
	case 3:
3723
	    switch (func) {
3724
		case GET_DEFAULT_ENGINE_CLOCK:
3725
		    *val = atomDataPtr->FirmwareInfo
3726
			.FirmwareInfo_V_1_3->ulDefaultEngineClock * 10;
3727
		    break;
3728
		case GET_DEFAULT_MEMORY_CLOCK:
3729
		    *val = atomDataPtr->FirmwareInfo
3730
			.FirmwareInfo_V_1_3->ulDefaultMemoryClock * 10;
3731
		    break;
3732
		case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT:
3733
		    *val = atomDataPtr->FirmwareInfo
3734
			.FirmwareInfo_V_1_3->ulMaxPixelClockPLL_Output * 10;
3735
		    break;
3736
		case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT:
3737
		    *val = atomDataPtr->FirmwareInfo
3738
			.FirmwareInfo_V_1_3->usMinPixelClockPLL_Output * 10;
3739
		    break;
3740
		case GET_MAX_PIXEL_CLOCK_PLL_INPUT:
3741
		    *val = atomDataPtr->FirmwareInfo
3742
			.FirmwareInfo_V_1_3->usMaxPixelClockPLL_Input * 10;
3743
		    break;
3744
		case GET_MIN_PIXEL_CLOCK_PLL_INPUT:
3745
		    *val = atomDataPtr->FirmwareInfo
3746
			.FirmwareInfo_V_1_3->usMinPixelClockPLL_Input * 10;
3747
		    break;
3748
		case GET_MAX_PIXEL_CLK:
3749
		    *val = atomDataPtr->FirmwareInfo
3750
			.FirmwareInfo_V_1_3->usMaxPixelClock * 10;
3751
		    break;
3752
		case GET_REF_CLOCK:
3753
		    *val = atomDataPtr->FirmwareInfo
3754
			.FirmwareInfo_V_1_3->usReferenceClock * 10;
3755
		    break;
3756
		default:
3757
		    return ATOM_NOT_IMPLEMENTED;
3758
	    }
3759
	    break;
3760
	case 4:
3761
	    switch (func) {
3762
		case GET_DEFAULT_ENGINE_CLOCK:
3763
		    *val = atomDataPtr->FirmwareInfo
3764
			.FirmwareInfo_V_1_4->ulDefaultEngineClock * 10;
3765
		    break;
3766
		case GET_DEFAULT_MEMORY_CLOCK:
3767
		    *val = atomDataPtr->FirmwareInfo
3768
			.FirmwareInfo_V_1_4->ulDefaultMemoryClock * 10;
3769
		    break;
3770
		case GET_MAX_PIXEL_CLOCK_PLL_INPUT:
3771
		    *val = atomDataPtr->FirmwareInfo
3772
			.FirmwareInfo_V_1_4->usMaxPixelClockPLL_Input * 10;
3773
		    break;
3774
		case GET_MIN_PIXEL_CLOCK_PLL_INPUT:
3775
		    *val = atomDataPtr->FirmwareInfo
3776
			.FirmwareInfo_V_1_4->usMinPixelClockPLL_Input * 10;
3777
		    break;
3778
		case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT:
3779
		    *val = atomDataPtr->FirmwareInfo
3780
			.FirmwareInfo_V_1_4->ulMaxPixelClockPLL_Output * 10;
3781
		    break;
3782
		case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT:
3783
		    *val = atomDataPtr->FirmwareInfo
3784
			.FirmwareInfo_V_1_4->usMinPixelClockPLL_Output * 10;
3785
		    break;
3786
		case GET_MAX_PIXEL_CLK:
3787
		    *val = atomDataPtr->FirmwareInfo
3788
			.FirmwareInfo_V_1_4->usMaxPixelClock * 10;
3789
		    break;
3790
		case GET_REF_CLOCK:
3791
		    *val = atomDataPtr->FirmwareInfo
3792
			.FirmwareInfo_V_1_4->usReferenceClock * 10;
3793
		    break;
3794
		default:
3795
		    return ATOM_NOT_IMPLEMENTED;
3796
	    }
3797
	    break;
3798
	default:
3799
	    return ATOM_NOT_IMPLEMENTED;
3800
    }
3801
    return ATOM_SUCCESS;
3802
}
3803
 
3804
/*
3805
 *
3806
 */
3807
static AtomBiosResult
3808
rhdAtomGetConditionalGoldenSetting(atomBiosHandlePtr handle,
3809
			 AtomBiosRequestID func, AtomBiosArgPtr data)
3810
{
3811
    unsigned short *table = (unsigned short *)data->GoldenSettings.BIOSPtr;
3812
    unsigned short entry_size = *(table++);
3813
 
3814
    RHDFUNC(handle);
3815
 
3816
    RHDDebug(handle->scrnIndex, "%s: testing 0x%4.4x\n",__func__,
3817
	     data->GoldenSettings.value);
3818
 
3819
/* @@@ endian! */
3820
    while (table < (unsigned short *)data->GoldenSettings.End) {
3821
	RHDDebugCont("\t\t against: 0x%8.8x\n", table[1] << 16 | table[0]);
3822
	if ((data->GoldenSettings.value >> 16) == table[1]) {
3823
	    if ((data->GoldenSettings.value & 0xffff) <= table[0]) {
3824
		data->GoldenSettings.BIOSPtr = (unsigned char *)(table + 2);
3825
		return ATOM_SUCCESS;
3826
	    }
3827
	}
3828
	table = (unsigned short *)(((unsigned char *)table) + entry_size);
3829
    }
3830
    return ATOM_FAILED;
3831
}
3832
 
3833
#define Limit(n,max,name) ((n >= max) ? ( \
3834
     dbgprintf(handle->scrnIndex,X_ERROR,"%s: %s %i exceeds maximum %i\n", \
3835
               __func__,name,n,max), TRUE) : FALSE)
3836
 
3837
static const struct _rhd_connector_objs
3838
{
3839
    char *name;
3840
    rhdConnectorType con;
3841
} rhd_connector_objs[] = {
3842
    { "NONE", RHD_CONNECTOR_NONE },
3843
    { "SINGLE_LINK_DVI_I", RHD_CONNECTOR_DVI_SINGLE },
3844
    { "DUAL_LINK_DVI_I", RHD_CONNECTOR_DVI },
3845
    { "SINGLE_LINK_DVI_D", RHD_CONNECTOR_DVI_SINGLE },
3846
    { "DUAL_LINK_DVI_D", RHD_CONNECTOR_DVI },
3847
    { "VGA", RHD_CONNECTOR_VGA },
3848
    { "COMPOSITE", RHD_CONNECTOR_TV },
3849
    { "SVIDEO", RHD_CONNECTOR_TV, },
3850
    { "YPrPb", RHD_CONNECTOR_TV, },
3851
    { "D_CONNECTOR", RHD_CONNECTOR_NONE, },
3852
    { "9PIN_DIN", RHD_CONNECTOR_NONE },
3853
    { "SCART", RHD_CONNECTOR_TV },
3854
    { "HDMI_TYPE_A", RHD_CONNECTOR_DVI_SINGLE },
3855
    { "HDMI_TYPE_B", RHD_CONNECTOR_DVI },
3856
    { "LVDS", RHD_CONNECTOR_PANEL },
3857
    { "7PIN_DIN", RHD_CONNECTOR_TV },
3858
    { "PCIE_CONNECTOR", RHD_CONNECTOR_PCIE },
3859
    { "CROSSFIRE", RHD_CONNECTOR_NONE },
3860
    { "HARDCODE_DVI", RHD_CONNECTOR_NONE },
3861
    { "DISPLAYPORT", RHD_CONNECTOR_NONE}
3862
};
3863
static const int n_rhd_connector_objs = sizeof (rhd_connector_objs) / sizeof(struct _rhd_connector_objs);
3864
 
3865
static const struct _rhd_encoders
3866
{
3867
    char *name;
3868
    rhdOutputType ot[2];
3869
} rhd_encoders[] = {
3870
    { "NONE", {RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3871
    { "INTERNAL_LVDS", { RHD_OUTPUT_LVDS, RHD_OUTPUT_NONE }},
3872
    { "INTERNAL_TMDS1", { RHD_OUTPUT_TMDSA, RHD_OUTPUT_NONE }},
3873
    { "INTERNAL_TMDS2", { RHD_OUTPUT_TMDSB, RHD_OUTPUT_NONE }},
3874
    { "INTERNAL_DAC1", { RHD_OUTPUT_DACA, RHD_OUTPUT_NONE }},
3875
    { "INTERNAL_DAC2", { RHD_OUTPUT_DACB, RHD_OUTPUT_NONE }},
3876
    { "INTERNAL_SDVOA", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3877
    { "INTERNAL_SDVOB", { RHD_OUTPUT_NONE , RHD_OUTPUT_NONE }},
3878
    { "SI170B", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3879
    { "CH7303", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3880
    { "CH7301", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3881
    { "INTERNAL_DVO1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3882
    { "EXTERNAL_SDVOA", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3883
    { "EXTERNAL_SDVOB", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3884
    { "TITFP513", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3885
    { "INTERNAL_LVTM1", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_NONE }},
3886
    { "VT1623", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3887
    { "HDMI_SI1930", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3888
    { "HDMI_INTERNAL", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3889
    { "INTERNAL_KLDSCP_TMDS1", { RHD_OUTPUT_TMDSA, RHD_OUTPUT_NONE }},
3890
    { "INTERNAL_KLDSCP_DVO1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3891
    { "INTERNAL_KLDSCP_DAC1", { RHD_OUTPUT_DACA, RHD_OUTPUT_NONE }},
3892
    { "INTERNAL_KLDSCP_DAC2", { RHD_OUTPUT_DACB, RHD_OUTPUT_NONE }},
3893
    { "SI178", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3894
    { "MVPU_FPGA", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3895
    { "INTERNAL_DDI", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3896
    { "VT1625", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3897
    { "HDMI_SI1932", {RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3898
    { "AN9801", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3899
    { "DP501",  { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }},
3900
    { "UNIPHY",  { RHD_OUTPUT_UNIPHYA, RHD_OUTPUT_UNIPHYB }},
3901
    { "KLDSCP_LVTMA", { RHD_OUTPUT_KLDSKP_LVTMA, RHD_OUTPUT_NONE }},
3902
    { "UNIPHY1",  { RHD_OUTPUT_UNIPHYC, RHD_OUTPUT_UNIPHYD }},
3903
    { "UNIPHY2",  { RHD_OUTPUT_UNIPHYE, RHD_OUTPUT_UNIPHYF }}
3904
};
3905
static const int n_rhd_encoders = sizeof (rhd_encoders) / sizeof(struct _rhd_encoders);
3906
 
3907
static const struct _rhd_connectors
3908
{
3909
    char *name;
3910
    rhdConnectorType con;
3911
    Bool dual;
3912
} rhd_connectors[] = {
3913
    {"NONE", RHD_CONNECTOR_NONE, FALSE },
3914
    {"VGA", RHD_CONNECTOR_VGA, FALSE },
3915
    {"DVI-I", RHD_CONNECTOR_DVI, TRUE },
3916
    {"DVI-D", RHD_CONNECTOR_DVI, FALSE },
3917
    {"DVI-A", RHD_CONNECTOR_DVI, FALSE },
3918
    {"SVIDEO", RHD_CONNECTOR_TV, FALSE },
3919
    {"COMPOSITE", RHD_CONNECTOR_TV, FALSE },
3920
    {"PANEL", RHD_CONNECTOR_PANEL, FALSE },
3921
    {"DIGITAL_LINK", RHD_CONNECTOR_NONE, FALSE },
3922
    {"SCART", RHD_CONNECTOR_TV, FALSE },
3923
    {"HDMI Type A", RHD_CONNECTOR_DVI_SINGLE, FALSE },
3924
    {"HDMI Type B", RHD_CONNECTOR_DVI, FALSE },
3925
    {"UNKNOWN", RHD_CONNECTOR_NONE, FALSE },
3926
    {"UNKNOWN", RHD_CONNECTOR_NONE, FALSE },
3927
    {"DVI+DIN", RHD_CONNECTOR_NONE, FALSE }
3928
};
3929
static const int n_rhd_connectors = sizeof(rhd_connectors) / sizeof(struct _rhd_connectors);
3930
 
3931
static const struct _rhd_devices
3932
{
3933
    char *name;
3934
    rhdOutputType ot[2];
3935
    enum atomDevice atomDevID;
3936
} rhd_devices[] = { /* { RHD_CHIP_EXTERNAL, RHD_CHIP_IGP } */
3937
    {" CRT1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomCRT1 },
3938
    {" LCD1", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_LVTMA }, atomLCD1 },
3939
    {" TV1",  { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomTV1 },
3940
    {" DFP1", { RHD_OUTPUT_TMDSA, RHD_OUTPUT_NONE }, atomDFP1 },
3941
    {" CRT2", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomCRT2 },
3942
    {" LCD2", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_NONE }, atomLCD2 },
3943
    {" TV2",  { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomTV2 },
3944
    {" DFP2", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_DVO }, atomDFP2 },
3945
    {" CV",   { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomCV },
3946
    {" DFP3", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_LVTMA }, atomDFP3 },
3947
    {" DFP4", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomDFP4 },
3948
    {" DFP5", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomDFP5 }
3949
};
3950
static const int n_rhd_devices = sizeof(rhd_devices) / sizeof(struct _rhd_devices);
3951
 
3952
static const rhdDDC hwddc[] = { RHD_DDC_0, RHD_DDC_1, RHD_DDC_2, RHD_DDC_3, RHD_DDC_4 };
3953
static const int n_hwddc = sizeof(hwddc) / sizeof(rhdDDC);
3954
 
3955
static const rhdOutputType acc_dac[] = { RHD_OUTPUT_NONE, RHD_OUTPUT_DACA,
3956
				  RHD_OUTPUT_DACB, RHD_OUTPUT_DAC_EXTERNAL };
3957
static const int n_acc_dac = sizeof(acc_dac) / sizeof (rhdOutputType);
3958
 
3959
/*
3960
 *
3961
 */
3962
static Bool
3963
rhdAtomInterpretObjectID(atomBiosHandlePtr handle,
3964
			 CARD16 id, CARD8 *obj_type, CARD8 *obj_id,
3965
			 CARD8 *num, char **name)
3966
{
3967
    *obj_id = (id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
3968
    *num = (id & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
3969
    *obj_type = (id & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
3970
 
3971
    *name = NULL;
3972
 
3973
    switch (*obj_type) {
3974
	case GRAPH_OBJECT_TYPE_CONNECTOR:
3975
	    if (!Limit(*obj_id, n_rhd_connector_objs, "connector_obj"))
3976
		*name = rhd_connector_objs[*obj_id].name;
3977
	    break;
3978
	case GRAPH_OBJECT_TYPE_ENCODER:
3979
	    if (!Limit(*obj_id, n_rhd_encoders, "encoder_obj"))
3980
		*name = rhd_encoders[*obj_id].name;
3981
	    break;
3982
	default:
3983
	    break;
3984
    }
3985
    return TRUE;
3986
}
3987
 
3988
/*
3989
 *
3990
 */
3991
static AtomBiosResult
3992
rhdAtomGetDDCIndex(atomBiosHandlePtr handle,
3993
		   rhdDDC *DDC, unsigned char i2c)
3994
{
3995
    atomDataTablesPtr atomDataPtr;
3996
    CARD8 crev, frev;
3997
    int i;
3998
 
3999
    RHDFUNC(handle);
4000
 
4001
    atomDataPtr = handle->atomDataPtr;
4002
 
4003
    if (!rhdAtomGetTableRevisionAndSize(
4004
	    &(atomDataPtr->GPIO_I2C_Info->sHeader), &crev,&frev,NULL)) {
4005
	return ATOM_NOT_IMPLEMENTED;
4006
    }
4007
    for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
4008
	if (atomDataPtr->GPIO_I2C_Info->asGPIO_Info[i].sucI2cId.ucAccess == i2c) {
4009
	    RHDDebug(handle->scrnIndex, " Found DDC GPIO Index: %i\n",i);
4010
	    if (Limit(i, n_hwddc, "GPIO_DDC Index"))
4011
		return ATOM_FAILED;
4012
	    *DDC = hwddc[i];
4013
	    return ATOM_SUCCESS;
4014
	}
4015
    }
4016
    return ATOM_FAILED;
4017
}
4018
 
4019
/*
4020
 *
4021
 */
4022
static void
4023
rhdAtomDDCFromI2CRecord(atomBiosHandlePtr handle,
4024
			ATOM_I2C_RECORD *Record, rhdDDC *DDC)
4025
{
4026
    RHDDebug(handle->scrnIndex,
4027
	     "   %s:  I2C Record: %s[%x] EngineID: %x I2CAddr: %x\n",
4028
                __func__,
4029
	     Record->sucI2cId.bfHW_Capable ? "HW_Line" : "GPIO_ID",
4030
	     Record->sucI2cId.bfI2C_LineMux,
4031
	     Record->sucI2cId.bfHW_EngineID,
4032
	     Record->ucI2CAddr);
4033
 
4034
  if (!*(unsigned char *)&(Record->sucI2cId))
4035
    *DDC = RHD_DDC_NONE;
4036
    else {
4037
	union {
4038
	    ATOM_I2C_ID_CONFIG i2cId;
4039
	    unsigned char i2cChar;
4040
	} u;
4041
    if (Record->ucI2CAddr != 0)
4042
        return;
4043
	    u.i2cId = Record->sucI2cId;
4044
	    if (!u.i2cChar
4045
		|| rhdAtomGetDDCIndex(handle, DDC, u.i2cChar) != ATOM_SUCCESS)
4046
		*DDC = RHD_DDC_NONE;
4047
  }
4048
}
4049
 
4050
/*
4051
 *
4052
 */
4053
static void
4054
rhdAtomParseGPIOLutForHPD(atomBiosHandlePtr handle,
4055
			  CARD8 pinID, rhdHPD *HPD)
4056
{
4057
    atomDataTablesPtr atomDataPtr;
4058
    ATOM_GPIO_PIN_LUT *gpio_pin_lut;
4059
    unsigned short size;
4060
    int i = 0;
4061
 
4062
    RHDFUNC(handle);
4063
 
4064
    atomDataPtr = handle->atomDataPtr;
4065
 
4066
    *HPD = RHD_HPD_NONE;
4067
 
4068
    if (!rhdAtomGetTableRevisionAndSize(
4069
	    &atomDataPtr->GPIO_Pin_LUT->sHeader, NULL, NULL, &size)) {
4070
	xf86DrvMsg(handle->scrnIndex, X_ERROR,
4071
		   "%s: No valid GPIO pin LUT in AtomBIOS\n",__func__);
4072
      return;
4073
    }
4074
    gpio_pin_lut = atomDataPtr->GPIO_Pin_LUT;
4075
 
4076
    while (1) {
4077
	if (gpio_pin_lut->asGPIO_Pin[i].ucGPIO_ID  == pinID) {
4078
 
4079
	    if ((sizeof(ATOM_COMMON_TABLE_HEADER)
4080
		  + (i * sizeof(ATOM_GPIO_PIN_ASSIGNMENT))) > size)
4081
		return;
4082
 
4083
	    RHDDebug(handle->scrnIndex,
4084
		     "   %s: GPIO PinID: %i Index: %x Shift: %i\n",
4085
		     __func__,
4086
		     pinID,
4087
		     gpio_pin_lut->asGPIO_Pin[i].usGpioPin_AIndex,
4088
		     gpio_pin_lut->asGPIO_Pin[i].ucGpioPinBitShift);
4089
 
4090
	    /* grr... map backwards: register indices -> line numbers */
4091
	    if (gpio_pin_lut->asGPIO_Pin[i].usGpioPin_AIndex
4092
		== (DC_GPIO_HPD_A >> 2)) {
4093
		switch (gpio_pin_lut->asGPIO_Pin[i].ucGpioPinBitShift) {
4094
		    case 0:
4095
			*HPD = RHD_HPD_0;
4096
			return;
4097
		    case 8:
4098
			*HPD = RHD_HPD_1;
4099
			return;
4100
		    case 16:
4101
			*HPD = RHD_HPD_2;
4102
			return;
4103
		    case 24:
4104
			*HPD = RHD_HPD_3;
4105
			return;
4106
		}
4107
	    }
4108
	}
4109
	i++;
4110
    }
4111
}
4112
 
4113
/*
4114
 *
4115
 */
4116
static void
4117
rhdAtomHPDFromRecord(atomBiosHandlePtr handle,
4118
		     ATOM_HPD_INT_RECORD *Record, rhdHPD *HPD)
4119
{
4120
    RHDDebug(handle->scrnIndex,
4121
	     "   %s:  HPD Record: GPIO ID: %x Plugged_PinState: %x\n",
4122
	     __func__,
4123
	     Record->ucHPDIntGPIOID,
4124
	     Record->ucPluggged_PinState);
4125
    rhdAtomParseGPIOLutForHPD(handle, Record->ucHPDIntGPIOID, HPD);
4126
}
4127
 
4128
/*
4129
 *
4130
 */
4131
static char *
4132
rhdAtomDeviceTagsFromRecord(atomBiosHandlePtr handle,
4133
			    ATOM_CONNECTOR_DEVICE_TAG_RECORD *Record)
4134
{
4135
    int i, j, k;
4136
    char *devices;
4137
 
4138
    RHDFUNC(handle);
4139
 
4140
    RHDDebug(handle->scrnIndex,"   NumberOfDevice: %i\n",
4141
	     Record->ucNumberOfDevice);
4142
 
4143
    if (!Record->ucNumberOfDevice) return NULL;
4144
 
4145
    devices = (char *)xcalloc(Record->ucNumberOfDevice * 4 + 1,1);
4146
 
4147
    for (i = 0; i < Record->ucNumberOfDevice; i++) {
4148
	k = 0;
4149
	j = Record->asDeviceTag[i].usDeviceID;
4150
 
4151
	if (!j) continue;
4152
 
4153
	while (!(j & 0x1)) { j >>= 1; k++; };
4154
 
4155
	if (!Limit(k,n_rhd_devices,"usDeviceID"))
4156
	    strcat(devices, rhd_devices[k].name);
4157
    }
4158
 
4159
    RHDDebug(handle->scrnIndex,"   Devices:%s\n",devices);
4160
 
4161
    return devices;
4162
}
4163
 
4164
/*
4165
 *
4166
 */
4167
static rhdConnectorType
4168
rhdAtomGetConnectorID(atomBiosHandlePtr handle, rhdConnectorType connector, int num)
4169
{
4170
    RHDFUNC(handle);
4171
 
4172
    switch (connector) {
4173
	case RHD_CONNECTOR_PCIE:
4174
	{
4175
	    atomDataTablesPtr atomDataPtr;
4176
	    CARD8 crev, frev;
4177
	    CARD32 val;
4178
 
4179
	    atomDataPtr = handle->atomDataPtr;
4180
 
4181
	    if (!rhdAtomGetTableRevisionAndSize(
4182
		    (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base),
4183
		    &crev,&frev,NULL) || crev != 2) {
4184
		    return RHD_CONNECTOR_NONE; 	    /* sorry, we can't do any better */
4185
	    }
4186
	    RHDDebug(handle->scrnIndex,"PCIE[%i]", num);
4187
	    switch (num) {
4188
		case 1:
4189
		    val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot1Config;
4190
		    break;
4191
		case 2:
4192
		    val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot2Config;
4193
		    break;
4194
		default:
4195
		    RHDDebugCont("\n");
4196
		    return RHD_CONNECTOR_NONE;
4197
	    }
4198
	    val >>= 16;
4199
	    val &= 0xff;
4200
	    RHDDebugCont(" ObjectID: %i",val);
4201
	    if (Limit((int)val, n_rhd_connector_objs, "obj_id")) {
4202
		RHDDebugCont("\n");
4203
		return RHD_CONNECTOR_NONE;
4204
	    }
4205
 
4206
	    RHDDebugCont(" ConnectorName: %s\n",rhd_connector_objs[val].name);
4207
	    return  rhd_connector_objs[val].con;
4208
	}
4209
	default:
4210
	    return connector;
4211
    }
4212
}
4213
 
4214
/*
4215
 *
4216
 */
4217
static AtomBiosResult
4218
rhdAtomOutputDeviceListFromObjectHeader(atomBiosHandlePtr handle,
4219
				  struct rhdAtomOutputDeviceList **ptr)
4220
{
4221
    atomDataTablesPtr atomDataPtr;
4222
    CARD8 crev, frev;
4223
    ATOM_DISPLAY_OBJECT_PATH_TABLE *disObjPathTable;
4224
    ATOM_DISPLAY_OBJECT_PATH *disObjPath;
4225
    rhdConnectorInfoPtr cp;
4226
    unsigned long object_header_end;
4227
    unsigned int i,j;
4228
    unsigned short object_header_size;
4229
    struct rhdAtomOutputDeviceList *DeviceList = NULL;
4230
    int cnt = 0;
4231
 
4232
    RHDFUNC(handle);
4233
 
4234
    atomDataPtr = handle->atomDataPtr;
4235
 
4236
    if (!rhdAtomGetTableRevisionAndSize(
4237
	    &atomDataPtr->Object_Header->sHeader,
4238
	    &crev,&frev,&object_header_size)) {
4239
	return ATOM_NOT_IMPLEMENTED;
4240
    }
4241
 
4242
    if (crev < 2) /* don't bother with anything below rev 2 */
4243
	return ATOM_NOT_IMPLEMENTED;
4244
 
4245
    if (!(cp = (rhdConnectorInfoPtr)xcalloc(sizeof(struct rhdConnectorInfo),
4246
					 RHD_CONNECTORS_MAX)))
4247
	return ATOM_FAILED;
4248
 
4249
    object_header_end =
4250
	atomDataPtr->Object_Header->usConnectorObjectTableOffset
4251
	+ object_header_size;
4252
 
4253
    RHDDebug(handle->scrnIndex,"ObjectTable - size: %u, BIOS - size: %u "
4254
	     "TableOffset: %u object_header_end: %u\n",
4255
	     object_header_size, handle->BIOSImageSize,
4256
	     atomDataPtr->Object_Header->usConnectorObjectTableOffset,
4257
	     object_header_end);
4258
 
4259
    if ((object_header_size > handle->BIOSImageSize)
4260
	|| (atomDataPtr->Object_Header->usConnectorObjectTableOffset
4261
	    > handle->BIOSImageSize)
4262
	|| object_header_end > handle->BIOSImageSize) {
4263
	xf86DrvMsg(handle->scrnIndex, X_ERROR,
4264
		   "%s: Object table information is bogus\n",__func__);
4265
	return ATOM_FAILED;
4266
    }
4267
 
4268
    if (((unsigned long)&atomDataPtr->Object_Header->sHeader
4269
	 + object_header_end) >  ((unsigned long)handle->BIOSBase
4270
		     + handle->BIOSImageSize)) {
4271
	xf86DrvMsg(handle->scrnIndex, X_ERROR,
4272
		   "%s: Object table extends beyond BIOS Image\n",__func__);
4273
	return ATOM_FAILED;
4274
    }
4275
    disObjPathTable = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
4276
	((char *)&atomDataPtr->Object_Header->sHeader +
4277
	 atomDataPtr->Object_Header->usDisplayPathTableOffset);
4278
    RHDDebug(handle->scrnIndex, "DisplayPathObjectTable: entries: %i version: %i\n",
4279
	     disObjPathTable->ucNumOfDispPath, disObjPathTable->ucVersion);
4280
 
4281
    disObjPath = &disObjPathTable->asDispPath[0];
4282
    for (i = 0; i < disObjPathTable->ucNumOfDispPath; i++) {
4283
	CARD8 objNum, cObjNum;
4284
	CARD8 objId;
4285
	CARD8 objType;
4286
	rhdConnectorType ct;
4287
	char *name;
4288
 
4289
	rhdAtomInterpretObjectID(handle, disObjPath->usConnObjectId, &objType, &objId, &objNum, &name);
4290
	RHDDebug(handle->scrnIndex, "  DisplaPathTable[%i]: size: %i DeviceTag: 0x%x ConnObjId: 0x%x NAME: %s GPUObjId: 0x%x\n",
4291
		 i, disObjPath->usSize, disObjPath->usDeviceTag, disObjPath->usConnObjectId, name, disObjPath->usGPUObjectId);
4292
 
4293
	if (objType != GRAPH_OBJECT_TYPE_CONNECTOR)
4294
	    continue;
4295
 
4296
	ct = rhd_connector_objs[objId].con;
4297
	cObjNum = objNum;
4298
 
4299
	for (j = 0; j < disObjPath->usSize / sizeof(USHORT) - 4; j++) {
4300
	    int k = 0,l;
4301
 
4302
	    rhdAtomInterpretObjectID(handle, disObjPath->usGraphicObjIds[j], &objType, &objId, &objNum, &name);
4303
	    RHDDebug(handle->scrnIndex, "   GraphicsObj[%i] ID: 0x%x Type: 0x%x ObjID: 0x%x ENUM: 0x%x NAME: %s\n",
4304
		     j, disObjPath->usGraphicObjIds[j], objType, objId, objNum, name);
4305
 
4306
	    if (objType != GRAPH_OBJECT_TYPE_ENCODER)
4307
		continue;
4308
 
4309
	    Limit(objId, n_rhd_encoders, "usGraphicsObjId");
4310
 
4311
	    l = disObjPath->usDeviceTag;
4312
	    if (!l) continue;
4313
 
4314
	    while (!(l & 0x1)) { l >>= 1; k++; };
4315
	    if (!Limit(k,n_rhd_devices,"usDeviceID")) {
4316
		if (!(DeviceList = (struct rhdAtomOutputDeviceList *)xrealloc(DeviceList, sizeof (struct rhdAtomOutputDeviceList) * (cnt + 1))))
4317
		    return ATOM_FAILED;
4318
 
4319
		DeviceList[cnt].DeviceId = rhd_devices[k].atomDevID;
4320
		DeviceList[cnt].ConnectorType = rhdAtomGetConnectorID(handle, ct, cObjNum);
4321
		DeviceList[cnt].OutputType = rhd_encoders[objId].ot[objNum - 1];
4322
		cnt++;
4323
		RHDDebug(handle->scrnIndex, "   DeviceIndex: 0x%x\n",k);
4324
	    }
4325
	}
4326
	disObjPath = (ATOM_DISPLAY_OBJECT_PATH*)(((char *)disObjPath) + disObjPath->usSize);
4327
	if ((((unsigned long)&atomDataPtr->Object_Header->sHeader + object_header_end)
4328
	     < (((unsigned long) disObjPath) + sizeof(ATOM_DISPLAY_OBJECT_PATH)))
4329
	    || (((unsigned long)&atomDataPtr->Object_Header->sHeader + object_header_end)
4330
		< (((unsigned long) disObjPath) + disObjPath->usSize)))
4331
	    break;
4332
    }
4333
    DeviceList = xrealloc(DeviceList, sizeof(struct rhdAtomOutputDeviceList) * (cnt + 1));
4334
    DeviceList[cnt].DeviceId = atomNone;
4335
 
4336
    *ptr = DeviceList;
4337
 
4338
    return ATOM_SUCCESS;
4339
}
4340
 
4341
/*
4342
 *
4343
 */
4344
static AtomBiosResult
4345
rhdAtomConnectorInfoFromObjectHeader(atomBiosHandlePtr handle,
4346
				     rhdConnectorInfoPtr *ptr)
4347
{
4348
    atomDataTablesPtr atomDataPtr;
4349
    CARD8 crev, frev;
4350
    ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
4351
    rhdConnectorInfoPtr cp;
4352
    unsigned long object_header_end;
4353
    int ncon = 0;
4354
    int i,j;
4355
    unsigned short object_header_size;
4356
 
4357
    RHDFUNC(handle);
4358
 
4359
    atomDataPtr = handle->atomDataPtr;
4360
 
4361
    if (!rhdAtomGetTableRevisionAndSize(
4362
	    &atomDataPtr->Object_Header->sHeader,
4363
	    &crev,&frev,&object_header_size)) {
4364
	return ATOM_NOT_IMPLEMENTED;
4365
    }
4366
 
4367
    if (crev < 2) /* don't bother with anything below rev 2 */
4368
	return ATOM_NOT_IMPLEMENTED;
4369
 
4370
    if (!(cp = (rhdConnectorInfoPtr)xcalloc(sizeof(struct rhdConnectorInfo),
4371
					 RHD_CONNECTORS_MAX)))
4372
    return ATOM_FAILED;
4373
 
4374
    object_header_end =
4375
	atomDataPtr->Object_Header->usConnectorObjectTableOffset
4376
	+ object_header_size;
4377
 
4378
    RHDDebug(handle->scrnIndex,"ObjectTable - size: %u, BIOS - size: %u "
4379
	     "TableOffset: %u object_header_end: %u\n",
4380
	     object_header_size, handle->BIOSImageSize,
4381
	     atomDataPtr->Object_Header->usConnectorObjectTableOffset,
4382
	     object_header_end);
4383
 
4384
    if ((object_header_size > handle->BIOSImageSize)
4385
	|| (atomDataPtr->Object_Header->usConnectorObjectTableOffset
4386
	    > handle->BIOSImageSize)
4387
	|| object_header_end > handle->BIOSImageSize) {
4388
	xfree(cp);
4389
	xf86DrvMsg(handle->scrnIndex, X_ERROR,
4390
		   "%s: Object table information is bogus\n",__func__);
4391
   return ATOM_FAILED;
4392
    }
4393
 
4394
    if (((unsigned long)&atomDataPtr->Object_Header->sHeader
4395
	 + object_header_end) >  ((unsigned long)handle->BIOSBase
4396
		     + handle->BIOSImageSize)) {
4397
	xfree(cp);
4398
	xf86DrvMsg(handle->scrnIndex, X_ERROR,
4399
		   "%s: Object table extends beyond BIOS Image\n",__func__);
4400
    return ATOM_FAILED;
4401
    }
4402
 
4403
    con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
4404
	((char *)&atomDataPtr->Object_Header->sHeader +
4405
	 atomDataPtr->Object_Header->usConnectorObjectTableOffset);
4406
 
4407
    for (i = 0; i < con_obj->ucNumberOfObjects; i++) {
4408
      ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *SrcDstTable;
4409
      ATOM_COMMON_RECORD_HEADER *Record;
4410
      int record_base;
4411
      CARD8 obj_type, obj_id, num;
4412
      char *name;
4413
 
4414
      rhdAtomInterpretObjectID(handle, con_obj->asObjects[i].usObjectID,
4415
                               &obj_type, &obj_id, &num, &name);
4416
 
4417
	RHDDebug(handle->scrnIndex, "Object: ID: %x name: %s type: %x id: %x\n",
4418
                 con_obj->asObjects[i].usObjectID, name ? name : "",
4419
		 obj_type, obj_id);
4420
 
4421
 
4422
     if (obj_type != GRAPH_OBJECT_TYPE_CONNECTOR)
4423
       continue;
4424
 
4425
     SrcDstTable = (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
4426
                   ((char *)&atomDataPtr->Object_Header->sHeader
4427
                    + con_obj->asObjects[i].usSrcDstTableOffset);
4428
 
4429
     if (con_obj->asObjects[i].usSrcDstTableOffset
4430
         + (SrcDstTable->ucNumberOfSrc
4431
	       * sizeof(ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT))
4432
	    > handle->BIOSImageSize) {
4433
	    xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: SrcDstTable[%i] extends "
4434
		       "beyond Object_Header table\n",__func__,i);
4435
       continue;
4436
     }
4437
	cp[ncon].Type = rhdAtomGetConnectorID(handle, rhd_connector_objs[obj_id].con, num);
4438
     cp[ncon].Name = RhdAppendString(cp[ncon].Name,name);
4439
 
4440
	for (j = 0; ((j < SrcDstTable->ucNumberOfSrc) &&
4441
		     (j < MAX_OUTPUTS_PER_CONNECTOR)); j++) {
4442
       CARD8 stype, sobj_id, snum;
4443
       char *sname;
4444
 
4445
       rhdAtomInterpretObjectID(handle, SrcDstTable->usSrcObjectID[j],
4446
              &stype, &sobj_id, &snum, &sname);
4447
 
4448
	    RHDDebug(handle->scrnIndex, " * SrcObject: ID: %x name: %s enum: %i\n",
4449
		     SrcDstTable->usSrcObjectID[j], sname, snum);
4450
 
4451
	    if (snum <= 2)
4452
		cp[ncon].Output[j] = rhd_encoders[sobj_id].ot[snum - 1];
4453
     }
4454
 
4455
	Record = (ATOM_COMMON_RECORD_HEADER *)
4456
	    ((char *)&atomDataPtr->Object_Header->sHeader
4457
	     + con_obj->asObjects[i].usRecordOffset);
4458
 
4459
	record_base = con_obj->asObjects[i].usRecordOffset;
4460
 
4461
	while (Record->ucRecordType > 0
4462
	       && Record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER ) {
4463
	    char *taglist;
4464
 
4465
	    if ((record_base += Record->ucRecordSize)
4466
		> object_header_size) {
4467
		xf86DrvMsg(handle->scrnIndex, X_ERROR,
4468
			   "%s: Object Records extend beyond Object Table\n",
4469
			   __func__);
4470
		break;
4471
	    }
4472
 
4473
	    RHDDebug(handle->scrnIndex, " - Record Type: %x\n",
4474
		     Record->ucRecordType);
4475
 
4476
	    switch (Record->ucRecordType) {
4477
 
4478
		case ATOM_I2C_RECORD_TYPE:
4479
		    rhdAtomDDCFromI2CRecord(handle,
4480
					    (ATOM_I2C_RECORD *)Record,
4481
					    &cp[ncon].DDC);
4482
		    break;
4483
 
4484
		case ATOM_HPD_INT_RECORD_TYPE:
4485
		    rhdAtomHPDFromRecord(handle,
4486
					 (ATOM_HPD_INT_RECORD *)Record,
4487
					 &cp[ncon].HPD);
4488
		    break;
4489
 
4490
		case ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE:
4491
		    taglist = rhdAtomDeviceTagsFromRecord(handle,
4492
							  (ATOM_CONNECTOR_DEVICE_TAG_RECORD *)Record);
4493
		    if (taglist) {
4494
			cp[ncon].Name = RhdAppendString(cp[ncon].Name,taglist);
4495
			xfree(taglist);
4496
		    }
4497
		    break;
4498
 
4499
		default:
4500
		    break;
4501
	    }
4502
 
4503
	    Record = (ATOM_COMMON_RECORD_HEADER*)
4504
		((char *)Record + Record->ucRecordSize);
4505
 
4506
	}
4507
 
4508
	if ((++ncon) == RHD_CONNECTORS_MAX)
4509
	    break;
4510
    }
4511
    *ptr = cp;
4512
 
4513
    RhdPrintConnectorInfo(handle->rhdPtr, cp);
4514
 
4515
    return ATOM_SUCCESS;
4516
}
4517
 
4518
/*
4519
 *
4520
 */
4521
static AtomBiosResult
4522
rhdAtomOutputDeviceListFromSupportedDevices(atomBiosHandlePtr handle,
4523
					     Bool igp,
4524
					     struct rhdAtomOutputDeviceList **Ptr)
4525
{
4526
    atomDataTablesPtr atomDataPtr;
4527
    CARD8 crev, frev;
4528
    int n;
4529
    int cnt = 0;
4530
    struct rhdAtomOutputDeviceList *DeviceList = NULL;
4531
    struct rhdConnectorInfo *cp;
4532
 
4533
    RHDFUNC(handle);
4534
 
4535
    atomDataPtr = handle->atomDataPtr;
4536
 
4537
    if (!rhdAtomGetTableRevisionAndSize(
4538
	    &(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader),
4539
	    &crev,&frev,NULL)) {
4540
	return ATOM_NOT_IMPLEMENTED;
4541
    }
4542
 
4543
    if (!(cp = (rhdConnectorInfoPtr)xcalloc(RHD_CONNECTORS_MAX,
4544
					 sizeof(struct rhdConnectorInfo))))
4545
	return ATOM_FAILED;
4546
 
4547
    for (n = 0; n < ATOM_MAX_SUPPORTED_DEVICE; n++) {
4548
	ATOM_CONNECTOR_INFO_I2C ci
4549
	    = atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[n];
4550
 
4551
	if (!(atomDataPtr->SupportedDevicesInfo
4552
	      .SupportedDevicesInfo->usDeviceSupport & (1 << n)))
4553
	    continue;
4554
 
4555
	if (Limit(ci.sucConnectorInfo.sbfAccess.bfConnectorType,
4556
		  n_rhd_connectors, "bfConnectorType"))
4557
	    continue;
4558
 
4559
	if (!(DeviceList = (struct rhdAtomOutputDeviceList *)xrealloc(DeviceList, sizeof(struct rhdAtomOutputDeviceList) * (cnt + 1))))
4560
	    return ATOM_FAILED;
4561
 
4562
	DeviceList[cnt].ConnectorType = rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].con;
4563
	DeviceList[cnt].DeviceId = rhd_devices[n].atomDevID;
4564
 
4565
	if (!Limit(ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC,
4566
		   n_acc_dac, "bfAssociatedDAC")) {
4567
	    if ((DeviceList[cnt].OutputType
4568
		 = acc_dac[ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC])
4569
		== RHD_OUTPUT_NONE) {
4570
		DeviceList[cnt].OutputType = rhd_devices[n].ot[igp ? 1 : 0];
4571
	    }
4572
	    cnt++;
4573
	}
4574
    }
4575
    DeviceList = (struct rhdAtomOutputDeviceList *)xrealloc(DeviceList, sizeof(struct rhdAtomOutputDeviceList) * (cnt + 1));
4576
    DeviceList[cnt].DeviceId = atomNone;
4577
 
4578
    *Ptr = DeviceList;
4579
 
4580
    return ATOM_SUCCESS;
4581
}
4582
 
4583
/*
4584
 *
4585
 */
4586
static AtomBiosResult
4587
rhdAtomConnectorInfoFromSupportedDevices(atomBiosHandlePtr handle,
4588
					 Bool igp,
4589
					 rhdConnectorInfoPtr *ptr)
4590
{
4591
  atomDataTablesPtr atomDataPtr;
4592
  CARD8 crev, frev;
4593
  rhdConnectorInfoPtr cp;
4594
    struct {
4595
    rhdOutputType ot;
4596
    rhdConnectorType con;
4597
    rhdDDC ddc;
4598
    rhdHPD hpd;
4599
    Bool dual;
4600
    char *name;
4601
    char *outputName;
4602
  } devices[ATOM_MAX_SUPPORTED_DEVICE];
4603
  int ncon = 0;
4604
  int n;
4605
 
4606
  RHDFUNC(handle);
4607
 
4608
  atomDataPtr = handle->atomDataPtr;
4609
 
4610
  if (!rhdAtomGetTableRevisionAndSize(
4611
	    &(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader),
4612
	    &crev,&frev,NULL)) {
4613
	return ATOM_NOT_IMPLEMENTED;
4614
    }
4615
 
4616
    if (!(cp = (rhdConnectorInfoPtr)xcalloc(RHD_CONNECTORS_MAX,
4617
           sizeof(struct rhdConnectorInfo))))
4618
      return ATOM_FAILED;
4619
 
4620
    for (n = 0; n < ATOM_MAX_SUPPORTED_DEVICE; n++) {
4621
    ATOM_CONNECTOR_INFO_I2C ci
4622
	    = atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[n];
4623
 
4624
	devices[n].ot = RHD_OUTPUT_NONE;
4625
 
4626
	if (!(atomDataPtr->SupportedDevicesInfo
4627
	      .SupportedDevicesInfo->usDeviceSupport & (1 << n)))
4628
	    continue;
4629
 
4630
	if (Limit(ci.sucConnectorInfo.sbfAccess.bfConnectorType,
4631
		  n_rhd_connectors, "bfConnectorType"))
4632
	    continue;
4633
 
4634
	devices[n].con
4635
	    = rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].con;
4636
	if (devices[n].con == RHD_CONNECTOR_NONE)
4637
	    continue;
4638
 
4639
	devices[n].dual
4640
	    = rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].dual;
4641
	devices[n].name
4642
	    = rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].name;
4643
 
4644
	RHDDebug(handle->scrnIndex,"AtomBIOS Connector[%i]: %s Device:%s ",n,
4645
		 rhd_connectors[ci.sucConnectorInfo
4646
				.sbfAccess.bfConnectorType].name,
4647
		 rhd_devices[n].name);
4648
 
4649
	devices[n].outputName = rhd_devices[n].name;
4650
 
4651
	if (!Limit(ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC,
4652
		   n_acc_dac, "bfAssociatedDAC")) {
4653
	    if ((devices[n].ot
4654
		 = acc_dac[ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC])
4655
		== RHD_OUTPUT_NONE) {
4656
		devices[n].ot = rhd_devices[n].ot[igp ? 1 : 0];
4657
	    }
4658
	} else
4659
	    devices[n].ot = RHD_OUTPUT_NONE;
4660
 
4661
	RHDDebugCont("Output: %x ",devices[n].ot);
4662
 
4663
	if (!ci.sucI2cId.ucAccess
4664
	    || rhdAtomGetDDCIndex(handle, &devices[n].ddc, ci.sucI2cId.ucAccess) != ATOM_SUCCESS) {
4665
	    RHDDebugCont("NO DDC ");
4666
		devices[n].ddc = RHD_DDC_NONE;
4667
	} else
4668
	    RHDDebugCont("HW DDC %i ",
4669
			 ci.sucI2cId.sbfAccess.bfI2C_LineMux);
4670
 
4671
	if (crev > 1) {
4672
	    ATOM_CONNECTOR_INC_SRC_BITMAP isb
4673
		= atomDataPtr->SupportedDevicesInfo
4674
		.SupportedDevicesInfo_HD->asIntSrcInfo[n];
4675
 
4676
	    switch (isb.ucIntSrcBitmap) {
4677
		case 0x4:
4678
		    RHDDebugCont("HPD 0\n");
4679
		    devices[n].hpd = RHD_HPD_0;
4680
		    break;
4681
		case 0xa:
4682
		    RHDDebugCont("HPD 1\n");
4683
		    devices[n].hpd = RHD_HPD_1;
4684
		    break;
4685
		default:
4686
		    RHDDebugCont("NO HPD\n");
4687
		    devices[n].hpd = RHD_HPD_NONE;
4688
		    break;
4689
	    }
4690
	} else {
4691
	    RHDDebugCont("NO HPD\n");
4692
	    devices[n].hpd = RHD_HPD_NONE;
4693
	}
4694
    }
4695
    /* sort devices for connectors */
4696
    for (n = 0; n < ATOM_MAX_SUPPORTED_DEVICE; n++) {
4697
	int i;
4698
 
4699
	if (devices[n].ot == RHD_OUTPUT_NONE)
4700
	    continue;
4701
	if (devices[n].con == RHD_CONNECTOR_NONE)
4702
	    continue;
4703
 
4704
	cp[ncon].DDC = devices[n].ddc;
4705
	cp[ncon].HPD = devices[n].hpd;
4706
	cp[ncon].Output[0] = devices[n].ot;
4707
	cp[ncon].Output[1] = RHD_OUTPUT_NONE;
4708
	cp[ncon].Type = devices[n].con;
4709
	cp[ncon].Name = strdup(devices[n].name);
4710
	cp[ncon].Name = RhdAppendString(cp[ncon].Name, devices[n].outputName);
4711
 
4712
	if (devices[n].dual) {
4713
    if (devices[n].ddc == RHD_DDC_NONE)
4714
		xf86DrvMsg(handle->scrnIndex, X_ERROR,
4715
			   "No DDC channel for device %s found."
4716
			   " Cannot find matching device.\n",devices[n].name);
4717
	    else {
4718
		for (i = n + 1; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
4719
 
4720
		    if (!devices[i].dual)
4721
          continue;
4722
 
4723
		    if (devices[n].ddc != devices[i].ddc)
4724
          continue;
4725
 
4726
		    if (((devices[n].ot == RHD_OUTPUT_DACA
4727
           || devices[n].ot == RHD_OUTPUT_DACB)
4728
           && (devices[i].ot == RHD_OUTPUT_LVTMA
4729
			     || devices[i].ot == RHD_OUTPUT_TMDSA))
4730
           || ((devices[i].ot == RHD_OUTPUT_DACA
4731
			     || devices[i].ot == RHD_OUTPUT_DACB)
4732
           && (devices[n].ot == RHD_OUTPUT_LVTMA
4733
				|| devices[n].ot == RHD_OUTPUT_TMDSA))) {
4734
 
4735
          cp[ncon].Output[1] = devices[i].ot;
4736
 
4737
          if (cp[ncon].HPD == RHD_HPD_NONE)
4738
            cp[ncon].HPD = devices[i].hpd;
4739
 
4740
          cp[ncon].Name = RhdAppendString(cp[ncon].Name,
4741
                          devices[i].outputName);
4742
          devices[i].ot = RHD_OUTPUT_NONE; /* zero the device */
4743
		    }
4744
      }
4745
    }
4746
	}
4747
	/* Some connector table mark a VGA as DVI-X. This heuristic fixes it */
4748
	if (cp[ncon].Type == RHD_CONNECTOR_DVI) {
4749
	    if ( ((cp[ncon].Output[0] == RHD_OUTPUT_NONE
4750
		  && (cp[ncon].Output[1] == RHD_OUTPUT_DACA
4751
		      || cp[ncon].Output[1] == RHD_OUTPUT_DACB))
4752
		 || (cp[ncon].Output[1] == RHD_OUTPUT_NONE
4753
		     && (cp[ncon].Output[0] == RHD_OUTPUT_DACA
4754
			 || cp[ncon].Output[0] == RHD_OUTPUT_DACB)))
4755
		 && cp[ncon].HPD == RHD_HPD_NONE)
4756
		cp[ncon].Type = RHD_CONNECTOR_VGA;
4757
	}
4758
 
4759
	if ((++ncon) == RHD_CONNECTORS_MAX)
4760
	    break;
4761
    }
4762
    *ptr = cp;
4763
 
4764
  RhdPrintConnectorInfo(handle->rhdPtr, cp);
4765
 
4766
  return ATOM_SUCCESS;
4767
}
4768
 
4769
/*
4770
 *
4771
 */
4772
static AtomBiosResult
4773
rhdAtomConnectorInfo(atomBiosHandlePtr handle,
4774
		     AtomBiosRequestID unused, AtomBiosArgPtr data)
4775
{
4776
    int chipset = data->chipset;
4777
 
4778
    RHDFUNC(handle);
4779
 
4780
    if (rhdAtomConnectorInfoFromObjectHeader(handle,&data->ConnectorInfo)
4781
	== ATOM_SUCCESS)
4782
	return ATOM_SUCCESS;
4783
    else {
4784
	Bool igp = RHDIsIGP(chipset);
4785
	return rhdAtomConnectorInfoFromSupportedDevices(handle, igp,
4786
							&data->ConnectorInfo);
4787
    }
4788
}
4789
 
4790
/*
4791
 *
4792
 */
4793
static AtomBiosResult
4794
rhdAtomOutputDeviceList(atomBiosHandlePtr handle,
4795
		     AtomBiosRequestID unused, AtomBiosArgPtr data)
4796
{
4797
    int chipset = data->chipset;
4798
 
4799
    RHDFUNC(handle);
4800
 
4801
    if (rhdAtomOutputDeviceListFromObjectHeader(handle, &data->OutputDeviceList)
4802
	== ATOM_SUCCESS) {
4803
	return ATOM_SUCCESS;
4804
    } else {
4805
	    Bool igp = RHDIsIGP(chipset);
4806
	    return rhdAtomOutputDeviceListFromSupportedDevices(handle, igp, &data->OutputDeviceList);
4807
    }
4808
}
4809
 
4810
/*
4811
 *
4812
 */
4813
struct atomCodeDataTableHeader
4814
{
4815
    unsigned char signature;
4816
    unsigned short size;
4817
};
4818
 
4819
#define CODE_DATA_TABLE_SIGNATURE 0x7a
4820
#define ATOM_EOT_COMMAND 0x5b
4821
 
4822
static AtomBiosResult
4823
rhdAtomGetDataInCodeTable(atomBiosHandlePtr handle,
4824
			   AtomBiosRequestID unused, AtomBiosArgPtr data)
4825
{
4826
    unsigned char *command_table;
4827
    unsigned short size;
4828
    unsigned short offset;
4829
 
4830
    int i;
4831
 
4832
    RHDFUNC(handle);
4833
 
4834
    if (data->val > sizeof (struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES) / sizeof (USHORT))
4835
	return ATOM_FAILED;
4836
 
4837
    if ((offset = ((USHORT *)&(((ATOM_MASTER_COMMAND_TABLE *)handle->codeTable)
4838
			       ->ListOfCommandTables))[data->val]))
4839
	command_table = handle->BIOSBase + offset;
4840
    else
4841
	return ATOM_FAILED;
4842
 
4843
    if (!rhdAtomGetTableRevisionAndSize(&(((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)
4844
					     command_table)->CommonHeader),
4845
					NULL, NULL, &size))
4846
	return ATOM_FAILED;
4847
 
4848
    for (i = sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER); i < size - 1; i++) {
4849
 
4850
	if (command_table[i] == ATOM_EOT_COMMAND
4851
	    && command_table[i+1] == CODE_DATA_TABLE_SIGNATURE) {
4852
	    unsigned short *dt_size = (unsigned short*)(command_table + i + 2);
4853
 
4854
	    int diff;
4855
 
4856
	    diff = size - (i + 1) + sizeof(struct atomCodeDataTableHeader) + *dt_size;
4857
 
4858
      DBG(dbgprintf("Table[0x%2.2x] = 0x%4.4x -> data_size: 0x%x\n",data->val, size, *dt_size));
4859
 
4860
	    if (diff < 0) {
4861
		xf86DrvMsg(handle->scrnIndex, X_ERROR,
4862
			   "Data table in command table %li extends %i bytes "
4863
			   "beyond command table size\n",
4864
			   (unsigned long) data->val, -diff);
4865
 
4866
		return  ATOM_FAILED;
4867
	    }
4868
	    data->CommandDataTable.loc =
4869
		command_table + i + 2 + sizeof(unsigned short);
4870
 
4871
	    data->CommandDataTable.size = *dt_size;
4872
//      DEBUGP(RhdDebugDump(handle->scrnIndex, data->CommandDataTable.loc, *dt_size));
4873
 
4874
	    return ATOM_SUCCESS;
4875
	}
4876
    }
4877
 
4878
    return ATOM_FAILED;
4879
}
4880
 
4881
# ifdef ATOM_BIOS_PARSER
4882
static AtomBiosResult
4883
rhdAtomExec (atomBiosHandlePtr handle,
4884
	     AtomBiosRequestID unused, AtomBiosArgPtr data)
4885
{
4886
  RHDPtr rhdPtr = handle->rhdPtr;
4887
  Bool ret = FALSE;
4888
  char *msg;
4889
  int idx = data->exec.index;
4890
  void *pspace = data->exec.pspace;
4891
  pointer *dataSpace = data->exec.dataSpace;
4892
 
4893
    RHDFUNCI(handle->scrnIndex);
4894
 
4895
    if (dataSpace) {
4896
    if (!handle->fbBase && !handle->scratchBase)
4897
	    return ATOM_FAILED;
4898
	if (handle->fbBase) {
4899
	    if (!rhdPtr->FbBase) {
4900
		xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: "
4901
			   "Cannot exec AtomBIOS: framebuffer not mapped\n",
4902
			   __func__);
4903
		return ATOM_FAILED;
4904
	    }
4905
	    *dataSpace = (CARD8*)rhdPtr->FbBase + handle->fbBase;
4906
	} else
4907
	    *dataSpace = (CARD8*)handle->scratchBase;
4908
    }
4909
    ret = ParseTableWrapper(pspace, idx, handle,
4910
			    handle->BIOSBase,
4911
			    &msg);
4912
  if (!ret)
4913
	xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s\n",msg);
4914
  else
4915
	xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 5, "%s\n",msg);
4916
 
4917
  return (ret) ? ATOM_SUCCESS : ATOM_FAILED;
4918
}
4919
# endif
4920
 
4921
AtomBiosResult
4922
RHDAtomBiosFunc(RHDPtr rhdPtr, atomBiosHandlePtr handle,
4923
		AtomBiosRequestID id, AtomBiosArgPtr data)
4924
{
4925
  AtomBiosResult ret = ATOM_FAILED;
4926
  int scrnIndex = rhdPtr->scrnIndex;
4927
  int i;
4928
  char *msg = NULL;
4929
  enum msgDataFormat msg_f = MSG_FORMAT_NONE;
4930
  AtomBiosRequestFunc req_func = NULL;
4931
 
4932
    RHDFUNCI(scrnIndex);
4933
 
4934
    for (i = 0; AtomBiosRequestList[i].id != FUNC_END; i++) {
4935
	if (id ==  AtomBiosRequestList[i].id) {
4936
	    req_func = AtomBiosRequestList[i].request;
4937
	    msg = AtomBiosRequestList[i].message;
4938
	    msg_f = AtomBiosRequestList[i].message_format;
4939
	    break;
4940
    }
4941
  }
4942
 
4943
    if (req_func == NULL) {
4944
	xf86DrvMsg(scrnIndex, X_ERROR, "Unknown AtomBIOS request: %i\n",id);
4945
    return ATOM_NOT_IMPLEMENTED;
4946
  }
4947
    /* Hack for now */
4948
  if (id == ATOMBIOS_INIT)
4949
    data->val = (CARD32)rhdPtr;
4950
 
4951
  if (id == ATOMBIOS_INIT || handle)
4952
    ret = req_func(handle, id, data);
4953
 
4954
    if (ret == ATOM_SUCCESS) {
4955
 
4956
	switch (msg_f) {
4957
	    case MSG_FORMAT_DEC:
4958
		xf86DrvMsg(scrnIndex,X_INFO,"%s: %li\n", msg,
4959
			   (unsigned long) data->val);
4960
        break;
4961
	    case MSG_FORMAT_HEX:
4962
		xf86DrvMsg(scrnIndex,X_INFO,"%s: 0x%lx\n",msg ,
4963
			   (unsigned long) data->val);
4964
        break;
4965
	    case MSG_FORMAT_NONE:
4966
		xf86DrvMsgVerb(scrnIndex, 7, X_INFO,
4967
			       "Call to %s succeeded\n", msg);
4968
        break;
4969
    }
4970
 
4971
    } else {
4972
 
4973
	char *result = (ret == ATOM_FAILED) ? "failed"
4974
          : "not implemented";
4975
	switch (msg_f) {
4976
	    case MSG_FORMAT_DEC:
4977
	    case MSG_FORMAT_HEX:
4978
		xf86DrvMsgVerb(scrnIndex, 1, X_WARNING,
4979
			       "Call to %s %s\n", msg, result);
4980
		break;
4981
	    case MSG_FORMAT_NONE:
4982
		xf86DrvMsg(scrnIndex,X_INFO,"Query for %s: %s\n", msg, result);
4983
		    break;
4984
    }
4985
  }
4986
  return ret;
4987
}
4988
 
4989
/*
4990
 *
4991
 */
4992
static void
4993
atomRegisterSaveList(atomBiosHandlePtr handle, struct atomSaveListRecord **SaveList)
4994
{
4995
    struct atomSaveListObject *ListObject = handle->SaveListObjects;
4996
    RHDFUNC(handle);
4997
 
4998
    while (ListObject) {
4999
	if (ListObject->SaveList == SaveList)
5000
	    return;
5001
	ListObject = ListObject->next;
5002
    }
5003
    if (!(ListObject = (struct atomSaveListObject *)xcalloc(1,sizeof (struct atomSaveListObject))))
5004
	return;
5005
    ListObject->next = handle->SaveListObjects;
5006
    ListObject->SaveList = SaveList;
5007
    handle->SaveListObjects = ListObject;
5008
}
5009
 
5010
/*
5011
 *
5012
 */
5013
static void
5014
atomUnregisterSaveList(atomBiosHandlePtr handle, struct atomSaveListRecord **SaveList)
5015
{
5016
    struct atomSaveListObject **ListObject;
5017
    RHDFUNC(handle);
5018
 
5019
    if (!handle->SaveListObjects)
5020
	return;
5021
    ListObject  = &handle->SaveListObjects;
5022
 
5023
    while (1) {
5024
	if ((*ListObject)->SaveList == SaveList) {
5025
	    struct atomSaveListObject *tmp = *ListObject;
5026
	    *ListObject = ((*ListObject)->next);
5027
	    xfree(tmp);
5028
	}
5029
	if (!(*ListObject) || !(*ListObject)->next)
5030
	    return;
5031
	ListObject = &((*ListObject)->next);
5032
    }
5033
}
5034
 
5035
/*
5036
 *
5037
 */
5038
static AtomBiosResult
5039
atomSetRegisterListLocation(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data)
5040
{
5041
    RHDFUNC(handle);
5042
 
5043
    handle->SaveList = (struct atomSaveListRecord **)data->Address;
5044
    if (handle->SaveList)
5045
	atomRegisterSaveList(handle, handle->SaveList);
5046
 
5047
    return ATOM_SUCCESS;
5048
}
5049
 
5050
/*
5051
 *
5052
 */
5053
static AtomBiosResult
5054
atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data)
5055
{
5056
    struct atomSaveListRecord *List = *(data->Address);
5057
    int i;
5058
 
5059
    RHDFUNC(handle);
5060
 
5061
    if (!List)
5062
	return ATOM_FAILED;
5063
 
5064
    for (i = 0; i < List->Last; i++) {
5065
	switch ( List->RegisterList[i].Type) {
5066
	    case atomRegisterMMIO:
5067
		RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MMIO(0x%4.4x) = 0x%4.4x\n",__func__, List->Last,
5068
			      List->RegisterList[i].Address, List->RegisterList[i].Value);
5069
		RHDRegWrite(handle, List->RegisterList[i].Address, List->RegisterList[i].Value);
5070
		break;
5071
	    case atomRegisterMC:
5072
		RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MC(0x%4.4x) = 0x%4.4x\n",__func__, List->Last,
5073
			      List->RegisterList[i].Address, List->RegisterList[i].Value);
5074
		RHDWriteMC(handle,  List->RegisterList[i].Address | MC_IND_ALL | MC_IND_WR_EN,
5075
			   List->RegisterList[i].Value);
5076
		break;
5077
	    case atomRegisterPLL:
5078
		RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PLL(0x%4.4x) = 0x%4.4x\n",__func__, List->Last,
5079
			      List->RegisterList[i].Address, List->RegisterList[i].Value);
5080
		_RHDWritePLL(handle->scrnIndex, List->RegisterList[i].Address, List->RegisterList[i].Value);
5081
		break;
5082
	    case atomRegisterPCICFG:
5083
		RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PCICFG(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,
5084
			      List->RegisterList[i].Address, List->RegisterList[i].Value);
5085
#ifdef XSERVER_LIBPCIACCESS
5086
		pci_device_cfg_write(RHDPTRI(handle)->PciInfo,
5087
				     &List->RegisterList[i].Value,
5088
				     List->RegisterList[i].Address, 4, NULL);
5089
#else
5090
		{
5091
		    PCITAG tag = RHDPTRI(handle)->PciTag;
5092
		    pciWriteLong(tag, List->RegisterList[i].Address,
5093
				 List->RegisterList[i].Value);
5094
		}
5095
#endif
5096
		break;
5097
	}
5098
    }
5099
 
5100
    /* deallocate list */
5101
    atomUnregisterSaveList(handle, (struct atomSaveListRecord **)data->Address);
5102
    xfree(List);
5103
    *(data->Address) = NULL;
5104
 
5105
    return ATOM_SUCCESS;
5106
}
5107
 
5108
# ifdef ATOM_BIOS_PARSER
5109
 
5110
#define ALLOC_CNT 25
5111
 
5112
/*
5113
 *
5114
 */
5115
static void
5116
atomSaveRegisters(atomBiosHandlePtr handle, enum atomRegisterType Type, CARD32 address)
5117
{
5118
    struct atomSaveListRecord *List;
5119
    CARD32 val = 0;
5120
    int i;
5121
    struct atomSaveListObject *SaveListObj = handle->SaveListObjects;
5122
 
5123
    RHDFUNC(handle);
5124
 
5125
    if (!handle->SaveList)
5126
	return;
5127
 
5128
    if (!(*(handle->SaveList))) {
5129
	if (!(*handle->SaveList = (struct atomSaveListRecord *)xalloc(sizeof(struct atomSaveListRecord)
5130
								  + sizeof(struct  atomRegisterList) * (ALLOC_CNT - 1))))
5131
	    return;
5132
	(*(handle->SaveList))->Length = ALLOC_CNT;
5133
	(*(handle->SaveList))->Last = 0;
5134
    } else if ((*(handle->SaveList))->Length == (*(handle->SaveList))->Last) {
5135
	if (!(List = (struct atomSaveListRecord *)xrealloc(*handle->SaveList,
5136
						      sizeof(struct atomSaveListRecord)
5137
						      + (sizeof(struct  atomRegisterList)
5138
							 * ((*(handle->SaveList))->Length + ALLOC_CNT - 1)))))
5139
	    return;
5140
	*handle->SaveList = List;
5141
	List->Length = (*(handle->SaveList))->Length + ALLOC_CNT;
5142
    }
5143
    List = *handle->SaveList;
5144
 
5145
    while (SaveListObj) {
5146
	struct atomSaveListRecord *ListFromObj = *(SaveListObj->SaveList);
5147
 
5148
	if (ListFromObj) {
5149
	    for (i = 0; i < ListFromObj->Last; i++)
5150
		if (ListFromObj->RegisterList[i].Address == address
5151
		    && ListFromObj->RegisterList[i].Type == Type)
5152
		    return;
5153
	}
5154
	SaveListObj = SaveListObj->next;
5155
    }
5156
 
5157
    switch (Type) {
5158
	case atomRegisterMMIO:
5159
	    val = RHDRegRead(handle, address);
5160
	    RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MMIO(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val);
5161
	    break;
5162
	case atomRegisterMC:
5163
	    val = RHDReadMC(handle, address | MC_IND_ALL);
5164
	    RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MC(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val);
5165
	    break;
5166
	case atomRegisterPLL:
5167
	    val = _RHDReadPLL(handle->scrnIndex, address);
5168
	    RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PLL(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val);
5169
	    break;
5170
	case atomRegisterPCICFG:
5171
#ifdef XSERVER_LIBPCIACCESS
5172
	    val = pci_device_cfg_write(RHDPTRI(handle)->PciInfo,
5173
				       &val, address, 4, NULL);
5174
#else
5175
	    {
5176
		PCITAG tag = RHDPTRI(handle)->PciTag;
5177
		val =  pciReadLong(tag, address);
5178
	    }
5179
#endif
5180
	    RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PCICFG(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val);
5181
	    break;
5182
    }
5183
    List->RegisterList[List->Last].Address = address;
5184
    List->RegisterList[List->Last].Value = val;
5185
    List->RegisterList[List->Last].Type = Type;
5186
    List->Last++;
5187
}
5188
 
5189
/*
5190
 *
5191
 */
5192
VOID*
5193
CailAllocateMemory(VOID *CAIL,UINT16 size)
5194
{
5195
    CAILFUNC(CAIL);
5196
 
5197
    return malloc(size);
5198
}
5199
 
5200
VOID
5201
CailReleaseMemory(VOID *CAIL, VOID *addr)
5202
{
5203
    CAILFUNC(CAIL);
5204
 
5205
    free(addr);
5206
}
5207
 
5208
VOID
5209
CailDelayMicroSeconds(VOID *CAIL, UINT32 delay)
5210
{
5211
    CAILFUNC(CAIL);
5212
 
5213
    usleep(delay);
5214
 
5215
  //  DEBUGP(xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_INFO,"Delay %i usec\n",delay));
5216
}
5217
 
5218
UINT32
5219
CailReadATIRegister(VOID* CAIL, UINT32 idx)
5220
{
5221
    UINT32 ret;
5222
    CAILFUNC(CAIL);
5223
 
5224
    ret  =  RHDRegRead(((atomBiosHandlePtr)CAIL), idx << 2);
5225
//    DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret));
5226
    return ret;
5227
}
5228
 
5229
VOID
5230
CailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data)
5231
{
5232
    CAILFUNC(CAIL);
5233
 
5234
    atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterMMIO, idx << 2);
5235
 
5236
    RHDRegWrite(((atomBiosHandlePtr)CAIL),idx << 2,data);
5237
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,idx << 2,data);
5238
}
5239
 
5240
UINT32
5241
CailReadFBData(VOID* CAIL, UINT32 idx)
5242
{
5243
  UINT32 ret;
5244
 
5245
  CAILFUNC(CAIL);
5246
 
5247
    if (((atomBiosHandlePtr)CAIL)->fbBase) {
5248
	CARD8 *FBBase = (CARD8*)
5249
	    RHDPTRI((atomBiosHandlePtr)CAIL)->FbBase;
5250
    ret =  *((CARD32*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx));
5251
	RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,idx,ret);
5252
    } else if (((atomBiosHandlePtr)CAIL)->scratchBase) {
5253
    ret = *(CARD32*)((CARD8*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx);
5254
	RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,idx,ret);
5255
    } else {
5256
	xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR,
5257
		   "%s: no fbbase set\n",__func__);
5258
    return 0;
5259
  }
5260
  return ret;
5261
}
5262
 
5263
VOID
5264
CailWriteFBData(VOID *CAIL, UINT32 idx, UINT32 data)
5265
{
5266
  CAILFUNC(CAIL);
5267
 
5268
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,idx,data);
5269
    if (((atomBiosHandlePtr)CAIL)->fbBase) {
5270
	CARD8 *FBBase = (CARD8*)
5271
	    RHDPTRI((atomBiosHandlePtr)CAIL)->FbBase;
5272
    *((CARD32*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)) = data;
5273
    } else if (((atomBiosHandlePtr)CAIL)->scratchBase) {
5274
    *(CARD32*)((CARD8*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx) = data;
5275
    } else
5276
	xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR,
5277
		   "%s: no fbbase set\n",__func__);
5278
}
5279
 
5280
ULONG
5281
CailReadMC(VOID *CAIL, ULONG Address)
5282
{
5283
    ULONG ret;
5284
 
5285
    CAILFUNC(CAIL);
5286
 
5287
    ret = RHDReadMC(((atomBiosHandlePtr)CAIL)->rhdPtr, Address | MC_IND_ALL);
5288
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,Address,ret);
5289
    return ret;
5290
}
5291
 
5292
VOID
5293
CailWriteMC(VOID *CAIL, ULONG Address, ULONG data)
5294
{
5295
  CAILFUNC(CAIL);
5296
 
5297
 
5298
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,Address,data);
5299
 
5300
    atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterMC, Address);
5301
 
5302
  RHDWriteMC(((atomBiosHandlePtr)CAIL)->rhdPtr, Address | MC_IND_ALL | MC_IND_WR_EN, data);
5303
}
5304
 
5305
#ifdef XSERVER_LIBPCIACCESS
5306
 
5307
VOID
5308
CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size)
5309
{
5310
    pci_device_cfg_read(RHDPTRI((atomBiosHandlePtr)CAIL)->PciInfo,
5311
				ret,idx << 2 , size >> 3, NULL);
5312
}
5313
 
5314
VOID
5315
CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size)
5316
{
5317
    atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterPCICFG, idx << 2);
5318
    pci_device_cfg_write(RHDPTRI((atomBiosHandlePtr)CAIL)->PciInfo,
5319
			 src, idx << 2, size >> 3, NULL);
5320
}
5321
 
5322
#else
5323
 
5324
VOID
5325
CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size)
5326
{ u32_t bus, devfn;
5327
  PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag;
5328
 
5329
  CAILFUNC(CAIL);
5330
  bus   = PCI_BUS_FROM_TAG(tag);
5331
  devfn = PCI_DFN_FROM_TAG(tag);
5332
 
5333
    switch (size) {
5334
    case 8:
5335
      *(CARD8*)ret = PciRead8(bus,devfn,idx << 2);
5336
	    break;
5337
    case 16:
5338
      *(CARD16*)ret = PciRead16(bus,devfn,idx << 2);
5339
	    break;
5340
    case 32:
5341
      *(CARD32*)ret = PciRead32(bus,devfn,idx << 2);
5342
	    break;
5343
    default:
5344
	xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,
5345
		   X_ERROR,"%s: Unsupported size: %i\n",
5346
		   __func__,(int)size);
5347
      return;
5348
      break;
5349
  }
5350
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,idx,*(unsigned int*)ret);
5351
 
5352
}
5353
 
5354
VOID
5355
CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size)
5356
{
5357
  u32_t bus, devfn;
5358
  PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag;
5359
  bus   = PCI_BUS_FROM_TAG(tag);
5360
  devfn = PCI_DFN_FROM_TAG(tag);
5361
 
5362
  CAILFUNC(CAIL);
5363
 
5364
  RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,idx,(*(unsigned int*)src));
5365
 
5366
  atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterPCICFG, idx << 2);
5367
    switch (size) {
5368
    case 8:
5369
      PciWrite8(bus,devfn, idx << 2,*(CARD8*)src);
5370
      break;
5371
    case 16:
5372
      PciWrite16(bus,devfn,idx << 2,*(CARD16*)src);
5373
      break;
5374
    case 32:
5375
      PciWrite32(bus,devfn,idx << 2,*(CARD32*)src);
5376
      break;
5377
    default:
5378
	    xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR,
5379
		       "%s: Unsupported size: %i\n",__func__,(int)size);
5380
      break;
5381
  }
5382
}
5383
#endif
5384
 
5385
ULONG
5386
CailReadPLL(VOID *CAIL, ULONG Address)
5387
{
5388
    ULONG ret;
5389
 
5390
    CAILFUNC(CAIL);
5391
 
5392
    ret = _RHDReadPLL(((atomBiosHandlePtr)CAIL)->rhdPtr, Address);
5393
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,Address,ret);
5394
    return ret;
5395
}
5396
 
5397
VOID
5398
CailWritePLL(VOID *CAIL, ULONG Address,ULONG Data)
5399
{
5400
    CAILFUNC(CAIL);
5401
 
5402
    RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,Address,Data);
5403
    atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterPLL, Address);
5404
    _RHDWritePLL(((atomBiosHandlePtr)CAIL)->scrnIndex, Address, Data);
5405
}
5406
 
5407
# endif
5408
 
5409
#endif /* ATOM_BIOS */