0,0 → 1,5409 |
/* |
* Copyright 2007, 2008 Egbert Eich <eich@novell.com> |
* Copyright 2007, 2008 Luc Verhaegen <lverhaegen@novell.com> |
* Copyright 2007, 2008 Matthias Hopf <mhopf@novell.com> |
* Copyright 2007, 2008 Advanced Micro Devices, Inc. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
*/ |
/* #define RHD_DEBUG */ |
|
#ifdef HAVE_CONFIG_H |
# include "config.h" |
#endif |
#include "xf86.h" |
|
|
/* only for testing now */ |
|
#include "rhd.h" |
#include "edid.h" |
#include "rhd_atombios.h" |
#include "rhd_connector.h" |
#include "rhd_output.h" |
#include "rhd_biosscratch.h" |
#include "rhd_monitor.h" |
#include "rhd_card.h" |
#include "rhd_regs.h" |
|
#ifdef ATOM_BIOS |
# include "rhd_atomwrapper.h" |
//# include "xf86int10.h" |
# ifdef ATOM_BIOS_PARSER |
# define INT8 INT8 |
# define INT16 INT16 |
# define INT32 INT32 |
# include "AtomBios/includes/CD_Common_Types.h" |
# else |
# ifndef ULONG |
typedef unsigned int ULONG; |
# define ULONG ULONG |
# endif |
# ifndef UCHAR |
typedef unsigned char UCHAR; |
# define UCHAR UCHAR |
# endif |
# ifndef USHORT |
typedef unsigned short USHORT; |
# define USHORT USHORT |
# endif |
# endif |
|
# include "atomBios/includes/atombios.h" |
# include "atomBios/includes/ObjectID.h" |
|
typedef AtomBiosResult (*AtomBiosRequestFunc)(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data); |
typedef struct rhdConnectorInfo *rhdConnectorInfoPtr; |
|
static AtomBiosResult rhdAtomInit(atomBiosHandlePtr unused1, |
AtomBiosRequestID unused2, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomTearDown(atomBiosHandlePtr handle, |
AtomBiosRequestID unused1, AtomBiosArgPtr unused2); |
static AtomBiosResult rhdAtomGetDataInCodeTable(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomVramInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomAllocateFbScratch(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomConnectorInfo(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data); |
static AtomBiosResult rhdAtomOutputDeviceList(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data); |
static AtomBiosResult |
rhdAtomAnalogTVInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult |
rhdAtomGetConditionalGoldenSetting(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
|
# ifdef ATOM_BIOS_PARSER |
static AtomBiosResult rhdAtomExec(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data); |
# endif |
static AtomBiosResult |
rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult |
rhdAtomIntegratedSystemInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult |
atomSetRegisterListLocation(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data); |
static AtomBiosResult |
atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data); |
|
|
enum msgDataFormat { |
MSG_FORMAT_NONE, |
MSG_FORMAT_HEX, |
MSG_FORMAT_DEC |
}; |
|
enum atomRegisterType { |
atomRegisterMMIO, |
atomRegisterMC, |
atomRegisterPLL, |
atomRegisterPCICFG |
}; |
|
struct atomBIOSRequests { |
AtomBiosRequestID id; |
AtomBiosRequestFunc request; |
char *message; |
enum msgDataFormat message_format; |
} AtomBiosRequestList [] = { |
{ATOMBIOS_INIT, rhdAtomInit, |
"AtomBIOS Init", MSG_FORMAT_NONE}, |
{ATOMBIOS_TEARDOWN, rhdAtomTearDown, |
"AtomBIOS Teardown", MSG_FORMAT_NONE}, |
# ifdef ATOM_BIOS_PARSER |
{ATOMBIOS_EXEC, rhdAtomExec, |
"AtomBIOS Exec", MSG_FORMAT_NONE}, |
#endif |
{ATOMBIOS_ALLOCATE_FB_SCRATCH, rhdAtomAllocateFbScratch, |
"AtomBIOS Set FB Space", MSG_FORMAT_NONE}, |
{ATOMBIOS_GET_CONNECTORS, rhdAtomConnectorInfo, |
"AtomBIOS Get Connectors", MSG_FORMAT_NONE}, |
{ATOMBIOS_GET_OUTPUT_DEVICE_LIST, rhdAtomOutputDeviceList, |
"AtomBIOS Get Output Info", MSG_FORMAT_NONE}, |
{ATOMBIOS_GET_PANEL_MODE, rhdAtomLvdsGetTimings, |
"AtomBIOS Get Panel Mode", MSG_FORMAT_NONE}, |
{ATOMBIOS_GET_PANEL_EDID, rhdAtomLvdsGetTimings, |
"AtomBIOS Get Panel EDID", MSG_FORMAT_NONE}, |
{ATOMBIOS_GET_CODE_DATA_TABLE, rhdAtomGetDataInCodeTable, |
"AtomBIOS Get Datatable from Codetable", MSG_FORMAT_NONE}, |
{GET_DEFAULT_ENGINE_CLOCK, rhdAtomFirmwareInfoQuery, |
"Default Engine Clock", MSG_FORMAT_DEC}, |
{GET_DEFAULT_MEMORY_CLOCK, rhdAtomFirmwareInfoQuery, |
"Default Memory Clock", MSG_FORMAT_DEC}, |
{GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, |
"Maximum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, |
{GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, rhdAtomFirmwareInfoQuery, |
"Minimum Pixel ClockPLL Frequency Output", MSG_FORMAT_DEC}, |
{GET_MAX_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, |
"Maximum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, |
{GET_MIN_PIXEL_CLOCK_PLL_INPUT, rhdAtomFirmwareInfoQuery, |
"Minimum Pixel ClockPLL Frequency Input", MSG_FORMAT_DEC}, |
{GET_MAX_PIXEL_CLK, rhdAtomFirmwareInfoQuery, |
"Maximum Pixel Clock", MSG_FORMAT_DEC}, |
{GET_REF_CLOCK, rhdAtomFirmwareInfoQuery, |
"Reference Clock", MSG_FORMAT_DEC}, |
{GET_FW_FB_START, rhdAtomVramInfoQuery, |
"Start of VRAM area used by Firmware", MSG_FORMAT_HEX}, |
{GET_FW_FB_SIZE, rhdAtomVramInfoQuery, |
"Framebuffer space used by Firmware (kb)", MSG_FORMAT_DEC}, |
{ATOM_TMDS_MAX_FREQUENCY, rhdAtomTmdsInfoQuery, |
"TMDS Max Frequency", MSG_FORMAT_DEC}, |
{ATOM_TMDS_PLL_CHARGE_PUMP, rhdAtomTmdsInfoQuery, |
"TMDS PLL ChargePump", MSG_FORMAT_DEC}, |
{ATOM_TMDS_PLL_DUTY_CYCLE, rhdAtomTmdsInfoQuery, |
"TMDS PLL DutyCycle", MSG_FORMAT_DEC}, |
{ATOM_TMDS_PLL_VCO_GAIN, rhdAtomTmdsInfoQuery, |
"TMDS PLL VCO Gain", MSG_FORMAT_DEC}, |
{ATOM_TMDS_PLL_VOLTAGE_SWING, rhdAtomTmdsInfoQuery, |
"TMDS PLL VoltageSwing", MSG_FORMAT_DEC}, |
{ATOM_LVDS_SUPPORTED_REFRESH_RATE, rhdAtomLvdsInfoQuery, |
"LVDS Supported Refresh Rate", MSG_FORMAT_DEC}, |
{ATOM_LVDS_OFF_DELAY, rhdAtomLvdsInfoQuery, |
"LVDS Off Delay", MSG_FORMAT_DEC}, |
{ATOM_LVDS_SEQ_DIG_ONTO_DE, rhdAtomLvdsInfoQuery, |
"LVDS SEQ Dig onto DE", MSG_FORMAT_DEC}, |
{ATOM_LVDS_SEQ_DE_TO_BL, rhdAtomLvdsInfoQuery, |
"LVDS SEQ DE to BL", MSG_FORMAT_DEC}, |
{ATOM_LVDS_TEMPORAL_DITHER, rhdAtomLvdsInfoQuery, |
"LVDS Temporal Dither ", MSG_FORMAT_HEX}, |
{ATOM_LVDS_SPATIAL_DITHER, rhdAtomLvdsInfoQuery, |
"LVDS Spatial Dither ", MSG_FORMAT_HEX}, |
{ATOM_LVDS_DUALLINK, rhdAtomLvdsInfoQuery, |
"LVDS Duallink", MSG_FORMAT_HEX}, |
{ATOM_LVDS_GREYLVL, rhdAtomLvdsInfoQuery, |
"LVDS Grey Level", MSG_FORMAT_HEX}, |
{ATOM_LVDS_FPDI, rhdAtomLvdsInfoQuery, |
"LVDS FPDI", MSG_FORMAT_HEX}, |
{ATOM_LVDS_24BIT, rhdAtomLvdsInfoQuery, |
"LVDS 24Bit", MSG_FORMAT_HEX}, |
{ATOM_GPIO_I2C_CLK_MASK, rhdAtomGPIOI2CInfoQuery, |
"GPIO_I2C_Clk_Mask", MSG_FORMAT_HEX}, |
{ATOM_GPIO_I2C_CLK_MASK_SHIFT, rhdAtomGPIOI2CInfoQuery, |
"GPIO_I2C_Clk_Mask_Shift", MSG_FORMAT_HEX}, |
{ATOM_GPIO_I2C_DATA_MASK, rhdAtomGPIOI2CInfoQuery, |
"GPIO_I2C_Data_Mask", MSG_FORMAT_HEX}, |
{ATOM_GPIO_I2C_DATA_MASK_SHIFT, rhdAtomGPIOI2CInfoQuery, |
"GPIO_I2C_Data_Mask_Shift", MSG_FORMAT_HEX}, |
{ATOM_DAC1_BG_ADJ, rhdAtomCompassionateDataQuery, |
"DAC1 BG Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC1_DAC_ADJ, rhdAtomCompassionateDataQuery, |
"DAC1 DAC Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC1_FORCE, rhdAtomCompassionateDataQuery, |
"DAC1 Force Data", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CRTC2_BG_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_CRTC2 BG Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_NTSC_BG_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_NTSC BG Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_PAL_BG_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_PAL BG Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CV_BG_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_CV BG Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CRTC2_DAC_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_CRTC2 DAC Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_NTSC_DAC_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_NTSC DAC Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_PAL_DAC_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_PAL DAC Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CV_DAC_ADJ, rhdAtomCompassionateDataQuery, |
"DAC2_CV DAC Adjustment", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CRTC2_FORCE, rhdAtomCompassionateDataQuery, |
"DAC2_CRTC2 Force", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CRTC2_MUX_REG_IND,rhdAtomCompassionateDataQuery, |
"DAC2_CRTC2 Mux Register Index", MSG_FORMAT_HEX}, |
{ATOM_DAC2_CRTC2_MUX_REG_INFO,rhdAtomCompassionateDataQuery, |
"DAC2_CRTC2 Mux Register Info", MSG_FORMAT_HEX}, |
{ATOM_ANALOG_TV_MODE, rhdAtomAnalogTVInfoQuery, |
"Analog TV Mode", MSG_FORMAT_NONE}, |
{ATOM_ANALOG_TV_DEFAULT_MODE, rhdAtomAnalogTVInfoQuery, |
"Analog TV Default Mode", MSG_FORMAT_DEC}, |
{ATOM_ANALOG_TV_SUPPORTED_MODES, rhdAtomAnalogTVInfoQuery, |
"Analog TV Supported Modes", MSG_FORMAT_HEX}, |
{ATOM_GET_CONDITIONAL_GOLDEN_SETTINGS, rhdAtomGetConditionalGoldenSetting, |
"Conditional Golden Setting", MSG_FORMAT_NONE}, |
{ATOM_GET_PCIENB_CFG_REG7, rhdAtomIntegratedSystemInfoQuery, |
"PCIE NB Cfg7Reg", MSG_FORMAT_HEX}, |
{ATOM_GET_CAPABILITY_FLAG, rhdAtomIntegratedSystemInfoQuery, |
"CapabilityFlag", MSG_FORMAT_HEX}, |
{ATOM_GET_PCIE_LANES, rhdAtomIntegratedSystemInfoQuery, |
"PCI Lanes", MSG_FORMAT_NONE}, |
{ATOM_SET_REGISTER_LIST_LOCATION, atomSetRegisterListLocation, |
"Register List Location", MSG_FORMAT_NONE}, |
{ATOM_RESTORE_REGISTERS, atomRestoreRegisters, |
"Restore Registers", MSG_FORMAT_NONE}, |
{FUNC_END, NULL, |
NULL, MSG_FORMAT_NONE} |
}; |
|
/* |
* This works around a bug in atombios.h where |
* ATOM_MAX_SUPPORTED_DEVICE_INFO is specified incorrectly. |
*/ |
|
#define ATOM_MAX_SUPPORTED_DEVICE_INFO_HD (ATOM_DEVICE_RESERVEDF_INDEX+1) |
typedef struct _ATOM_SUPPORTED_DEVICES_INFO_HD |
{ |
ATOM_COMMON_TABLE_HEADER sHeader; |
USHORT usDeviceSupport; |
ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_HD]; |
ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_HD]; |
} ATOM_SUPPORTED_DEVICES_INFO_HD; |
|
typedef struct _atomDataTables |
{ |
unsigned char *UtilityPipeLine; |
ATOM_MULTIMEDIA_CAPABILITY_INFO *MultimediaCapabilityInfo; |
ATOM_MULTIMEDIA_CONFIG_INFO *MultimediaConfigInfo; |
ATOM_STANDARD_VESA_TIMING *StandardVESA_Timing; |
union { |
void *base; |
ATOM_FIRMWARE_INFO *FirmwareInfo; |
ATOM_FIRMWARE_INFO_V1_2 *FirmwareInfo_V_1_2; |
ATOM_FIRMWARE_INFO_V1_3 *FirmwareInfo_V_1_3; |
ATOM_FIRMWARE_INFO_V1_4 *FirmwareInfo_V_1_4; |
} FirmwareInfo; |
ATOM_DAC_INFO *DAC_Info; |
union { |
void *base; |
ATOM_LVDS_INFO *LVDS_Info; |
ATOM_LVDS_INFO_V12 *LVDS_Info_v12; |
} LVDS_Info; |
ATOM_TMDS_INFO *TMDS_Info; |
ATOM_ANALOG_TV_INFO *AnalogTV_Info; |
union { |
void *base; |
ATOM_SUPPORTED_DEVICES_INFO *SupportedDevicesInfo; |
ATOM_SUPPORTED_DEVICES_INFO_2 *SupportedDevicesInfo_2; |
ATOM_SUPPORTED_DEVICES_INFO_2d1 *SupportedDevicesInfo_2d1; |
ATOM_SUPPORTED_DEVICES_INFO_HD *SupportedDevicesInfo_HD; |
} SupportedDevicesInfo; |
ATOM_GPIO_I2C_INFO *GPIO_I2C_Info; |
ATOM_VRAM_USAGE_BY_FIRMWARE *VRAM_UsageByFirmware; |
ATOM_GPIO_PIN_LUT *GPIO_Pin_LUT; |
ATOM_VESA_TO_INTENAL_MODE_LUT *VESA_ToInternalModeLUT; |
union { |
void *base; |
ATOM_COMPONENT_VIDEO_INFO *ComponentVideoInfo; |
ATOM_COMPONENT_VIDEO_INFO_V21 *ComponentVideoInfo_v21; |
} ComponentVideoInfo; |
/**/unsigned char *PowerPlayInfo; |
COMPASSIONATE_DATA *CompassionateData; |
ATOM_DISPLAY_DEVICE_PRIORITY_INFO *SaveRestoreInfo; |
/**/unsigned char *PPLL_SS_Info; |
ATOM_OEM_INFO *OemInfo; |
ATOM_XTMDS_INFO *XTMDS_Info; |
ATOM_ASIC_MVDD_INFO *MclkSS_Info; |
ATOM_OBJECT_HEADER *Object_Header; |
INDIRECT_IO_ACCESS *IndirectIOAccess; |
ATOM_MC_INIT_PARAM_TABLE *MC_InitParameter; |
/**/unsigned char *ASIC_VDDC_Info; |
ATOM_ASIC_INTERNAL_SS_INFO *ASIC_InternalSS_Info; |
/**/unsigned char *TV_VideoMode; |
union { |
void *base; |
ATOM_VRAM_INFO_V2 *VRAM_Info_v2; |
ATOM_VRAM_INFO_V3 *VRAM_Info_v3; |
} VRAM_Info; |
ATOM_MEMORY_TRAINING_INFO *MemoryTrainingInfo; |
union { |
void *base; |
ATOM_INTEGRATED_SYSTEM_INFO *IntegratedSystemInfo; |
ATOM_INTEGRATED_SYSTEM_INFO_V2 *IntegratedSystemInfo_v2; |
} IntegratedSystemInfo; |
ATOM_ASIC_PROFILING_INFO *ASIC_ProfilingInfo; |
ATOM_VOLTAGE_OBJECT_INFO *VoltageObjectInfo; |
ATOM_POWER_SOURCE_INFO *PowerSourceInfo; |
} atomDataTables, *atomDataTablesPtr; |
|
struct atomSaveListRecord |
{ |
/* header */ |
int Length; |
int Last; |
struct atomRegisterList{ |
enum atomRegisterType Type; |
CARD32 Address; |
CARD32 Value; |
} RegisterList[1]; |
}; |
|
struct atomSaveListObject |
{ |
struct atomSaveListObject *next; |
struct atomSaveListRecord **SaveList; |
}; |
|
typedef struct _atomBiosHandle { |
int scrnIndex; |
RHDPtr rhdPtr; |
unsigned char *BIOSBase; |
atomDataTablesPtr atomDataPtr; |
pointer *scratchBase; |
CARD32 fbBase; |
PCITAG PciTag; |
unsigned int BIOSImageSize; |
unsigned char *codeTable; |
struct atomSaveListRecord **SaveList; |
struct atomSaveListObject *SaveListObjects; |
} atomBiosHandleRec; |
|
enum { |
legacyBIOSLocation = 0xC0000, |
legacyBIOSMax = 0x10000 |
}; |
|
struct atomConnectorInfoPrivate { |
enum atomDevice *Devices; |
}; |
|
# ifdef ATOM_BIOS_PARSER |
|
# define LOG_CAIL LOG_DEBUG + 1 |
|
static void |
atomDebugPrintPspace(atomBiosHandlePtr handle, AtomBiosArgPtr data, int size) |
{ |
CARD32 *pspace = (CARD32 *)data->exec.pspace; |
int i = 0; |
|
size >>= 2; |
|
while (i++,size--) |
RHDDebug(handle->scrnIndex, " Pspace[%2.2i]: 0x%8.8x\n", i, *(pspace++)); |
} |
|
/* |
#define va_start(v,l) __builtin_va_start(v,l) |
#define va_end(v) __builtin_va_end(v) |
#define va_arg(v,l) __builtin_va_arg(v,l) |
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L |
#define va_copy(d,s) __builtin_va_copy(d,s) |
#endif |
#define __va_copy(d,s) __builtin_va_copy(d,s) |
|
typedef __builtin_va_list __gnuc_va_list; |
typedef __gnuc_va_list va_list; |
|
#define arg(x) va_arg (ap, u32_t) |
|
static void |
CailDebug(int scrnIndex, const char *format, ...) |
{ |
va_list ap; |
|
va_start(ap, format); |
xf86VDrvMsgVerb(scrnIndex, X_INFO, LOG_CAIL, format, ap); |
va_end(ap); |
} |
# define CAILFUNC(ptr) \ |
CailDebug(((atomBiosHandlePtr)(ptr))->scrnIndex, "CAIL: %s\n", __func__) |
*/ |
|
# endif |
|
# define DEBUG_VERSION(index, handle, version) \ |
xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 3, "%s returned version %i for index 0x%x\n" ,__func__,version.cref,index) |
# define DEBUG_VERSION_NAME(index, handle, name, version) \ |
xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 3, "%s(%s) returned version %i for index 0x%x\n",\ |
__func__,name,version.cref,index) |
|
static int |
rhdAtomAnalyzeCommonHdr(ATOM_COMMON_TABLE_HEADER *hdr) |
{ |
if (hdr->usStructureSize == 0xaa55) |
return FALSE; |
|
return TRUE; |
} |
|
static int |
rhdAtomAnalyzeRomHdr(unsigned char *rombase, |
ATOM_ROM_HEADER *hdr, |
unsigned int *data_offset, unsigned int *code_table) |
{ |
if (!rhdAtomAnalyzeCommonHdr(&hdr->sHeader)) { |
return FALSE; |
} |
xf86DrvMsg(-1,X_NONE,"\tSubsystemVendorID: 0x%4.4x SubsystemID: 0x%4.4x\n", |
hdr->usSubsystemVendorID,hdr->usSubsystemID); |
xf86DrvMsg(-1,X_NONE,"\tIOBaseAddress: 0x%4.4x\n",hdr->usIoBaseAddress); |
xf86DrvMsgVerb(-1,X_NONE,3,"\tFilename: %s\n",rombase + hdr->usConfigFilenameOffset); |
xf86DrvMsgVerb(-1,X_NONE,3,"\tBIOS Bootup Message: %s\n", |
rombase + hdr->usBIOS_BootupMessageOffset); |
|
*data_offset = hdr->usMasterDataTableOffset; |
*code_table = hdr->usMasterCommandTableOffset; |
|
return TRUE; |
} |
|
static int |
rhdAtomAnalyzeRomDataTable(unsigned char *base, int offset, |
void *ptr,unsigned short *size) |
{ |
ATOM_COMMON_TABLE_HEADER *table = (ATOM_COMMON_TABLE_HEADER *) |
(base + offset); |
|
if (!*size || !rhdAtomAnalyzeCommonHdr(table)) { |
if (*size) *size -= 2; |
*(void **)ptr = NULL; |
return FALSE; |
} |
*size -= 2; |
*(void **)ptr = (void *)(table); |
return TRUE; |
} |
|
static Bool |
rhdAtomGetTableRevisionAndSize(ATOM_COMMON_TABLE_HEADER *hdr, |
CARD8 *contentRev, |
CARD8 *formatRev, |
unsigned short *size) |
{ |
if (!hdr) |
return FALSE; |
|
if (contentRev) *contentRev = hdr->ucTableContentRevision; |
if (formatRev) *formatRev = hdr->ucTableFormatRevision; |
if (size) *size = (short)hdr->usStructureSize |
- sizeof(ATOM_COMMON_TABLE_HEADER); |
|
return TRUE; |
} |
|
static Bool |
rhdAtomGetCommandTableRevisionSize(atomBiosHandlePtr handle, int index, |
CARD8 *contentRev, CARD8 *formatRev, unsigned short *size) |
{ |
unsigned short offset = ((USHORT *)&(((ATOM_MASTER_COMMAND_TABLE *)handle->codeTable) |
->ListOfCommandTables))[index]; |
ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *hdr = (ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)(handle->BIOSBase + offset); |
ATOM_COMMON_TABLE_HEADER hdr1 = hdr->CommonHeader; |
|
if (!offset) { |
*contentRev = *formatRev = 0; |
return FALSE; |
} |
return rhdAtomGetTableRevisionAndSize(&hdr1, contentRev, formatRev, size); |
} |
|
static Bool |
rhdAtomAnalyzeMasterDataTable(unsigned char *base, |
ATOM_MASTER_DATA_TABLE *table, |
atomDataTablesPtr data) |
{ |
ATOM_MASTER_LIST_OF_DATA_TABLES *data_table = |
&table->ListOfDataTables; |
unsigned short size; |
|
if (!rhdAtomAnalyzeCommonHdr(&table->sHeader)) |
return FALSE; |
if (!rhdAtomGetTableRevisionAndSize(&table->sHeader,NULL,NULL, |
&size)) |
return FALSE; |
# define SET_DATA_TABLE(x) {\ |
rhdAtomAnalyzeRomDataTable(base,data_table->x,(void *)(&(data->x)),&size); \ |
} |
|
# define SET_DATA_TABLE_VERS(x) {\ |
rhdAtomAnalyzeRomDataTable(base,data_table->x,&(data->x.base),&size); \ |
} |
|
SET_DATA_TABLE(UtilityPipeLine); |
SET_DATA_TABLE(MultimediaCapabilityInfo); |
SET_DATA_TABLE(MultimediaConfigInfo); |
SET_DATA_TABLE(StandardVESA_Timing); |
SET_DATA_TABLE_VERS(FirmwareInfo); |
SET_DATA_TABLE(DAC_Info); |
SET_DATA_TABLE_VERS(LVDS_Info); |
SET_DATA_TABLE(TMDS_Info); |
SET_DATA_TABLE(AnalogTV_Info); |
SET_DATA_TABLE_VERS(SupportedDevicesInfo); |
SET_DATA_TABLE(GPIO_I2C_Info); |
SET_DATA_TABLE(VRAM_UsageByFirmware); |
SET_DATA_TABLE(GPIO_Pin_LUT); |
SET_DATA_TABLE(VESA_ToInternalModeLUT); |
SET_DATA_TABLE_VERS(ComponentVideoInfo); |
SET_DATA_TABLE(PowerPlayInfo); |
SET_DATA_TABLE(CompassionateData); |
SET_DATA_TABLE(SaveRestoreInfo); |
SET_DATA_TABLE(PPLL_SS_Info); |
SET_DATA_TABLE(OemInfo); |
SET_DATA_TABLE(XTMDS_Info); |
SET_DATA_TABLE(MclkSS_Info); |
SET_DATA_TABLE(Object_Header); |
SET_DATA_TABLE(IndirectIOAccess); |
SET_DATA_TABLE(MC_InitParameter); |
SET_DATA_TABLE(ASIC_VDDC_Info); |
SET_DATA_TABLE(ASIC_InternalSS_Info); |
SET_DATA_TABLE(TV_VideoMode); |
SET_DATA_TABLE_VERS(VRAM_Info); |
SET_DATA_TABLE(MemoryTrainingInfo); |
SET_DATA_TABLE_VERS(IntegratedSystemInfo); |
SET_DATA_TABLE(ASIC_ProfilingInfo); |
SET_DATA_TABLE(VoltageObjectInfo); |
SET_DATA_TABLE(PowerSourceInfo); |
# undef SET_DATA_TABLE |
|
return TRUE; |
} |
|
static Bool |
rhdAtomGetTables(RHDPtr rhdPtr, unsigned char *base, |
atomDataTables *atomDataPtr, unsigned char **codeTablePtr, |
unsigned int BIOSImageSize) |
{ |
unsigned int data_offset; |
unsigned int code_offset; |
int scrnIndex=0; |
|
unsigned int atom_romhdr_off = *(unsigned short*) |
(base + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); |
ATOM_ROM_HEADER *atom_rom_hdr = |
(ATOM_ROM_HEADER *)(base + atom_romhdr_off); |
|
RHDFUNCI(scrnIndex); |
|
if (atom_romhdr_off + sizeof(ATOM_ROM_HEADER) > BIOSImageSize) { |
xf86DrvMsg(scrnIndex,X_ERROR, |
"%s: AtomROM header extends beyond BIOS image\n",__func__); |
return FALSE; |
} |
|
if (memcmp("ATOM",&atom_rom_hdr->uaFirmWareSignature,4)) { |
xf86DrvMsg(scrnIndex,X_ERROR,"%s: No AtomBios signature found\n", |
__func__); |
return FALSE; |
} |
xf86DrvMsg(scrnIndex, X_INFO, "ATOM BIOS Rom: \n"); |
if (!rhdAtomAnalyzeRomHdr(base, atom_rom_hdr, &data_offset, &code_offset)) { |
xf86DrvMsg(scrnIndex, X_ERROR, "RomHeader invalid\n"); |
return FALSE; |
} |
|
if (data_offset + sizeof (ATOM_MASTER_DATA_TABLE) > BIOSImageSize) { |
xf86DrvMsg(scrnIndex,X_ERROR,"%s: Atom data table outside of BIOS\n", |
__func__); |
return FALSE; |
} |
|
if (code_offset + sizeof (ATOM_MASTER_COMMAND_TABLE) > BIOSImageSize) { |
xf86DrvMsg(scrnIndex, X_ERROR, "%s: Atom command table outside of BIOS\n", |
__func__); |
(*codeTablePtr) = NULL; |
} else |
(*codeTablePtr) = base + code_offset; |
|
if (!rhdAtomAnalyzeMasterDataTable(base, (ATOM_MASTER_DATA_TABLE *) |
(base + data_offset), |
atomDataPtr)) { |
xf86DrvMsg(scrnIndex, X_ERROR, "%s: ROM Master Table invalid\n", |
__func__); |
return FALSE; |
} |
|
return TRUE; |
} |
|
static Bool |
rhdAtomGetFbBaseAndSize(atomBiosHandlePtr handle, unsigned int *base, |
unsigned int *size) |
{ |
AtomBiosArgRec data; |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, GET_FW_FB_SIZE, &data) |
== ATOM_SUCCESS) { |
if (data.val == 0) { |
xf86DrvMsg(handle->scrnIndex, X_WARNING, "%s: AtomBIOS specified VRAM " |
"scratch space size invalid\n", __func__); |
return FALSE; |
} |
if (size) |
*size = (int)data.val; |
} else |
return FALSE; |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, GET_FW_FB_START, &data) |
== ATOM_SUCCESS) { |
if (data.val == 0) |
return FALSE; |
if (base) |
*base = (int)data.val; |
} |
return TRUE; |
} |
|
/* |
* Uses videoRam form ScrnInfoRec. |
*/ |
static AtomBiosResult |
rhdAtomAllocateFbScratch(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
unsigned int fb_base = 0; |
unsigned int fb_size = 0; |
unsigned int start = data->fb.start; |
unsigned int size = data->fb.size; |
handle->scratchBase = NULL; |
handle->fbBase = 0; |
|
if (rhdAtomGetFbBaseAndSize(handle, &fb_base, &fb_size)) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS requests %ikB" |
" of VRAM scratch space\n",fb_size); |
fb_size *= 1024; /* convert to bytes */ |
xf86DrvMsg(handle->scrnIndex, X_INFO, "AtomBIOS VRAM scratch base: 0x%x\n", |
fb_base); |
} else { |
fb_size = 20 * 1024; |
xf86DrvMsg(handle->scrnIndex, X_INFO, " default to: %i\n",fb_size); |
} |
if (fb_base && fb_size && size) { |
/* 4k align */ |
fb_size = (fb_size & ~(CARD32)0xfff) + ((fb_size & 0xfff) ? 1 : 0); |
if ((fb_base + fb_size) > (start + size)) { |
xf86DrvMsg(handle->scrnIndex, X_WARNING, |
"%s: FW FB scratch area %i (size: %i)" |
" extends beyond available framebuffer size %i\n", |
__func__, fb_base, fb_size, size); |
} else if ((fb_base + fb_size) < (start + size)) { |
xf86DrvMsg(handle->scrnIndex, X_WARNING, |
"%s: FW FB scratch area not located " |
"at the end of VRAM. Scratch End: " |
"0x%x VRAM End: 0x%x\n", __func__, |
(unsigned int)(fb_base + fb_size), |
size); |
} else if (fb_base < start) { |
xf86DrvMsg(handle->scrnIndex, X_WARNING, |
"%s: FW FB scratch area extends below " |
"the base of the free VRAM: 0x%x Base: 0x%x\n", |
__func__, (unsigned int)(fb_base), start); |
} else { |
size -= fb_size; |
handle->fbBase = fb_base; |
return ATOM_SUCCESS; |
} |
} |
|
if (!handle->fbBase) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, |
"Cannot get VRAM scratch space. " |
"Allocating in main memory instead\n"); |
handle->scratchBase = xcalloc(fb_size,1); |
return ATOM_SUCCESS; |
} |
return ATOM_FAILED; |
} |
|
# ifdef ATOM_BIOS_PARSER |
static Bool |
rhdAtomASICInit(atomBiosHandlePtr handle) |
{ |
ASIC_INIT_PS_ALLOCATION asicInit; |
AtomBiosArgRec data; |
|
RHDFUNC(handle); |
|
RHDAtomBiosFunc(handle->rhdPtr, handle, |
GET_DEFAULT_ENGINE_CLOCK, |
&data); |
asicInit.sASICInitClocks.ulDefaultEngineClock = data.val / 10;/*in 10 Khz*/ |
RHDAtomBiosFunc(handle->rhdPtr, handle, |
GET_DEFAULT_MEMORY_CLOCK, |
&data); |
asicInit.sASICInitClocks.ulDefaultMemoryClock = data.val / 10;/*in 10 Khz*/ |
data.exec.dataSpace = NULL; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, ASIC_Init); |
data.exec.pspace = &asicInit; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling ASIC Init\n"); |
atomDebugPrintPspace(handle, &data, sizeof(asicInit)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomASICInitVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, ASIC_Init); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomSetScaler(atomBiosHandlePtr handle, enum atomScaler scalerID, enum atomScaleMode mode) |
{ |
ENABLE_SCALER_PARAMETERS scaler; |
AtomBiosArgRec data; |
|
RHDFUNC(handle); |
|
switch (scalerID) { |
case atomScaler1: |
scaler.ucScaler = ATOM_SCALER1; |
break; |
case atomScaler2: |
scaler.ucScaler = ATOM_SCALER2; |
break; |
} |
|
switch (mode) { |
case atomScaleDisable: |
scaler.ucEnable = ATOM_SCALER_DISABLE; |
break; |
case atomScaleCenter: |
scaler.ucEnable = ATOM_SCALER_CENTER; |
break; |
case atomScaleExpand: |
scaler.ucEnable = ATOM_SCALER_EXPANSION; |
break; |
case atomScaleMulttabExpand: |
scaler.ucEnable = ATOM_SCALER_MULTI_EX; |
break; |
} |
|
data.exec.dataSpace = NULL; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler); |
data.exec.pspace = &scaler; |
atomDebugPrintPspace(handle, &data, sizeof(scaler)); |
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableScaler\n"); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableScaler Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableScaler Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomSetScalerVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomSetTVEncoder(atomBiosHandlePtr handle, Bool enable, int mode) |
{ |
TV_ENCODER_CONTROL_PS_ALLOCATION tvEncoder; |
AtomBiosArgRec data; |
|
RHDFUNC(handle); |
|
tvEncoder.sTVEncoder.ucTvStandard = mode; |
tvEncoder.sTVEncoder.ucAction = enable ? 1 :0; |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &tvEncoder; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetTVEncoder\n"); |
atomDebugPrintPspace(handle, &data, sizeof(tvEncoder)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetTVEncoder Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetTVEncoder Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
#if (ATOM_TRANSMITTER_CONFIG_COHERENT != ATOM_TRANSMITTER_CONFIG_V2_COHERENT) |
# error |
#endif |
|
Bool |
rhdAtomDigTransmitterControl(atomBiosHandlePtr handle, enum atomTransmitter id, |
enum atomTransmitterAction action, struct atomTransmitterConfig *config) |
{ |
DIG_TRANSMITTER_CONTROL_PARAMETERS Transmitter; |
AtomBiosArgRec data; |
char *name = NULL; |
struct atomCodeTableVersion version; |
|
RHDFUNC(handle); |
|
switch (action) { |
case atomTransDisable: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_DISABLE; |
break; |
case atomTransEnable: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE; |
break; |
case atomTransEnableOutput: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT; |
break; |
case atomTransDisableOutput: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT; |
break; |
case atomTransLcdBlOff: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_LCD_BLOFF; |
break; |
case atomTransLcdBlOn: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_LCD_BLON; |
break; |
case atomTransLcdBlBrightness: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL; |
break; |
case atomTransSetup: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_SETUP; |
break; |
case atomTransInit: |
Transmitter.ucAction = ATOM_TRANSMITTER_ACTION_INIT; |
break; |
} |
|
Transmitter.ucConfig = 0; |
|
/* INIT is only called by ASIC_Init, for our actions this is always the PXLCLK */ |
switch (config->LinkCnt) { |
case atomSingleLink: |
Transmitter.usPixelClock = config->PixelClock * 4 / 10; |
break; |
|
case atomDualLink: |
Transmitter.usPixelClock = config->PixelClock * 2/ 10; |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; |
break; |
} |
|
if (config->Coherent) |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; |
|
switch (id) { |
case atomTransmitterDIG1: |
case atomTransmitterUNIPHY: |
case atomTransmitterUNIPHY1: |
case atomTransmitterUNIPHY2: |
case atomTransmitterPCIEPHY: |
data.exec.index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); |
name = "UNIPHYTransmitterControl"; |
|
rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version.cref, &version.fref, NULL); |
|
if (version.fref > 1 || version.cref > 2) |
return FALSE; |
|
switch (version.cref) { |
case 1: |
|
switch (config->Link) { |
case atomTransLinkA: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; |
break; |
case atomTransLinkAB: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA_B; |
break; |
case atomTransLinkB: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; |
break; |
case atomTransLinkBA: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB_A; |
break; |
} |
switch (config->Encoder) { |
case atomEncoderDIG1: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; |
break; |
|
case atomEncoderDIG2: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s called with invalid encoder %x for DIG transmitter\n", |
__func__, config->Encoder); |
return FALSE; |
} |
if (id == atomTransmitterPCIEPHY) { |
switch (config->Lanes) { |
case atomPCIELaneNONE: |
Transmitter.ucConfig |= 0; |
break; |
case atomPCIELane0_3: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; |
break; |
case atomPCIELane0_7: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; |
break; |
case atomPCIELane4_7: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; |
break; |
case atomPCIELane8_11: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; |
break; |
case atomPCIELane8_15: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; |
break; |
case atomPCIELane12_15: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; |
break; |
} |
/* According to ATI this is the only one used so far */ |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; |
} |
break; |
case 2: |
if (id == atomTransmitterPCIEPHY) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s PCIPHY not valid for DCE 3.2\n", |
__func__); |
return FALSE; |
} |
switch (config->Link) { |
case atomTransLinkA: |
case atomTransLinkAB: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_LINKA; |
break; |
case atomTransLinkB: |
case atomTransLinkBA: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_LINKB; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s called with invalid transmitter link selection %x for DIG transmitter\n", |
__func__, config->Link); |
return FALSE; |
} |
switch (config->Encoder) { |
case atomEncoderDIG1: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER; |
break; |
case atomEncoderDIG2: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s called with invalid encoder %x for DIG transmitter\n", |
__func__, config->Encoder); |
return FALSE; |
} |
switch (id) { |
case atomTransmitterUNIPHY: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1; |
break; |
case atomTransmitterUNIPHY1: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2; |
break; |
case atomTransmitterUNIPHY2: |
Transmitter.ucConfig |= ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3; |
break; |
default: |
break; |
} |
|
if (config->Mode == atomDP) |
Transmitter.ucConfig |= ATOM_TRASMITTER_CONFIG_V2_DP_CONNECTOR; |
break; |
} |
|
break; |
|
case atomTransmitterLVTMA: |
case atomTransmitterDIG2: |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); |
name = "DIG2TransmitterControl"; |
break; |
} |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &Transmitter; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name); |
atomDebugPrintPspace(handle, &data, sizeof(Transmitter)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Failed\n",name); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomDigTransmitterControlVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
DEBUG_VERSION(index, handle, version); |
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomOutputControl(atomBiosHandlePtr handle, enum atomOutput OutputId, enum atomOutputAction Action) |
{ |
AtomBiosArgRec data; |
CARD8 version; |
char *name; |
|
union |
{ |
DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS op; |
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION opa; |
} ps; |
|
RHDFUNC(handle); |
|
switch (Action) { |
case atomOutputEnable: |
ps.op.ucAction = ATOM_ENABLE; |
break; |
case atomOutputDisable: |
ps.op.ucAction = ATOM_DISABLE; |
break; |
default: /* handle below */ |
if (OutputId != atomLCDOutput) |
return FALSE; |
} |
|
switch (OutputId) { |
case atomDVOOutput: |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); |
name = "DVOOutputControl"; |
if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL)) |
return FALSE; |
switch (version) { |
case 1: |
case 2: |
break; |
case 3: /* For now. This needs to be treated like DIGTransmitterControl. @@@ */ |
return FALSE; |
} |
break; |
case atomLCDOutput: |
data.exec.index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); |
name = "LCD1OutputControl"; |
switch (Action) { |
case atomOutputEnable: |
case atomOutputDisable: |
break; |
case atomOutputLcdOn: |
ps.op.ucAction = ATOM_LCD_BLON; |
break; |
case atomOutputLcdOff: |
ps.op.ucAction = ATOM_LCD_BLOFF; |
break; |
case atomOutputLcdBrightnessControl: |
ps.op.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL; |
break; |
case atomOutputLcdSelftestStart: |
ps.op.ucAction = ATOM_LCD_SELFTEST_START; |
break; |
case atomOutputLcdSelftestStop: |
ps.op.ucAction = ATOM_LCD_SELFTEST_STOP; |
break; |
case atomOutputEncoderInit: |
ps.op.ucAction = ATOM_ENCODER_INIT; |
break; |
default: |
return FALSE; |
} |
break; |
case atomCVOutput: |
data.exec.index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); |
name = "CV1OutputControl"; |
break; |
case atomTVOutput: |
name = "TV1OutputControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); |
break; |
case atomLVTMAOutput: |
name = "LVTMAOutputControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); |
switch (Action) { |
case atomOutputEnable: |
case atomOutputDisable: |
break; |
case atomOutputLcdOn: |
ps.op.ucAction = ATOM_LCD_BLON; |
break; |
case atomOutputLcdOff: |
ps.op.ucAction = ATOM_LCD_BLOFF; |
break; |
case atomOutputLcdBrightnessControl: |
ps.op.ucAction = ATOM_LCD_BL_BRIGHTNESS_CONTROL; |
break; |
case atomOutputLcdSelftestStart: |
ps.op.ucAction = ATOM_LCD_SELFTEST_START; |
break; |
case atomOutputLcdSelftestStop: |
ps.op.ucAction = ATOM_LCD_SELFTEST_STOP; |
break; |
case atomOutputEncoderInit: |
ps.op.ucAction = ATOM_ENCODER_INIT; |
break; |
default: |
return FALSE; |
} |
break; |
case atomTMDSAOutput: |
name = "TMDSAOutputControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); |
break; |
case atomDAC1Output: |
name = "DAC1OutputControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); |
break; |
case atomDAC2Output: |
name = "DAC2OutputControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); |
break; |
default: |
return FALSE; |
} |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Failed\n",name); |
|
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomOutputControlVersion(atomBiosHandlePtr handle, enum atomOutput OutputId) |
{ |
struct atomCodeTableVersion version = {0 , 0}; |
int index; |
char *name; |
|
switch (OutputId) { |
case atomDVOOutput: |
index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); |
name = "DVOOutputControl"; |
break; |
case atomLCDOutput: |
index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); |
name = "LCD1OutputControl"; |
break; |
case atomCVOutput: |
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); |
name = "CV1OutputControl"; |
break; |
case atomTVOutput: |
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); |
name = "TV1OutputControl"; |
break; |
case atomLVTMAOutput: |
index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); |
name = "LVTMAOutputControl"; |
break; |
case atomTMDSAOutput: |
index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); |
name = "TMDSAOutputControl"; |
break; |
case atomDAC1Output: |
index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); |
name = "DAC1OutputControl"; |
break; |
case atomDAC2Output: |
index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); |
name = "DAC2OutputContro"; |
break; |
default: |
return version; |
} |
|
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
DEBUG_VERSION_NAME(index, handle, name, version); |
return version; |
} |
|
/* |
* |
*/ |
Bool |
AtomDACLoadDetection(atomBiosHandlePtr handle, enum atomDevice Device, enum atomDAC dac) |
{ |
AtomBiosArgRec data; |
union |
{ |
DAC_LOAD_DETECTION_PARAMETERS ld; |
DAC_LOAD_DETECTION_PS_ALLOCATION lda; |
} ps; |
|
RHDFUNC(handle); |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); |
ps.ld.ucMisc = 0; |
|
switch (Device) { |
case atomCRT1: |
ps.ld.usDeviceID = ATOM_DEVICE_CRT1_SUPPORT; |
break; |
case atomCRT2: |
ps.ld.usDeviceID = ATOM_DEVICE_CRT2_SUPPORT; |
break; |
case atomTV1: |
ps.ld.usDeviceID = ATOM_DEVICE_TV1_SUPPORT; |
ps.ld.ucMisc = DAC_LOAD_MISC_YPrPb; |
break; |
case atomTV2: |
ps.ld.usDeviceID = ATOM_DEVICE_TV2_SUPPORT; |
ps.ld.ucMisc = DAC_LOAD_MISC_YPrPb; |
break; |
case atomCV: |
ps.ld.usDeviceID = ATOM_DEVICE_CV_SUPPORT; |
break; |
case atomLCD1: |
case atomDFP1: |
case atomLCD2: |
case atomDFP2: |
case atomDFP3: |
case atomDFP4: |
case atomDFP5: |
case atomNone: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "Unsupported device for load detection.\n"); |
return FALSE; |
} |
switch (dac) { |
case atomDACA: |
ps.ld.ucDacType = ATOM_DAC_A; |
break; |
case atomDACB: |
ps.ld.ucDacType = ATOM_DAC_B; |
break; |
case atomDACExt: |
ps.ld.ucDacType = ATOM_EXT_DAC; |
break; |
} |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling DAC_LoadDetection\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "DAC_LoadDetection Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "DAC_LoadDetection Failed\n"); |
|
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
AtomDACLoadDetectionVersion(atomBiosHandlePtr handle, enum atomDevice id) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
|
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomEncoderControl(atomBiosHandlePtr handle, enum atomEncoder EncoderId, |
enum atomEncoderAction Action, struct atomEncoderConfig *Config) |
{ |
AtomBiosArgRec data; |
char *name = NULL; |
CARD8 version; |
|
union |
{ |
DAC_ENCODER_CONTROL_PARAMETERS dac; |
DAC_ENCODER_CONTROL_PS_ALLOCATION dac_a; |
TV_ENCODER_CONTROL_PARAMETERS tv; |
TV_ENCODER_CONTROL_PS_ALLOCATION tv_a; |
LVDS_ENCODER_CONTROL_PARAMETERS lvds; |
LVDS_ENCODER_CONTROL_PS_ALLOCATION lvds_a; |
DIG_ENCODER_CONTROL_PARAMETERS dig; |
DIG_ENCODER_CONTROL_PS_ALLOCATION dig_a; |
EXTERNAL_ENCODER_CONTROL_PARAMETER ext; |
EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION ext_a; |
DVO_ENCODER_CONTROL_PARAMETERS dvo; |
DVO_ENCODER_CONTROL_PS_ALLOCATION dvo_a; |
DVO_ENCODER_CONTROL_PARAMETERS_V3 dvo_v3; |
DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 dvo_v3_a; |
LVDS_ENCODER_CONTROL_PARAMETERS_V2 lvdsv2; |
LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 lvds2_a; |
USHORT usPixelClock; |
} ps; |
|
RHDFUNC(handle); |
|
ps.usPixelClock = Config->PixelClock / 10; |
|
switch (EncoderId) { |
case atomEncoderDACA: |
case atomEncoderDACB: |
if (EncoderId == atomEncoderDACA) { |
name = "DACAEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); |
} else { |
name = "DACBEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); |
} |
{ |
DAC_ENCODER_CONTROL_PARAMETERS *dac = &ps.dac; |
switch (Config->u.dac.DacStandard) { |
case atomDAC_VGA: |
dac->ucDacStandard = ATOM_DAC1_PS2; |
break; |
case atomDAC_CV: |
dac->ucDacStandard = ATOM_DAC1_CV; |
break; |
case atomDAC_NTSC: |
dac->ucDacStandard = ATOM_DAC1_NTSC; |
break; |
case atomDAC_PAL: |
dac->ucDacStandard = ATOM_DAC1_PAL; |
break; |
} |
switch (Action) { |
case atomEncoderOn: |
dac->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
dac->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DAC unknown action\n",__func__); |
return FALSE; |
} |
} |
break; |
case atomEncoderTV: |
data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); |
name = "TVAEncoderControl"; |
{ |
TV_ENCODER_CONTROL_PARAMETERS *tv = &ps.tv; |
switch (Config->u.tv.TvStandard) { |
case RHD_TV_NTSC: |
tv->ucTvStandard = ATOM_TV_NTSC; |
break; |
case RHD_TV_NTSCJ: |
tv->ucTvStandard = ATOM_TV_NTSCJ; |
break; |
case RHD_TV_PAL: |
tv->ucTvStandard = ATOM_TV_PAL; |
break; |
case RHD_TV_PALM: |
tv->ucTvStandard = ATOM_TV_PALM; |
break; |
case RHD_TV_PALCN: |
tv->ucTvStandard = ATOM_TV_PALCN; |
break; |
case RHD_TV_PALN: |
tv->ucTvStandard = ATOM_TV_PALN; |
break; |
case RHD_TV_PAL60: |
tv->ucTvStandard = ATOM_TV_PAL60; |
break; |
case RHD_TV_SECAM: |
tv->ucTvStandard = ATOM_TV_SECAM; |
break; |
case RHD_TV_CV: |
tv->ucTvStandard = ATOM_TV_CV; |
break; |
case RHD_TV_NONE: |
return FALSE; |
} |
switch (Action) { |
case atomEncoderOn: |
tv->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
tv->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: TV unknown action\n",__func__); |
return FALSE; |
} |
} |
break; |
case atomEncoderTMDS1: |
case atomEncoderTMDS2: |
case atomEncoderLVDS: |
if (EncoderId == atomEncoderLVDS) { |
name = "LVDSEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); |
} else if (EncoderId == atomEncoderTMDS1) { |
name = "TMDSAEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, TMDSAEncoderControl); |
} else { |
name = "LVTMAEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, LVTMAEncoderControl); |
} |
if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL)) |
return FALSE; |
switch (version) { |
case 1: |
{ |
LVDS_ENCODER_CONTROL_PARAMETERS *lvds = &ps.lvds; |
lvds->ucMisc = 0; |
if (Config->u.lvds.LinkCnt == atomDualLink) |
lvds->ucMisc |= 0x1; |
if (Config->u.lvds.Is24bit) |
lvds->ucMisc |= 0x1 << 1; |
|
switch (Action) { |
case atomEncoderOn: |
lvds->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
lvds->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: LVDS unknown action\n",__func__); |
return FALSE; |
} |
break; |
} |
case 2: |
case 3: |
{ |
LVDS_ENCODER_CONTROL_PARAMETERS_V2 *lvds = &ps.lvdsv2; |
|
lvds->ucMisc = 0; |
if (Config->u.lvds2.LinkCnt == atomDualLink) |
lvds->ucMisc |= PANEL_ENCODER_MISC_DUAL; |
if (Config->u.lvds2.Coherent) |
lvds->ucMisc |= PANEL_ENCODER_MISC_COHERENT; |
if (Config->u.lvds2.LinkB) |
lvds->ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; |
if (Config->u.lvds2.Hdmi) |
lvds->ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; |
lvds->ucTruncate = 0; |
lvds->ucSpatial = 0; |
lvds->ucTemporal = 0; |
lvds->ucFRC = 0; |
|
if (EncoderId == atomEncoderLVDS) { |
if (Config->u.lvds2.Is24bit) { |
lvds->ucTruncate |= PANEL_ENCODER_TRUNCATE_DEPTH; |
lvds->ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; |
lvds->ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; |
} |
switch (Config->u.lvds2.TemporalGrey) { |
case atomTemporalDither0: |
break; |
case atomTemporalDither4: |
lvds->ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; |
case atomTemporalDither2: |
lvds->ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_EN; |
break; |
} |
switch (Config->u.lvds2.SpatialDither) |
lvds->ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_EN; |
} |
|
switch (Action) { |
case atomEncoderOn: |
lvds->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
lvds->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: LVDS2 unknown action\n",__func__); |
return FALSE; |
} |
break; |
} |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: LVDS unknown version\n",__func__); |
return FALSE; |
} |
break; |
case atomEncoderDIG1: |
case atomEncoderDIG2: |
case atomEncoderExternal: |
{ |
DIG_ENCODER_CONTROL_PARAMETERS *dig = &ps.dig; |
struct atomCodeTableVersion version; |
|
if (EncoderId == atomEncoderDIG1) { |
name = "DIG1EncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); |
} else if (EncoderId == atomEncoderDIG2) { |
name = "DIG2EncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); |
} else { |
name = "ExternalEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); |
} |
rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version.cref, &version.fref, NULL); |
if (version.fref > 1 || version.cref > 2) |
return FALSE; |
|
dig->ucConfig = 0; |
switch (version.cref) { |
case 1: |
switch (Config->u.dig.Link) { |
case atomTransLinkA: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKA; |
break; |
case atomTransLinkAB: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; |
break; |
case atomTransLinkB: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKB; |
break; |
case atomTransLinkBA: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_LINKB_A; |
break; |
} |
|
if (EncoderId != atomEncoderExternal) { |
switch (Config->u.dig.Transmitter) { |
case atomTransmitterUNIPHY: |
case atomTransmitterPCIEPHY: |
case atomTransmitterDIG1: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_UNIPHY; |
break; |
case atomTransmitterLVTMA: |
case atomTransmitterDIG2: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_LVTMA; |
break; |
/* |
* these are not DCE3.0 but we need them here as DIGxEncoderControl tables for |
* DCE3.2 still report cref 1. |
*/ |
case atomTransmitterUNIPHY1: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; |
break; |
case atomTransmitterUNIPHY2: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: Invalid Transmitter for DCE3.0: %x\n", |
__func__, Config->u.dig.Transmitter); |
return FALSE; |
} |
} |
break; |
|
case 2: |
switch (Config->u.dig.Link) { |
case atomTransLinkA: |
case atomTransLinkAB: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_LINKA; |
break; |
case atomTransLinkB: |
case atomTransLinkBA: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_LINKB; |
break; |
} |
switch (Config->u.dig.Transmitter) { |
case atomTransmitterUNIPHY: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_UNIPHY; |
break; |
case atomTransmitterUNIPHY1: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; |
break; |
case atomTransmitterUNIPHY2: |
dig->ucConfig |= ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: Invalid Encoder for DCE3.2: %x\n", |
__func__, Config->u.dig.Transmitter); |
return FALSE; |
} |
break; |
|
default: |
return FALSE; |
} |
|
switch (Config->u.dig.EncoderMode) { |
case atomDVI: |
dig->ucEncoderMode = ATOM_ENCODER_MODE_DVI; |
break; |
case atomDP: |
dig->ucEncoderMode = ATOM_ENCODER_MODE_DP; |
break; |
case atomLVDS: |
dig->ucEncoderMode = ATOM_ENCODER_MODE_LVDS; |
break; |
case atomHDMI: |
dig->ucEncoderMode = ATOM_ENCODER_MODE_HDMI; |
break; |
case atomSDVO: |
dig->ucEncoderMode = ATOM_ENCODER_MODE_SDVO; |
break; |
case atomNoEncoder: |
case atomTVComposite: |
case atomTVSVideo: |
case atomTVComponent: |
case atomCRT: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s called with invalid DIG encoder mode %i\n", |
__func__,Config->u.dig.EncoderMode); |
return FALSE; |
break; |
} |
|
switch (Action) { |
case atomEncoderOn: |
dig->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
dig->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DIG unknown action\n",__func__); |
return FALSE; |
} |
|
switch (Config->u.dig.LinkCnt) { |
case atomSingleLink: |
dig->ucLaneNum = 4; |
break; |
case atomDualLink: |
dig->ucLaneNum = 8; |
break; |
} |
break; |
case atomEncoderDVO: |
name = "DVOEncoderControl"; |
data.exec.index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); |
if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version.cref, NULL, NULL)) |
return FALSE; |
switch (version.cref) { |
case 1: |
case 2: |
{ |
DVO_ENCODER_CONTROL_PARAMETERS *dvo = &ps.dvo; |
dvo->usEncoderID = Config->u.dvo.EncoderID; |
switch (Config->u.dvo.DvoDeviceType) { |
case atomLCD1: |
case atomLCD2: |
dvo->ucDeviceType = ATOM_DEVICE_LCD1_INDEX; |
break; |
case atomCRT1: |
case atomCRT2: |
dvo->ucDeviceType = ATOM_DEVICE_CRT1_INDEX; |
break; |
case atomDFP1: |
case atomDFP2: |
case atomDFP3: |
case atomDFP4: |
case atomDFP5: |
dvo->ucDeviceType = ATOM_DEVICE_DFP1_INDEX; |
break; |
case atomTV1: |
case atomTV2: |
dvo->ucDeviceType = ATOM_DEVICE_TV1_INDEX; |
break; |
case atomCV: |
dvo->ucDeviceType = ATOM_DEVICE_CV_INDEX; |
break; |
case atomNone: |
return FALSE; |
} |
if (Config->u.dvo.digital) { |
dvo->usDevAttr.sDigAttrib.ucAttribute = 0; /* @@@ What do these attributes mean? */ |
} else { |
switch (Config->u.dvo.u.TVMode) { |
case RHD_TV_NTSC: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_NTSC; |
break; |
case RHD_TV_NTSCJ: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_NTSCJ; |
break; |
case RHD_TV_PAL: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PAL; |
break; |
case RHD_TV_PALM: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PALM; |
break; |
case RHD_TV_PALCN: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PALCN; |
break; |
case RHD_TV_PALN: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PALN; |
break; |
case RHD_TV_PAL60: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_PAL60; |
break; |
case RHD_TV_SECAM: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_SECAM; |
break; |
case RHD_TV_CV: |
dvo->usDevAttr.sAlgAttrib.ucTVStandard = ATOM_TV_CV; |
break; |
case RHD_TV_NONE: |
return FALSE; |
} |
} |
switch (Action) { |
case atomEncoderOn: |
dvo->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
dvo->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DVO unknown action\n",__func__); |
return FALSE; |
} |
break; |
} |
case 3: |
{ |
DVO_ENCODER_CONTROL_PARAMETERS_V3 *dvo = &ps.dvo_v3; |
dvo->ucDVOConfig = 0; |
if (Config->u.dvo3.Rate == atomDVO_RateSDR) |
dvo->ucDVOConfig |= DVO_ENCODER_CONFIG_SDR_SPEED; |
else |
dvo->ucDVOConfig |= DVO_ENCODER_CONFIG_DDR_SPEED; |
switch (Config->u.dvo3.DvoOutput) { |
case atomDVO_OutputLow12Bit: |
dvo->ucDVOConfig = DVO_ENCODER_CONFIG_LOW12BIT; |
break; |
case atomDVO_OutputHigh12Bit: |
dvo->ucDVOConfig = DVO_ENCODER_CONFIG_UPPER12BIT; |
break; |
case atomDVO_Output24Bit: |
dvo->ucDVOConfig = DVO_ENCODER_CONFIG_24BIT; |
break; |
} |
switch (Action) { |
case atomEncoderOn: |
dvo->ucAction = ATOM_ENABLE; |
break; |
case atomEncoderOff: |
dvo->ucAction = ATOM_DISABLE; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: DVO3 unknown action\n",__func__); |
return FALSE; |
} |
break; |
} |
} |
break; |
} |
case atomEncoderNone: |
return FALSE; |
} |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Failed\n",name); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomEncoderControlVersion(atomBiosHandlePtr handle, enum atomEncoder EncoderId) |
{ |
struct atomCodeTableVersion version = { 0, 0 }; |
int index; |
char *name; |
|
switch (EncoderId) { |
case atomEncoderDACA: |
index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); |
name = "DAC1EncoderControl"; |
break; |
case atomEncoderDACB: |
index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); |
name = "DAC2EncoderControl"; |
break; |
case atomEncoderTV: |
index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); |
name = "TVEncoderControl"; |
break; |
case atomEncoderTMDS1: |
case atomEncoderTMDS2: |
index = GetIndexIntoMasterTable(COMMAND, TMDSAEncoderControl); |
name = "TMDSAEncoderControl"; |
break; |
case atomEncoderLVDS: |
index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); |
name = " LVDSEncoderControl"; |
break; |
case atomEncoderDIG1: |
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); |
name = "DIG1EncoderControl"; |
break; |
case atomEncoderDIG2: |
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); |
name = "DIG2EncoderControl"; |
break; |
case atomEncoderExternal: |
index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); |
name = "ExternalEncoderControl"; |
break; |
case atomEncoderDVO: |
index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); |
name = "DVOEncoderControl"; |
break; |
default: |
return version; |
} |
|
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION_NAME(index, handle, name, version); |
|
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomUpdateCRTC_DoubleBufferRegisters(atomBiosHandlePtr handle, enum atomCrtc CrtcId, |
enum atomCrtcAction Action) |
{ |
AtomBiosArgRec data; |
union |
{ |
ENABLE_CRTC_PARAMETERS crtc; |
ENABLE_CRTC_PS_ALLOCATION crtc_a; |
} ps; |
|
RHDFUNC(handle); |
|
switch (CrtcId) { |
case atomCrtc1: |
ps.crtc.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.crtc.ucCRTC = ATOM_CRTC2; |
break; |
} |
|
switch (Action) { |
case atomCrtcEnable: |
ps.crtc.ucEnable = ATOM_ENABLE; |
break; |
case atomCrtcDisable: |
ps.crtc.ucEnable = ATOM_DISABLE; |
break; |
} |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling UpdateCRTC_DoubleBufferRegisters\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "UpdateCRTC_DoubleBufferRegisters Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "UpdateCRTC_DoubleBufferRegisters Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomUpdateCRTC_DoubleBufferRegistersVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
|
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomEnableCrtc(atomBiosHandlePtr handle, enum atomCrtc CrtcId, |
enum atomCrtcAction Action) |
{ |
AtomBiosArgRec data; |
union |
{ |
ENABLE_CRTC_PARAMETERS crtc; |
ENABLE_CRTC_PS_ALLOCATION crtc_a; |
} ps; |
|
RHDFUNC(handle); |
|
switch (CrtcId) { |
case atomCrtc1: |
ps.crtc.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.crtc.ucCRTC = ATOM_CRTC2; |
break; |
} |
|
switch (Action) { |
case atomCrtcEnable: |
ps.crtc.ucEnable = ATOM_ENABLE; |
break; |
case atomCrtcDisable: |
ps.crtc.ucEnable = ATOM_DISABLE; |
break; |
} |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableCRTC\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTC Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTC Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomEnableCrtcVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
|
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomEnableCrtcMemReq(atomBiosHandlePtr handle, enum atomCrtc CrtcId, |
enum atomCrtcAction Action) |
{ |
AtomBiosArgRec data; |
union |
{ |
ENABLE_CRTC_PARAMETERS crtc; |
ENABLE_CRTC_PS_ALLOCATION crtc_a; |
} ps; |
|
RHDFUNC(handle); |
|
switch (CrtcId) { |
case atomCrtc1: |
ps.crtc.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.crtc.ucCRTC = ATOM_CRTC2; |
break; |
} |
|
switch (Action) { |
case atomCrtcEnable: |
ps.crtc.ucEnable = ATOM_ENABLE; |
break; |
case atomCrtcDisable: |
ps.crtc.ucEnable = ATOM_DISABLE; |
break; |
} |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableCRTCMemReq\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTCMemReq Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "EnableCRTCMemReq Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomEnableCrtcMemReqVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
|
return version; |
|
} |
|
/* |
* |
*/ |
Bool |
rhdAtomSetCRTCTimings(atomBiosHandlePtr handle, enum atomCrtc id, DisplayModePtr mode, int depth) |
{ |
AtomBiosArgRec data; |
union |
{ |
SET_CRTC_TIMING_PARAMETERS crtc; |
/* SET_CRTC_TIMING_PS_ALLOCATION crtc_a; */ |
} ps; |
ATOM_MODE_MISC_INFO_ACCESS* msc = &(ps.crtc.susModeMiscInfo); |
|
RHDFUNC(handle); |
|
ps.crtc.usH_Total = mode->CrtcHTotal; |
ps.crtc.usH_Disp = mode->CrtcHDisplay; |
ps.crtc.usH_SyncStart = mode->CrtcHSyncStart; |
ps.crtc.usH_SyncWidth = mode->CrtcHSyncEnd - mode->CrtcHSyncStart; |
ps.crtc.usV_Total = mode->CrtcVTotal; |
ps.crtc.usV_Disp = mode->CrtcVDisplay; |
ps.crtc.usV_SyncStart = mode->CrtcVSyncStart; |
ps.crtc.usV_SyncWidth = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; |
ps.crtc.ucOverscanRight = mode->CrtcHBlankStart - mode->CrtcHDisplay; |
ps.crtc.ucOverscanLeft = mode->CrtcVTotal - mode->CrtcVBlankEnd; |
ps.crtc.ucOverscanBottom = mode->CrtcVBlankStart - mode->CrtcVDisplay; |
ps.crtc.ucOverscanTop = mode->CrtcVTotal - mode->CrtcVBlankEnd; |
switch (id) { |
case atomCrtc1: |
ps.crtc.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.crtc.ucCRTC = ATOM_CRTC2; |
break; |
} |
|
msc->sbfAccess.HorizontalCutOff = 0; |
msc->sbfAccess.HSyncPolarity = (mode->Flags & V_NHSYNC) ? 1 : 0; |
msc->sbfAccess.VSyncPolarity = (mode->Flags & V_NVSYNC) ? 1 : 0; |
msc->sbfAccess.VerticalCutOff = 0; |
msc->sbfAccess.H_ReplicationBy2 = 0; |
msc->sbfAccess.V_ReplicationBy2 = (mode->Flags & V_DBLSCAN) ? 1 : 0; |
msc->sbfAccess.CompositeSync = (mode->Flags & V_CSYNC); |
msc->sbfAccess.Interlace = (mode->Flags & V_INTERLACE) ? 1 : 0; |
msc->sbfAccess.DoubleClock = (mode->Flags & V_DBLCLK) ? 1 : 0; |
msc->sbfAccess.RGB888 = (depth == 24) ? 1 : 0; |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing); |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetCRTC_Timing\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetCRTC_Timing Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetCRTC_Timing Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomSetCRTCTimingsVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
return version; |
|
} |
|
/* |
* |
*/ |
Bool |
rhdAtomSetCRTCOverscan(atomBiosHandlePtr handle, enum atomCrtc id, struct atomCrtcOverscan *config) |
{ |
AtomBiosArgRec data; |
union |
{ |
SET_CRTC_OVERSCAN_PARAMETERS ovscn; |
SET_CRTC_OVERSCAN_PS_ALLOCATION ovscn_a; |
} ps; |
|
RHDFUNC(handle); |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); |
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
switch(id) { |
case atomCrtc1: |
ps.ovscn.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.ovscn.ucCRTC = ATOM_CRTC2; |
break; |
} |
ps.ovscn.usOverscanRight = config->ovscnRight; |
ps.ovscn.usOverscanLeft = config->ovscnLeft; |
ps.ovscn.usOverscanBottom = config->ovscnBottom; |
ps.ovscn.usOverscanTop = config->ovscnTop; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "CallingSetCRTC_OverScan\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "Set CRTC_OverScan Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetCRTC_OverScan Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomSetCRTCOverscanVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
return version; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomBlankCRTC(atomBiosHandlePtr handle, enum atomCrtc id, struct atomCrtcBlank *config) |
{ |
AtomBiosArgRec data; |
union |
{ |
BLANK_CRTC_PARAMETERS blank; |
BLANK_CRTC_PS_ALLOCATION blank_a; |
} ps; |
|
RHDFUNC(handle); |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); |
data.exec.pspace = &ps; |
data.exec.dataSpace = NULL; |
|
switch(id) { |
case atomCrtc1: |
ps.blank.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.blank.ucCRTC = ATOM_CRTC2; |
break; |
} |
|
switch (config->Action) { |
case atomBlankOn: |
ps.blank.ucBlanking = ATOM_BLANKING; |
break; |
case atomBlankOff: |
ps.blank.ucBlanking = ATOM_BLANKING_OFF; |
break; |
} |
ps.blank.usBlackColorRCr = config->r; |
ps.blank.usBlackColorGY = config->g; |
ps.blank.usBlackColorBCb = config->b; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling BlankCRTC\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "BlankCRTC Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "BlankCRTC Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomBlankCRTCVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
return version; |
} |
|
/* |
* |
*/ |
static int |
atomGetDevice(atomBiosHandlePtr handle, enum atomDevice Device) |
{ |
switch (Device) { |
case atomCRT1: |
return ATOM_DEVICE_CRT1_INDEX; |
case atomLCD1: |
return ATOM_DEVICE_LCD1_INDEX; |
case atomTV1: |
return ATOM_DEVICE_TV1_INDEX; |
case atomDFP1: |
return ATOM_DEVICE_DFP1_INDEX; |
case atomCRT2: |
return ATOM_DEVICE_CRT2_INDEX; |
case atomLCD2: |
return ATOM_DEVICE_LCD2_INDEX; |
case atomTV2: |
return ATOM_DEVICE_TV2_INDEX; |
case atomDFP2: |
return ATOM_DEVICE_DFP2_INDEX; |
case atomCV: |
return ATOM_DEVICE_CV_INDEX; |
case atomDFP3: |
return ATOM_DEVICE_DFP3_INDEX; |
case atomDFP4: |
return ATOM_DEVICE_DFP4_INDEX; |
case atomDFP5: |
return ATOM_DEVICE_DFP5_INDEX; |
case atomNone: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "Invalid Device\n"); |
return ATOM_MAX_SUPPORTED_DEVICE; |
} |
|
return ATOM_MAX_SUPPORTED_DEVICE; |
} |
|
/* |
* |
*/ |
Bool |
rhdAtomSetPixelClock(atomBiosHandlePtr handle, enum atomPxclk PCLKId, struct atomPixelClockConfig *Config) |
{ |
AtomBiosArgRec data; |
CARD8 version; |
Bool NeedMode = FALSE; |
union { |
PIXEL_CLOCK_PARAMETERS pclk; |
PIXEL_CLOCK_PARAMETERS_V2 pclk_v2; |
PIXEL_CLOCK_PARAMETERS_V3 pclk_v3; |
SET_PIXEL_CLOCK_PS_ALLOCATION pclk_a; |
} ps; |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); |
|
if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL)) |
return FALSE; |
switch (version) { |
case 1: |
if (Config->Enable) |
ps.pclk.usPixelClock = Config->PixelClock / 10; |
else |
ps.pclk.usPixelClock = 0; |
ps.pclk.usRefDiv = Config->RefDiv; |
ps.pclk.usFbDiv = Config->FbDiv; |
ps.pclk.ucPostDiv = Config->PostDiv; |
ps.pclk.ucFracFbDiv = Config->FracFbDiv; |
ps.pclk.ucRefDivSrc = 0; /* What's this? @@@ */ |
switch (PCLKId) { |
case atomPclk1: |
ps.pclk.ucPpll = ATOM_PPLL1; |
break; |
case atomPclk2: |
ps.pclk.ucPpll = ATOM_PPLL2; |
break; |
} |
switch (Config->Crtc) { |
case atomCrtc1: |
ps.pclk.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.pclk.ucCRTC = ATOM_CRTC2; |
break; |
} |
break; |
case 2: |
if (Config->Enable) |
ps.pclk_v2.usPixelClock = Config->PixelClock / 10; |
else |
ps.pclk_v2.usPixelClock = 0; |
ps.pclk_v2.usRefDiv = Config->RefDiv; |
ps.pclk_v2.usFbDiv = Config->FbDiv; |
ps.pclk_v2.ucPostDiv = Config->PostDiv; |
ps.pclk_v2.ucFracFbDiv = Config->FracFbDiv; |
switch (PCLKId) { |
case atomPclk1: |
ps.pclk_v2.ucPpll = ATOM_PPLL1; |
break; |
case atomPclk2: |
ps.pclk_v2.ucPpll = ATOM_PPLL2; |
break; |
} |
ps.pclk_v2.ucRefDivSrc = 1; /* See above... @@@ */ |
switch (Config->Crtc) { |
case atomCrtc1: |
ps.pclk_v2.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.pclk_v2.ucCRTC = ATOM_CRTC2; |
break; |
} |
ASSERTF((!Config->Enable || Config->u.v2.Device != atomNone), "Invalid Device Id\n"); |
ps.pclk_v2.ucMiscInfo = 0; |
ps.pclk_v2.ucMiscInfo |= (Config->u.v2.Force ? MISC_FORCE_REPROG_PIXEL_CLOCK : 0); |
if (Config->u.v2.Device != atomNone) |
ps.pclk_v2.ucMiscInfo |= (atomGetDevice(handle, Config->u.v2.Device) |
<< MISC_DEVICE_INDEX_SHIFT); |
RHDDebug(handle->scrnIndex,"%s Device: %i PixelClock: %i RefDiv: 0x%x FbDiv: 0x%x PostDiv: 0x%x " |
"PLL: %i Crtc: %i MiscInfo: 0x%x\n", |
__func__, |
Config->u.v2.Device, |
ps.pclk_v2.usPixelClock, |
ps.pclk_v2.usRefDiv, |
ps.pclk_v2.usFbDiv, |
ps.pclk_v2.ucPostDiv, |
ps.pclk_v2.ucPpll, |
ps.pclk_v2.ucCRTC, |
ps.pclk_v2.ucMiscInfo |
); |
break; |
case 3: |
if (Config->Enable) |
ps.pclk_v3.usPixelClock = Config->PixelClock / 10; |
else |
ps.pclk.usPixelClock = 0; |
ps.pclk_v3.usRefDiv = Config->RefDiv; |
ps.pclk_v3.usFbDiv = Config->FbDiv; |
ps.pclk_v3.ucPostDiv = Config->PostDiv; |
ps.pclk_v3.ucFracFbDiv = Config->FracFbDiv; |
switch (PCLKId) { |
case atomPclk1: |
ps.pclk_v3.ucPpll = ATOM_PPLL1; |
break; |
case atomPclk2: |
ps.pclk_v3.ucPpll = ATOM_PPLL2; |
break; |
} |
switch (Config->u.v3.OutputType) { |
case atomOutputKldskpLvtma: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA; |
NeedMode = TRUE; |
break; |
case atomOutputUniphyA: |
case atomOutputUniphyB: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_UNIPHY; |
NeedMode = TRUE; |
break; |
case atomOutputUniphyC: |
case atomOutputUniphyD: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_UNIPHY1; |
NeedMode = TRUE; |
break; |
case atomOutputUniphyE: |
case atomOutputUniphyF: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_UNIPHY2; |
NeedMode = TRUE; |
break; |
|
case atomOutputDacA: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; |
break; |
case atomOutputDacB: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; |
break; |
case atomOutputDvo: |
ps.pclk_v3.ucTransmitterId = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; |
NeedMode = TRUE; |
break; |
case atomOutputTmdsa: |
case atomOutputLvtma: |
case atomOutputNone: |
return FALSE; |
} |
if (NeedMode) { |
switch (Config->u.v3.EncoderMode) { |
case atomNoEncoder: |
ps.pclk_v3.ucEncoderMode = 0; |
case atomDVI: |
ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_DVI; |
break; |
case atomDP: |
ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_DP; |
break; |
case atomLVDS: |
ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_LVDS; |
break; |
case atomHDMI: |
ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_HDMI; |
break; |
case atomSDVO: |
ps.pclk_v3.ucEncoderMode = ATOM_ENCODER_MODE_SDVO; |
break; |
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR,"%s: invalid encoder type.\n",__func__); |
return FALSE; |
} |
} |
ps.pclk_v3.ucMiscInfo = (Config->u.v3.Force ? PIXEL_CLOCK_MISC_FORCE_PROG_PPLL : 0x0) |
| (Config->u.v3.UsePpll ? PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK : 0x0) |
| ((Config->Crtc == atomCrtc2) ? PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2 : PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1); |
|
RHDDebug(handle->scrnIndex,"%s PixelClock: %i RefDiv: 0x%x FbDiv: 0x%x PostDiv: 0x%x PLL: %i OutputType: %x " |
"EncoderMode: %x MiscInfo: 0x%x\n", |
__func__, |
ps.pclk_v3.usPixelClock, |
ps.pclk_v3.usRefDiv, |
ps.pclk_v3.usFbDiv, |
ps.pclk_v3.ucPostDiv, |
ps.pclk_v3.ucPpll, |
ps.pclk_v3.ucTransmitterId, |
ps.pclk_v3.ucEncoderMode, |
ps.pclk_v3.ucMiscInfo |
); |
break; |
default: |
return FALSE; |
} |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetPixelClock\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetPixelClock Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SetPixelClock Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomSetPixelClockVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
|
DEBUG_VERSION(index, handle, version); |
|
return version; |
|
} |
|
/* |
* |
*/ |
Bool |
rhdAtomSelectCrtcSource(atomBiosHandlePtr handle, enum atomCrtc CrtcId, |
struct atomCrtcSourceConfig *config) |
{ |
AtomBiosArgRec data; |
CARD8 version; |
Bool NeedMode = FALSE; |
|
union |
{ |
SELECT_CRTC_SOURCE_PARAMETERS crtc; |
SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_a; |
SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc2; |
/* SELECT_CRTC_SOURCE_PS_ALLOCATION_V2 crtc2_a; */ |
} ps; |
|
RHDFUNC(handle); |
|
data.exec.index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); |
|
if (!rhdAtomGetCommandTableRevisionSize(handle, data.exec.index, &version, NULL, NULL)) |
return FALSE; |
|
switch (version) { |
case 1: |
switch (CrtcId) { |
case atomCrtc1: |
ps.crtc.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.crtc.ucCRTC = ATOM_CRTC2; |
break; |
} |
switch (config->u.Device) { |
case atomCRT1: |
ps.crtc.ucDevice = ATOM_DEVICE_CRT1_INDEX; |
break; |
case atomLCD1: |
ps.crtc.ucDevice = ATOM_DEVICE_LCD1_INDEX; |
break; |
case atomTV1: |
ps.crtc.ucDevice = ATOM_DEVICE_TV1_INDEX; |
break; |
case atomDFP1: |
ps.crtc.ucDevice = ATOM_DEVICE_DFP1_INDEX; |
break; |
case atomCRT2: |
ps.crtc.ucDevice = ATOM_DEVICE_CRT2_INDEX; |
break; |
case atomLCD2: |
ps.crtc.ucDevice = ATOM_DEVICE_LCD2_INDEX; |
break; |
case atomTV2: |
ps.crtc.ucDevice = ATOM_DEVICE_TV2_INDEX; |
break; |
case atomDFP2: |
ps.crtc.ucDevice = ATOM_DEVICE_DFP2_INDEX; |
break; |
case atomCV: |
ps.crtc.ucDevice = ATOM_DEVICE_CV_INDEX; |
break; |
case atomDFP3: |
ps.crtc.ucDevice = ATOM_DEVICE_DFP3_INDEX; |
break; |
case atomDFP4: |
ps.crtc.ucDevice = ATOM_DEVICE_DFP4_INDEX; |
break; |
case atomDFP5: |
ps.crtc.ucDevice = ATOM_DEVICE_DFP5_INDEX; |
break; |
case atomNone: |
return FALSE; |
} |
break; |
case 2: |
switch (CrtcId) { |
case atomCrtc1: |
ps.crtc2.ucCRTC = ATOM_CRTC1; |
break; |
case atomCrtc2: |
ps.crtc2.ucCRTC = ATOM_CRTC2; |
break; |
} |
switch (config->u.crtc2.Encoder) { |
case atomEncoderDACA: |
ps.crtc2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; |
break; |
case atomEncoderDACB: |
ps.crtc2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; |
break; |
case atomEncoderTV: |
ps.crtc2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
break; |
case atomEncoderDVO: |
ps.crtc2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; |
NeedMode = TRUE; |
break; |
case atomEncoderDIG1: |
ps.crtc2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; |
NeedMode = TRUE; |
break; |
|
case atomEncoderDIG2: |
ps.crtc2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; |
break; |
case atomEncoderExternal: |
ps.crtc2.ucEncoderID = ASIC_EXT_DIG_ENCODER_ID; |
break; |
case atomEncoderTMDS1: |
case atomEncoderTMDS2: |
case atomEncoderLVDS: |
case atomEncoderNone: |
return FALSE; |
} |
if (NeedMode) { |
switch (config->u.crtc2.Mode) { |
case atomDVI: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_DVI; |
break; |
case atomDP: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_DP; |
break; |
case atomLVDS: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS; |
break; |
case atomHDMI: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_HDMI; |
break; |
case atomSDVO: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_SDVO; |
break; |
case atomTVComposite: |
case atomTVSVideo: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_TV; |
break; |
case atomTVComponent: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_CV; |
break; |
case atomCRT: |
ps.crtc2.ucEncodeMode = ATOM_ENCODER_MODE_CRT; |
break; |
case atomNoEncoder: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: invalid encoder type.\n",__func__); |
return FALSE; |
} |
} |
break; |
} |
|
data.exec.dataSpace = NULL; |
data.exec.pspace = &ps; |
|
xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SelectCRTCSource\n"); |
atomDebugPrintPspace(handle, &data, sizeof(ps)); |
if (RHDAtomBiosFunc(handle->rhdPtr, handle, |
ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SelectCRTCSource Successful\n"); |
return TRUE; |
} |
xf86DrvMsg(handle->scrnIndex, X_INFO, "SelectCRTCSource Failed\n"); |
return FALSE; |
} |
|
/* |
* |
*/ |
struct atomCodeTableVersion |
rhdAtomSelectCrtcSourceVersion(atomBiosHandlePtr handle) |
{ |
struct atomCodeTableVersion version; |
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); |
rhdAtomGetCommandTableRevisionSize(handle, index, &version.cref, &version.fref, NULL); |
DEBUG_VERSION(index, handle, version); |
return version; |
} |
|
|
# endif /* ATOM_BIOS_PARSER */ |
|
|
static AtomBiosResult |
rhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2, |
AtomBiosArgPtr data) |
{ |
int scrnIndex = data->val; |
RHDPtr rhdPtr = data->val; |
unsigned char *ptr; |
atomDataTablesPtr atomDataPtr; |
atomBiosHandlePtr handle = NULL; |
unsigned int BIOSImageSize = 0; |
Bool unposted = FALSE; |
unsigned char* codeTable; |
|
data->atomhandle = NULL; |
|
RHDFUNCI(scrnIndex); |
|
if (rhdPtr->BIOSCopy) { |
xf86DrvMsg(scrnIndex,X_INFO,"Getting BIOS copy from INT10\n"); |
ptr = rhdPtr->BIOSCopy; |
rhdPtr->BIOSCopy = NULL; |
|
BIOSImageSize = ptr[2] * 512; |
if (BIOSImageSize > legacyBIOSMax) { |
xf86DrvMsg(scrnIndex,X_ERROR,"Invalid BIOS length field\n"); |
return ATOM_FAILED; |
} |
} |
else |
{ |
// if (!xf86IsEntityPrimary(rhdPtr->entityIndex)) |
// { |
// if (!(BIOSImageSize = RHDReadPCIBios(rhdPtr, &ptr))) |
// return ATOM_FAILED; |
// unposted = TRUE; |
// } |
// else |
{ |
int read_len; |
unsigned char tmp[32]; |
|
DBG(dbgprintf("Getting BIOS copy from legacy VBIOS location\n")); |
memcpy(tmp,(char*)(OS_BASE+legacyBIOSLocation), 32); |
BIOSImageSize = tmp[2] * 512; |
if (BIOSImageSize > legacyBIOSMax) { |
xf86DrvMsg(0,X_ERROR,"Invalid BIOS length field\n"); |
return ATOM_FAILED; |
} |
if (!(ptr = (char*)KernelAlloc(BIOSImageSize))) |
{ |
DBG(dbgprintf("Cannot allocate %i bytes of memory " |
"for BIOS image\n",BIOSImageSize)); |
return ATOM_FAILED; |
} |
memcpy(ptr,(char*)(OS_BASE+legacyBIOSLocation), BIOSImageSize); |
rhdPtr->BIOSCopy = ptr; |
} |
} |
|
if (!(atomDataPtr = xcalloc(1, sizeof(atomDataTables)))) { |
xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory for " |
"ATOM BIOS data tabes\n"); |
goto error; |
} |
if (!rhdAtomGetTables(rhdPtr, ptr, atomDataPtr, &codeTable, BIOSImageSize)) |
goto error1; |
if (!(handle = xcalloc(1, sizeof(atomBiosHandleRec)))) { |
xf86DrvMsg(scrnIndex,X_ERROR,"Cannot allocate memory\n"); |
goto error1; |
} |
handle->BIOSBase = ptr; |
handle->atomDataPtr = atomDataPtr; |
handle->scrnIndex = scrnIndex; |
handle->rhdPtr = rhdPtr; |
handle->PciTag = rhdPtr->PciTag; |
handle->BIOSImageSize = BIOSImageSize; |
handle->codeTable = codeTable; |
handle->SaveListObjects = NULL; |
|
# ifdef ATOM_BIOS_PARSER |
/* Try to find out if BIOS has been posted (either by system or int10 */ |
if (unposted) { |
/* run AsicInit */ |
if (!rhdAtomASICInit(handle)) |
xf86DrvMsg(scrnIndex, X_WARNING, |
"%s: AsicInit failed. Won't be able to obtain in VRAM " |
"FB scratch space\n",__func__); |
} |
# endif |
|
data->atomhandle = handle; |
return ATOM_SUCCESS; |
|
error1: |
xfree(atomDataPtr); |
error: |
xfree(ptr); |
return ATOM_FAILED; |
} |
|
static AtomBiosResult |
rhdAtomTearDown(atomBiosHandlePtr handle, |
AtomBiosRequestID unused1, AtomBiosArgPtr unused2) |
{ |
RHDFUNC(handle); |
|
xfree(handle->BIOSBase); |
xfree(handle->atomDataPtr); |
if (handle->scratchBase) xfree(handle->scratchBase); |
xfree(handle); |
return ATOM_SUCCESS; |
} |
|
static AtomBiosResult |
rhdAtomVramInfoQuery(atomBiosHandlePtr handle, AtomBiosRequestID func, |
AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD32 *val = &data->val; |
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
switch (func) { |
case GET_FW_FB_START: |
*val = atomDataPtr->VRAM_UsageByFirmware |
->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware; |
break; |
case GET_FW_FB_SIZE: |
*val = atomDataPtr->VRAM_UsageByFirmware |
->asFirmwareVramReserveInfo[0].usFirmwareUseInKb; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
return ATOM_SUCCESS; |
} |
|
static AtomBiosResult |
rhdAtomTmdsInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD32 *val = &data->val; |
int i = 0, clock = *val; |
|
atomDataPtr = handle->atomDataPtr; |
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->TMDS_Info), |
NULL,NULL,NULL)) { |
return ATOM_FAILED; |
} |
|
RHDFUNC(handle); |
|
if (func == ATOM_TMDS_MAX_FREQUENCY) |
*val = atomDataPtr->TMDS_Info->usMaxFrequency * 10; |
else { |
if (clock > atomDataPtr->TMDS_Info->usMaxFrequency * 10) |
return ATOM_FAILED; |
|
for (;i < ATOM_MAX_MISC_INFO; i++) { |
if (clock < atomDataPtr->TMDS_Info->asMiscInfo[i].usFrequency * 10) { |
switch (func) { |
case ATOM_TMDS_PLL_CHARGE_PUMP: |
*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_ChargePump; |
break; |
case ATOM_TMDS_PLL_DUTY_CYCLE: |
*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_DutyCycle; |
break; |
case ATOM_TMDS_PLL_VCO_GAIN: |
*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_VCO_Gain; |
break; |
case ATOM_TMDS_PLL_VOLTAGE_SWING: |
*val = atomDataPtr->TMDS_Info->asMiscInfo[i].ucPLL_VoltageSwing; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
} |
} |
} |
|
if (i > ATOM_MAX_MISC_INFO) |
return ATOM_FAILED; |
|
return ATOM_SUCCESS; |
} |
|
static DisplayModePtr |
rhdAtomLvdsTimings(atomBiosHandlePtr handle, ATOM_DTD_FORMAT *dtd) |
{ |
DisplayModePtr mode; |
#define NAME_LEN 16 |
char name[NAME_LEN]; |
|
RHDFUNC(handle); |
|
if (!(mode = (DisplayModePtr)xcalloc(1,sizeof(DisplayModeRec)))) |
return NULL; |
|
mode->CrtcHDisplay = mode->HDisplay = dtd->usHActive; |
mode->CrtcVDisplay = mode->VDisplay = dtd->usVActive; |
mode->CrtcHBlankStart = dtd->usHActive + dtd->ucHBorder; |
mode->CrtcHBlankEnd = mode->CrtcHBlankStart + dtd->usHBlanking_Time; |
mode->CrtcHTotal = mode->HTotal = mode->CrtcHBlankEnd + dtd->ucHBorder; |
mode->CrtcVBlankStart = dtd->usVActive + dtd->ucVBorder; |
mode->CrtcVBlankEnd = mode->CrtcVBlankStart + dtd->usVBlanking_Time; |
mode->CrtcVTotal = mode->VTotal = mode->CrtcVBlankEnd + dtd->ucVBorder; |
mode->CrtcHSyncStart = mode->HSyncStart = dtd->usHActive + dtd->usHSyncOffset; |
mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + dtd->usHSyncWidth; |
mode->CrtcVSyncStart = mode->VSyncStart = dtd->usVActive + dtd->usVSyncOffset; |
mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + dtd->usVSyncWidth; |
|
mode->SynthClock = mode->Clock = dtd->usPixClk * 10; |
|
mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal); |
mode->VRefresh = (1000.0 * ((float) mode->Clock)) |
/ ((float)(((float)mode->HTotal) * ((float)mode->VTotal))); |
|
snprintf(name, NAME_LEN, "%dx%d", |
mode->HDisplay, mode->VDisplay); |
mode->name = strdup(name); |
|
RHDDebug(handle->scrnIndex,"%s: LVDS Modeline: %s " |
"%2.d %i (%i) %i %i (%i) %i %i (%i) %i %i (%i) %i\n", |
__func__, mode->name, mode->Clock, |
mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd, |
mode->CrtcHBlankEnd, mode->HTotal, |
mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd, |
mode->CrtcVBlankEnd, mode->VTotal); |
#undef NAME_LEN |
return mode; |
} |
|
static unsigned char* |
rhdAtomLvdsDDC(atomBiosHandlePtr handle, CARD32 offset, unsigned char *record) |
{ |
unsigned char *EDIDBlock; |
|
RHDFUNC(handle); |
|
while (*record != ATOM_RECORD_END_TYPE) { |
|
switch (*record) { |
case LCD_MODE_PATCH_RECORD_MODE_TYPE: |
offset += sizeof(ATOM_PATCH_RECORD_MODE); |
if (offset > handle->BIOSImageSize) break; |
record += sizeof(ATOM_PATCH_RECORD_MODE); |
break; |
|
case LCD_RTS_RECORD_TYPE: |
offset += sizeof(ATOM_LCD_RTS_RECORD); |
if (offset > handle->BIOSImageSize) break; |
record += sizeof(ATOM_LCD_RTS_RECORD); |
break; |
|
case LCD_CAP_RECORD_TYPE: |
offset += sizeof(ATOM_LCD_MODE_CONTROL_CAP); |
if (offset > handle->BIOSImageSize) break; |
record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); |
break; |
|
case LCD_FAKE_EDID_PATCH_RECORD_TYPE: |
offset += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); |
/* check if the structure still fully lives in the BIOS image */ |
if (offset > handle->BIOSImageSize) break; |
offset += ((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength |
- sizeof(UCHAR); |
if (offset > handle->BIOSImageSize) break; |
/* dup string as we free it later */ |
if (!(EDIDBlock = (unsigned char *)xalloc( |
((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength))) |
return NULL; |
memcpy(EDIDBlock,&((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDString, |
((ATOM_FAKE_EDID_PATCH_RECORD*)record)->ucFakeEDIDLength); |
|
/* for testing */ |
{ |
// xf86MonPtr mon = xf86InterpretEDID(handle->scrnIndex,EDIDBlock); |
// xf86PrintEDID(mon); |
// kfree(mon); |
} |
return EDIDBlock; |
|
case LCD_PANEL_RESOLUTION_RECORD_TYPE: |
offset += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); |
if (offset > handle->BIOSImageSize) break; |
record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); |
break; |
|
default: |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: unknown record type: %x\n",__func__,*record); |
return NULL; |
} |
} |
|
return NULL; |
} |
|
static AtomBiosResult |
rhdAtomLvdsGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, |
AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
unsigned long offset; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), |
&crev,&frev,NULL)) { |
return ATOM_FAILED; |
} |
|
switch (crev) { |
|
case 1: |
switch (func) { |
case ATOMBIOS_GET_PANEL_MODE: |
data->mode = rhdAtomLvdsTimings(handle, |
&atomDataPtr->LVDS_Info |
.LVDS_Info->sLCDTiming); |
if (data->mode) |
return ATOM_SUCCESS; |
default: |
return ATOM_FAILED; |
} |
case 2: |
switch (func) { |
case ATOMBIOS_GET_PANEL_MODE: |
data->mode = rhdAtomLvdsTimings(handle, |
&atomDataPtr->LVDS_Info |
.LVDS_Info_v12->sLCDTiming); |
if (data->mode) |
return ATOM_SUCCESS; |
return ATOM_FAILED; |
|
case ATOMBIOS_GET_PANEL_EDID: |
offset = (unsigned long)&atomDataPtr->LVDS_Info.base |
- (unsigned long)handle->BIOSBase |
+ atomDataPtr->LVDS_Info |
.LVDS_Info_v12->usExtInfoTableOffset; |
|
data->EDIDBlock |
= rhdAtomLvdsDDC(handle, offset, |
(unsigned char *) |
&atomDataPtr->LVDS_Info.base |
+ atomDataPtr->LVDS_Info |
.LVDS_Info_v12->usExtInfoTableOffset); |
if (data->EDIDBlock) |
return ATOM_SUCCESS; |
default: |
return ATOM_FAILED; |
} |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
/*NOTREACHED*/ |
} |
|
static AtomBiosResult |
rhdAtomLvdsInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
CARD32 *val = &data->val; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->LVDS_Info.base), |
&crev,&frev,NULL)) { |
return ATOM_FAILED; |
} |
|
switch (crev) { |
case 1: |
switch (func) { |
case ATOM_LVDS_SUPPORTED_REFRESH_RATE: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info->usSupportedRefreshRate; |
break; |
case ATOM_LVDS_OFF_DELAY: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info->usOffDelayInMs; |
break; |
case ATOM_LVDS_SEQ_DIG_ONTO_DE: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info->ucPowerSequenceDigOntoDEin10Ms * 10; |
break; |
case ATOM_LVDS_SEQ_DE_TO_BL: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info->ucPowerSequenceDEtoBLOnin10Ms * 10; |
break; |
case ATOM_LVDS_TEMPORAL_DITHER: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info->ucLVDS_Misc & 0x40) != 0; |
break; |
case ATOM_LVDS_SPATIAL_DITHER: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info->ucLVDS_Misc & 0x20) != 0; |
break; |
case ATOM_LVDS_FPDI: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info->ucLVDS_Misc & 0x10) != 0; |
break; |
case ATOM_LVDS_DUALLINK: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info->ucLVDS_Misc & 0x01) != 0; |
break; |
case ATOM_LVDS_24BIT: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info->ucLVDS_Misc & 0x02) != 0; |
break; |
case ATOM_LVDS_GREYLVL: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info->ucLVDS_Misc & ATOM_PANEL_MISC_GREY_LEVEL) |
>> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT ; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
case 2: |
switch (func) { |
case ATOM_LVDS_SUPPORTED_REFRESH_RATE: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info_v12->usSupportedRefreshRate; |
break; |
case ATOM_LVDS_OFF_DELAY: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info_v12->usOffDelayInMs; |
break; |
case ATOM_LVDS_SEQ_DIG_ONTO_DE: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucPowerSequenceDigOntoDEin10Ms * 10; |
break; |
case ATOM_LVDS_SEQ_DE_TO_BL: |
*val = atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucPowerSequenceDEtoBLOnin10Ms * 10; |
break; |
case ATOM_LVDS_FPDI: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucLVDS_Misc * 0x10) != 0; |
break; |
case ATOM_LVDS_SPATIAL_DITHER: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucLVDS_Misc & 0x20) != 0; |
break; |
case ATOM_LVDS_TEMPORAL_DITHER: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucLVDS_Misc & 0x40) != 0; |
break; |
case ATOM_LVDS_DUALLINK: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucLVDS_Misc & 0x01) != 0; |
break; |
case ATOM_LVDS_24BIT: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucLVDS_Misc & 0x02) != 0; |
break; |
case ATOM_LVDS_GREYLVL: |
*val = (atomDataPtr->LVDS_Info |
.LVDS_Info_v12->ucLVDS_Misc & 0x0C) >> 2; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
|
return ATOM_SUCCESS; |
} |
|
static AtomBiosResult |
rhdAtomCompassionateDataQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
CARD32 *val = &data->val; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->CompassionateData), |
&crev,&frev,NULL)) { |
return ATOM_FAILED; |
} |
|
switch (func) { |
case ATOM_DAC1_BG_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC1_BG_Adjustment; |
break; |
case ATOM_DAC1_DAC_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC1_DAC_Adjustment; |
break; |
case ATOM_DAC1_FORCE: |
*val = atomDataPtr->CompassionateData-> |
usDAC1_FORCE_Data; |
break; |
case ATOM_DAC2_CRTC2_BG_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_CRT2_BG_Adjustment; |
break; |
case ATOM_DAC2_NTSC_BG_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_NTSC_BG_Adjustment; |
break; |
case ATOM_DAC2_PAL_BG_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_PAL_BG_Adjustment; |
break; |
case ATOM_DAC2_CV_BG_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_CV_BG_Adjustment; |
break; |
case ATOM_DAC2_CRTC2_DAC_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_CRT2_DAC_Adjustment; |
break; |
case ATOM_DAC2_NTSC_DAC_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_NTSC_DAC_Adjustment; |
break; |
case ATOM_DAC2_PAL_DAC_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_PAL_DAC_Adjustment; |
break; |
case ATOM_DAC2_CV_DAC_ADJ: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_CV_DAC_Adjustment; |
break; |
case ATOM_DAC2_CRTC2_FORCE: |
*val = atomDataPtr->CompassionateData-> |
usDAC2_CRT2_FORCE_Data; |
break; |
case ATOM_DAC2_CRTC2_MUX_REG_IND: |
*val = atomDataPtr->CompassionateData-> |
usDAC2_CRT2_MUX_RegisterIndex; |
break; |
case ATOM_DAC2_CRTC2_MUX_REG_INFO: |
*val = atomDataPtr->CompassionateData-> |
ucDAC2_CRT2_MUX_RegisterInfo; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
enum atomPCIELanes atomPCIELanesMap[] = { |
atomPCIELaneNONE, |
atomPCIELane0_3, |
atomPCIELane4_7, |
atomPCIELane0_7, |
atomPCIELane8_11, |
atomPCIELaneNONE, |
atomPCIELaneNONE, |
atomPCIELaneNONE, |
atomPCIELane12_15, |
atomPCIELaneNONE, |
atomPCIELaneNONE, |
atomPCIELaneNONE, |
atomPCIELane8_15, |
atomPCIELaneNONE, |
atomPCIELaneNONE, |
atomPCIELaneNONE, |
atomPCIELaneNONE |
}; |
|
static AtomBiosResult |
rhdAtomIntegratedSystemInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
CARD32 *val = &data->val; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base), |
&crev,&frev,NULL)) { |
return ATOM_FAILED; |
} |
|
switch (crev) { |
case 1: |
switch (func) { |
case ATOM_GET_PCIENB_CFG_REG7: |
*val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usPCIENBCfgReg7; |
break; |
case ATOM_GET_CAPABILITY_FLAG: |
*val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo->usCapabilityFlag; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
case 2: |
switch (func) { |
case ATOM_GET_PCIE_LANES: |
{ |
CARD32 n; |
switch (*val) { |
case 1: |
n = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot1Config; |
break; |
case 2: |
n = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot2Config; |
break; |
default: |
return ATOM_FAILED; |
} |
data->pcieLanes.Chassis = atomPCIELanesMap[n & 0xf]; |
data->pcieLanes.Docking = atomPCIELanesMap[(n >> 4) & 0xf]; |
RHDDebug(handle->scrnIndex, "AtomBIOS IntegratedSystemInfo PCIELanes: Chassis=%x Docking=%x\n", |
data->pcieLanes.Chassis, data->pcieLanes.Docking); |
return ATOM_SUCCESS; |
} |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
return ATOM_NOT_IMPLEMENTED; |
} |
|
return ATOM_SUCCESS; |
} |
|
static DisplayModePtr |
rhdAtomAnalogTVTimings(atomBiosHandlePtr handle, |
ATOM_ANALOG_TV_INFO *tv_info, |
enum RHD_TV_MODE tvMode) |
{ |
atomDataTablesPtr atomDataPtr; |
DisplayModePtr mode; |
int mode_n; |
char *name; |
ATOM_MODE_TIMING *amt; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
switch (tvMode) { |
case NTSC_SUPPORT: |
case NTSCJ_SUPPORT: |
mode_n = 0; |
name = "TV_NTSC"; |
break; |
case PAL_SUPPORT: |
case PALM_SUPPORT: |
case PALCN_SUPPORT: |
case PALN_SUPPORT: |
case PAL60_SUPPORT: |
case SECAM_SUPPORT: |
mode_n = 1; |
name = "TV_PAL/SECAM"; |
break; |
default: |
return NULL; |
} |
|
|
if (!(tv_info->ucTV_SupportedStandard & (tvMode))) |
return NULL; |
|
if (!(mode = (DisplayModePtr)xcalloc(1,sizeof(DisplayModeRec)))) |
return NULL; |
|
amt = &tv_info->aModeTimings[mode_n]; |
|
mode->CrtcHDisplay = mode->HDisplay = amt->usCRTC_H_Disp; |
mode->CrtcHSyncStart = mode->HSyncStart = amt->usCRTC_H_SyncStart; |
mode->CrtcHSyncEnd = mode->HSyncEnd = mode->HSyncStart + amt->usCRTC_H_SyncWidth; |
mode->CrtcHTotal = mode->HTotal = amt->usCRTC_H_Total; |
mode->CrtcHBlankStart = mode->HDisplay + amt->usCRTC_OverscanRight; |
mode->CrtcHBlankEnd = mode->HTotal - amt->usCRTC_OverscanLeft; |
|
mode->CrtcVDisplay = mode->VDisplay = amt->usCRTC_V_Disp; |
mode->CrtcVSyncStart = mode->VSyncStart = amt->usCRTC_V_SyncStart; |
mode->CrtcVSyncEnd = mode->VSyncEnd = mode->VSyncStart + amt->usCRTC_V_SyncWidth; |
mode->CrtcVTotal = mode->VTotal = amt->usCRTC_V_Total; |
mode->CrtcVBlankStart = mode->VDisplay + amt->usCRTC_OverscanBottom; |
mode->CrtcVBlankEnd = mode->CrtcVTotal - amt->usCRTC_OverscanTop; |
|
mode->SynthClock = mode->Clock = amt->usPixelClock * 10; |
if (amt->susModeMiscInfo.usAccess & ATOM_HSYNC_POLARITY) |
mode->Flags |= V_NHSYNC; |
else |
mode->Flags |= V_PHSYNC; |
if (amt->susModeMiscInfo.usAccess & ATOM_VSYNC_POLARITY) |
mode->Flags |= V_NVSYNC; |
else |
mode->Flags |= V_PVSYNC; |
if (amt->susModeMiscInfo.usAccess & ATOM_INTERLACE) |
mode->Flags |= V_INTERLACE; |
if (amt->susModeMiscInfo.usAccess & ATOM_COMPOSITESYNC) |
mode->Flags |= V_CSYNC; |
if (amt->susModeMiscInfo.usAccess & ATOM_DOUBLE_CLOCK_MODE) |
mode->Flags |= V_DBLCLK; |
|
mode->HSync = ((float) mode->Clock) / ((float)mode->HTotal); |
mode->VRefresh = (1000.0 * ((float) mode->Clock)) |
/ ((float)(((float)mode->HTotal) * ((float)mode->VTotal))); |
|
mode->name = strdup(name); |
|
RHDDebug(handle->scrnIndex,"%s: TV Modeline: %s " |
"%2.d %i (%i) %i %i (%i) %i %i (%i) %i %i (%i) %i\n", |
__func__, mode->name, mode->Clock, |
mode->HDisplay, mode->CrtcHBlankStart, mode->HSyncStart, mode->CrtcHSyncEnd, |
mode->CrtcHBlankEnd, mode->HTotal, |
mode->VDisplay, mode->CrtcVBlankStart, mode->VSyncStart, mode->VSyncEnd, |
mode->CrtcVBlankEnd, mode->VTotal); |
|
|
return mode; |
} |
|
static AtomBiosResult |
rhdAtomAnalogTVInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
CARD8 crev, frev; |
atomDataTablesPtr atomDataPtr = handle->atomDataPtr; |
int mode = 0, i; |
struct { enum RHD_TV_MODE rhd_mode; int atomMode; } |
tv_modes[] = { |
{ RHD_TV_NTSC, NTSC_SUPPORT }, |
{ RHD_TV_NTSCJ, NTSCJ_SUPPORT}, |
{ RHD_TV_PAL, PAL_SUPPORT }, |
{ RHD_TV_PALM, PALM_SUPPORT }, |
{ RHD_TV_PALCN, PALCN_SUPPORT}, |
{ RHD_TV_PALN, PALN_SUPPORT }, |
{ RHD_TV_PAL60, PAL60_SUPPORT}, |
{ RHD_TV_SECAM, SECAM_SUPPORT}, |
{ RHD_TV_NONE, 0 } |
}; |
|
|
RHDFUNC(handle); |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->AnalogTV_Info), |
&crev,&frev,NULL)) { |
return ATOM_FAILED; |
} |
switch (func) { |
case ATOM_ANALOG_TV_MODE: |
for (i = 0; tv_modes[i].atomMode; i++) { |
if (data->tvMode == tv_modes[i].rhd_mode) { |
mode = tv_modes[i].atomMode; |
break; |
} |
} |
data->mode = rhdAtomAnalogTVTimings(handle, |
atomDataPtr->AnalogTV_Info, |
mode); |
if (!data->mode) |
return ATOM_FAILED; |
return ATOM_SUCCESS; |
case ATOM_ANALOG_TV_DEFAULT_MODE: |
data->tvMode = tv_modes[atomDataPtr->AnalogTV_Info->ucTV_BootUpDefaultStandard - 1].rhd_mode; |
break; |
case ATOM_ANALOG_TV_SUPPORTED_MODES: |
mode = (CARD32)atomDataPtr->AnalogTV_Info->ucTV_SupportedStandard; |
data->val = 0; |
for (i = 0; tv_modes[i].atomMode; i++) { |
if (tv_modes[i].atomMode & mode) { |
data->val |= tv_modes[i].rhd_mode; |
} |
} |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
|
return ATOM_SUCCESS; |
} |
|
static AtomBiosResult |
rhdAtomGPIOI2CInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
CARD32 *val = &data->val; |
unsigned short size; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->GPIO_I2C_Info), |
&crev,&frev,&size)) { |
return ATOM_FAILED; |
} |
|
if ((sizeof(ATOM_COMMON_TABLE_HEADER) |
+ (*val * sizeof(ATOM_GPIO_I2C_ASSIGMENT))) > size) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: GPIO_I2C Device " |
"num %lu exeeds table size %u\n",__func__, |
(unsigned long)val, |
size); |
return ATOM_FAILED; |
} |
|
switch (func) { |
case ATOM_GPIO_I2C_DATA_MASK: |
*val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] |
.usDataMaskRegisterIndex; |
break; |
|
case ATOM_GPIO_I2C_DATA_MASK_SHIFT: |
*val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] |
.ucDataMaskShift; |
break; |
|
case ATOM_GPIO_I2C_CLK_MASK: |
*val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] |
.usClkMaskRegisterIndex; |
break; |
|
case ATOM_GPIO_I2C_CLK_MASK_SHIFT: |
*val = atomDataPtr->GPIO_I2C_Info->asGPIO_Info[*val] |
.ucClkMaskShift; |
break; |
|
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
return ATOM_SUCCESS; |
} |
|
static AtomBiosResult |
rhdAtomFirmwareInfoQuery(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
CARD32 *val = &data->val; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->FirmwareInfo.base), |
&crev,&frev,NULL)) { |
return ATOM_FAILED; |
} |
|
switch (crev) { |
case 1: |
switch (func) { |
case GET_DEFAULT_ENGINE_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->ulDefaultEngineClock * 10; |
break; |
case GET_DEFAULT_MEMORY_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->ulDefaultMemoryClock * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->ulMaxPixelClockPLL_Output * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->usMinPixelClockPLL_Output * 10; |
case GET_MAX_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->usMaxPixelClockPLL_Input * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->usMinPixelClockPLL_Input * 10; |
break; |
case GET_MAX_PIXEL_CLK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->usMaxPixelClock * 10; |
break; |
case GET_REF_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo->usReferenceClock * 10; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
case 2: |
switch (func) { |
case GET_DEFAULT_ENGINE_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->ulDefaultEngineClock * 10; |
break; |
case GET_DEFAULT_MEMORY_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->ulDefaultMemoryClock * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->ulMaxPixelClockPLL_Output * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->usMinPixelClockPLL_Output * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->usMaxPixelClockPLL_Input * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->usMinPixelClockPLL_Input * 10; |
break; |
case GET_MAX_PIXEL_CLK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->usMaxPixelClock * 10; |
break; |
case GET_REF_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_2->usReferenceClock * 10; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
case 3: |
switch (func) { |
case GET_DEFAULT_ENGINE_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->ulDefaultEngineClock * 10; |
break; |
case GET_DEFAULT_MEMORY_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->ulDefaultMemoryClock * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->ulMaxPixelClockPLL_Output * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->usMinPixelClockPLL_Output * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->usMaxPixelClockPLL_Input * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->usMinPixelClockPLL_Input * 10; |
break; |
case GET_MAX_PIXEL_CLK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->usMaxPixelClock * 10; |
break; |
case GET_REF_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_3->usReferenceClock * 10; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
case 4: |
switch (func) { |
case GET_DEFAULT_ENGINE_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->ulDefaultEngineClock * 10; |
break; |
case GET_DEFAULT_MEMORY_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->ulDefaultMemoryClock * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->usMaxPixelClockPLL_Input * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_INPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->usMinPixelClockPLL_Input * 10; |
break; |
case GET_MAX_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->ulMaxPixelClockPLL_Output * 10; |
break; |
case GET_MIN_PIXEL_CLOCK_PLL_OUTPUT: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->usMinPixelClockPLL_Output * 10; |
break; |
case GET_MAX_PIXEL_CLK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->usMaxPixelClock * 10; |
break; |
case GET_REF_CLOCK: |
*val = atomDataPtr->FirmwareInfo |
.FirmwareInfo_V_1_4->usReferenceClock * 10; |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
break; |
default: |
return ATOM_NOT_IMPLEMENTED; |
} |
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomGetConditionalGoldenSetting(atomBiosHandlePtr handle, |
AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
unsigned short *table = (unsigned short *)data->GoldenSettings.BIOSPtr; |
unsigned short entry_size = *(table++); |
|
RHDFUNC(handle); |
|
RHDDebug(handle->scrnIndex, "%s: testing 0x%4.4x\n",__func__, |
data->GoldenSettings.value); |
|
/* @@@ endian! */ |
while (table < (unsigned short *)data->GoldenSettings.End) { |
RHDDebugCont("\t\t against: 0x%8.8x\n", table[1] << 16 | table[0]); |
if ((data->GoldenSettings.value >> 16) == table[1]) { |
if ((data->GoldenSettings.value & 0xffff) <= table[0]) { |
data->GoldenSettings.BIOSPtr = (unsigned char *)(table + 2); |
return ATOM_SUCCESS; |
} |
} |
table = (unsigned short *)(((unsigned char *)table) + entry_size); |
} |
return ATOM_FAILED; |
} |
|
#define Limit(n,max,name) ((n >= max) ? ( \ |
dbgprintf(handle->scrnIndex,X_ERROR,"%s: %s %i exceeds maximum %i\n", \ |
__func__,name,n,max), TRUE) : FALSE) |
|
static const struct _rhd_connector_objs |
{ |
char *name; |
rhdConnectorType con; |
} rhd_connector_objs[] = { |
{ "NONE", RHD_CONNECTOR_NONE }, |
{ "SINGLE_LINK_DVI_I", RHD_CONNECTOR_DVI_SINGLE }, |
{ "DUAL_LINK_DVI_I", RHD_CONNECTOR_DVI }, |
{ "SINGLE_LINK_DVI_D", RHD_CONNECTOR_DVI_SINGLE }, |
{ "DUAL_LINK_DVI_D", RHD_CONNECTOR_DVI }, |
{ "VGA", RHD_CONNECTOR_VGA }, |
{ "COMPOSITE", RHD_CONNECTOR_TV }, |
{ "SVIDEO", RHD_CONNECTOR_TV, }, |
{ "YPrPb", RHD_CONNECTOR_TV, }, |
{ "D_CONNECTOR", RHD_CONNECTOR_NONE, }, |
{ "9PIN_DIN", RHD_CONNECTOR_NONE }, |
{ "SCART", RHD_CONNECTOR_TV }, |
{ "HDMI_TYPE_A", RHD_CONNECTOR_DVI_SINGLE }, |
{ "HDMI_TYPE_B", RHD_CONNECTOR_DVI }, |
{ "LVDS", RHD_CONNECTOR_PANEL }, |
{ "7PIN_DIN", RHD_CONNECTOR_TV }, |
{ "PCIE_CONNECTOR", RHD_CONNECTOR_PCIE }, |
{ "CROSSFIRE", RHD_CONNECTOR_NONE }, |
{ "HARDCODE_DVI", RHD_CONNECTOR_NONE }, |
{ "DISPLAYPORT", RHD_CONNECTOR_NONE} |
}; |
static const int n_rhd_connector_objs = sizeof (rhd_connector_objs) / sizeof(struct _rhd_connector_objs); |
|
static const struct _rhd_encoders |
{ |
char *name; |
rhdOutputType ot[2]; |
} rhd_encoders[] = { |
{ "NONE", {RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_LVDS", { RHD_OUTPUT_LVDS, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_TMDS1", { RHD_OUTPUT_TMDSA, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_TMDS2", { RHD_OUTPUT_TMDSB, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_DAC1", { RHD_OUTPUT_DACA, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_DAC2", { RHD_OUTPUT_DACB, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_SDVOA", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_SDVOB", { RHD_OUTPUT_NONE , RHD_OUTPUT_NONE }}, |
{ "SI170B", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "CH7303", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "CH7301", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_DVO1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "EXTERNAL_SDVOA", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "EXTERNAL_SDVOB", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "TITFP513", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_LVTM1", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_NONE }}, |
{ "VT1623", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "HDMI_SI1930", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "HDMI_INTERNAL", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_KLDSCP_TMDS1", { RHD_OUTPUT_TMDSA, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_KLDSCP_DVO1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_KLDSCP_DAC1", { RHD_OUTPUT_DACA, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_KLDSCP_DAC2", { RHD_OUTPUT_DACB, RHD_OUTPUT_NONE }}, |
{ "SI178", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "MVPU_FPGA", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "INTERNAL_DDI", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "VT1625", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "HDMI_SI1932", {RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "AN9801", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "DP501", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }}, |
{ "UNIPHY", { RHD_OUTPUT_UNIPHYA, RHD_OUTPUT_UNIPHYB }}, |
{ "KLDSCP_LVTMA", { RHD_OUTPUT_KLDSKP_LVTMA, RHD_OUTPUT_NONE }}, |
{ "UNIPHY1", { RHD_OUTPUT_UNIPHYC, RHD_OUTPUT_UNIPHYD }}, |
{ "UNIPHY2", { RHD_OUTPUT_UNIPHYE, RHD_OUTPUT_UNIPHYF }} |
}; |
static const int n_rhd_encoders = sizeof (rhd_encoders) / sizeof(struct _rhd_encoders); |
|
static const struct _rhd_connectors |
{ |
char *name; |
rhdConnectorType con; |
Bool dual; |
} rhd_connectors[] = { |
{"NONE", RHD_CONNECTOR_NONE, FALSE }, |
{"VGA", RHD_CONNECTOR_VGA, FALSE }, |
{"DVI-I", RHD_CONNECTOR_DVI, TRUE }, |
{"DVI-D", RHD_CONNECTOR_DVI, FALSE }, |
{"DVI-A", RHD_CONNECTOR_DVI, FALSE }, |
{"SVIDEO", RHD_CONNECTOR_TV, FALSE }, |
{"COMPOSITE", RHD_CONNECTOR_TV, FALSE }, |
{"PANEL", RHD_CONNECTOR_PANEL, FALSE }, |
{"DIGITAL_LINK", RHD_CONNECTOR_NONE, FALSE }, |
{"SCART", RHD_CONNECTOR_TV, FALSE }, |
{"HDMI Type A", RHD_CONNECTOR_DVI_SINGLE, FALSE }, |
{"HDMI Type B", RHD_CONNECTOR_DVI, FALSE }, |
{"UNKNOWN", RHD_CONNECTOR_NONE, FALSE }, |
{"UNKNOWN", RHD_CONNECTOR_NONE, FALSE }, |
{"DVI+DIN", RHD_CONNECTOR_NONE, FALSE } |
}; |
static const int n_rhd_connectors = sizeof(rhd_connectors) / sizeof(struct _rhd_connectors); |
|
static const struct _rhd_devices |
{ |
char *name; |
rhdOutputType ot[2]; |
enum atomDevice atomDevID; |
} rhd_devices[] = { /* { RHD_CHIP_EXTERNAL, RHD_CHIP_IGP } */ |
{" CRT1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomCRT1 }, |
{" LCD1", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_LVTMA }, atomLCD1 }, |
{" TV1", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomTV1 }, |
{" DFP1", { RHD_OUTPUT_TMDSA, RHD_OUTPUT_NONE }, atomDFP1 }, |
{" CRT2", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomCRT2 }, |
{" LCD2", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_NONE }, atomLCD2 }, |
{" TV2", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomTV2 }, |
{" DFP2", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_DVO }, atomDFP2 }, |
{" CV", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomCV }, |
{" DFP3", { RHD_OUTPUT_LVTMA, RHD_OUTPUT_LVTMA }, atomDFP3 }, |
{" DFP4", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomDFP4 }, |
{" DFP5", { RHD_OUTPUT_NONE, RHD_OUTPUT_NONE }, atomDFP5 } |
}; |
static const int n_rhd_devices = sizeof(rhd_devices) / sizeof(struct _rhd_devices); |
|
static const rhdDDC hwddc[] = { RHD_DDC_0, RHD_DDC_1, RHD_DDC_2, RHD_DDC_3, RHD_DDC_4 }; |
static const int n_hwddc = sizeof(hwddc) / sizeof(rhdDDC); |
|
static const rhdOutputType acc_dac[] = { RHD_OUTPUT_NONE, RHD_OUTPUT_DACA, |
RHD_OUTPUT_DACB, RHD_OUTPUT_DAC_EXTERNAL }; |
static const int n_acc_dac = sizeof(acc_dac) / sizeof (rhdOutputType); |
|
/* |
* |
*/ |
static Bool |
rhdAtomInterpretObjectID(atomBiosHandlePtr handle, |
CARD16 id, CARD8 *obj_type, CARD8 *obj_id, |
CARD8 *num, char **name) |
{ |
*obj_id = (id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; |
*num = (id & ENUM_ID_MASK) >> ENUM_ID_SHIFT; |
*obj_type = (id & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; |
|
*name = NULL; |
|
switch (*obj_type) { |
case GRAPH_OBJECT_TYPE_CONNECTOR: |
if (!Limit(*obj_id, n_rhd_connector_objs, "connector_obj")) |
*name = rhd_connector_objs[*obj_id].name; |
break; |
case GRAPH_OBJECT_TYPE_ENCODER: |
if (!Limit(*obj_id, n_rhd_encoders, "encoder_obj")) |
*name = rhd_encoders[*obj_id].name; |
break; |
default: |
break; |
} |
return TRUE; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomGetDDCIndex(atomBiosHandlePtr handle, |
rhdDDC *DDC, unsigned char i2c) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
int i; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
&(atomDataPtr->GPIO_I2C_Info->sHeader), &crev,&frev,NULL)) { |
return ATOM_NOT_IMPLEMENTED; |
} |
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { |
if (atomDataPtr->GPIO_I2C_Info->asGPIO_Info[i].sucI2cId.ucAccess == i2c) { |
RHDDebug(handle->scrnIndex, " Found DDC GPIO Index: %i\n",i); |
if (Limit(i, n_hwddc, "GPIO_DDC Index")) |
return ATOM_FAILED; |
*DDC = hwddc[i]; |
return ATOM_SUCCESS; |
} |
} |
return ATOM_FAILED; |
} |
|
/* |
* |
*/ |
static void |
rhdAtomDDCFromI2CRecord(atomBiosHandlePtr handle, |
ATOM_I2C_RECORD *Record, rhdDDC *DDC) |
{ |
RHDDebug(handle->scrnIndex, |
" %s: I2C Record: %s[%x] EngineID: %x I2CAddr: %x\n", |
__func__, |
Record->sucI2cId.bfHW_Capable ? "HW_Line" : "GPIO_ID", |
Record->sucI2cId.bfI2C_LineMux, |
Record->sucI2cId.bfHW_EngineID, |
Record->ucI2CAddr); |
|
if (!*(unsigned char *)&(Record->sucI2cId)) |
*DDC = RHD_DDC_NONE; |
else { |
union { |
ATOM_I2C_ID_CONFIG i2cId; |
unsigned char i2cChar; |
} u; |
if (Record->ucI2CAddr != 0) |
return; |
u.i2cId = Record->sucI2cId; |
if (!u.i2cChar |
|| rhdAtomGetDDCIndex(handle, DDC, u.i2cChar) != ATOM_SUCCESS) |
*DDC = RHD_DDC_NONE; |
} |
} |
|
/* |
* |
*/ |
static void |
rhdAtomParseGPIOLutForHPD(atomBiosHandlePtr handle, |
CARD8 pinID, rhdHPD *HPD) |
{ |
atomDataTablesPtr atomDataPtr; |
ATOM_GPIO_PIN_LUT *gpio_pin_lut; |
unsigned short size; |
int i = 0; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
*HPD = RHD_HPD_NONE; |
|
if (!rhdAtomGetTableRevisionAndSize( |
&atomDataPtr->GPIO_Pin_LUT->sHeader, NULL, NULL, &size)) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: No valid GPIO pin LUT in AtomBIOS\n",__func__); |
return; |
} |
gpio_pin_lut = atomDataPtr->GPIO_Pin_LUT; |
|
while (1) { |
if (gpio_pin_lut->asGPIO_Pin[i].ucGPIO_ID == pinID) { |
|
if ((sizeof(ATOM_COMMON_TABLE_HEADER) |
+ (i * sizeof(ATOM_GPIO_PIN_ASSIGNMENT))) > size) |
return; |
|
RHDDebug(handle->scrnIndex, |
" %s: GPIO PinID: %i Index: %x Shift: %i\n", |
__func__, |
pinID, |
gpio_pin_lut->asGPIO_Pin[i].usGpioPin_AIndex, |
gpio_pin_lut->asGPIO_Pin[i].ucGpioPinBitShift); |
|
/* grr... map backwards: register indices -> line numbers */ |
if (gpio_pin_lut->asGPIO_Pin[i].usGpioPin_AIndex |
== (DC_GPIO_HPD_A >> 2)) { |
switch (gpio_pin_lut->asGPIO_Pin[i].ucGpioPinBitShift) { |
case 0: |
*HPD = RHD_HPD_0; |
return; |
case 8: |
*HPD = RHD_HPD_1; |
return; |
case 16: |
*HPD = RHD_HPD_2; |
return; |
case 24: |
*HPD = RHD_HPD_3; |
return; |
} |
} |
} |
i++; |
} |
} |
|
/* |
* |
*/ |
static void |
rhdAtomHPDFromRecord(atomBiosHandlePtr handle, |
ATOM_HPD_INT_RECORD *Record, rhdHPD *HPD) |
{ |
RHDDebug(handle->scrnIndex, |
" %s: HPD Record: GPIO ID: %x Plugged_PinState: %x\n", |
__func__, |
Record->ucHPDIntGPIOID, |
Record->ucPluggged_PinState); |
rhdAtomParseGPIOLutForHPD(handle, Record->ucHPDIntGPIOID, HPD); |
} |
|
/* |
* |
*/ |
static char * |
rhdAtomDeviceTagsFromRecord(atomBiosHandlePtr handle, |
ATOM_CONNECTOR_DEVICE_TAG_RECORD *Record) |
{ |
int i, j, k; |
char *devices; |
|
RHDFUNC(handle); |
|
RHDDebug(handle->scrnIndex," NumberOfDevice: %i\n", |
Record->ucNumberOfDevice); |
|
if (!Record->ucNumberOfDevice) return NULL; |
|
devices = (char *)xcalloc(Record->ucNumberOfDevice * 4 + 1,1); |
|
for (i = 0; i < Record->ucNumberOfDevice; i++) { |
k = 0; |
j = Record->asDeviceTag[i].usDeviceID; |
|
if (!j) continue; |
|
while (!(j & 0x1)) { j >>= 1; k++; }; |
|
if (!Limit(k,n_rhd_devices,"usDeviceID")) |
strcat(devices, rhd_devices[k].name); |
} |
|
RHDDebug(handle->scrnIndex," Devices:%s\n",devices); |
|
return devices; |
} |
|
/* |
* |
*/ |
static rhdConnectorType |
rhdAtomGetConnectorID(atomBiosHandlePtr handle, rhdConnectorType connector, int num) |
{ |
RHDFUNC(handle); |
|
switch (connector) { |
case RHD_CONNECTOR_PCIE: |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
CARD32 val; |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
(ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->IntegratedSystemInfo.base), |
&crev,&frev,NULL) || crev != 2) { |
return RHD_CONNECTOR_NONE; /* sorry, we can't do any better */ |
} |
RHDDebug(handle->scrnIndex,"PCIE[%i]", num); |
switch (num) { |
case 1: |
val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot1Config; |
break; |
case 2: |
val = atomDataPtr->IntegratedSystemInfo.IntegratedSystemInfo_v2->ulDDISlot2Config; |
break; |
default: |
RHDDebugCont("\n"); |
return RHD_CONNECTOR_NONE; |
} |
val >>= 16; |
val &= 0xff; |
RHDDebugCont(" ObjectID: %i",val); |
if (Limit((int)val, n_rhd_connector_objs, "obj_id")) { |
RHDDebugCont("\n"); |
return RHD_CONNECTOR_NONE; |
} |
|
RHDDebugCont(" ConnectorName: %s\n",rhd_connector_objs[val].name); |
return rhd_connector_objs[val].con; |
} |
default: |
return connector; |
} |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomOutputDeviceListFromObjectHeader(atomBiosHandlePtr handle, |
struct rhdAtomOutputDeviceList **ptr) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
ATOM_DISPLAY_OBJECT_PATH_TABLE *disObjPathTable; |
ATOM_DISPLAY_OBJECT_PATH *disObjPath; |
rhdConnectorInfoPtr cp; |
unsigned long object_header_end; |
unsigned int i,j; |
unsigned short object_header_size; |
struct rhdAtomOutputDeviceList *DeviceList = NULL; |
int cnt = 0; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
&atomDataPtr->Object_Header->sHeader, |
&crev,&frev,&object_header_size)) { |
return ATOM_NOT_IMPLEMENTED; |
} |
|
if (crev < 2) /* don't bother with anything below rev 2 */ |
return ATOM_NOT_IMPLEMENTED; |
|
if (!(cp = (rhdConnectorInfoPtr)xcalloc(sizeof(struct rhdConnectorInfo), |
RHD_CONNECTORS_MAX))) |
return ATOM_FAILED; |
|
object_header_end = |
atomDataPtr->Object_Header->usConnectorObjectTableOffset |
+ object_header_size; |
|
RHDDebug(handle->scrnIndex,"ObjectTable - size: %u, BIOS - size: %u " |
"TableOffset: %u object_header_end: %u\n", |
object_header_size, handle->BIOSImageSize, |
atomDataPtr->Object_Header->usConnectorObjectTableOffset, |
object_header_end); |
|
if ((object_header_size > handle->BIOSImageSize) |
|| (atomDataPtr->Object_Header->usConnectorObjectTableOffset |
> handle->BIOSImageSize) |
|| object_header_end > handle->BIOSImageSize) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: Object table information is bogus\n",__func__); |
return ATOM_FAILED; |
} |
|
if (((unsigned long)&atomDataPtr->Object_Header->sHeader |
+ object_header_end) > ((unsigned long)handle->BIOSBase |
+ handle->BIOSImageSize)) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: Object table extends beyond BIOS Image\n",__func__); |
return ATOM_FAILED; |
} |
disObjPathTable = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) |
((char *)&atomDataPtr->Object_Header->sHeader + |
atomDataPtr->Object_Header->usDisplayPathTableOffset); |
RHDDebug(handle->scrnIndex, "DisplayPathObjectTable: entries: %i version: %i\n", |
disObjPathTable->ucNumOfDispPath, disObjPathTable->ucVersion); |
|
disObjPath = &disObjPathTable->asDispPath[0]; |
for (i = 0; i < disObjPathTable->ucNumOfDispPath; i++) { |
CARD8 objNum, cObjNum; |
CARD8 objId; |
CARD8 objType; |
rhdConnectorType ct; |
char *name; |
|
rhdAtomInterpretObjectID(handle, disObjPath->usConnObjectId, &objType, &objId, &objNum, &name); |
RHDDebug(handle->scrnIndex, " DisplaPathTable[%i]: size: %i DeviceTag: 0x%x ConnObjId: 0x%x NAME: %s GPUObjId: 0x%x\n", |
i, disObjPath->usSize, disObjPath->usDeviceTag, disObjPath->usConnObjectId, name, disObjPath->usGPUObjectId); |
|
if (objType != GRAPH_OBJECT_TYPE_CONNECTOR) |
continue; |
|
ct = rhd_connector_objs[objId].con; |
cObjNum = objNum; |
|
for (j = 0; j < disObjPath->usSize / sizeof(USHORT) - 4; j++) { |
int k = 0,l; |
|
rhdAtomInterpretObjectID(handle, disObjPath->usGraphicObjIds[j], &objType, &objId, &objNum, &name); |
RHDDebug(handle->scrnIndex, " GraphicsObj[%i] ID: 0x%x Type: 0x%x ObjID: 0x%x ENUM: 0x%x NAME: %s\n", |
j, disObjPath->usGraphicObjIds[j], objType, objId, objNum, name); |
|
if (objType != GRAPH_OBJECT_TYPE_ENCODER) |
continue; |
|
Limit(objId, n_rhd_encoders, "usGraphicsObjId"); |
|
l = disObjPath->usDeviceTag; |
if (!l) continue; |
|
while (!(l & 0x1)) { l >>= 1; k++; }; |
if (!Limit(k,n_rhd_devices,"usDeviceID")) { |
if (!(DeviceList = (struct rhdAtomOutputDeviceList *)xrealloc(DeviceList, sizeof (struct rhdAtomOutputDeviceList) * (cnt + 1)))) |
return ATOM_FAILED; |
|
DeviceList[cnt].DeviceId = rhd_devices[k].atomDevID; |
DeviceList[cnt].ConnectorType = rhdAtomGetConnectorID(handle, ct, cObjNum); |
DeviceList[cnt].OutputType = rhd_encoders[objId].ot[objNum - 1]; |
cnt++; |
RHDDebug(handle->scrnIndex, " DeviceIndex: 0x%x\n",k); |
} |
} |
disObjPath = (ATOM_DISPLAY_OBJECT_PATH*)(((char *)disObjPath) + disObjPath->usSize); |
if ((((unsigned long)&atomDataPtr->Object_Header->sHeader + object_header_end) |
< (((unsigned long) disObjPath) + sizeof(ATOM_DISPLAY_OBJECT_PATH))) |
|| (((unsigned long)&atomDataPtr->Object_Header->sHeader + object_header_end) |
< (((unsigned long) disObjPath) + disObjPath->usSize))) |
break; |
} |
DeviceList = xrealloc(DeviceList, sizeof(struct rhdAtomOutputDeviceList) * (cnt + 1)); |
DeviceList[cnt].DeviceId = atomNone; |
|
*ptr = DeviceList; |
|
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomConnectorInfoFromObjectHeader(atomBiosHandlePtr handle, |
rhdConnectorInfoPtr *ptr) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
ATOM_CONNECTOR_OBJECT_TABLE *con_obj; |
rhdConnectorInfoPtr cp; |
unsigned long object_header_end; |
int ncon = 0; |
int i,j; |
unsigned short object_header_size; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
&atomDataPtr->Object_Header->sHeader, |
&crev,&frev,&object_header_size)) { |
return ATOM_NOT_IMPLEMENTED; |
} |
|
if (crev < 2) /* don't bother with anything below rev 2 */ |
return ATOM_NOT_IMPLEMENTED; |
|
if (!(cp = (rhdConnectorInfoPtr)xcalloc(sizeof(struct rhdConnectorInfo), |
RHD_CONNECTORS_MAX))) |
return ATOM_FAILED; |
|
object_header_end = |
atomDataPtr->Object_Header->usConnectorObjectTableOffset |
+ object_header_size; |
|
RHDDebug(handle->scrnIndex,"ObjectTable - size: %u, BIOS - size: %u " |
"TableOffset: %u object_header_end: %u\n", |
object_header_size, handle->BIOSImageSize, |
atomDataPtr->Object_Header->usConnectorObjectTableOffset, |
object_header_end); |
|
if ((object_header_size > handle->BIOSImageSize) |
|| (atomDataPtr->Object_Header->usConnectorObjectTableOffset |
> handle->BIOSImageSize) |
|| object_header_end > handle->BIOSImageSize) { |
xfree(cp); |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: Object table information is bogus\n",__func__); |
return ATOM_FAILED; |
} |
|
if (((unsigned long)&atomDataPtr->Object_Header->sHeader |
+ object_header_end) > ((unsigned long)handle->BIOSBase |
+ handle->BIOSImageSize)) { |
xfree(cp); |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: Object table extends beyond BIOS Image\n",__func__); |
return ATOM_FAILED; |
} |
|
con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) |
((char *)&atomDataPtr->Object_Header->sHeader + |
atomDataPtr->Object_Header->usConnectorObjectTableOffset); |
|
for (i = 0; i < con_obj->ucNumberOfObjects; i++) { |
ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *SrcDstTable; |
ATOM_COMMON_RECORD_HEADER *Record; |
int record_base; |
CARD8 obj_type, obj_id, num; |
char *name; |
|
rhdAtomInterpretObjectID(handle, con_obj->asObjects[i].usObjectID, |
&obj_type, &obj_id, &num, &name); |
|
RHDDebug(handle->scrnIndex, "Object: ID: %x name: %s type: %x id: %x\n", |
con_obj->asObjects[i].usObjectID, name ? name : "", |
obj_type, obj_id); |
|
|
if (obj_type != GRAPH_OBJECT_TYPE_CONNECTOR) |
continue; |
|
SrcDstTable = (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) |
((char *)&atomDataPtr->Object_Header->sHeader |
+ con_obj->asObjects[i].usSrcDstTableOffset); |
|
if (con_obj->asObjects[i].usSrcDstTableOffset |
+ (SrcDstTable->ucNumberOfSrc |
* sizeof(ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT)) |
> handle->BIOSImageSize) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: SrcDstTable[%i] extends " |
"beyond Object_Header table\n",__func__,i); |
continue; |
} |
cp[ncon].Type = rhdAtomGetConnectorID(handle, rhd_connector_objs[obj_id].con, num); |
cp[ncon].Name = RhdAppendString(cp[ncon].Name,name); |
|
for (j = 0; ((j < SrcDstTable->ucNumberOfSrc) && |
(j < MAX_OUTPUTS_PER_CONNECTOR)); j++) { |
CARD8 stype, sobj_id, snum; |
char *sname; |
|
rhdAtomInterpretObjectID(handle, SrcDstTable->usSrcObjectID[j], |
&stype, &sobj_id, &snum, &sname); |
|
RHDDebug(handle->scrnIndex, " * SrcObject: ID: %x name: %s enum: %i\n", |
SrcDstTable->usSrcObjectID[j], sname, snum); |
|
if (snum <= 2) |
cp[ncon].Output[j] = rhd_encoders[sobj_id].ot[snum - 1]; |
} |
|
Record = (ATOM_COMMON_RECORD_HEADER *) |
((char *)&atomDataPtr->Object_Header->sHeader |
+ con_obj->asObjects[i].usRecordOffset); |
|
record_base = con_obj->asObjects[i].usRecordOffset; |
|
while (Record->ucRecordType > 0 |
&& Record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER ) { |
char *taglist; |
|
if ((record_base += Record->ucRecordSize) |
> object_header_size) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"%s: Object Records extend beyond Object Table\n", |
__func__); |
break; |
} |
|
RHDDebug(handle->scrnIndex, " - Record Type: %x\n", |
Record->ucRecordType); |
|
switch (Record->ucRecordType) { |
|
case ATOM_I2C_RECORD_TYPE: |
rhdAtomDDCFromI2CRecord(handle, |
(ATOM_I2C_RECORD *)Record, |
&cp[ncon].DDC); |
break; |
|
case ATOM_HPD_INT_RECORD_TYPE: |
rhdAtomHPDFromRecord(handle, |
(ATOM_HPD_INT_RECORD *)Record, |
&cp[ncon].HPD); |
break; |
|
case ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE: |
taglist = rhdAtomDeviceTagsFromRecord(handle, |
(ATOM_CONNECTOR_DEVICE_TAG_RECORD *)Record); |
if (taglist) { |
cp[ncon].Name = RhdAppendString(cp[ncon].Name,taglist); |
xfree(taglist); |
} |
break; |
|
default: |
break; |
} |
|
Record = (ATOM_COMMON_RECORD_HEADER*) |
((char *)Record + Record->ucRecordSize); |
|
} |
|
if ((++ncon) == RHD_CONNECTORS_MAX) |
break; |
} |
*ptr = cp; |
|
RhdPrintConnectorInfo(handle->rhdPtr, cp); |
|
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomOutputDeviceListFromSupportedDevices(atomBiosHandlePtr handle, |
Bool igp, |
struct rhdAtomOutputDeviceList **Ptr) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
int n; |
int cnt = 0; |
struct rhdAtomOutputDeviceList *DeviceList = NULL; |
struct rhdConnectorInfo *cp; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
&(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader), |
&crev,&frev,NULL)) { |
return ATOM_NOT_IMPLEMENTED; |
} |
|
if (!(cp = (rhdConnectorInfoPtr)xcalloc(RHD_CONNECTORS_MAX, |
sizeof(struct rhdConnectorInfo)))) |
return ATOM_FAILED; |
|
for (n = 0; n < ATOM_MAX_SUPPORTED_DEVICE; n++) { |
ATOM_CONNECTOR_INFO_I2C ci |
= atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[n]; |
|
if (!(atomDataPtr->SupportedDevicesInfo |
.SupportedDevicesInfo->usDeviceSupport & (1 << n))) |
continue; |
|
if (Limit(ci.sucConnectorInfo.sbfAccess.bfConnectorType, |
n_rhd_connectors, "bfConnectorType")) |
continue; |
|
if (!(DeviceList = (struct rhdAtomOutputDeviceList *)xrealloc(DeviceList, sizeof(struct rhdAtomOutputDeviceList) * (cnt + 1)))) |
return ATOM_FAILED; |
|
DeviceList[cnt].ConnectorType = rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].con; |
DeviceList[cnt].DeviceId = rhd_devices[n].atomDevID; |
|
if (!Limit(ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC, |
n_acc_dac, "bfAssociatedDAC")) { |
if ((DeviceList[cnt].OutputType |
= acc_dac[ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC]) |
== RHD_OUTPUT_NONE) { |
DeviceList[cnt].OutputType = rhd_devices[n].ot[igp ? 1 : 0]; |
} |
cnt++; |
} |
} |
DeviceList = (struct rhdAtomOutputDeviceList *)xrealloc(DeviceList, sizeof(struct rhdAtomOutputDeviceList) * (cnt + 1)); |
DeviceList[cnt].DeviceId = atomNone; |
|
*Ptr = DeviceList; |
|
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomConnectorInfoFromSupportedDevices(atomBiosHandlePtr handle, |
Bool igp, |
rhdConnectorInfoPtr *ptr) |
{ |
atomDataTablesPtr atomDataPtr; |
CARD8 crev, frev; |
rhdConnectorInfoPtr cp; |
struct { |
rhdOutputType ot; |
rhdConnectorType con; |
rhdDDC ddc; |
rhdHPD hpd; |
Bool dual; |
char *name; |
char *outputName; |
} devices[ATOM_MAX_SUPPORTED_DEVICE]; |
int ncon = 0; |
int n; |
|
RHDFUNC(handle); |
|
atomDataPtr = handle->atomDataPtr; |
|
if (!rhdAtomGetTableRevisionAndSize( |
&(atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->sHeader), |
&crev,&frev,NULL)) { |
return ATOM_NOT_IMPLEMENTED; |
} |
|
if (!(cp = (rhdConnectorInfoPtr)xcalloc(RHD_CONNECTORS_MAX, |
sizeof(struct rhdConnectorInfo)))) |
return ATOM_FAILED; |
|
for (n = 0; n < ATOM_MAX_SUPPORTED_DEVICE; n++) { |
ATOM_CONNECTOR_INFO_I2C ci |
= atomDataPtr->SupportedDevicesInfo.SupportedDevicesInfo->asConnInfo[n]; |
|
devices[n].ot = RHD_OUTPUT_NONE; |
|
if (!(atomDataPtr->SupportedDevicesInfo |
.SupportedDevicesInfo->usDeviceSupport & (1 << n))) |
continue; |
|
if (Limit(ci.sucConnectorInfo.sbfAccess.bfConnectorType, |
n_rhd_connectors, "bfConnectorType")) |
continue; |
|
devices[n].con |
= rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].con; |
if (devices[n].con == RHD_CONNECTOR_NONE) |
continue; |
|
devices[n].dual |
= rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].dual; |
devices[n].name |
= rhd_connectors[ci.sucConnectorInfo.sbfAccess.bfConnectorType].name; |
|
RHDDebug(handle->scrnIndex,"AtomBIOS Connector[%i]: %s Device:%s ",n, |
rhd_connectors[ci.sucConnectorInfo |
.sbfAccess.bfConnectorType].name, |
rhd_devices[n].name); |
|
devices[n].outputName = rhd_devices[n].name; |
|
if (!Limit(ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC, |
n_acc_dac, "bfAssociatedDAC")) { |
if ((devices[n].ot |
= acc_dac[ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC]) |
== RHD_OUTPUT_NONE) { |
devices[n].ot = rhd_devices[n].ot[igp ? 1 : 0]; |
} |
} else |
devices[n].ot = RHD_OUTPUT_NONE; |
|
RHDDebugCont("Output: %x ",devices[n].ot); |
|
if (!ci.sucI2cId.ucAccess |
|| rhdAtomGetDDCIndex(handle, &devices[n].ddc, ci.sucI2cId.ucAccess) != ATOM_SUCCESS) { |
RHDDebugCont("NO DDC "); |
devices[n].ddc = RHD_DDC_NONE; |
} else |
RHDDebugCont("HW DDC %i ", |
ci.sucI2cId.sbfAccess.bfI2C_LineMux); |
|
if (crev > 1) { |
ATOM_CONNECTOR_INC_SRC_BITMAP isb |
= atomDataPtr->SupportedDevicesInfo |
.SupportedDevicesInfo_HD->asIntSrcInfo[n]; |
|
switch (isb.ucIntSrcBitmap) { |
case 0x4: |
RHDDebugCont("HPD 0\n"); |
devices[n].hpd = RHD_HPD_0; |
break; |
case 0xa: |
RHDDebugCont("HPD 1\n"); |
devices[n].hpd = RHD_HPD_1; |
break; |
default: |
RHDDebugCont("NO HPD\n"); |
devices[n].hpd = RHD_HPD_NONE; |
break; |
} |
} else { |
RHDDebugCont("NO HPD\n"); |
devices[n].hpd = RHD_HPD_NONE; |
} |
} |
/* sort devices for connectors */ |
for (n = 0; n < ATOM_MAX_SUPPORTED_DEVICE; n++) { |
int i; |
|
if (devices[n].ot == RHD_OUTPUT_NONE) |
continue; |
if (devices[n].con == RHD_CONNECTOR_NONE) |
continue; |
|
cp[ncon].DDC = devices[n].ddc; |
cp[ncon].HPD = devices[n].hpd; |
cp[ncon].Output[0] = devices[n].ot; |
cp[ncon].Output[1] = RHD_OUTPUT_NONE; |
cp[ncon].Type = devices[n].con; |
cp[ncon].Name = strdup(devices[n].name); |
cp[ncon].Name = RhdAppendString(cp[ncon].Name, devices[n].outputName); |
|
if (devices[n].dual) { |
if (devices[n].ddc == RHD_DDC_NONE) |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"No DDC channel for device %s found." |
" Cannot find matching device.\n",devices[n].name); |
else { |
for (i = n + 1; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { |
|
if (!devices[i].dual) |
continue; |
|
if (devices[n].ddc != devices[i].ddc) |
continue; |
|
if (((devices[n].ot == RHD_OUTPUT_DACA |
|| devices[n].ot == RHD_OUTPUT_DACB) |
&& (devices[i].ot == RHD_OUTPUT_LVTMA |
|| devices[i].ot == RHD_OUTPUT_TMDSA)) |
|| ((devices[i].ot == RHD_OUTPUT_DACA |
|| devices[i].ot == RHD_OUTPUT_DACB) |
&& (devices[n].ot == RHD_OUTPUT_LVTMA |
|| devices[n].ot == RHD_OUTPUT_TMDSA))) { |
|
cp[ncon].Output[1] = devices[i].ot; |
|
if (cp[ncon].HPD == RHD_HPD_NONE) |
cp[ncon].HPD = devices[i].hpd; |
|
cp[ncon].Name = RhdAppendString(cp[ncon].Name, |
devices[i].outputName); |
devices[i].ot = RHD_OUTPUT_NONE; /* zero the device */ |
} |
} |
} |
} |
/* Some connector table mark a VGA as DVI-X. This heuristic fixes it */ |
if (cp[ncon].Type == RHD_CONNECTOR_DVI) { |
if ( ((cp[ncon].Output[0] == RHD_OUTPUT_NONE |
&& (cp[ncon].Output[1] == RHD_OUTPUT_DACA |
|| cp[ncon].Output[1] == RHD_OUTPUT_DACB)) |
|| (cp[ncon].Output[1] == RHD_OUTPUT_NONE |
&& (cp[ncon].Output[0] == RHD_OUTPUT_DACA |
|| cp[ncon].Output[0] == RHD_OUTPUT_DACB))) |
&& cp[ncon].HPD == RHD_HPD_NONE) |
cp[ncon].Type = RHD_CONNECTOR_VGA; |
} |
|
if ((++ncon) == RHD_CONNECTORS_MAX) |
break; |
} |
*ptr = cp; |
|
RhdPrintConnectorInfo(handle->rhdPtr, cp); |
|
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomConnectorInfo(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data) |
{ |
int chipset = data->chipset; |
|
RHDFUNC(handle); |
|
if (rhdAtomConnectorInfoFromObjectHeader(handle,&data->ConnectorInfo) |
== ATOM_SUCCESS) |
return ATOM_SUCCESS; |
else { |
Bool igp = RHDIsIGP(chipset); |
return rhdAtomConnectorInfoFromSupportedDevices(handle, igp, |
&data->ConnectorInfo); |
} |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
rhdAtomOutputDeviceList(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data) |
{ |
int chipset = data->chipset; |
|
RHDFUNC(handle); |
|
if (rhdAtomOutputDeviceListFromObjectHeader(handle, &data->OutputDeviceList) |
== ATOM_SUCCESS) { |
return ATOM_SUCCESS; |
} else { |
Bool igp = RHDIsIGP(chipset); |
return rhdAtomOutputDeviceListFromSupportedDevices(handle, igp, &data->OutputDeviceList); |
} |
} |
|
/* |
* |
*/ |
struct atomCodeDataTableHeader |
{ |
unsigned char signature; |
unsigned short size; |
}; |
|
#define CODE_DATA_TABLE_SIGNATURE 0x7a |
#define ATOM_EOT_COMMAND 0x5b |
|
static AtomBiosResult |
rhdAtomGetDataInCodeTable(atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data) |
{ |
unsigned char *command_table; |
unsigned short size; |
unsigned short offset; |
|
int i; |
|
RHDFUNC(handle); |
|
if (data->val > sizeof (struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES) / sizeof (USHORT)) |
return ATOM_FAILED; |
|
if ((offset = ((USHORT *)&(((ATOM_MASTER_COMMAND_TABLE *)handle->codeTable) |
->ListOfCommandTables))[data->val])) |
command_table = handle->BIOSBase + offset; |
else |
return ATOM_FAILED; |
|
if (!rhdAtomGetTableRevisionAndSize(&(((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *) |
command_table)->CommonHeader), |
NULL, NULL, &size)) |
return ATOM_FAILED; |
|
for (i = sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER); i < size - 1; i++) { |
|
if (command_table[i] == ATOM_EOT_COMMAND |
&& command_table[i+1] == CODE_DATA_TABLE_SIGNATURE) { |
unsigned short *dt_size = (unsigned short*)(command_table + i + 2); |
|
int diff; |
|
diff = size - (i + 1) + sizeof(struct atomCodeDataTableHeader) + *dt_size; |
|
DBG(dbgprintf("Table[0x%2.2x] = 0x%4.4x -> data_size: 0x%x\n",data->val, size, *dt_size)); |
|
if (diff < 0) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, |
"Data table in command table %li extends %i bytes " |
"beyond command table size\n", |
(unsigned long) data->val, -diff); |
|
return ATOM_FAILED; |
} |
data->CommandDataTable.loc = |
command_table + i + 2 + sizeof(unsigned short); |
|
data->CommandDataTable.size = *dt_size; |
// DEBUGP(RhdDebugDump(handle->scrnIndex, data->CommandDataTable.loc, *dt_size)); |
|
return ATOM_SUCCESS; |
} |
} |
|
return ATOM_FAILED; |
} |
|
# ifdef ATOM_BIOS_PARSER |
static AtomBiosResult |
rhdAtomExec (atomBiosHandlePtr handle, |
AtomBiosRequestID unused, AtomBiosArgPtr data) |
{ |
RHDPtr rhdPtr = handle->rhdPtr; |
Bool ret = FALSE; |
char *msg; |
int idx = data->exec.index; |
void *pspace = data->exec.pspace; |
pointer *dataSpace = data->exec.dataSpace; |
|
RHDFUNCI(handle->scrnIndex); |
|
if (dataSpace) { |
if (!handle->fbBase && !handle->scratchBase) |
return ATOM_FAILED; |
if (handle->fbBase) { |
if (!rhdPtr->FbBase) { |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s: " |
"Cannot exec AtomBIOS: framebuffer not mapped\n", |
__func__); |
return ATOM_FAILED; |
} |
*dataSpace = (CARD8*)rhdPtr->FbBase + handle->fbBase; |
} else |
*dataSpace = (CARD8*)handle->scratchBase; |
} |
ret = ParseTableWrapper(pspace, idx, handle, |
handle->BIOSBase, |
&msg); |
if (!ret) |
xf86DrvMsg(handle->scrnIndex, X_ERROR, "%s\n",msg); |
else |
xf86DrvMsgVerb(handle->scrnIndex, X_INFO, 5, "%s\n",msg); |
|
return (ret) ? ATOM_SUCCESS : ATOM_FAILED; |
} |
# endif |
|
AtomBiosResult |
RHDAtomBiosFunc(RHDPtr rhdPtr, atomBiosHandlePtr handle, |
AtomBiosRequestID id, AtomBiosArgPtr data) |
{ |
AtomBiosResult ret = ATOM_FAILED; |
int scrnIndex = rhdPtr->scrnIndex; |
int i; |
char *msg = NULL; |
enum msgDataFormat msg_f = MSG_FORMAT_NONE; |
AtomBiosRequestFunc req_func = NULL; |
|
RHDFUNCI(scrnIndex); |
|
for (i = 0; AtomBiosRequestList[i].id != FUNC_END; i++) { |
if (id == AtomBiosRequestList[i].id) { |
req_func = AtomBiosRequestList[i].request; |
msg = AtomBiosRequestList[i].message; |
msg_f = AtomBiosRequestList[i].message_format; |
break; |
} |
} |
|
if (req_func == NULL) { |
xf86DrvMsg(scrnIndex, X_ERROR, "Unknown AtomBIOS request: %i\n",id); |
return ATOM_NOT_IMPLEMENTED; |
} |
/* Hack for now */ |
if (id == ATOMBIOS_INIT) |
data->val = (CARD32)rhdPtr; |
|
if (id == ATOMBIOS_INIT || handle) |
ret = req_func(handle, id, data); |
|
if (ret == ATOM_SUCCESS) { |
|
switch (msg_f) { |
case MSG_FORMAT_DEC: |
xf86DrvMsg(scrnIndex,X_INFO,"%s: %li\n", msg, |
(unsigned long) data->val); |
break; |
case MSG_FORMAT_HEX: |
xf86DrvMsg(scrnIndex,X_INFO,"%s: 0x%lx\n",msg , |
(unsigned long) data->val); |
break; |
case MSG_FORMAT_NONE: |
xf86DrvMsgVerb(scrnIndex, 7, X_INFO, |
"Call to %s succeeded\n", msg); |
break; |
} |
|
} else { |
|
char *result = (ret == ATOM_FAILED) ? "failed" |
: "not implemented"; |
switch (msg_f) { |
case MSG_FORMAT_DEC: |
case MSG_FORMAT_HEX: |
xf86DrvMsgVerb(scrnIndex, 1, X_WARNING, |
"Call to %s %s\n", msg, result); |
break; |
case MSG_FORMAT_NONE: |
xf86DrvMsg(scrnIndex,X_INFO,"Query for %s: %s\n", msg, result); |
break; |
} |
} |
return ret; |
} |
|
/* |
* |
*/ |
static void |
atomRegisterSaveList(atomBiosHandlePtr handle, struct atomSaveListRecord **SaveList) |
{ |
struct atomSaveListObject *ListObject = handle->SaveListObjects; |
RHDFUNC(handle); |
|
while (ListObject) { |
if (ListObject->SaveList == SaveList) |
return; |
ListObject = ListObject->next; |
} |
if (!(ListObject = (struct atomSaveListObject *)xcalloc(1,sizeof (struct atomSaveListObject)))) |
return; |
ListObject->next = handle->SaveListObjects; |
ListObject->SaveList = SaveList; |
handle->SaveListObjects = ListObject; |
} |
|
/* |
* |
*/ |
static void |
atomUnregisterSaveList(atomBiosHandlePtr handle, struct atomSaveListRecord **SaveList) |
{ |
struct atomSaveListObject **ListObject; |
RHDFUNC(handle); |
|
if (!handle->SaveListObjects) |
return; |
ListObject = &handle->SaveListObjects; |
|
while (1) { |
if ((*ListObject)->SaveList == SaveList) { |
struct atomSaveListObject *tmp = *ListObject; |
*ListObject = ((*ListObject)->next); |
xfree(tmp); |
} |
if (!(*ListObject) || !(*ListObject)->next) |
return; |
ListObject = &((*ListObject)->next); |
} |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
atomSetRegisterListLocation(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
RHDFUNC(handle); |
|
handle->SaveList = (struct atomSaveListRecord **)data->Address; |
if (handle->SaveList) |
atomRegisterSaveList(handle, handle->SaveList); |
|
return ATOM_SUCCESS; |
} |
|
/* |
* |
*/ |
static AtomBiosResult |
atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data) |
{ |
struct atomSaveListRecord *List = *(data->Address); |
int i; |
|
RHDFUNC(handle); |
|
if (!List) |
return ATOM_FAILED; |
|
for (i = 0; i < List->Last; i++) { |
switch ( List->RegisterList[i].Type) { |
case atomRegisterMMIO: |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MMIO(0x%4.4x) = 0x%4.4x\n",__func__, List->Last, |
List->RegisterList[i].Address, List->RegisterList[i].Value); |
RHDRegWrite(handle, List->RegisterList[i].Address, List->RegisterList[i].Value); |
break; |
case atomRegisterMC: |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MC(0x%4.4x) = 0x%4.4x\n",__func__, List->Last, |
List->RegisterList[i].Address, List->RegisterList[i].Value); |
RHDWriteMC(handle, List->RegisterList[i].Address | MC_IND_ALL | MC_IND_WR_EN, |
List->RegisterList[i].Value); |
break; |
case atomRegisterPLL: |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PLL(0x%4.4x) = 0x%4.4x\n",__func__, List->Last, |
List->RegisterList[i].Address, List->RegisterList[i].Value); |
_RHDWritePLL(handle->scrnIndex, List->RegisterList[i].Address, List->RegisterList[i].Value); |
break; |
case atomRegisterPCICFG: |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PCICFG(0x%4.4x) = 0x%4.4x\n",__func__,List->Last, |
List->RegisterList[i].Address, List->RegisterList[i].Value); |
#ifdef XSERVER_LIBPCIACCESS |
pci_device_cfg_write(RHDPTRI(handle)->PciInfo, |
&List->RegisterList[i].Value, |
List->RegisterList[i].Address, 4, NULL); |
#else |
{ |
PCITAG tag = RHDPTRI(handle)->PciTag; |
pciWriteLong(tag, List->RegisterList[i].Address, |
List->RegisterList[i].Value); |
} |
#endif |
break; |
} |
} |
|
/* deallocate list */ |
atomUnregisterSaveList(handle, (struct atomSaveListRecord **)data->Address); |
xfree(List); |
*(data->Address) = NULL; |
|
return ATOM_SUCCESS; |
} |
|
# ifdef ATOM_BIOS_PARSER |
|
#define ALLOC_CNT 25 |
|
/* |
* |
*/ |
static void |
atomSaveRegisters(atomBiosHandlePtr handle, enum atomRegisterType Type, CARD32 address) |
{ |
struct atomSaveListRecord *List; |
CARD32 val = 0; |
int i; |
struct atomSaveListObject *SaveListObj = handle->SaveListObjects; |
|
RHDFUNC(handle); |
|
if (!handle->SaveList) |
return; |
|
if (!(*(handle->SaveList))) { |
if (!(*handle->SaveList = (struct atomSaveListRecord *)xalloc(sizeof(struct atomSaveListRecord) |
+ sizeof(struct atomRegisterList) * (ALLOC_CNT - 1)))) |
return; |
(*(handle->SaveList))->Length = ALLOC_CNT; |
(*(handle->SaveList))->Last = 0; |
} else if ((*(handle->SaveList))->Length == (*(handle->SaveList))->Last) { |
if (!(List = (struct atomSaveListRecord *)xrealloc(*handle->SaveList, |
sizeof(struct atomSaveListRecord) |
+ (sizeof(struct atomRegisterList) |
* ((*(handle->SaveList))->Length + ALLOC_CNT - 1))))) |
return; |
*handle->SaveList = List; |
List->Length = (*(handle->SaveList))->Length + ALLOC_CNT; |
} |
List = *handle->SaveList; |
|
while (SaveListObj) { |
struct atomSaveListRecord *ListFromObj = *(SaveListObj->SaveList); |
|
if (ListFromObj) { |
for (i = 0; i < ListFromObj->Last; i++) |
if (ListFromObj->RegisterList[i].Address == address |
&& ListFromObj->RegisterList[i].Type == Type) |
return; |
} |
SaveListObj = SaveListObj->next; |
} |
|
switch (Type) { |
case atomRegisterMMIO: |
val = RHDRegRead(handle, address); |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MMIO(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val); |
break; |
case atomRegisterMC: |
val = RHDReadMC(handle, address | MC_IND_ALL); |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: MC(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val); |
break; |
case atomRegisterPLL: |
val = _RHDReadPLL(handle->scrnIndex, address); |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PLL(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val); |
break; |
case atomRegisterPCICFG: |
#ifdef XSERVER_LIBPCIACCESS |
val = pci_device_cfg_write(RHDPTRI(handle)->PciInfo, |
&val, address, 4, NULL); |
#else |
{ |
PCITAG tag = RHDPTRI(handle)->PciTag; |
val = pciReadLong(tag, address); |
} |
#endif |
RHDDebugVerb(handle->scrnIndex,1, "%s[%i]: PCICFG(0x%4.4x) = 0x%4.4x\n",__func__,List->Last,address,val); |
break; |
} |
List->RegisterList[List->Last].Address = address; |
List->RegisterList[List->Last].Value = val; |
List->RegisterList[List->Last].Type = Type; |
List->Last++; |
} |
|
/* |
* |
*/ |
VOID* |
CailAllocateMemory(VOID *CAIL,UINT16 size) |
{ |
CAILFUNC(CAIL); |
|
return malloc(size); |
} |
|
VOID |
CailReleaseMemory(VOID *CAIL, VOID *addr) |
{ |
CAILFUNC(CAIL); |
|
free(addr); |
} |
|
VOID |
CailDelayMicroSeconds(VOID *CAIL, UINT32 delay) |
{ |
CAILFUNC(CAIL); |
|
usleep(delay); |
|
// DEBUGP(xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_INFO,"Delay %i usec\n",delay)); |
} |
|
UINT32 |
CailReadATIRegister(VOID* CAIL, UINT32 idx) |
{ |
UINT32 ret; |
CAILFUNC(CAIL); |
|
ret = RHDRegRead(((atomBiosHandlePtr)CAIL), idx << 2); |
// DEBUGP(ErrorF("%s(%x) = %x\n",__func__,idx << 2,ret)); |
return ret; |
} |
|
VOID |
CailWriteATIRegister(VOID *CAIL, UINT32 idx, UINT32 data) |
{ |
CAILFUNC(CAIL); |
|
atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterMMIO, idx << 2); |
|
RHDRegWrite(((atomBiosHandlePtr)CAIL),idx << 2,data); |
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,idx << 2,data); |
} |
|
UINT32 |
CailReadFBData(VOID* CAIL, UINT32 idx) |
{ |
UINT32 ret; |
|
CAILFUNC(CAIL); |
|
if (((atomBiosHandlePtr)CAIL)->fbBase) { |
CARD8 *FBBase = (CARD8*) |
RHDPTRI((atomBiosHandlePtr)CAIL)->FbBase; |
ret = *((CARD32*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)); |
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,idx,ret); |
} else if (((atomBiosHandlePtr)CAIL)->scratchBase) { |
ret = *(CARD32*)((CARD8*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx); |
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,idx,ret); |
} else { |
xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, |
"%s: no fbbase set\n",__func__); |
return 0; |
} |
return ret; |
} |
|
VOID |
CailWriteFBData(VOID *CAIL, UINT32 idx, UINT32 data) |
{ |
CAILFUNC(CAIL); |
|
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,idx,data); |
if (((atomBiosHandlePtr)CAIL)->fbBase) { |
CARD8 *FBBase = (CARD8*) |
RHDPTRI((atomBiosHandlePtr)CAIL)->FbBase; |
*((CARD32*)(FBBase + (((atomBiosHandlePtr)CAIL)->fbBase) + idx)) = data; |
} else if (((atomBiosHandlePtr)CAIL)->scratchBase) { |
*(CARD32*)((CARD8*)(((atomBiosHandlePtr)CAIL)->scratchBase) + idx) = data; |
} else |
xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, |
"%s: no fbbase set\n",__func__); |
} |
|
ULONG |
CailReadMC(VOID *CAIL, ULONG Address) |
{ |
ULONG ret; |
|
CAILFUNC(CAIL); |
|
ret = RHDReadMC(((atomBiosHandlePtr)CAIL)->rhdPtr, Address | MC_IND_ALL); |
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,Address,ret); |
return ret; |
} |
|
VOID |
CailWriteMC(VOID *CAIL, ULONG Address, ULONG data) |
{ |
CAILFUNC(CAIL); |
|
|
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,Address,data); |
|
atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterMC, Address); |
|
RHDWriteMC(((atomBiosHandlePtr)CAIL)->rhdPtr, Address | MC_IND_ALL | MC_IND_WR_EN, data); |
} |
|
#ifdef XSERVER_LIBPCIACCESS |
|
VOID |
CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) |
{ |
pci_device_cfg_read(RHDPTRI((atomBiosHandlePtr)CAIL)->PciInfo, |
ret,idx << 2 , size >> 3, NULL); |
} |
|
VOID |
CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) |
{ |
atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterPCICFG, idx << 2); |
pci_device_cfg_write(RHDPTRI((atomBiosHandlePtr)CAIL)->PciInfo, |
src, idx << 2, size >> 3, NULL); |
} |
|
#else |
|
VOID |
CailReadPCIConfigData(VOID*CAIL, VOID* ret, UINT32 idx,UINT16 size) |
{ u32_t bus, devfn; |
PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; |
|
CAILFUNC(CAIL); |
bus = PCI_BUS_FROM_TAG(tag); |
devfn = PCI_DFN_FROM_TAG(tag); |
|
switch (size) { |
case 8: |
*(CARD8*)ret = PciRead8(bus,devfn,idx << 2); |
break; |
case 16: |
*(CARD16*)ret = PciRead16(bus,devfn,idx << 2); |
break; |
case 32: |
*(CARD32*)ret = PciRead32(bus,devfn,idx << 2); |
break; |
default: |
xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex, |
X_ERROR,"%s: Unsupported size: %i\n", |
__func__,(int)size); |
return; |
break; |
} |
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,idx,*(unsigned int*)ret); |
|
} |
|
VOID |
CailWritePCIConfigData(VOID*CAIL,VOID*src,UINT32 idx,UINT16 size) |
{ |
u32_t bus, devfn; |
PCITAG tag = ((atomBiosHandlePtr)CAIL)->PciTag; |
bus = PCI_BUS_FROM_TAG(tag); |
devfn = PCI_DFN_FROM_TAG(tag); |
|
CAILFUNC(CAIL); |
|
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,idx,(*(unsigned int*)src)); |
|
atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterPCICFG, idx << 2); |
switch (size) { |
case 8: |
PciWrite8(bus,devfn, idx << 2,*(CARD8*)src); |
break; |
case 16: |
PciWrite16(bus,devfn,idx << 2,*(CARD16*)src); |
break; |
case 32: |
PciWrite32(bus,devfn,idx << 2,*(CARD32*)src); |
break; |
default: |
xf86DrvMsg(((atomBiosHandlePtr)CAIL)->scrnIndex,X_ERROR, |
"%s: Unsupported size: %i\n",__func__,(int)size); |
break; |
} |
} |
#endif |
|
ULONG |
CailReadPLL(VOID *CAIL, ULONG Address) |
{ |
ULONG ret; |
|
CAILFUNC(CAIL); |
|
ret = _RHDReadPLL(((atomBiosHandlePtr)CAIL)->rhdPtr, Address); |
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x) = %x\n",__func__,Address,ret); |
return ret; |
} |
|
VOID |
CailWritePLL(VOID *CAIL, ULONG Address,ULONG Data) |
{ |
CAILFUNC(CAIL); |
|
RHDDebugVerb(((atomBiosHandlePtr)CAIL)->scrnIndex,1,"%s(%x,%x)\n",__func__,Address,Data); |
atomSaveRegisters((atomBiosHandlePtr)CAIL, atomRegisterPLL, Address); |
_RHDWritePLL(((atomBiosHandlePtr)CAIL)->scrnIndex, Address, Data); |
} |
|
# endif |
|
#endif /* ATOM_BIOS */ |