1 // SPDX-License-Identifier: GPL-2.0
5 #include "ddk750_sii164.h"
6 #include "ddk750_hwi2c.h"
8 /* I2C Address of each SII164 chip */
9 #define SII164_I2C_ADDRESS 0x70
11 /* Define this definition to use hardware i2c. */
15 #define i2cWriteReg sm750_hw_i2c_write_reg
16 #define i2cReadReg sm750_hw_i2c_read_reg
18 #define i2cWriteReg sm750_sw_i2c_write_reg
19 #define i2cReadReg sm750_sw_i2c_read_reg
22 /* SII164 Vendor and Device ID */
23 #define SII164_VENDOR_ID 0x0001
24 #define SII164_DEVICE_ID 0x0006
26 #ifdef SII164_FULL_FUNCTIONS
27 /* Name of the DVI Controller chip */
28 static char *gDviCtrlChipName = "Silicon Image SiI 164";
33 * This function gets the vendor ID of the DVI controller chip.
38 unsigned short sii164GetVendorID(void)
40 unsigned short vendorID;
42 vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
43 (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
50 * This function gets the device ID of the DVI controller chip.
55 unsigned short sii164GetDeviceID(void)
57 unsigned short deviceID;
59 deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
60 (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
67 /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
71 * This function initialize and detect the DVI controller chip.
74 * edgeSelect - Edge Select:
75 * 0 = Input data is falling edge latched (falling edge
76 * latched first in dual edge mode)
77 * 1 = Input data is rising edge latched (rising edge
78 * latched first in dual edge mode)
79 * busSelect - Input Bus Select:
80 * 0 = Input data bus is 12-bits wide
81 * 1 = Input data bus is 24-bits wide
82 * dualEdgeClkSelect - Dual Edge Clock Select
83 * 0 = Input data is single edge latched
84 * 1 = Input data is dual edge latched
85 * hsyncEnable - Horizontal Sync Enable:
86 * 0 = HSYNC input is transmitted as fixed LOW
87 * 1 = HSYNC input is transmitted as is
88 * vsyncEnable - Vertical Sync Enable:
89 * 0 = VSYNC input is transmitted as fixed LOW
90 * 1 = VSYNC input is transmitted as is
91 * deskewEnable - De-skewing Enable:
92 * 0 = De-skew disabled
94 * deskewSetting - De-skewing Setting (increment of 260psec)
95 * 0 = 1 step --> minimum setup / maximum hold
102 * 7 = 8 step --> maximum setup / minimum hold
103 * continuousSyncEnable- SYNC Continuous:
106 * pllFilterEnable - PLL Filter Enable
107 * 0 = Disable PLL Filter
108 * 1 = Enable PLL Filter
109 * pllFilterValue - PLL Filter characteristics:
110 * 0~7 (recommended value is 4)
116 long sii164InitChip(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)
127 unsigned char config;
129 /* Initialize the i2c bus */
132 sm750_hw_i2c_init(1);
134 sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
137 /* Check if SII164 Chip exists */
138 if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
140 * Initialize SII164 controller chip.
143 /* Select the edge */
145 config = SII164_CONFIGURATION_LATCH_FALLING;
147 config = SII164_CONFIGURATION_LATCH_RISING;
149 /* Select bus wide */
151 config |= SII164_CONFIGURATION_BUS_12BITS;
153 config |= SII164_CONFIGURATION_BUS_24BITS;
155 /* Select Dual/Single Edge Clock */
156 if (dualEdgeClkSelect == 0)
157 config |= SII164_CONFIGURATION_CLOCK_SINGLE;
159 config |= SII164_CONFIGURATION_CLOCK_DUAL;
161 /* Select HSync Enable */
162 if (hsyncEnable == 0)
163 config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
165 config |= SII164_CONFIGURATION_HSYNC_AS_IS;
167 /* Select VSync Enable */
168 if (vsyncEnable == 0)
169 config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
171 config |= SII164_CONFIGURATION_VSYNC_AS_IS;
173 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
176 * De-skew enabled with default 111b value.
177 * This fixes some artifacts problem in some mode on board 2.2.
178 * Somehow this fix does not affect board 2.1.
180 if (deskewEnable == 0)
181 config = SII164_DESKEW_DISABLE;
183 config = SII164_DESKEW_ENABLE;
185 switch (deskewSetting) {
187 config |= SII164_DESKEW_1_STEP;
190 config |= SII164_DESKEW_2_STEP;
193 config |= SII164_DESKEW_3_STEP;
196 config |= SII164_DESKEW_4_STEP;
199 config |= SII164_DESKEW_5_STEP;
202 config |= SII164_DESKEW_6_STEP;
205 config |= SII164_DESKEW_7_STEP;
208 config |= SII164_DESKEW_8_STEP;
211 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
213 /* Enable/Disable Continuous Sync. */
214 if (continuousSyncEnable == 0)
215 config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
217 config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
219 /* Enable/Disable PLL Filter */
220 if (pllFilterEnable == 0)
221 config |= SII164_PLL_FILTER_DISABLE;
223 config |= SII164_PLL_FILTER_ENABLE;
225 /* Set the PLL Filter value */
226 config |= ((pllFilterValue & 0x07) << 1);
228 i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
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);
238 /* Return -1 if initialization fails. */
246 /* below sii164 function is not necessary */
248 #ifdef SII164_FULL_FUNCTIONS
252 * This function resets the DVI Controller Chip.
254 void sii164ResetChip(void)
262 * sii164GetChipString
263 * This function returns a char string name of the current DVI Controller chip.
264 * It's convenient for application need to display the chip name.
266 char *sii164GetChipString(void)
268 return gDviCtrlChipName;
273 * This function sets the power configuration of the DVI Controller Chip.
276 * powerUp - Flag to set the power down or up
278 void sii164SetPower(unsigned char powerUp)
280 unsigned char config;
282 config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
284 /* Power up the chip */
285 config &= ~SII164_CONFIGURATION_POWER_MASK;
286 config |= SII164_CONFIGURATION_POWER_NORMAL;
287 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
289 /* Power down the chip */
290 config &= ~SII164_CONFIGURATION_POWER_MASK;
291 config |= SII164_CONFIGURATION_POWER_DOWN;
292 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
297 * sii164SelectHotPlugDetectionMode
298 * This function selects the mode of the hot plug detection.
300 static void sii164SelectHotPlugDetectionMode(sii164_hot_plug_mode_t hotPlugMode)
302 unsigned char detectReg;
304 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
305 ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
306 switch (hotPlugMode) {
307 case SII164_HOTPLUG_DISABLE:
308 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
310 case SII164_HOTPLUG_USE_MDI:
311 detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
312 detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
313 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
315 case SII164_HOTPLUG_USE_RSEN:
316 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
318 case SII164_HOTPLUG_USE_HTPLG:
319 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
323 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
327 * sii164EnableHotPlugDetection
328 * This function enables the Hot Plug detection.
330 * enableHotPlug - Enable (=1) / disable (=0) Hot Plug detection
332 void sii164EnableHotPlugDetection(unsigned char enableHotPlug)
334 unsigned char detectReg;
336 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
338 /* Depending on each DVI controller, need to enable the hot plug based on each
339 * individual chip design.
341 if (enableHotPlug != 0)
342 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
344 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
349 * Check if the DVI Monitor is connected.
355 unsigned char sii164IsConnected(void)
357 unsigned char hotPlugValue;
359 hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
360 SII164_DETECT_HOT_PLUG_STATUS_MASK;
361 if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
368 * sii164CheckInterrupt
369 * Checks if interrupt has occurred.
373 * 1 - Interrupt occurs
375 unsigned char sii164CheckInterrupt(void)
377 unsigned char detectReg;
379 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
380 SII164_DETECT_MONITOR_STATE_MASK;
381 if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
388 * sii164ClearInterrupt
389 * Clear the hot plug interrupt.
391 void sii164ClearInterrupt(void)
393 unsigned char detectReg;
395 /* Clear the MDI interrupt */
396 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
397 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT,
398 detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);