]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
81dee67e SM |
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 | |
6bdbe62b | 15 | #define i2cWriteReg sm750_hw_i2c_write_reg |
5ccf7340 | 16 | #define i2cReadReg sm750_hw_i2c_read_reg |
81dee67e | 17 | #else |
9a357143 MR |
18 | #define i2cWriteReg sm750_sw_i2c_write_reg |
19 | #define i2cReadReg sm750_sw_i2c_read_reg | |
81dee67e SM |
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 */ | |
28 | static 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 | */ | |
6fa7db83 | 38 | unsigned short sii164GetVendorID(void) |
81dee67e | 39 | { |
78376535 | 40 | unsigned short vendorID; |
81dee67e | 41 | |
8193e6ad JS |
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); | |
81dee67e | 46 | |
78376535 | 47 | return vendorID; |
81dee67e SM |
48 | } |
49 | ||
50 | /* | |
51 | * sii164GetDeviceID | |
52 | * This function gets the device ID of the DVI controller chip. | |
53 | * | |
54 | * Output: | |
55 | * Device ID | |
56 | */ | |
6fa7db83 | 57 | unsigned short sii164GetDeviceID(void) |
81dee67e | 58 | { |
78376535 | 59 | unsigned short deviceID; |
81dee67e | 60 | |
8193e6ad JS |
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); | |
81dee67e | 65 | |
78376535 | 66 | return deviceID; |
81dee67e SM |
67 | } |
68 | ||
8193e6ad JS |
69 | /* |
70 | * DVI.C will handle all SiI164 chip stuffs and try its best to make code | |
71 | * minimal and useful | |
72 | */ | |
81dee67e SM |
73 | |
74 | /* | |
75 | * sii164InitChip | |
76 | * This function initialize and detect the DVI controller chip. | |
77 | * | |
78 | * Input: | |
de5e4aea ND |
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) | |
81dee67e SM |
116 | * |
117 | * Output: | |
118 | * 0 - Success | |
119 | * -1 - Fail. | |
120 | */ | |
de5e4aea ND |
121 | long 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) | |
81dee67e | 131 | { |
81dee67e | 132 | unsigned char config; |
81dee67e | 133 | |
78376535 | 134 | /* Initialize the i2c bus */ |
81dee67e | 135 | #ifdef USE_HW_I2C |
78376535 | 136 | /* Use fast mode. */ |
19f70eae | 137 | sm750_hw_i2c_init(1); |
81dee67e | 138 | #else |
f2ea7733 | 139 | sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA); |
81dee67e SM |
140 | #endif |
141 | ||
78376535 | 142 | /* Check if SII164 Chip exists */ |
8193e6ad | 143 | if ((sii164GetVendorID() == SII164_VENDOR_ID) && |
836c336e | 144 | (sii164GetDeviceID() == SII164_DEVICE_ID)) { |
78376535 JL |
145 | /* |
146 | * Initialize SII164 controller chip. | |
147 | */ | |
148 | ||
149 | /* Select the edge */ | |
de5e4aea | 150 | if (edge_select == 0) |
78376535 JL |
151 | config = SII164_CONFIGURATION_LATCH_FALLING; |
152 | else | |
153 | config = SII164_CONFIGURATION_LATCH_RISING; | |
154 | ||
155 | /* Select bus wide */ | |
de5e4aea | 156 | if (bus_select == 0) |
78376535 JL |
157 | config |= SII164_CONFIGURATION_BUS_12BITS; |
158 | else | |
159 | config |= SII164_CONFIGURATION_BUS_24BITS; | |
160 | ||
161 | /* Select Dual/Single Edge Clock */ | |
de5e4aea | 162 | if (dual_edge_clk_select == 0) |
78376535 JL |
163 | config |= SII164_CONFIGURATION_CLOCK_SINGLE; |
164 | else | |
165 | config |= SII164_CONFIGURATION_CLOCK_DUAL; | |
166 | ||
167 | /* Select HSync Enable */ | |
de5e4aea | 168 | if (hsync_enable == 0) |
78376535 JL |
169 | config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW; |
170 | else | |
171 | config |= SII164_CONFIGURATION_HSYNC_AS_IS; | |
172 | ||
173 | /* Select VSync Enable */ | |
de5e4aea | 174 | if (vsync_enable == 0) |
78376535 JL |
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 | ||
f5016082 ES |
181 | /* |
182 | * De-skew enabled with default 111b value. | |
35e4d8ca EF |
183 | * This fixes some artifacts problem in some mode on board 2.2. |
184 | * Somehow this fix does not affect board 2.1. | |
78376535 | 185 | */ |
de5e4aea | 186 | if (deskew_enable == 0) |
78376535 JL |
187 | config = SII164_DESKEW_DISABLE; |
188 | else | |
189 | config = SII164_DESKEW_ENABLE; | |
190 | ||
de5e4aea | 191 | switch (deskew_setting) { |
78376535 JL |
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. */ | |
de5e4aea | 220 | if (continuous_sync_enable == 0) |
78376535 JL |
221 | config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE; |
222 | else | |
223 | config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE; | |
224 | ||
225 | /* Enable/Disable PLL Filter */ | |
de5e4aea | 226 | if (pll_filter_enable == 0) |
78376535 JL |
227 | config |= SII164_PLL_FILTER_DISABLE; |
228 | else | |
229 | config |= SII164_PLL_FILTER_ENABLE; | |
230 | ||
231 | /* Set the PLL Filter value */ | |
de5e4aea | 232 | config |= ((pll_filter_value & 0x07) << 1); |
78376535 JL |
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. */ | |
732053a0 | 245 | return -1; |
81dee67e SM |
246 | } |
247 | ||
69e98df7 | 248 | /* below sii164 function is not necessary */ |
81dee67e SM |
249 | |
250 | #ifdef SII164_FULL_FUNCTIONS | |
251 | ||
252 | /* | |
253 | * sii164ResetChip | |
254 | * This function resets the DVI Controller Chip. | |
255 | */ | |
6fa7db83 | 256 | void sii164ResetChip(void) |
81dee67e | 257 | { |
78376535 JL |
258 | /* Power down */ |
259 | sii164SetPower(0); | |
260 | sii164SetPower(1); | |
81dee67e SM |
261 | } |
262 | ||
81dee67e SM |
263 | /* |
264 | * sii164GetChipString | |
8193e6ad JS |
265 | * This function returns a char string name of the current DVI Controller |
266 | * chip. | |
267 | * | |
81dee67e SM |
268 | * It's convenient for application need to display the chip name. |
269 | */ | |
6fa7db83 | 270 | char *sii164GetChipString(void) |
81dee67e | 271 | { |
78376535 | 272 | return gDviCtrlChipName; |
81dee67e SM |
273 | } |
274 | ||
81dee67e SM |
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 | */ | |
c9750456 | 282 | void sii164SetPower(unsigned char powerUp) |
81dee67e | 283 | { |
78376535 JL |
284 | unsigned char config; |
285 | ||
286 | config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION); | |
259fef35 | 287 | if (powerUp == 1) { |
78376535 JL |
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); | |
259fef35 | 292 | } else { |
78376535 JL |
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 | } | |
81dee67e SM |
298 | } |
299 | ||
81dee67e SM |
300 | /* |
301 | * sii164SelectHotPlugDetectionMode | |
302 | * This function selects the mode of the hot plug detection. | |
303 | */ | |
60d379e1 KR |
304 | static |
305 | void sii164SelectHotPlugDetectionMode(enum sii164_hot_plug_mode hotPlugMode) | |
81dee67e | 306 | { |
78376535 JL |
307 | unsigned char detectReg; |
308 | ||
c9750456 MD |
309 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & |
310 | ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG; | |
259fef35 | 311 | switch (hotPlugMode) { |
78376535 JL |
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); | |
81dee67e SM |
329 | } |
330 | ||
331 | /* | |
332 | * sii164EnableHotPlugDetection | |
333 | * This function enables the Hot Plug detection. | |
334 | * | |
335 | * enableHotPlug - Enable (=1) / disable (=0) Hot Plug detection | |
336 | */ | |
c9750456 | 337 | void sii164EnableHotPlugDetection(unsigned char enableHotPlug) |
81dee67e | 338 | { |
78376535 | 339 | unsigned char detectReg; |
40403c1b | 340 | |
78376535 JL |
341 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); |
342 | ||
8193e6ad JS |
343 | /* Depending on each DVI controller, need to enable the hot plug based |
344 | * on each individual chip design. | |
35e4d8ca | 345 | */ |
78376535 JL |
346 | if (enableHotPlug != 0) |
347 | sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI); | |
348 | else | |
349 | sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE); | |
81dee67e SM |
350 | } |
351 | ||
352 | /* | |
353 | * sii164IsConnected | |
354 | * Check if the DVI Monitor is connected. | |
355 | * | |
356 | * Output: | |
357 | * 0 - Not Connected | |
358 | * 1 - Connected | |
359 | */ | |
6fa7db83 | 360 | unsigned char sii164IsConnected(void) |
81dee67e | 361 | { |
78376535 | 362 | unsigned char hotPlugValue; |
81dee67e | 363 | |
c9750456 MD |
364 | hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & |
365 | SII164_DETECT_HOT_PLUG_STATUS_MASK; | |
78376535 JL |
366 | if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON) |
367 | return 1; | |
368 | else | |
369 | return 0; | |
81dee67e SM |
370 | } |
371 | ||
372 | /* | |
373 | * sii164CheckInterrupt | |
69e98df7 | 374 | * Checks if interrupt has occurred. |
81dee67e SM |
375 | * |
376 | * Output: | |
377 | * 0 - No interrupt | |
378 | * 1 - Interrupt occurs | |
379 | */ | |
6fa7db83 | 380 | unsigned char sii164CheckInterrupt(void) |
81dee67e | 381 | { |
78376535 | 382 | unsigned char detectReg; |
81dee67e | 383 | |
c9750456 MD |
384 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & |
385 | SII164_DETECT_MONITOR_STATE_MASK; | |
78376535 JL |
386 | if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE) |
387 | return 1; | |
388 | else | |
389 | return 0; | |
81dee67e SM |
390 | } |
391 | ||
392 | /* | |
393 | * sii164ClearInterrupt | |
394 | * Clear the hot plug interrupt. | |
395 | */ | |
6fa7db83 | 396 | void sii164ClearInterrupt(void) |
81dee67e | 397 | { |
78376535 | 398 | unsigned char detectReg; |
81dee67e | 399 | |
78376535 JL |
400 | /* Clear the MDI interrupt */ |
401 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); | |
c9750456 MD |
402 | i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, |
403 | detectReg | SII164_DETECT_MONITOR_STATE_CLEAR); | |
81dee67e SM |
404 | } |
405 | ||
406 | #endif | |
407 | ||
408 | #endif |