Subversion Repositories Kolibri OS

Rev

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.  
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #include "xf86.h"
  30. #if HAVE_XF86_ANSIC_H
  31. # include "xf86_ansic.h"
  32. #else
  33. # include <unistd.h>
  34. # include <stdio.h>
  35. #endif
  36.  
  37. #include "rhd.h"
  38. #include "edid.h"
  39. #include "rhd_i2c.h"
  40. #include "xf86DDC.h"
  41.  
  42. #include "rhd_regs.h"
  43.  
  44. #ifdef ATOM_BIOS
  45. #include "rhd_atombios.h"
  46. #endif
  47.  
  48. #define MAX_I2C_LINES 6
  49.  
  50. #define RHD_I2C_STATUS_LOOPS 5000
  51.  
  52. enum rhdDDClines {
  53.     rhdDdc1data = 0,
  54.     rhdDdc2data = 2,
  55.     rhdDdc3data = 4,
  56.     rhdDdc4data = 6, /* arbirarily choosen */
  57.     rhdVIP_DOUT_scl = 0x41,
  58.     rhdDvoData12 = 0x28,
  59.     rhdDdc5data = 0x48,
  60.     rhdDdc6data = 0x4a,
  61.     rhdDdc1clk = 1,
  62.     rhdDdc2clk = 3,
  63.     rhdDdc3clk = 5,
  64.     rhdDdc4clk = 7, /* arbirarily choosen */
  65.     rhdVIP_DOUTvipclk = 0x42,
  66.     rhdDvoData13 = 0x29,
  67.     rhdDdc5clk  = 0x49,
  68.     rhdDdc6clk  = 0x4b,
  69.     rhdDdcUnknown
  70. };
  71.  
  72. typedef struct _rhdI2CRec
  73. {
  74.     CARD16 prescale;
  75.     union {
  76.         CARD8 line;
  77.         struct i2cGpio {
  78.             enum rhdDDClines Sda;
  79.             enum rhdDDClines Scl;
  80.             CARD32 SdaReg;
  81.             CARD32 SclReg;
  82.         } Gpio;
  83.     } u;
  84.     int scrnIndex;
  85. } rhdI2CRec;
  86.  
  87. enum _rhdR6xxI2CBits {
  88.     /* R6_DC_I2C_TRANSACTION0 */
  89.     R6_DC_I2C_RW0   = (0x1 << 0),
  90.     R6_DC_I2C_STOP_ON_NACK0         = (0x1 << 8),
  91.     R6_DC_I2C_ACK_ON_READ0  = (0x1 << 9),
  92.     R6_DC_I2C_START0        = (0x1 << 12),
  93.     R6_DC_I2C_STOP0         = (0x1 << 13),
  94.     R6_DC_I2C_COUNT0        = (0xff << 16),
  95.     /* R6_DC_I2C_TRANSACTION1 */
  96.     R6_DC_I2C_RW1   = (0x1 << 0),
  97.     R6_DC_I2C_STOP_ON_NACK1         = (0x1 << 8),
  98.     R6_DC_I2C_ACK_ON_READ1  = (0x1 << 9),
  99.     R6_DC_I2C_START1        = (0x1 << 12),
  100.     R6_DC_I2C_STOP1         = (0x1 << 13),
  101.     R6_DC_I2C_COUNT1        = (0xff << 16),
  102.     /* R6_DC_I2C_DATA */
  103.     R6_DC_I2C_DATA_RW       = (0x1 << 0),
  104.     R6_DC_I2C_DATA_BIT      = (0xff << 8),
  105.     R6_DC_I2C_INDEX         = (0xff << 16),
  106.     R6_DC_I2C_INDEX_WRITE   = (0x1 << 31),
  107.     /* R6_DC_I2C_CONTROL */
  108.     R6_DC_I2C_GO    = (0x1 << 0),
  109.     R6_DC_I2C_SOFT_RESET    = (0x1 << 1),
  110.     R6_DC_I2C_SEND_RESET    = (0x1 << 2),
  111.     R6_DC_I2C_SW_STATUS_RESET       = (0x1 << 3),
  112.     R6_DC_I2C_SDVO_EN       = (0x1 << 4),
  113.     R6_DC_I2C_SDVO_ADDR_SEL         = (0x1 << 6),
  114.     R6_DC_I2C_DDC_SELECT    = (0x7 << 8),
  115.     R6_DC_I2C_TRANSACTION_COUNT     = (0x3 << 20),
  116.     R6_DC_I2C_SW_DONE_INT   = (0x1 << 0),
  117.     R6_DC_I2C_SW_DONE_ACK   = (0x1 << 1),
  118.     R6_DC_I2C_SW_DONE_MASK  = (0x1 << 2),
  119.     R6_DC_I2C_DDC1_HW_DONE_INT      = (0x1 << 4),
  120.     R6_DC_I2C_DDC1_HW_DONE_ACK      = (0x1 << 5),
  121.     R6_DC_I2C_DDC1_HW_DONE_MASK     = (0x1 << 6),
  122.     R6_DC_I2C_DDC2_HW_DONE_INT      = (0x1 << 8),
  123.     R6_DC_I2C_DDC2_HW_DONE_ACK      = (0x1 << 9),
  124.     R6_DC_I2C_DDC2_HW_DONE_MASK     = (0x1 << 10),
  125.     R6_DC_I2C_DDC3_HW_DONE_INT      = (0x1 << 12),
  126.     R6_DC_I2C_DDC3_HW_DONE_ACK      = (0x1 << 13),
  127.     R6_DC_I2C_DDC3_HW_DONE_MASK     = (0x1 << 14),
  128.     R6_DC_I2C_DDC4_HW_DONE_INT      = (0x1 << 16),
  129.     R6_DC_I2C_DDC4_HW_DONE_ACK      = (0x1 << 17),
  130.     R6_DC_I2C_DDC4_HW_DONE_MASK     = (0x1 << 18),
  131.     /* R6_DC_I2C_SW_STATUS */
  132.     R6_DC_I2C_SW_STATUS_BIT         = (0x3 << 0),
  133.     R6_DC_I2C_SW_DONE       = (0x1 << 2),
  134.     R6_DC_I2C_SW_ABORTED    = (0x1 << 4),
  135.     R6_DC_I2C_SW_TIMEOUT    = (0x1 << 5),
  136.     R6_DC_I2C_SW_INTERRUPTED        = (0x1 << 6),
  137.     R6_DC_I2C_SW_BUFFER_OVERFLOW    = (0x1 << 7),
  138.     R6_DC_I2C_SW_STOPPED_ON_NACK    = (0x1 << 8),
  139.     R6_DC_I2C_SW_SDVO_NACK  = (0x1 << 10),
  140.     R6_DC_I2C_SW_NACK0      = (0x1 << 12),
  141.     R6_DC_I2C_SW_NACK1      = (0x1 << 13),
  142.     R6_DC_I2C_SW_NACK2      = (0x1 << 14),
  143.     R6_DC_I2C_SW_NACK3      = (0x1 << 15),
  144.     R6_DC_I2C_SW_REQ        = (0x1 << 18)
  145. };
  146.  
  147. enum _rhdR5xxI2CBits {
  148.  /* R5_DC_I2C_STATUS1 */
  149.     R5_DC_I2C_DONE       = (0x1 << 0),
  150.     R5_DC_I2C_NACK       = (0x1 << 1),
  151.     R5_DC_I2C_HALT       = (0x1 << 2),
  152.     R5_DC_I2C_GO         = (0x1 << 3),
  153.  /* R5_DC_I2C_RESET */
  154.     R5_DC_I2C_SOFT_RESET         = (0x1 << 0),
  155.     R5_DC_I2C_ABORT      = (0x1 << 8),
  156.  /* R5_DC_I2C_CONTROL1 */
  157.     R5_DC_I2C_START      = (0x1 << 0),
  158.     R5_DC_I2C_STOP       = (0x1 << 1),
  159.     R5_DC_I2C_RECEIVE    = (0x1 << 2),
  160.     R5_DC_I2C_EN         = (0x1 << 8),
  161.     R5_DC_I2C_PIN_SELECT         = (0x3 << 16),
  162.  /* R5_DC_I2C_CONTROL2 */
  163.     R5_DC_I2C_ADDR_COUNT         = (0x7 << 0),
  164.     R5_DC_I2C_DATA_COUNT         = (0xf << 8),
  165.     R5_DC_I2C_PRESCALE_LOWER     = (0xff << 16),
  166.     R5_DC_I2C_PRESCALE_UPPER     = (0xff << 24),
  167.  /* R5_DC_I2C_CONTROL3 */
  168.     R5_DC_I2C_DATA_DRIVE_EN      = (0x1 << 0),
  169.     R5_DC_I2C_DATA_DRIVE_SEL     = (0x1 << 1),
  170.     R5_DC_I2C_CLK_DRIVE_EN       = (0x1 << 7),
  171.     R5_DC_I2C_RD_INTRA_BYTE_DELAY        = (0xff << 8),
  172.     R5_DC_I2C_WR_INTRA_BYTE_DELAY        = (0xff << 16),
  173.     R5_DC_I2C_TIME_LIMIT         = (0xff << 24),
  174.  /* R5_DC_I2C_DATA */
  175.     R5_DC_I2C_DATA_BIT   = (0xff << 0),
  176.  /* R5_DC_I2C_INTERRUPT_CONTROL */
  177.     R5_DC_I2C_INTERRUPT_STATUS   = (0x1 << 0),
  178.     R5_DC_I2C_INTERRUPT_AK       = (0x1 << 8),
  179.     R5_DC_I2C_INTERRUPT_ENABLE   = (0x1 << 16),
  180.  /* R5_DC_I2C_ARBITRATION */
  181.     R5_DC_I2C_SW_WANTS_TO_USE_I2C        = (0x1 << 0),
  182.     R5_DC_I2C_SW_CAN_USE_I2C     = (0x1 << 1),
  183.     R5_DC_I2C_SW_DONE_USING_I2C  = (0x1 << 8),
  184.     R5_DC_I2C_HW_NEEDS_I2C       = (0x1 << 9),
  185.     R5_DC_I2C_ABORT_HDCP_I2C     = (0x1 << 16),
  186.     R5_DC_I2C_HW_USING_I2C       = (0x1 << 17)
  187. };
  188.  
  189. enum _rhdRS69I2CBits {
  190.     /* RS69_DC_I2C_TRANSACTION0 */
  191.     RS69_DC_I2C_RW0   = (0x1 << 0),
  192.     RS69_DC_I2C_STOP_ON_NACK0         = (0x1 << 8),
  193.     RS69_DC_I2C_START0        = (0x1 << 12),
  194.     RS69_DC_I2C_STOP0         = (0x1 << 13),
  195.     /* RS69_DC_I2C_TRANSACTION1 */
  196.     RS69_DC_I2C_RW1   = (0x1 << 0),
  197.     RS69_DC_I2C_START1        = (0x1 << 12),
  198.     RS69_DC_I2C_STOP1         = (0x1 << 13),
  199.     /* RS69_DC_I2C_DATA */
  200.     RS69_DC_I2C_DATA_RW       = (0x1 << 0),
  201.     RS69_DC_I2C_INDEX_WRITE   = (0x1 << 31),
  202.     /* RS69_DC_I2C_CONTROL */
  203.     RS69_DC_I2C_GO    = (0x1 << 0),
  204.     RS69_DC_I2C_TRANSACTION_COUNT     = (0x3 << 20),
  205.     RS69_DC_I2C_SW_DONE_ACK   = (0x1 << 1),
  206.     /* RS69_DC_I2C_SW_STATUS */
  207.     RS69_DC_I2C_SW_DONE       = (0x1 << 2),
  208.     RS69_DC_I2C_SW_ABORTED    = (0x1 << 4),
  209.     RS69_DC_I2C_SW_TIMEOUT    = (0x1 << 5),
  210.     RS69_DC_I2C_SW_INTERRUPTED= (0x1 << 6),
  211.     RS69_DC_I2C_SW_BUFFER_OVERFLOW= (0x1 << 7),
  212.     RS69_DC_I2C_SW_STOPPED_ON_NACK    = (0x1 << 8),
  213.     RS69_DC_I2C_SW_NACK0      = (0x1 << 12),
  214.     RS69_DC_I2C_SW_NACK1      = (0x1 << 13)
  215. };
  216.  
  217. /* RV620 */
  218. enum rv620I2CBits {
  219.     /* GENERIC_I2C_CONTROL */
  220.     RV62_DC_I2C_GO    = (0x1 << 0),
  221.     RV62_GENERIC_I2C_GO       = (0x1 << 0),
  222.     RV62_GENERIC_I2C_SOFT_RESET       = (0x1 << 1),
  223.     RV62_GENERIC_I2C_SEND_RESET       = (0x1 << 2),
  224.     /* GENERIC_I2C_INTERRUPT_CONTROL */
  225.     RV62_GENERIC_I2C_DONE_INT         = (0x1 << 0),
  226.     RV62_GENERIC_I2C_DONE_ACK         = (0x1 << 1),
  227.     RV62_GENERIC_I2C_DONE_MASK        = (0x1 << 2),
  228.     /* GENERIC_I2C_STATUS */
  229.     RV62_GENERIC_I2C_STATUS_BIT       = (0xf << 0),
  230.     RV62_GENERIC_I2C_DONE     = (0x1 << 4),
  231.     RV62_GENERIC_I2C_ABORTED  = (0x1 << 5),
  232.     RV62_GENERIC_I2C_TIMEOUT  = (0x1 << 6),
  233.     RV62_GENERIC_I2C_STOPPED_ON_NACK  = (0x1 << 9),
  234.     RV62_GENERIC_I2C_NACK     = (0x1 << 10),
  235.     /* GENERIC_I2C_SPEED */
  236.     RV62_GENERIC_I2C_THRESHOLD        = (0x3 << 0),
  237.     RV62_GENERIC_I2C_DISABLE_FILTER_DURING_STALL      = (0x1 << 4),
  238.     RV62_GENERIC_I2C_PRESCALE         = (0xffff << 16),
  239.     /* GENERIC_I2C_SETUP */
  240.     RV62_GENERIC_I2C_DATA_DRIVE_EN    = (0x1 << 0),
  241.     RV62_GENERIC_I2C_DATA_DRIVE_SEL   = (0x1 << 1),
  242.     RV62_GENERIC_I2C_CLK_DRIVE_EN     = (0x1 << 7),
  243.     RV62_GENERIC_I2C_INTRA_BYTE_DELAY         = (0xff << 8),
  244.     RV62_GENERIC_I2C_TIME_LIMIT       = (0xff << 24),
  245.     /* GENERIC_I2C_TRANSACTION */
  246.     RV62_GENERIC_I2C_RW       = (0x1 << 0),
  247.     RV62_GENERIC_I2C_STOP_ON_NACK     = (0x1 << 8),
  248.     RV62_GENERIC_I2C_ACK_ON_READ      = (0x1 << 9),
  249.     RV62_GENERIC_I2C_START    = (0x1 << 12),
  250.     RV62_GENERIC_I2C_STOP     = (0x1 << 13),
  251.     RV62_GENERIC_I2C_COUNT    = (0xf << 16),
  252.     /* GENERIC_I2C_DATA */
  253.     RV62_GENERIC_I2C_DATA_RW  = (0x1 << 0),
  254.     RV62_GENERIC_I2C_DATA_BIT         = (0xff << 8),
  255.     RV62_GENERIC_I2C_INDEX    = (0xf << 16),
  256.     RV62_GENERIC_I2C_INDEX_WRITE      = (0x1 << 31),
  257.     /* GENERIC_I2C_PIN_SELECTION */
  258.     RV62_GENERIC_I2C_SCL_PIN_SEL_SHIFT = 0,
  259.     RV62_GENERIC_I2C_SCL_PIN_SEL      = (0x7f << RV62_GENERIC_I2C_SCL_PIN_SEL_SHIFT),
  260.     RV62_GENERIC_I2C_SDA_PIN_SEL_SHIFT = 8,
  261.     RV62_GENERIC_I2C_SDA_PIN_SEL      = (0x7f << RV62_GENERIC_I2C_SDA_PIN_SEL_SHIFT)
  262. };
  263.  
  264. /*
  265.  *
  266.  */
  267. static enum rhdDDClines
  268. getDDCLineFromGPIO(int scrnIndex, CARD32 gpio, int shift)
  269. {
  270.     switch (gpio) {
  271.     case 0x1f90:
  272.         switch (shift) {
  273.             case 0:
  274.                 return rhdDdc1clk; /* ddc1 clk */
  275.             case 8:
  276.                 return rhdDdc1data; /* ddc1 data */
  277.         }
  278.         break;
  279.     case 0x1f94: /* ddc2 */
  280.         switch (shift) {
  281.             case 0:
  282.                 return rhdDdc2clk; /* ddc2 clk */
  283.             case 8:
  284.                 return rhdDdc2data; /* ddc2 data */
  285.         }
  286.         break;
  287.     case 0x1f98: /* ddc3 */
  288.         switch (shift) {
  289.             case 0:
  290.                 return rhdDdc3clk; /* ddc3 clk */
  291.             case 8:
  292.                 return rhdDdc3data; /* ddc3 data */
  293.         }
  294.     case 0x1f80: /* ddc4 - on r6xx */
  295.         switch (shift) {
  296.             case 0:
  297.                 return rhdDdc4clk; /* ddc4 clk */
  298.             case 8:
  299.                 return rhdDdc4data; /* ddc4 data */
  300.         }
  301.         break;
  302.     case 0x1f88: /* ddc5 */
  303.         switch (shift) {
  304.             case 0:
  305.                 return rhdVIP_DOUTvipclk; /* ddc5 clk */
  306.             case 8:
  307.                 return rhdVIP_DOUT_scl; /* ddc5 data */
  308.         }
  309.         break;
  310.     case 0x1fda: /* ddc6 */
  311.         switch (shift) {
  312.             case 0:
  313.                 return rhdDvoData13; /* ddc6 clk */
  314.             case 1:
  315.                 return rhdDvoData12; /* ddc6 data */
  316.         }
  317.         break;
  318.     case 0x1fc4:
  319.         switch (shift) {
  320.             case 0:
  321.                 return rhdDdc5clk;
  322.             case 8:
  323.                 return rhdDdc5data;
  324.         }
  325.         break;
  326.     case 0x1fe8: /* ddc6 */
  327.         switch (shift) {
  328.             case 0:
  329.                 return rhdDdc6clk; /* ddc6 clk */
  330.             case 8:
  331.                 return rhdDdc6data; /* ddc6 data */
  332.         }
  333.         break;
  334.     }
  335.  
  336.     xf86DrvMsg(scrnIndex, X_WARNING,
  337.                "%s: Failed to match GPIO 0x%04X.%d with a known DDC line\n",
  338.                __func__, (unsigned int) gpio, shift);
  339.     return rhdDdcUnknown;
  340. }
  341.  
  342. /*
  343.  *
  344.  */
  345. static Bool
  346. rhdI2CGetDataClkLines(RHDPtr rhdPtr, int line,
  347.                       enum rhdDDClines *scl, enum rhdDDClines *sda,
  348.                       CARD32 *sda_reg, CARD32 *scl_reg)
  349. {
  350. #ifdef ATOM_BIOS
  351.     AtomBiosResult result;
  352.     AtomBiosArgRec data;
  353.  
  354.     /* scl register */
  355.     data.val = line & 0x0f;
  356.     result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  357.                              ATOM_GPIO_I2C_CLK_MASK, &data);
  358.     if (result != ATOM_SUCCESS)
  359.         return FALSE;
  360.     *scl_reg = data.val;
  361.  
  362.     /* scl DDC line */
  363.         data.val = line & 0x0f;
  364.     result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  365.                              ATOM_GPIO_I2C_CLK_MASK_SHIFT, &data);
  366.     if (result != ATOM_SUCCESS)
  367.         return FALSE;
  368.     *scl = getDDCLineFromGPIO(rhdPtr->scrnIndex, *scl_reg, data.val);
  369.  
  370.     /* sda register */
  371.             data.val = line & 0x0f;
  372.     result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  373.                              ATOM_GPIO_I2C_DATA_MASK, &data);
  374.     if (result != ATOM_SUCCESS)
  375.         return FALSE;
  376.     *sda_reg = data.val;
  377.  
  378.     /* sda DDC line */
  379.                 data.val = line & 0x0f;
  380.     result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  381.                              ATOM_GPIO_I2C_DATA_MASK_SHIFT, &data);
  382.     if (result != ATOM_SUCCESS)
  383.         return FALSE;
  384.     *sda = getDDCLineFromGPIO(rhdPtr->scrnIndex, *sda_reg, data.val);
  385.  
  386.     if ((*scl == rhdDdcUnknown) || (*sda == rhdDdcUnknown)) {
  387.         xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING,
  388.                    "%s: failed to map gpio lines for DDC line %d\n",
  389.                    __func__, line);
  390.         return FALSE;
  391.     }
  392.  
  393.                     return TRUE;
  394. #else /* ATOM_BIOS */
  395.     return FALSE;
  396. #endif
  397. }
  398.  
  399. /* R5xx */
  400. static Bool
  401. rhd5xxI2CSetupStatus(I2CBusPtr I2CPtr, int line)
  402. {
  403.     RHDFUNC(I2CPtr);
  404.  
  405.     line &= 0xf;
  406.  
  407.  
  408.     switch (line) {
  409.         case 0:
  410.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC1_MASK, 0x0, 0xffff);
  411.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC1_A, 0x0, 0xffff);
  412.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_EN, 0x0, 0xffff);
  413.             break;
  414.         case 1:
  415.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC2_MASK, 0x0, 0xffff);
  416.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC2_A, 0x0, 0xffff);
  417.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_EN, 0x0, 0xffff);
  418.             break;
  419.         case 2:
  420.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC3_MASK, 0x0, 0xffff);
  421.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC3_A, 0x0, 0xffff);
  422.             RHDRegMask(I2CPtr, R5_DC_GPIO_DDC3_EN, 0x0, 0xffff);
  423.             break;
  424.         default:
  425.             xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
  426.                        "%s: Trying to initialize non-existent I2C line: %i\n",
  427.                        __func__,line);
  428.             return FALSE;
  429.     }
  430.     return TRUE;
  431. }
  432.  
  433. static Bool
  434. rhd5xxI2CStatus(I2CBusPtr I2CPtr)
  435. {
  436.     int count = RHD_I2C_STATUS_LOOPS;
  437.     CARD32 res;
  438.  
  439.     RHDFUNC(I2CPtr);
  440.  
  441.     while (count-- != 0) {
  442.         usleep (10);
  443.         if (((RHDRegRead(I2CPtr, R5_DC_I2C_STATUS1)) & R5_DC_I2C_GO) != 0)
  444.             continue;
  445.         res = RHDRegRead(I2CPtr, R5_DC_I2C_STATUS1);
  446.         RHDDebugVerb(I2CPtr->scrnIndex,1,"SW_STATUS: 0x%x %i\n",
  447.                      (unsigned int)res,count);
  448.         if (res & R5_DC_I2C_DONE)
  449.             return TRUE;
  450.         else
  451.             return FALSE;
  452.     }
  453.     RHDRegMask(I2CPtr, R5_DC_I2C_RESET, R5_DC_I2C_ABORT, 0xff00);
  454.     return FALSE;
  455. }
  456.  
  457. Bool
  458. rhd5xxWriteReadChunk(I2CDevPtr i2cDevPtr, int line, I2CByte *WriteBuffer,
  459.                 int nWrite, I2CByte *ReadBuffer, int nRead)
  460. {
  461.     I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
  462.     I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
  463.     rhdI2CPtr I2C = (rhdI2CPtr)(I2CPtr->DriverPrivate.ptr);
  464.     int prescale = I2C->prescale;
  465.     CARD32 save_I2C_CONTROL1, save_494;
  466.     CARD32  tmp32;
  467.     Bool ret = TRUE;
  468.  
  469.     RHDFUNC(i2cDevPtr->pI2CBus);
  470.  
  471.     RHDRegMask(I2CPtr, 0x28, 0x200, 0x200);
  472.     save_I2C_CONTROL1 = RHDRegRead(I2CPtr, R5_DC_I2C_CONTROL1);
  473.     save_494 = RHDRegRead(I2CPtr, 0x494);
  474.     RHDRegMask(I2CPtr, 0x494, 1, 1);
  475.     RHDRegMask(I2CPtr, R5_DC_I2C_ARBITRATION,
  476.                R5_DC_I2C_SW_WANTS_TO_USE_I2C,
  477.                R5_DC_I2C_SW_WANTS_TO_USE_I2C);
  478.  
  479.     if (!RHDRegRead(I2CPtr, R5_DC_I2C_ARBITRATION) & R5_DC_I2C_SW_CAN_USE_I2C) {
  480.         RHDDebug(I2CPtr->scrnIndex, "%s SW cannot use I2C line %i\n",__func__,line);
  481.         ret = FALSE;
  482.     } else {
  483.  
  484.         RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_DONE
  485.                    | R5_DC_I2C_NACK
  486.                    | R5_DC_I2C_HALT, 0xff);
  487.         RHDRegMask(I2CPtr, R5_DC_I2C_RESET, R5_DC_I2C_SOFT_RESET, 0xffff);
  488.         RHDRegWrite(I2CPtr, R5_DC_I2C_RESET, 0);
  489.  
  490.         RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL1,
  491.                    (line  & 0x0f) << 16 | R5_DC_I2C_EN,
  492.                    R5_DC_I2C_PIN_SELECT | R5_DC_I2C_EN);
  493.     }
  494.  
  495.     if (ret && (nWrite || !nRead)) { /* special case for bus probing */
  496.         /*
  497.          * chip can't just write the slave address without data.
  498.          * Add a dummy byte.
  499.          */
  500.         RHDRegWrite(I2CPtr, R5_DC_I2C_CONTROL2,
  501.                     prescale << 16 |
  502.                     (nWrite ? nWrite : 1) << 8 | 0x01); /* addr_cnt: 1 */
  503.         RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL3,
  504.                    0x30 << 24, 0xff << 24); /* time limit 30 */
  505.  
  506.         RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, slave);
  507.  
  508.         /* Add dummy byte */
  509.         if (!nWrite)
  510.             RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, 0);
  511.         else
  512.             while (nWrite--)
  513.                 RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, *WriteBuffer++);
  514.  
  515.         RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL1,
  516.                    R5_DC_I2C_START | R5_DC_I2C_STOP, 0xff);
  517.         RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_GO, 0xff);
  518.  
  519.         if ((ret = rhd5xxI2CStatus(I2CPtr)))
  520.             RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1,R5_DC_I2C_DONE, 0xff);
  521.         else
  522.             ret = FALSE;
  523.     }
  524.  
  525.     if (ret && nRead) {
  526.  
  527.         RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, slave | 1); /*slave*/
  528.         RHDRegWrite(I2CPtr, R5_DC_I2C_CONTROL2,
  529.                     prescale << 16 | nRead << 8 | 0x01); /* addr_cnt: 1 */
  530.  
  531.         RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL1,
  532.                    R5_DC_I2C_START | R5_DC_I2C_STOP | R5_DC_I2C_RECEIVE, 0xff);
  533.         RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_GO, 0xff);
  534.         if ((ret = rhd5xxI2CStatus(I2CPtr))) {
  535.             RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_DONE, 0xff);
  536.             while (nRead--) {
  537.                 *(ReadBuffer++) = (CARD8)RHDRegRead(I2CPtr, R5_DC_I2C_DATA);
  538.             }
  539.         } else
  540.             ret = FALSE;
  541.     }
  542.  
  543.     RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1,
  544.                R5_DC_I2C_DONE | R5_DC_I2C_NACK | R5_DC_I2C_HALT, 0xff);
  545.     RHDRegMask(I2CPtr, R5_DC_I2C_RESET, R5_DC_I2C_SOFT_RESET, 0xff);
  546.     RHDRegWrite(I2CPtr,R5_DC_I2C_RESET, 0);
  547.  
  548.     RHDRegMask(I2CPtr,R5_DC_I2C_ARBITRATION,
  549.                R5_DC_I2C_SW_DONE_USING_I2C, 0xff00);
  550.  
  551.     RHDRegWrite(I2CPtr,R5_DC_I2C_CONTROL1, save_I2C_CONTROL1);
  552.     RHDRegWrite(I2CPtr,0x494, save_494);
  553.     tmp32 = RHDRegRead(I2CPtr,0x28);
  554.     RHDRegWrite(I2CPtr,0x28, tmp32 & 0xfffffdff);
  555.  
  556.     return ret;
  557. }
  558.  
  559. static Bool
  560. rhd5xxWriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead)
  561. {
  562.     /*
  563.      * Since the transaction buffer can only hold
  564.      * 15 bytes (+ the slave address) we bail out
  565.      * on every transaction that is bigger unless
  566.      * it's a read transaction following a write
  567.      * transaction sending just one byte.
  568.      * In this case we assume, that this byte is
  569.      * an offset address. Thus we will restart
  570.      * the transaction after 15 bytes sending
  571.      * a new offset.
  572.      */
  573.  
  574.     I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
  575.     int  ddc_line;
  576.  
  577.     RHDFUNC(I2CPtr);
  578.  
  579.     if (nWrite > 15 || (nRead > 15 && nWrite != 1)) {
  580.         xf86DrvMsg(i2cDevPtr->pI2CBus->scrnIndex,X_ERROR,
  581.                    "%s: Currently only I2C transfers with "
  582.                    "maximally 15bytes are supported\n",
  583.                    __func__);
  584.         return FALSE;
  585.     }
  586.  
  587.     ddc_line = ((rhdI2CPtr)(I2CPtr->DriverPrivate.ptr))->u.line;
  588.  
  589.     rhd5xxI2CSetupStatus(I2CPtr, ddc_line);
  590.  
  591.     if (nRead > 15) {
  592.         I2CByte offset = *WriteBuffer;
  593.         while (nRead) {
  594.             int n = nRead > 15 ? 15 : nRead;
  595.             if (!rhd5xxWriteReadChunk(i2cDevPtr, ddc_line, &offset, 1, ReadBuffer, n))
  596.                 return FALSE;
  597.             ReadBuffer += n;
  598.             nRead -= n;
  599.             offset += n;
  600.         }
  601.         return TRUE;
  602.     } else
  603.         return rhd5xxWriteReadChunk(i2cDevPtr, ddc_line, WriteBuffer, nWrite,
  604.             ReadBuffer, nRead);
  605. }
  606.  
  607. /* RS690 */
  608. static Bool
  609. rhdRS69I2CStatus(I2CBusPtr I2CPtr)
  610. {
  611.     volatile CARD32 val;
  612.     int i;
  613.  
  614.     RHDFUNC(I2CPtr);
  615.  
  616.     for (i = 0; i < RHD_I2C_STATUS_LOOPS; i++) {
  617.         usleep(10);
  618.  
  619.         val = RHDRegRead(I2CPtr, RS69_DC_I2C_SW_STATUS);
  620.  
  621.         RHDDebugVerb(I2CPtr->scrnIndex, 1, "SW_STATUS: 0x%x %i\n",
  622.                      (unsigned int) val, i);
  623.  
  624.         if (val & RS69_DC_I2C_SW_DONE)
  625.             break;
  626.     }
  627.  
  628.     RHDRegMask(I2CPtr, RS69_DC_I2C_INTERRUPT_CONTROL, RS69_DC_I2C_SW_DONE_ACK,
  629.                RS69_DC_I2C_SW_DONE_ACK);
  630.  
  631.     if ((i == RHD_I2C_STATUS_LOOPS) ||
  632.         (val & (RS69_DC_I2C_SW_ABORTED | RS69_DC_I2C_SW_TIMEOUT |
  633.                 RS69_DC_I2C_SW_INTERRUPTED | RS69_DC_I2C_SW_BUFFER_OVERFLOW |
  634.                 RS69_DC_I2C_SW_STOPPED_ON_NACK |
  635.                 RS69_DC_I2C_SW_NACK0 | RS69_DC_I2C_SW_NACK1 | 0x3)))
  636.         return FALSE; /* 2 */
  637.  
  638.     return TRUE; /* 1 */
  639. }
  640.  
  641. static Bool
  642. rhdRS69I2CSetupStatus(I2CBusPtr I2CPtr, enum rhdDDClines sda, enum rhdDDClines scl, int prescale)
  643. {
  644.     CARD32 clk_pin, data_pin;
  645.  
  646.     RHDFUNC(I2CPtr);
  647.  
  648.     switch (sda) {
  649.         case rhdDdc1data:
  650.             data_pin = 0;
  651.             break;
  652.         case rhdDdc2data:
  653.             data_pin = 1;
  654.             break;
  655.         case rhdDdc3data:
  656.             data_pin = 2;
  657.             break;
  658.         default:
  659.             return FALSE;
  660.     }
  661.     switch (scl) {
  662.         case rhdDdc1data:
  663.             clk_pin = 4;
  664.             break;
  665.         case rhdDdc2data:
  666.             clk_pin = 5;
  667.             break;
  668.         case rhdDdc3data:
  669.             clk_pin = 6;
  670.             break;
  671.         case rhdDdc1clk:
  672.             clk_pin = 0;
  673.             break;
  674.         case rhdDdc2clk:
  675.             clk_pin = 1;
  676.             break;
  677.         case rhdDdc3clk:
  678.             clk_pin = 2;
  679.             break;
  680.         default:
  681.             return FALSE;
  682.     }
  683.  
  684.     RHDRegMask(I2CPtr, 0x28, 0x200, 0x200);
  685.     RHDRegMask(I2CPtr, RS69_DC_I2C_UNKNOWN_1, prescale << 16 | 0x2, 0xffff00ff);
  686.     RHDRegWrite(I2CPtr, RS69_DC_I2C_DDC_SETUP_Q, 0x30000000);
  687.     RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, ((data_pin & 0x3) << 16) | (clk_pin << 8), 0xffff00);
  688.     RHDRegMask(I2CPtr, RS69_DC_I2C_INTERRUPT_CONTROL, 0x2, 0x2);
  689.     RHDRegMask(I2CPtr, RS69_DC_I2C_UNKNOWN_2, 0x2, 0xff);
  690.  
  691.     return TRUE;
  692. }
  693.  
  694. static Bool
  695. rhdRS69WriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer,
  696.                  int nWrite, I2CByte *ReadBuffer, int nRead)
  697. {
  698.     Bool ret = FALSE;
  699.     CARD32 data = 0;
  700.     I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
  701.     I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
  702.     rhdI2CPtr I2C = (rhdI2CPtr)I2CPtr->DriverPrivate.ptr;
  703.     int prescale = I2C->prescale;
  704.     int idx = 1;
  705.  
  706.     enum {
  707.         TRANS_WRITE_READ,
  708.         TRANS_WRITE,
  709.         TRANS_READ
  710.     } trans;
  711.  
  712.     RHDFUNC(i2cDevPtr->pI2CBus);
  713.  
  714.     if (nWrite > 0 && nRead > 0) {
  715.         trans = TRANS_WRITE_READ;
  716.     } else if (nWrite > 0) {
  717.         trans = TRANS_WRITE;
  718.     } else if (nRead > 0) {
  719.         trans = TRANS_READ;
  720.     } else {
  721.         /* for bus probing */
  722.         trans = TRANS_WRITE;
  723.     }
  724.     if (slave & 0xff00) {
  725.         xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
  726.                    "%s: 10 bit I2C slave addresses not supported\n",__func__);
  727.         return FALSE;
  728.     }
  729.  
  730.     if (!rhdRS69I2CSetupStatus(I2CPtr, I2C->u.Gpio.Sda, I2C->u.Gpio.Scl,  prescale))
  731.         return FALSE;
  732.  
  733.     RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, (trans == TRANS_WRITE_READ)
  734.                ? (1 << 20) : 0, RS69_DC_I2C_TRANSACTION_COUNT); /* 2 or 1 Transaction */
  735.     RHDRegMask(I2CPtr, RS69_DC_I2C_TRANSACTION0,
  736.                RS69_DC_I2C_STOP_ON_NACK0
  737.                | (trans == TRANS_READ ? RS69_DC_I2C_RW0 : 0)
  738.                | RS69_DC_I2C_START0
  739.                | (trans == TRANS_WRITE_READ ? 0 : RS69_DC_I2C_STOP0 )
  740.                | ((trans == TRANS_READ ? nRead : nWrite)  << 16),
  741.                0xffffff);
  742.     if (trans == TRANS_WRITE_READ)
  743.         RHDRegMask(I2CPtr, RS69_DC_I2C_TRANSACTION1,
  744.                    nRead << 16
  745.                    | RS69_DC_I2C_RW1
  746.                    | RS69_DC_I2C_START1
  747.                    | RS69_DC_I2C_STOP1,
  748.                    0xffffff); /* <bytes> read */
  749.  
  750.     data = RS69_DC_I2C_INDEX_WRITE
  751.         | (((slave & 0xfe) | (trans == TRANS_READ ? 1 : 0)) << 8 )
  752.         | (0 << 16);
  753.     RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, data);
  754.     if (trans != TRANS_READ) { /* we have bytes to write */
  755.         while (nWrite--) {
  756.             data = RS69_DC_I2C_INDEX_WRITE | ( *(WriteBuffer++) << 8 )
  757.                 | (idx++ << 16);
  758.             RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, data);
  759.         }
  760.     }
  761.     if (trans == TRANS_WRITE_READ) { /* we have bytes to read after write */
  762.         data = RS69_DC_I2C_INDEX_WRITE | ((slave | 0x1) << 8) | (idx++ << 16);
  763.         RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, data);
  764.     }
  765.     /* Go! */
  766.     RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, RS69_DC_I2C_GO, RS69_DC_I2C_GO);
  767.     if (rhdRS69I2CStatus(I2CPtr)) {
  768.         /* Hopefully this doesn't write data to index */
  769.         RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, RS69_DC_I2C_INDEX_WRITE
  770.                     | RS69_DC_I2C_DATA_RW  | /* idx++ */3 << 16);
  771.         while (nRead--) {
  772.             data = RHDRegRead(I2CPtr, RS69_DC_I2C_DATA);
  773.             *(ReadBuffer++) = (data >> 8) & 0xff;
  774.         }
  775.         ret = TRUE;
  776.     }
  777.  
  778.     RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, 0x2, 0xff);
  779.     usleep(10);
  780.     RHDRegWrite(I2CPtr, RS69_DC_I2C_CONTROL, 0);
  781.  
  782.     return ret;
  783. }
  784.  
  785.  
  786. /* R6xx */
  787. static Bool
  788. rhdR6xxI2CStatus(I2CBusPtr I2CPtr)
  789. {
  790.     volatile CARD32 val;
  791.     int i;
  792.  
  793.     RHDFUNC(I2CPtr);
  794.  
  795.     for (i = 0; i < RHD_I2C_STATUS_LOOPS; i++) {
  796.         usleep(10);
  797.  
  798.         val = RHDRegRead(I2CPtr, R6_DC_I2C_SW_STATUS);
  799.  
  800.         RHDDebugVerb(I2CPtr->scrnIndex, 1, "SW_STATUS: 0x%x %i\n",
  801.                      (unsigned int) val, i);
  802.  
  803.         if (val & R6_DC_I2C_SW_DONE)
  804.             break;
  805.     }
  806.  
  807.     RHDRegMask(I2CPtr, R6_DC_I2C_INTERRUPT_CONTROL, R6_DC_I2C_SW_DONE_ACK,
  808.                R6_DC_I2C_SW_DONE_ACK);
  809.  
  810.     if ((i == RHD_I2C_STATUS_LOOPS) ||
  811.         (val & (R6_DC_I2C_SW_ABORTED | R6_DC_I2C_SW_TIMEOUT |
  812.                 R6_DC_I2C_SW_INTERRUPTED | R6_DC_I2C_SW_BUFFER_OVERFLOW |
  813.                 R6_DC_I2C_SW_STOPPED_ON_NACK |
  814.                 R6_DC_I2C_SW_NACK0 | R6_DC_I2C_SW_NACK1 | 0x3)))
  815.         return FALSE; /* 2 */
  816.  
  817.     return TRUE; /* 1 */
  818. }
  819.  
  820. static Bool
  821. rhd6xxI2CSetupStatus(I2CBusPtr I2CPtr, int line, int prescale)
  822. {
  823.     line &= 0xf;
  824.  
  825.     RHDFUNC(I2CPtr);
  826.  
  827.     switch (line) {
  828.         case 0:
  829.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_MASK, 0x0, 0xffff);
  830.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_A, 0x0, 0xffff);
  831.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_EN, 0x0, 0xffff);
  832.             RHDRegMask(I2CPtr, R6_DC_I2C_DDC1_SPEED, (prescale << 16) | 2,
  833.                        0xffff00ff);
  834.             RHDRegWrite(I2CPtr, R6_DC_I2C_DDC1_SETUP, 0x30000000);
  835.             break;
  836.         case 1:
  837.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_MASK, 0x0, 0xffff);
  838.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_A, 0x0, 0xffff);
  839.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_EN, 0x0, 0xffff);
  840.             RHDRegMask(I2CPtr, R6_DC_I2C_DDC2_SPEED, (prescale << 16) | 2,
  841.                        0xffff00ff);
  842.             RHDRegWrite(I2CPtr, R6_DC_I2C_DDC2_SETUP, 0x30000000);
  843.             break;
  844.         case 2:
  845.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC3_MASK, 0x0, 0xffff);
  846.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC3_A, 0x0, 0xffff);
  847.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC3_EN, 0x0, 0xffff);
  848.             RHDRegMask(I2CPtr, R6_DC_I2C_DDC3_SPEED, (prescale << 16) | 2,
  849.                        0xffff00ff);
  850.             RHDRegWrite(I2CPtr, R6_DC_I2C_DDC3_SETUP, 0x30000000);
  851.             break;
  852.         case 3:
  853.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC4_MASK, 0x0, 0xffff);
  854.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC4_A, 0x0, 0xffff);
  855.             RHDRegMask(I2CPtr, R6_DC_GPIO_DDC4_EN, 0x0, 0xffff);
  856.             RHDRegMask(I2CPtr, R6_DC_I2C_DDC4_SPEED, (prescale << 16) | 2,
  857.                        0xffff00ff);
  858.             RHDRegWrite(I2CPtr, R6_DC_I2C_DDC4_SETUP, 0x30000000);
  859.             break;
  860.         default:
  861.             xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
  862.                        "%s: Trying to initialize non-existent I2C line: %i\n",
  863.                        __func__,line);
  864.             return FALSE;
  865.     }
  866.     RHDRegWrite(I2CPtr, R6_DC_I2C_CONTROL, line << 8);
  867.     RHDRegMask(I2CPtr, R6_DC_I2C_INTERRUPT_CONTROL, 0x2, 0x2);
  868.     RHDRegMask(I2CPtr, R6_DC_I2C_ARBITRATION, 0, 0xff);
  869.     return TRUE;
  870. }
  871.  
  872. static Bool
  873. rhd6xxWriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead)
  874. {
  875.     Bool ret = FALSE;
  876.     CARD32 data = 0;
  877.     I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
  878.     I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
  879.     rhdI2CPtr I2C = (rhdI2CPtr)I2CPtr->DriverPrivate.ptr;
  880.     CARD32 ddc_line = I2C->u.line;
  881.     int prescale = I2C->prescale;
  882.     int idx = 1;
  883.     enum {
  884.         TRANS_WRITE_READ,
  885.         TRANS_WRITE,
  886.         TRANS_READ
  887.     } trans;
  888.  
  889.     RHDFUNC(i2cDevPtr->pI2CBus);
  890.  
  891.     if (nWrite > 0 && nRead > 0) {
  892.         trans = TRANS_WRITE_READ;
  893.     } else if (nWrite > 0) {
  894.         trans = TRANS_WRITE;
  895.     } else if (nRead > 0) {
  896.         trans = TRANS_READ;
  897.     } else {
  898.         /* for bus probing */
  899.         trans = TRANS_WRITE;
  900.     }
  901.     if (slave & 0xff00) {
  902.         xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
  903.                    "%s: 10 bit I2C slave addresses not supported\n",__func__);
  904.         return FALSE;
  905.     }
  906.  
  907.     if (!rhd6xxI2CSetupStatus(I2CPtr, ddc_line,  prescale))
  908.         return FALSE;
  909.  
  910.     RHDRegMask(I2CPtr, R6_DC_I2C_CONTROL, (trans == TRANS_WRITE_READ)
  911.                ? (1 << 20) : 0, R6_DC_I2C_TRANSACTION_COUNT); /* 2 or 1 Transaction */
  912.     RHDRegMask(I2CPtr, R6_DC_I2C_TRANSACTION0,
  913.                R6_DC_I2C_STOP_ON_NACK0
  914.                | (trans == TRANS_READ ? R6_DC_I2C_RW0 : 0)
  915.                | R6_DC_I2C_START0
  916.                | (trans == TRANS_WRITE_READ ? 0 : R6_DC_I2C_STOP0 )
  917.                | ((trans == TRANS_READ ? nRead : nWrite)  << 16),
  918.                0xffffff);
  919.     if (trans == TRANS_WRITE_READ)
  920.         RHDRegMask(I2CPtr, R6_DC_I2C_TRANSACTION1,
  921.                    nRead << 16
  922.                    | R6_DC_I2C_RW1
  923.                    | R6_DC_I2C_START1
  924.                    | R6_DC_I2C_STOP1,
  925.                    0xffffff); /* <bytes> read */
  926.  
  927.     data = R6_DC_I2C_INDEX_WRITE
  928.         | (((slave & 0xfe) | (trans == TRANS_READ ? 1 : 0)) << 8 )
  929.         | (0 << 16);
  930.     RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, data);
  931.     if (trans != TRANS_READ) { /* we have bytes to write */
  932.         while (nWrite--) {
  933.             data = R6_DC_I2C_INDEX_WRITE | ( *(WriteBuffer++) << 8 )
  934.                 | (idx++ << 16);
  935.             RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, data);
  936.         }
  937.     }
  938.     if (trans == TRANS_WRITE_READ) { /* we have bytes to read after write */
  939.         data = R6_DC_I2C_INDEX_WRITE | ((slave | 0x1) << 8) | (idx++ << 16);
  940.         RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, data);
  941.     }
  942.     /* Go! */
  943.     RHDRegMask(I2CPtr, R6_DC_I2C_CONTROL, R6_DC_I2C_GO, R6_DC_I2C_GO);
  944.     if (rhdR6xxI2CStatus(I2CPtr)) {
  945.         /* Hopefully this doesn't write data to index */
  946.         RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, R6_DC_I2C_INDEX_WRITE
  947.                     | R6_DC_I2C_DATA_RW  | /* idx++ */3 << 16);
  948.         while (nRead--) {
  949.             data = RHDRegRead(I2CPtr, R6_DC_I2C_DATA);
  950.             *(ReadBuffer++) = (data >> 8) & 0xff;
  951.         }
  952.         ret = TRUE;
  953.     }
  954.  
  955.     RHDRegMask(I2CPtr, R6_DC_I2C_CONTROL, 0x2, 0xff);
  956.     usleep(10);
  957.     RHDRegWrite(I2CPtr, R6_DC_I2C_CONTROL, 0);
  958.  
  959.     return ret;
  960. }
  961.  
  962. /* RV620 */
  963. static Bool
  964. rhdRV620I2CStatus(I2CBusPtr I2CPtr)
  965. {
  966.     volatile CARD32 val;
  967.     int i;
  968.  
  969.     RHDFUNC(I2CPtr);
  970.  
  971.     for (i = 0; i < RHD_I2C_STATUS_LOOPS; i++) {
  972.         usleep(10);
  973.  
  974.         val = RHDRegRead(I2CPtr, RV62_GENERIC_I2C_STATUS);
  975.  
  976.         RHDDebugVerb(I2CPtr->scrnIndex, 1,
  977.                      "SW_STATUS: 0x%x %i\n", (unsigned int) val, i);
  978.         if (val & RV62_GENERIC_I2C_DONE)
  979.             break;
  980.     }
  981.  
  982.     RHDRegMask(I2CPtr, RV62_GENERIC_I2C_INTERRUPT_CONTROL, 0x2, 0xff);
  983.  
  984.     if ((i == RHD_I2C_STATUS_LOOPS) ||
  985.         (val & (RV62_GENERIC_I2C_STOPPED_ON_NACK | RV62_GENERIC_I2C_NACK |
  986.                 RV62_GENERIC_I2C_ABORTED | RV62_GENERIC_I2C_TIMEOUT)))
  987.         return FALSE; /* 2 */
  988.  
  989.     return TRUE; /* 1 */
  990. }
  991.  
  992. /*
  993.  *
  994.  */
  995. static  Bool
  996. rhdRV620I2CSetupStatus(I2CBusPtr I2CPtr, struct i2cGpio *Gpio, int prescale)
  997. {
  998.     CARD32 reg_7d9c = 0; /* 0 is invalid */
  999.     CARD32 scl_reg;
  1000.  
  1001.     RHDFUNC(I2CPtr);
  1002.  
  1003.     scl_reg = Gpio->SclReg;
  1004.     reg_7d9c = (Gpio->Scl << RV62_GENERIC_I2C_SCL_PIN_SEL_SHIFT)
  1005.         | (Gpio->Sda << RV62_GENERIC_I2C_SDA_PIN_SEL_SHIFT);
  1006.  
  1007.     scl_reg = Gpio->SclReg;
  1008.     /* Don't understand this yet */
  1009.     if (scl_reg == 0x1fda)
  1010.         scl_reg = 0x1f90;
  1011.  
  1012.     RHDRegWrite(I2CPtr, scl_reg << 2, 0);
  1013.  
  1014.     RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_PIN_SELECTION, reg_7d9c);
  1015.     RHDRegMask(I2CPtr, RV62_GENERIC_I2C_SPEED,
  1016.             (prescale & 0xffff) << 16 | 0x02, 0xffff00ff);
  1017.     RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_SETUP, 0x30000000);
  1018.     RHDRegMask(I2CPtr, RV62_GENERIC_I2C_INTERRUPT_CONTROL,
  1019.             RV62_GENERIC_I2C_DONE_ACK, RV62_GENERIC_I2C_DONE_ACK);
  1020.  
  1021.     return TRUE;
  1022. }
  1023.  
  1024. static Bool
  1025. rhdRV620Transaction(I2CDevPtr i2cDevPtr, Bool Write, I2CByte *Buffer, int count)
  1026. {
  1027.     I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
  1028.     I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
  1029.     Bool Start = TRUE;
  1030.  
  1031.     RHDFUNC(I2CPtr);
  1032.  
  1033. #define MAX 8
  1034.  
  1035.     while (count > 0 || (Write && Start)) {
  1036.         int num;
  1037.         int idx = 0;
  1038.         CARD32 data = 0;
  1039.  
  1040.         if (count > MAX) {
  1041.             num = MAX;
  1042.             RHDRegMask(I2CPtr, RV62_GENERIC_I2C_TRANSACTION,
  1043.                     (MAX - (((Start) ? 0 : 1))) << 16
  1044.                     | RV62_GENERIC_I2C_STOP_ON_NACK
  1045.                     | RV62_GENERIC_I2C_ACK_ON_READ
  1046.                     | (Start ? RV62_GENERIC_I2C_START : 0)
  1047.                     | (!Write ? RV62_GENERIC_I2C_RW : 0 ),
  1048.                     0xFFFFFF);
  1049.         } else {
  1050.             num = count;
  1051.             data = ( count - (((Start) ? 0 : 1)) ) << 16
  1052.                 | RV62_GENERIC_I2C_STOP_ON_NACK
  1053.                 |  RV62_GENERIC_I2C_STOP
  1054.                 | (Start ? RV62_GENERIC_I2C_START : 0)
  1055.                 | (!Write ? RV62_GENERIC_I2C_RW : 0);
  1056.             RHDRegMask(I2CPtr, RV62_GENERIC_I2C_TRANSACTION,
  1057.                     data,
  1058.                     0xFFFFFF);
  1059.         }
  1060.  
  1061.         if (Start) {
  1062.             data = RV62_GENERIC_I2C_INDEX_WRITE
  1063.                 | (((slave & 0xfe) | ( Write ? 0 : 1)) << 8)
  1064.                 | (idx++ << 16);
  1065.             RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_DATA, data);
  1066.         }
  1067.  
  1068.         if (Write) {
  1069.             while (num--) {
  1070.                 data = RV62_GENERIC_I2C_INDEX_WRITE
  1071.                     | (idx++ << 16)
  1072.                     | *(Buffer++) << 8;
  1073.                 RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_DATA, data);
  1074.             }
  1075.  
  1076.             RHDRegMask(I2CPtr, RV62_GENERIC_I2C_CONTROL,
  1077.                     RV62_GENERIC_I2C_GO, RV62_GENERIC_I2C_GO);
  1078.             if (!rhdRV620I2CStatus(I2CPtr))
  1079.                 return FALSE;
  1080.         } else {
  1081.  
  1082.             RHDRegMask(I2CPtr, RV62_GENERIC_I2C_CONTROL,
  1083.                     RV62_GENERIC_I2C_GO, RV62_GENERIC_I2C_GO);
  1084.             if (!rhdRV620I2CStatus(I2CPtr))
  1085.                 return FALSE;
  1086.  
  1087.             RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_DATA,
  1088.                      RV62_GENERIC_I2C_INDEX_WRITE
  1089.                      | (idx++ << 16)
  1090.                      | RV62_GENERIC_I2C_RW);
  1091.  
  1092.             while (num--) {
  1093.                 data = RHDRegRead(I2CPtr, RV62_GENERIC_I2C_DATA);
  1094.                 *(Buffer++) = (CARD8)((data >> 8) & 0xff);
  1095.             }
  1096.         }
  1097.         Start = FALSE;
  1098.         count -= MAX;
  1099.     }
  1100.  
  1101.     return TRUE;
  1102. }
  1103.  
  1104. static Bool
  1105. rhdRV620WriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead)
  1106. {
  1107.     I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
  1108.     rhdI2CPtr I2C = (rhdI2CPtr)I2CPtr->DriverPrivate.ptr;
  1109.     int prescale = I2C->prescale;
  1110.  
  1111.     RHDFUNC(I2C);
  1112.  
  1113.     rhdRV620I2CSetupStatus(I2CPtr, &I2C->u.Gpio, prescale);
  1114.  
  1115.     if (nWrite || !nRead)
  1116.         if (!rhdRV620Transaction(i2cDevPtr, TRUE, WriteBuffer, nWrite))
  1117.             return FALSE;
  1118.     if (nRead)
  1119.         if (!rhdRV620Transaction(i2cDevPtr, FALSE, ReadBuffer, nRead))
  1120.             return FALSE;
  1121.  
  1122.     return TRUE;
  1123. }
  1124.  
  1125. static void
  1126. rhdTearDownI2C(I2CBusPtr *I2C)
  1127. {
  1128.     int i;
  1129.  
  1130.     /*
  1131.      * xf86I2CGetScreenBuses() is
  1132.      * broken in older server versions.
  1133.      * So we cannot use it. How bad!
  1134.      */
  1135.     for (i = 0; i < MAX_I2C_LINES; i++) {
  1136.         char *name;
  1137.         if (!I2C[i])
  1138.             break;
  1139.         name = I2C[i]->BusName;
  1140.         xfree(I2C[i]->DriverPrivate.ptr);
  1141.         xf86DestroyI2CBusRec(I2C[i], TRUE, TRUE);
  1142.         xfree(name);
  1143.     }
  1144.     xfree(I2C);
  1145. }
  1146.  
  1147. #define TARGET_HW_I2C_CLOCK 25 /*  kHz */
  1148. #define DEFAULT_ENGINE_CLOCK 453000 /* kHz (guessed) */
  1149. #define DEFAULT_REF_CLOCK 27000
  1150.  
  1151. static CARD32
  1152. rhdGetI2CPrescale(RHDPtr rhdPtr)
  1153. {
  1154. #ifdef ATOM_BIOS
  1155.     AtomBiosArgRec atomBiosArg;
  1156.     RHDFUNC(rhdPtr);
  1157.  
  1158.     if (rhdPtr->ChipSet < RHD_R600) {
  1159.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1160.                             GET_DEFAULT_ENGINE_CLOCK, &atomBiosArg)
  1161.             == ATOM_SUCCESS)
  1162.             return (0x7f << 8)
  1163.                 + (atomBiosArg.val / (4 * 0x7f * TARGET_HW_I2C_CLOCK));
  1164.         else
  1165.             return (0x7f << 8)
  1166.                 + (DEFAULT_ENGINE_CLOCK / (4 * 0x7f * TARGET_HW_I2C_CLOCK));
  1167.     } else if (rhdPtr->ChipSet < RHD_RV620) {
  1168.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1169.                             GET_REF_CLOCK, &atomBiosArg) == ATOM_SUCCESS)
  1170.             return (atomBiosArg.val / TARGET_HW_I2C_CLOCK);
  1171.         else
  1172.             return (DEFAULT_REF_CLOCK / TARGET_HW_I2C_CLOCK);
  1173.     } else {
  1174.     if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  1175.                             GET_REF_CLOCK, &atomBiosArg) == ATOM_SUCCESS)
  1176.             return (atomBiosArg.val / (4 * TARGET_HW_I2C_CLOCK));
  1177.         else
  1178.             return (DEFAULT_REF_CLOCK / (4 * TARGET_HW_I2C_CLOCK));
  1179.     }
  1180. #else
  1181.     RHDFUNC(rhdPtr);
  1182.  
  1183.     if (rhdPtr->ChipSet < RHD_R600) {
  1184.         return (0x7f << 8)
  1185.             + (DEFAULT_ENGINE_CLOCK) / (4 * 0x7f * TARGET_HW_I2C_CLOCK);
  1186.     } else if (rhdPtr->ChipSet < RHD_RV620) {
  1187.         return (DEFAULT_REF_CLOCK / TARGET_HW_I2C_CLOCK);
  1188.     } else
  1189.           return (DEFAULT_REF_CLOCK / (4 * TARGET_HW_I2C_CLOCK));
  1190. #endif
  1191. }
  1192.  
  1193. static Bool
  1194. rhdI2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
  1195. {
  1196.     d->SlaveAddr = addr;
  1197.     return xf86I2CWriteRead(d, NULL, 0, NULL, 0);
  1198. }
  1199.  
  1200. /*
  1201.  * This stub is needed to keep xf86I2CProbeAddress() happy.
  1202.  */
  1203. static void
  1204. rhdI2CStop(I2CDevPtr d)
  1205. {
  1206. }
  1207.  
  1208. static I2CBusPtr *
  1209. rhdInitI2C(int scrnIndex)
  1210. {
  1211.     int i;
  1212.     rhdI2CPtr I2C;
  1213.     I2CBusPtr I2CPtr = NULL;
  1214.     RHDPtr rhdPtr = (RHDPtr)scrnIndex;
  1215.     I2CBusPtr *I2CList;
  1216.     int numLines;
  1217.     CARD16 prescale = rhdGetI2CPrescale(rhdPtr);
  1218.     enum rhdDDClines sda = 0, scl = 0;
  1219.     CARD32 scl_reg = 0, sda_reg = 0;
  1220.     Bool valid;
  1221.  
  1222.     RHDFUNCI(scrnIndex);
  1223.  
  1224.     if (rhdPtr->ChipSet < RHD_RS600)
  1225.         numLines = 3;
  1226.     else if (rhdPtr->ChipSet < RHD_R600)
  1227.         numLines = 4;
  1228.     else if (rhdPtr->ChipSet < RHD_RV730)
  1229.         numLines = 4;
  1230.     else
  1231.         numLines = MAX_I2C_LINES;
  1232.  
  1233.     if (!(I2CList = xcalloc(MAX_I2C_LINES, sizeof(I2CBusPtr)))) {
  1234.         xf86DrvMsg(scrnIndex, X_ERROR,
  1235.                    "%s: Out of memory.\n",__func__);
  1236.     }
  1237.     /* We have 4 I2C lines */
  1238.     for (i = 0; i < numLines; i++) {
  1239.         if (!(I2C = xcalloc(sizeof(rhdI2CRec),1))) {
  1240.             xf86DrvMsg(scrnIndex, X_ERROR,
  1241.                        "%s: Out of memory.\n",__func__);
  1242.             goto error;
  1243.         }
  1244.         I2C->scrnIndex = scrnIndex;
  1245.  
  1246.         valid = rhdI2CGetDataClkLines(rhdPtr, i, &scl, &sda, &sda_reg, &scl_reg);
  1247.         if (rhdPtr->ChipSet < RHD_RS600
  1248.             || (rhdPtr->ChipSet > RHD_RS740 && rhdPtr->ChipSet < RHD_RV620)) {
  1249.  
  1250.             if (valid) {
  1251.                 if (sda == rhdDdc1data && scl == rhdDdc1clk)
  1252.                     I2C->u.line = 0;
  1253.                 else if (sda == rhdDdc2data && scl == rhdDdc2clk)
  1254.                     I2C->u.line = 1;
  1255.                 else if (sda == rhdDdc3data && scl == rhdDdc3clk)
  1256.                     I2C->u.line = 2;
  1257.                 else if (rhdPtr->ChipSet > RHD_RS740 && sda == rhdDdc4data && scl == rhdDdc4clk)
  1258.                     I2C->u.line = 3; /* R6XX only */
  1259.                 else {
  1260.                     xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "No DDC line found for index %i: scl=0x%2.2x sda=0x%2.2x\n",
  1261.                                i, scl, sda);
  1262.                     xfree(I2C);
  1263.                     continue;
  1264.                 }
  1265.  
  1266.             } else
  1267.                 I2C->u.line = i;
  1268.  
  1269.         } else if (rhdPtr->ChipSet <= RHD_RS740) {
  1270.  
  1271.             if (valid) {
  1272.                 if (sda != rhdDdc1data && sda != rhdDdc2data && sda != rhdDdc3data) {
  1273.                     xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "Invalid DDC CLK pin found: %i\n",
  1274.                                sda);
  1275.                     xfree(I2C);
  1276.                     continue;
  1277.                 }
  1278.                 if (scl != rhdDdc1data && scl != rhdDdc2data && scl != rhdDdc3data
  1279.                     && scl != rhdDdc1clk && scl != rhdDdc2clk && scl != rhdDdc3clk) {
  1280.                     xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "Invalid DDC CLK pin found: %i\n",
  1281.                                scl);
  1282.                     xfree(I2C);
  1283.                     continue;
  1284.                 }
  1285.                 I2C->u.Gpio.Sda = sda;
  1286.                 I2C->u.Gpio.Scl = scl;
  1287.                 I2C->u.Gpio.SdaReg = sda_reg;
  1288.                 I2C->u.Gpio.SclReg = scl_reg;
  1289.  
  1290.             } else {
  1291.                 xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "Invalid ClkLine for DDC. "
  1292.                            "AtomBIOS reported wrong or AtomBIOS unavailable\n");
  1293.                 xfree(I2C);
  1294.                 goto error;
  1295.             }
  1296.  
  1297.         } else {
  1298.  
  1299.             if (valid) {
  1300.                 I2C->u.Gpio.Sda = sda;
  1301.                 I2C->u.Gpio.Scl = scl;
  1302.                 I2C->u.Gpio.SdaReg = sda_reg;
  1303.                 I2C->u.Gpio.SclReg = scl_reg;
  1304.             } else {
  1305.                 CARD32 gpioReg[] = { 0x1f90, 0x1f94, 0x1f98 };
  1306.                 enum rhdDDClines sdaList[] = { rhdDdc1data, rhdDdc2data, rhdDdc3data };
  1307.                 enum rhdDDClines sclList[] = { rhdDdc1clk, rhdDdc2clk, rhdDdc3clk };
  1308.                 if (i > 2) {
  1309.                     xfree(I2C);
  1310.                     continue;
  1311.                 }
  1312.                 I2C->u.Gpio.Sda = sdaList[i];
  1313.                 I2C->u.Gpio.Scl = sclList[i];
  1314.                 I2C->u.Gpio.SclReg = I2C->u.Gpio.SdaReg = gpioReg[i];
  1315.             }
  1316.  
  1317.         }
  1318.  
  1319.         /*
  1320.          * This is a value that has been found to work on many cards.
  1321.          * It nees to be replaced by the proper calculation formula
  1322.          * once this is available.
  1323.          */
  1324.         I2C->prescale = prescale;
  1325.         xf86DrvMsgVerb(scrnIndex, X_INFO, 5, "I2C clock prescale value: %x\n",I2C->prescale);
  1326.  
  1327.         if (!(I2CPtr = xf86CreateI2CBusRec())) {
  1328.             xf86DrvMsg(scrnIndex, X_ERROR,
  1329.                        "Cannot allocate I2C BusRec.\n");
  1330.             xfree(I2C);
  1331.             goto error;
  1332.         }
  1333.         I2CPtr->DriverPrivate.ptr = I2C;
  1334.         if (!(I2CPtr->BusName = xalloc(18))) {
  1335.             xf86DrvMsg(scrnIndex, X_ERROR,
  1336.                        "%s: Cannot allocate memory.\n",__func__);
  1337.             xfree(I2C);
  1338.             xf86DestroyI2CBusRec(I2CPtr, TRUE, FALSE);
  1339.             goto error;
  1340.         }
  1341.         snprintf(I2CPtr->BusName,17,"RHD I2C line %1.1i",i);
  1342.         I2CPtr->scrnIndex = scrnIndex;
  1343.         if (rhdPtr->ChipSet < RHD_RS600)
  1344.             I2CPtr->I2CWriteRead = rhd5xxWriteRead;
  1345.         else if (rhdPtr->ChipSet >= RHD_RS600 && rhdPtr->ChipSet <= RHD_RS740)
  1346.             I2CPtr->I2CWriteRead = rhdRS69WriteRead;
  1347.         else if (rhdPtr->ChipSet < RHD_RV620)
  1348.             I2CPtr->I2CWriteRead = rhd6xxWriteRead;
  1349.         else
  1350.             I2CPtr->I2CWriteRead = rhdRV620WriteRead;
  1351.         I2CPtr->I2CAddress = rhdI2CAddress;
  1352.         I2CPtr->I2CStop = rhdI2CStop;
  1353.  
  1354.         if (!(xf86I2CBusInit(I2CPtr))) {
  1355.             xf86DrvMsg(scrnIndex, X_ERROR,
  1356.                        "I2C BusInit failed for bus %i\n",i);
  1357.             xfree(I2CPtr->BusName);
  1358.             xfree(I2C);
  1359.             xf86DestroyI2CBusRec(I2CPtr, TRUE, FALSE);
  1360.             goto error;
  1361.         }
  1362.         I2CList[i] = I2CPtr;
  1363.     }
  1364.     return I2CList;
  1365.  error:
  1366.     rhdTearDownI2C(I2CList);
  1367.     return NULL;
  1368. }
  1369.  
  1370. RHDI2CResult
  1371. rhdI2CProbeAddress(int scrnIndex, I2CBusPtr I2CBusPtr, CARD8 slave)
  1372. {
  1373.     I2CDevPtr dev;
  1374.     char *name = "I2CProbe";
  1375.  
  1376.     if ((dev = xf86CreateI2CDevRec())) {
  1377.         dev->DevName = name;
  1378.         dev->pI2CBus = I2CBusPtr;
  1379.  
  1380.         if (xf86I2CDevInit(dev)) {
  1381.             Bool ret;
  1382.  
  1383.             dev->SlaveAddr = slave & 0xFE;
  1384.  
  1385.             ret = xf86I2CWriteRead(dev, NULL, 0, NULL, 0);
  1386.  
  1387.             if (ret) {
  1388.                 unsigned char offset = 0;
  1389.                 unsigned char buf[2];
  1390.  
  1391.                 /*
  1392.                   ASUS M2A-VM (R690) motherboards ACK all I2C slaves on the
  1393.                   HDMI line when the HDMI riser card is not installed.
  1394.                   We therefore need to read the first two bytes and check
  1395.                   if they are part of an I2C header.
  1396.                 */
  1397.                 ret = xf86I2CWriteRead(dev, &offset, 1, buf, 2);
  1398.                 if (ret && (buf[0] != 0 || buf[1] != 0xff))
  1399.                     ret = FALSE;
  1400.             }
  1401.             xf86DestroyI2CDevRec(dev, TRUE);
  1402.  
  1403.             return ret ? RHD_I2C_SUCCESS : RHD_I2C_FAILED;
  1404.         }
  1405.     }
  1406.  
  1407.     return RHD_I2C_FAILED;
  1408. }
  1409.  
  1410. RHDI2CResult
  1411. RHDI2CFunc(int scrnIndex, I2CBusPtr *I2CList, RHDi2cFunc func,
  1412.            RHDI2CDataArgPtr datap)
  1413. {
  1414.     RHDFUNCI(scrnIndex);
  1415.  
  1416.     if (func == RHD_I2C_INIT) {
  1417.         if (!(datap->I2CBusList = rhdInitI2C(scrnIndex)))
  1418.             return RHD_I2C_FAILED;
  1419.         else
  1420.             return RHD_I2C_SUCCESS;
  1421.     }
  1422.     if (func == RHD_I2C_DDC) {
  1423.         if (datap->i >= MAX_I2C_LINES || !I2CList[datap->i])
  1424.             return RHD_I2C_NOLINE;
  1425.  
  1426.         datap->monitor = xf86DoEDID_DDC2(scrnIndex, I2CList[datap->i]);
  1427.         return RHD_I2C_SUCCESS;
  1428.     }
  1429.     if (func == RHD_I2C_PROBE_ADDR_LINE) {
  1430.  
  1431.         if (datap->target.line >= MAX_I2C_LINES || !I2CList[datap->target.line])
  1432.             return RHD_I2C_NOLINE;
  1433.         return rhdI2CProbeAddress(scrnIndex, I2CList[datap->target.line], datap->target.slave);
  1434.     }
  1435.     if (func == RHD_I2C_PROBE_ADDR) {
  1436.         return rhdI2CProbeAddress(scrnIndex, datap->probe.i2cBusPtr, datap->probe.slave);
  1437.     }
  1438.     if (func == RHD_I2C_GETBUS) {
  1439.         if (datap->i >= MAX_I2C_LINES || !I2CList[datap->i])
  1440.             return RHD_I2C_NOLINE;
  1441.  
  1442.         datap->i2cBusPtr = I2CList[datap->i];
  1443.         return RHD_I2C_SUCCESS;
  1444.     }
  1445.     if (func == RHD_I2C_TEARDOWN) {
  1446.         if (I2CList)
  1447.             rhdTearDownI2C(I2CList);
  1448.         return RHD_I2C_SUCCESS;
  1449.     }
  1450.     return RHD_I2C_FAILED;
  1451. }
  1452.  
  1453.