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 * edge_select - Edge Select:
73 * 0 = Input data is falling edge latched (falling
74 * edge latched first in dual edge mode)
75 * 1 = Input data is rising edge latched (rising
76 * edge latched first in dual edge mode)
77 * bus_select - Input Bus Select:
78 * 0 = Input data bus is 12-bits wide
79 * 1 = Input data bus is 24-bits wide
80 * dual_edge_clk_select - Dual Edge Clock Select
81 * 0 = Input data is single edge latched
82 * 1 = Input data is dual edge latched
83 * hsync_enable - Horizontal Sync Enable:
84 * 0 = HSYNC input is transmitted as fixed LOW
85 * 1 = HSYNC input is transmitted as is
86 * vsync_enable - Vertical Sync Enable:
87 * 0 = VSYNC input is transmitted as fixed LOW
88 * 1 = VSYNC input is transmitted as is
89 * deskew_enable - De-skewing Enable:
90 * 0 = De-skew disabled
92 * deskew_setting - De-skewing Setting (increment of 260psec)
93 * 0 = 1 step --> minimum setup / maximum hold
100 * 7 = 8 step --> maximum setup / minimum hold
101 * continuous_sync_enable- SYNC Continuous:
104 * pll_filter_enable - PLL Filter Enable
105 * 0 = Disable PLL Filter
106 * 1 = Enable PLL Filter
107 * pll_filter_value - PLL Filter characteristics:
108 * 0~7 (recommended value is 4)
114 long sii164InitChip(unsigned char edge_select,
115 unsigned char bus_select,
116 unsigned char dual_edge_clk_select,
117 unsigned char hsync_enable,
118 unsigned char vsync_enable,
119 unsigned char deskew_enable,
120 unsigned char deskew_setting,
121 unsigned char continuous_sync_enable,
122 unsigned char pll_filter_enable,
123 unsigned char pll_filter_value)
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 */
142 if (edge_select == 0)
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 (dual_edge_clk_select == 0)
155 config |= SII164_CONFIGURATION_CLOCK_SINGLE;
157 config |= SII164_CONFIGURATION_CLOCK_DUAL;
159 /* Select HSync Enable */
160 if (hsync_enable == 0)
161 config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
163 config |= SII164_CONFIGURATION_HSYNC_AS_IS;
165 /* Select VSync Enable */
166 if (vsync_enable == 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 (deskew_enable == 0)
179 config = SII164_DESKEW_DISABLE;
181 config = SII164_DESKEW_ENABLE;
183 switch (deskew_setting) {
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 (continuous_sync_enable == 0)
213 config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
215 config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
217 /* Enable/Disable PLL Filter */
218 if (pll_filter_enable == 0)
219 config |= SII164_PLL_FILTER_DISABLE;
221 config |= SII164_PLL_FILTER_ENABLE;
223 /* Set the PLL Filter value */
224 config |= ((pll_filter_value & 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);