Subversion Repositories Kolibri OS

Rev

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

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