linux/drivers/staging/sm750fb/ddk750_sii164.c
<<
>>
Prefs
   1#define USE_DVICHIP
   2#ifdef USE_DVICHIP
   3
   4#include "ddk750_sii164.h"
   5#include "ddk750_hwi2c.h"
   6
   7/* I2C Address of each SII164 chip */
   8#define SII164_I2C_ADDRESS                  0x70
   9
  10/* Define this definition to use hardware i2c. */
  11#define USE_HW_I2C
  12
  13#ifdef USE_HW_I2C
  14    #define i2cWriteReg sm750_hw_i2c_write_reg
  15    #define i2cReadReg  sm750_hw_i2c_read_reg
  16#else
  17    #define i2cWriteReg sm750_sw_i2c_write_reg
  18    #define i2cReadReg  sm750_sw_i2c_read_reg
  19#endif
  20
  21/* SII164 Vendor and Device ID */
  22#define SII164_VENDOR_ID                    0x0001
  23#define SII164_DEVICE_ID                    0x0006
  24
  25#ifdef SII164_FULL_FUNCTIONS
  26/* Name of the DVI Controller chip */
  27static char *gDviCtrlChipName = "Silicon Image SiI 164";
  28#endif
  29
  30/*
  31 *  sii164GetVendorID
  32 *      This function gets the vendor ID of the DVI controller chip.
  33 *
  34 *  Output:
  35 *      Vendor ID
  36 */
  37unsigned short sii164GetVendorID(void)
  38{
  39        unsigned short vendorID;
  40
  41        vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
  42                    (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
  43
  44        return vendorID;
  45}
  46
  47/*
  48 *  sii164GetDeviceID
  49 *      This function gets the device ID of the DVI controller chip.
  50 *
  51 *  Output:
  52 *      Device ID
  53 */
  54unsigned short sii164GetDeviceID(void)
  55{
  56        unsigned short deviceID;
  57
  58        deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
  59                    (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
  60
  61        return deviceID;
  62}
  63
  64
  65
  66/* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
  67
  68/*
  69 *  sii164InitChip
  70 *      This function initialize and detect the DVI controller chip.
  71 *
  72 *  Input:
  73 *      edgeSelect          - Edge Select:
  74 *                              0 = Input data is falling edge latched (falling edge
  75 *                                  latched first in dual edge mode)
  76 *                              1 = Input data is rising edge latched (rising edge
  77 *                                  latched first in dual edge mode)
  78 *      busSelect           - Input Bus Select:
  79 *                              0 = Input data bus is 12-bits wide
  80 *                              1 = Input data bus is 24-bits wide
  81 *      dualEdgeClkSelect   - Dual Edge Clock Select
  82 *                              0 = Input data is single edge latched
  83 *                              1 = Input data is dual edge latched
  84 *      hsyncEnable         - Horizontal Sync Enable:
  85 *                              0 = HSYNC input is transmitted as fixed LOW
  86 *                              1 = HSYNC input is transmitted as is
  87 *      vsyncEnable         - Vertical Sync Enable:
  88 *                              0 = VSYNC input is transmitted as fixed LOW
  89 *                              1 = VSYNC input is transmitted as is
  90 *      deskewEnable        - De-skewing Enable:
  91 *                              0 = De-skew disabled
  92 *                              1 = De-skew enabled
  93 *      deskewSetting       - De-skewing Setting (increment of 260psec)
  94 *                              0 = 1 step --> minimum setup / maximum hold
  95 *                              1 = 2 step
  96 *                              2 = 3 step
  97 *                              3 = 4 step
  98 *                              4 = 5 step
  99 *                              5 = 6 step
 100 *                              6 = 7 step
 101 *                              7 = 8 step --> maximum setup / minimum hold
 102 *      continuousSyncEnable- SYNC Continuous:
 103 *                              0 = Disable
 104 *                              1 = Enable
 105 *      pllFilterEnable     - PLL Filter Enable
 106 *                              0 = Disable PLL Filter
 107 *                              1 = Enable PLL Filter
 108 *      pllFilterValue      - PLL Filter characteristics:
 109 *                              0~7 (recommended value is 4)
 110 *
 111 *  Output:
 112 *      0   - Success
 113 *     -1   - Fail.
 114 */
 115long sii164InitChip(
 116        unsigned char edgeSelect,
 117        unsigned char busSelect,
 118        unsigned char dualEdgeClkSelect,
 119        unsigned char hsyncEnable,
 120        unsigned char vsyncEnable,
 121        unsigned char deskewEnable,
 122        unsigned char deskewSetting,
 123        unsigned char continuousSyncEnable,
 124        unsigned char pllFilterEnable,
 125        unsigned char pllFilterValue
 126)
 127{
 128        unsigned char config;
 129
 130        /* Initialize the i2c bus */
 131#ifdef USE_HW_I2C
 132        /* Use fast mode. */
 133        sm750_hw_i2c_init(1);
 134#else
 135        sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
 136#endif
 137
 138        /* Check if SII164 Chip exists */
 139        if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
 140                /*
 141                 *  Initialize SII164 controller chip.
 142                 */
 143
 144                /* Select the edge */
 145                if (edgeSelect == 0)
 146                        config = SII164_CONFIGURATION_LATCH_FALLING;
 147                else
 148                        config = SII164_CONFIGURATION_LATCH_RISING;
 149
 150                /* Select bus wide */
 151                if (busSelect == 0)
 152                        config |= SII164_CONFIGURATION_BUS_12BITS;
 153                else
 154                        config |= SII164_CONFIGURATION_BUS_24BITS;
 155
 156                /* Select Dual/Single Edge Clock */
 157                if (dualEdgeClkSelect == 0)
 158                        config |= SII164_CONFIGURATION_CLOCK_SINGLE;
 159                else
 160                        config |= SII164_CONFIGURATION_CLOCK_DUAL;
 161
 162                /* Select HSync Enable */
 163                if (hsyncEnable == 0)
 164                        config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
 165                else
 166                        config |= SII164_CONFIGURATION_HSYNC_AS_IS;
 167
 168                /* Select VSync Enable */
 169                if (vsyncEnable == 0)
 170                        config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
 171                else
 172                        config |= SII164_CONFIGURATION_VSYNC_AS_IS;
 173
 174                i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
 175
 176                /* De-skew enabled with default 111b value.
 177                   This will fix some artifacts problem in some mode on board 2.2.
 178                   Somehow this fix does not affect board 2.1.
 179                 */
 180                if (deskewEnable == 0)
 181                        config = SII164_DESKEW_DISABLE;
 182                else
 183                        config = SII164_DESKEW_ENABLE;
 184
 185                switch (deskewSetting) {
 186                case 0:
 187                        config |= SII164_DESKEW_1_STEP;
 188                        break;
 189                case 1:
 190                        config |= SII164_DESKEW_2_STEP;
 191                        break;
 192                case 2:
 193                        config |= SII164_DESKEW_3_STEP;
 194                        break;
 195                case 3:
 196                        config |= SII164_DESKEW_4_STEP;
 197                        break;
 198                case 4:
 199                        config |= SII164_DESKEW_5_STEP;
 200                        break;
 201                case 5:
 202                        config |= SII164_DESKEW_6_STEP;
 203                        break;
 204                case 6:
 205                        config |= SII164_DESKEW_7_STEP;
 206                        break;
 207                case 7:
 208                        config |= SII164_DESKEW_8_STEP;
 209                        break;
 210                }
 211                i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
 212
 213                /* Enable/Disable Continuous Sync. */
 214                if (continuousSyncEnable == 0)
 215                        config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
 216                else
 217                        config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
 218
 219                /* Enable/Disable PLL Filter */
 220                if (pllFilterEnable == 0)
 221                        config |= SII164_PLL_FILTER_DISABLE;
 222                else
 223                        config |= SII164_PLL_FILTER_ENABLE;
 224
 225                /* Set the PLL Filter value */
 226                config |= ((pllFilterValue & 0x07) << 1);
 227
 228                i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
 229
 230                /* Recover from Power Down and enable output. */
 231                config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
 232                config |= SII164_CONFIGURATION_POWER_NORMAL;
 233                i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
 234
 235                return 0;
 236        }
 237
 238        /* Return -1 if initialization fails. */
 239        return -1;
 240}
 241
 242
 243
 244
 245
 246/* below sii164 function is not necessary */
 247
 248#ifdef SII164_FULL_FUNCTIONS
 249
 250/*
 251 *  sii164ResetChip
 252 *      This function resets the DVI Controller Chip.
 253 */
 254void sii164ResetChip(void)
 255{
 256        /* Power down */
 257        sii164SetPower(0);
 258        sii164SetPower(1);
 259}
 260
 261
 262/*
 263 * sii164GetChipString
 264 *      This function returns a char string name of the current DVI Controller chip.
 265 *      It's convenient for application need to display the chip name.
 266 */
 267char *sii164GetChipString(void)
 268{
 269        return gDviCtrlChipName;
 270}
 271
 272
 273/*
 274 *  sii164SetPower
 275 *      This function sets the power configuration of the DVI Controller Chip.
 276 *
 277 *  Input:
 278 *      powerUp - Flag to set the power down or up
 279 */
 280void sii164SetPower(
 281        unsigned char powerUp
 282)
 283{
 284        unsigned char config;
 285
 286        config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
 287        if (powerUp == 1) {
 288                /* Power up the chip */
 289                config &= ~SII164_CONFIGURATION_POWER_MASK;
 290                config |= SII164_CONFIGURATION_POWER_NORMAL;
 291                i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
 292        } else {
 293                /* Power down the chip */
 294                config &= ~SII164_CONFIGURATION_POWER_MASK;
 295                config |= SII164_CONFIGURATION_POWER_DOWN;
 296                i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
 297        }
 298}
 299
 300
 301/*
 302 *  sii164SelectHotPlugDetectionMode
 303 *      This function selects the mode of the hot plug detection.
 304 */
 305static void sii164SelectHotPlugDetectionMode(
 306        sii164_hot_plug_mode_t hotPlugMode
 307)
 308{
 309        unsigned char detectReg;
 310
 311        detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
 312        switch (hotPlugMode) {
 313        case SII164_HOTPLUG_DISABLE:
 314                detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
 315                break;
 316        case SII164_HOTPLUG_USE_MDI:
 317                detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
 318                detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
 319                detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
 320                break;
 321        case SII164_HOTPLUG_USE_RSEN:
 322                detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
 323                break;
 324        case SII164_HOTPLUG_USE_HTPLG:
 325                detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
 326                break;
 327        }
 328
 329        i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
 330}
 331
 332/*
 333 *  sii164EnableHotPlugDetection
 334 *      This function enables the Hot Plug detection.
 335 *
 336 *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
 337 */
 338void sii164EnableHotPlugDetection(
 339        unsigned char enableHotPlug
 340)
 341{
 342        unsigned char detectReg;
 343
 344        detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
 345
 346        /* Depending on each DVI controller, need to enable the hot plug based on each
 347           individual chip design. */
 348        if (enableHotPlug != 0)
 349                sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
 350        else
 351                sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
 352}
 353
 354/*
 355 *  sii164IsConnected
 356 *      Check if the DVI Monitor is connected.
 357 *
 358 *  Output:
 359 *      0   - Not Connected
 360 *      1   - Connected
 361 */
 362unsigned char sii164IsConnected(void)
 363{
 364        unsigned char hotPlugValue;
 365
 366        hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
 367        if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
 368                return 1;
 369        else
 370                return 0;
 371}
 372
 373/*
 374 *  sii164CheckInterrupt
 375 *      Checks if interrupt has occurred.
 376 *
 377 *  Output:
 378 *      0   - No interrupt
 379 *      1   - Interrupt occurs
 380 */
 381unsigned char sii164CheckInterrupt(void)
 382{
 383        unsigned char detectReg;
 384
 385        detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
 386        if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
 387                return 1;
 388        else
 389                return 0;
 390}
 391
 392/*
 393 *  sii164ClearInterrupt
 394 *      Clear the hot plug interrupt.
 395 */
 396void sii164ClearInterrupt(void)
 397{
 398        unsigned char detectReg;
 399
 400        /* Clear the MDI interrupt */
 401        detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
 402        i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
 403}
 404
 405#endif
 406
 407#endif
 408
 409
 410