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