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);
65 /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
69 * This function initialize and detect the DVI controller chip.
72 * edgeSelect - Edge Select:
73 * 0 = Input data is falling edge latched (falling edge
74 * latched first in dual edge mode)
75 * 1 = Input data is rising edge latched (rising edge
76 * latched first in dual edge mode)
77 * busSelect - Input Bus Select:
78 * 0 = Input data bus is 12-bits wide
79 * 1 = Input data bus is 24-bits wide
80 * dualEdgeClkSelect - Dual Edge Clock Select
81 * 0 = Input data is single edge latched
82 * 1 = Input data is dual edge latched
83 * hsyncEnable - Horizontal Sync Enable:
84 * 0 = HSYNC input is transmitted as fixed LOW
85 * 1 = HSYNC input is transmitted as is
86 * vsyncEnable - Vertical Sync Enable:
87 * 0 = VSYNC input is transmitted as fixed LOW
88 * 1 = VSYNC input is transmitted as is
89 * deskewEnable - De-skewing Enable:
90 * 0 = De-skew disabled
92 * deskewSetting - De-skewing Setting (increment of 260psec)
93 * 0 = 1 step --> minimum setup / maximum hold
100 * 7 = 8 step --> maximum setup / minimum hold
101 * continuousSyncEnable- SYNC Continuous:
104 * pllFilterEnable - PLL Filter Enable
105 * 0 = Disable PLL Filter
106 * 1 = Enable PLL Filter
107 * pllFilterValue - PLL Filter characteristics:
108 * 0~7 (recommended value is 4)
114 long sii164InitChip(unsigned char edgeSelect,
115 unsigned char busSelect,
116 unsigned char dualEdgeClkSelect,
117 unsigned char hsyncEnable,
118 unsigned char vsyncEnable,
119 unsigned char deskewEnable,
120 unsigned char deskewSetting,
121 unsigned char continuousSyncEnable,
122 unsigned char pllFilterEnable,
123 unsigned char pllFilterValue)
125 unsigned char config;
127 /* Initialize the i2c bus */
130 sm750_hw_i2c_init(1);
132 sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
135 /* Check if SII164 Chip exists */
136 if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
138 * Initialize SII164 controller chip.
141 /* Select the edge */
143 config = SII164_CONFIGURATION_LATCH_FALLING;
145 config = SII164_CONFIGURATION_LATCH_RISING;
147 /* Select bus wide */
149 config |= SII164_CONFIGURATION_BUS_12BITS;
151 config |= SII164_CONFIGURATION_BUS_24BITS;
153 /* Select Dual/Single Edge Clock */
154 if (dualEdgeClkSelect == 0)
155 config |= SII164_CONFIGURATION_CLOCK_SINGLE;
157 config |= SII164_CONFIGURATION_CLOCK_DUAL;
159 /* Select HSync Enable */
160 if (hsyncEnable == 0)
161 config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
163 config |= SII164_CONFIGURATION_HSYNC_AS_IS;
165 /* Select VSync Enable */
166 if (vsyncEnable == 0)
167 config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
169 config |= SII164_CONFIGURATION_VSYNC_AS_IS;
171 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
174 * De-skew enabled with default 111b value.
175 * This fixes some artifacts problem in some mode on board 2.2.
176 * Somehow this fix does not affect board 2.1.
178 if (deskewEnable == 0)
179 config = SII164_DESKEW_DISABLE;
181 config = SII164_DESKEW_ENABLE;
183 switch (deskewSetting) {
185 config |= SII164_DESKEW_1_STEP;
188 config |= SII164_DESKEW_2_STEP;
191 config |= SII164_DESKEW_3_STEP;
194 config |= SII164_DESKEW_4_STEP;
197 config |= SII164_DESKEW_5_STEP;
200 config |= SII164_DESKEW_6_STEP;
203 config |= SII164_DESKEW_7_STEP;
206 config |= SII164_DESKEW_8_STEP;
209 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
211 /* Enable/Disable Continuous Sync. */
212 if (continuousSyncEnable == 0)
213 config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
215 config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
217 /* Enable/Disable PLL Filter */
218 if (pllFilterEnable == 0)
219 config |= SII164_PLL_FILTER_DISABLE;
221 config |= SII164_PLL_FILTER_ENABLE;
223 /* Set the PLL Filter value */
224 config |= ((pllFilterValue & 0x07) << 1);
226 i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
228 /* Recover from Power Down and enable output. */
229 config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
230 config |= SII164_CONFIGURATION_POWER_NORMAL;
231 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
236 /* Return -1 if initialization fails. */
240 /* below sii164 function is not necessary */
242 #ifdef SII164_FULL_FUNCTIONS
246 * This function resets the DVI Controller Chip.
248 void sii164ResetChip(void)
256 * sii164GetChipString
257 * This function returns a char string name of the current DVI Controller chip.
258 * It's convenient for application need to display the chip name.
260 char *sii164GetChipString(void)
262 return gDviCtrlChipName;
267 * This function sets the power configuration of the DVI Controller Chip.
270 * powerUp - Flag to set the power down or up
272 void sii164SetPower(unsigned char powerUp)
274 unsigned char config;
276 config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
278 /* Power up the chip */
279 config &= ~SII164_CONFIGURATION_POWER_MASK;
280 config |= SII164_CONFIGURATION_POWER_NORMAL;
281 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
283 /* Power down the chip */
284 config &= ~SII164_CONFIGURATION_POWER_MASK;
285 config |= SII164_CONFIGURATION_POWER_DOWN;
286 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
291 * sii164SelectHotPlugDetectionMode
292 * This function selects the mode of the hot plug detection.
295 void sii164SelectHotPlugDetectionMode(enum sii164_hot_plug_mode hotPlugMode)
297 unsigned char detectReg;
299 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
300 ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
301 switch (hotPlugMode) {
302 case SII164_HOTPLUG_DISABLE:
303 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
305 case SII164_HOTPLUG_USE_MDI:
306 detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
307 detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
308 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
310 case SII164_HOTPLUG_USE_RSEN:
311 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
313 case SII164_HOTPLUG_USE_HTPLG:
314 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
318 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
322 * sii164EnableHotPlugDetection
323 * This function enables the Hot Plug detection.
325 * enableHotPlug - Enable (=1) / disable (=0) Hot Plug detection
327 void sii164EnableHotPlugDetection(unsigned char enableHotPlug)
329 unsigned char detectReg;
331 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
333 /* Depending on each DVI controller, need to enable the hot plug based on each
334 * individual chip design.
336 if (enableHotPlug != 0)
337 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
339 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
344 * Check if the DVI Monitor is connected.
350 unsigned char sii164IsConnected(void)
352 unsigned char hotPlugValue;
354 hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
355 SII164_DETECT_HOT_PLUG_STATUS_MASK;
356 if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
363 * sii164CheckInterrupt
364 * Checks if interrupt has occurred.
368 * 1 - Interrupt occurs
370 unsigned char sii164CheckInterrupt(void)
372 unsigned char detectReg;
374 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) &
375 SII164_DETECT_MONITOR_STATE_MASK;
376 if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
383 * sii164ClearInterrupt
384 * Clear the hot plug interrupt.
386 void sii164ClearInterrupt(void)
388 unsigned char detectReg;
390 /* Clear the MDI interrupt */
391 detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
392 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT,
393 detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);