]>
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 | |
78376535 JL |
42 | vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) | |
43 | (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW); | |
81dee67e | 44 | |
78376535 | 45 | return vendorID; |
81dee67e SM |
46 | } |
47 | ||
48 | /* | |
49 | * sii164GetDeviceID | |
50 | * This function gets the device ID of the DVI controller chip. | |
51 | * | |
52 | * Output: | |
53 | * Device ID | |
54 | */ | |
6fa7db83 | 55 | unsigned short sii164GetDeviceID(void) |
81dee67e | 56 | { |
78376535 | 57 | unsigned short deviceID; |
81dee67e | 58 | |
78376535 JL |
59 | deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) | |
60 | (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW); | |
81dee67e | 61 | |
78376535 | 62 | return deviceID; |
81dee67e SM |
63 | } |
64 | ||
65 | ||
66 | ||
67 | /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */ | |
68 | ||
69 | /* | |
70 | * sii164InitChip | |
71 | * This function initialize and detect the DVI controller chip. | |
72 | * | |
73 | * Input: | |
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 | |
93 | * 1 = De-skew enabled | |
94 | * deskewSetting - De-skewing Setting (increment of 260psec) | |
95 | * 0 = 1 step --> minimum setup / maximum hold | |
96 | * 1 = 2 step | |
97 | * 2 = 3 step | |
98 | * 3 = 4 step | |
99 | * 4 = 5 step | |
100 | * 5 = 6 step | |
101 | * 6 = 7 step | |
102 | * 7 = 8 step --> maximum setup / minimum hold | |
103 | * continuousSyncEnable- SYNC Continuous: | |
104 | * 0 = Disable | |
105 | * 1 = Enable | |
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) | |
111 | * | |
112 | * Output: | |
113 | * 0 - Success | |
114 | * -1 - Fail. | |
115 | */ | |
c9750456 MD |
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) | |
81dee67e | 126 | { |
81dee67e | 127 | unsigned char config; |
81dee67e | 128 | |
78376535 | 129 | /* Initialize the i2c bus */ |
81dee67e | 130 | #ifdef USE_HW_I2C |
78376535 | 131 | /* Use fast mode. */ |
19f70eae | 132 | sm750_hw_i2c_init(1); |
81dee67e | 133 | #else |
f2ea7733 | 134 | sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA); |
81dee67e SM |
135 | #endif |
136 | ||
78376535 | 137 | /* Check if SII164 Chip exists */ |
259fef35 | 138 | if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) { |
78376535 JL |
139 | /* |
140 | * Initialize SII164 controller chip. | |
141 | */ | |
142 | ||
143 | /* Select the edge */ | |
144 | if (edgeSelect == 0) | |
145 | config = SII164_CONFIGURATION_LATCH_FALLING; | |
146 | else | |
147 | config = SII164_CONFIGURATION_LATCH_RISING; | |
148 | ||
149 | /* Select bus wide */ | |
150 | if (busSelect == 0) | |
151 | config |= SII164_CONFIGURATION_BUS_12BITS; | |
152 | else | |
153 | config |= SII164_CONFIGURATION_BUS_24BITS; | |
154 | ||
155 | /* Select Dual/Single Edge Clock */ | |
156 | if (dualEdgeClkSelect == 0) | |
157 | config |= SII164_CONFIGURATION_CLOCK_SINGLE; | |
158 | else | |
159 | config |= SII164_CONFIGURATION_CLOCK_DUAL; | |
160 | ||
161 | /* Select HSync Enable */ | |
162 | if (hsyncEnable == 0) | |
163 | config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW; | |
164 | else | |
165 | config |= SII164_CONFIGURATION_HSYNC_AS_IS; | |
166 | ||
167 | /* Select VSync Enable */ | |
168 | if (vsyncEnable == 0) | |
169 | config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW; | |
170 | else | |
171 | config |= SII164_CONFIGURATION_VSYNC_AS_IS; | |
172 | ||
173 | i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); | |
174 | ||
f5016082 ES |
175 | /* |
176 | * De-skew enabled with default 111b value. | |
35e4d8ca EF |
177 | * This fixes some artifacts problem in some mode on board 2.2. |
178 | * Somehow this fix does not affect board 2.1. | |
78376535 JL |
179 | */ |
180 | if (deskewEnable == 0) | |
181 | config = SII164_DESKEW_DISABLE; | |
182 | else | |
183 | config = SII164_DESKEW_ENABLE; | |
184 | ||
259fef35 | 185 | switch (deskewSetting) { |
78376535 JL |
186 | case 0: |
187 | config |= SII164_DESKEW_1_STEP; | |
188 | break; | |
189 | case 1: | |
190 | config |= SII164_DESKEW_2_STEP; | |
191 | break; | |
192 | case 2: | |
193 | config |= SII164_DESKEW_3_STEP; | |
194 | break; | |
195 | case 3: | |
196 | config |= SII164_DESKEW_4_STEP; | |
197 | break; | |
198 | case 4: | |
199 | config |= SII164_DESKEW_5_STEP; | |
200 | break; | |
201 | case 5: | |
202 | config |= SII164_DESKEW_6_STEP; | |
203 | break; | |
204 | case 6: | |
205 | config |= SII164_DESKEW_7_STEP; | |
206 | break; | |
207 | case 7: | |
208 | config |= SII164_DESKEW_8_STEP; | |
209 | break; | |
210 | } | |
211 | i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config); | |
212 | ||
213 | /* Enable/Disable Continuous Sync. */ | |
214 | if (continuousSyncEnable == 0) | |
215 | config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE; | |
216 | else | |
217 | config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE; | |
218 | ||
219 | /* Enable/Disable PLL Filter */ | |
220 | if (pllFilterEnable == 0) | |
221 | config |= SII164_PLL_FILTER_DISABLE; | |
222 | else | |
223 | config |= SII164_PLL_FILTER_ENABLE; | |
224 | ||
225 | /* Set the PLL Filter value */ | |
226 | config |= ((pllFilterValue & 0x07) << 1); | |
227 | ||
228 | i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config); | |
229 | ||
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); | |
234 | ||
235 | return 0; | |
236 | } | |
237 | ||
238 | /* Return -1 if initialization fails. */ | |
732053a0 | 239 | return -1; |
81dee67e SM |
240 | } |
241 | ||
242 | ||
243 | ||
244 | ||
245 | ||
69e98df7 | 246 | /* below sii164 function is not necessary */ |
81dee67e SM |
247 | |
248 | #ifdef SII164_FULL_FUNCTIONS | |
249 | ||
250 | /* | |
251 | * sii164ResetChip | |
252 | * This function resets the DVI Controller Chip. | |
253 | */ | |
6fa7db83 | 254 | void sii164ResetChip(void) |
81dee67e | 255 | { |
78376535 JL |
256 | /* Power down */ |
257 | sii164SetPower(0); | |
258 | sii164SetPower(1); | |
81dee67e SM |
259 | } |
260 | ||
81dee67e SM |
261 | /* |
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. | |
265 | */ | |
6fa7db83 | 266 | char *sii164GetChipString(void) |
81dee67e | 267 | { |
78376535 | 268 | return gDviCtrlChipName; |
81dee67e SM |
269 | } |
270 | ||
81dee67e SM |
271 | /* |
272 | * sii164SetPower | |
273 | * This function sets the power configuration of the DVI Controller Chip. | |
274 | * | |
275 | * Input: | |
276 | * powerUp - Flag to set the power down or up | |
277 | */ | |
c9750456 | 278 | void sii164SetPower(unsigned char powerUp) |
81dee67e | 279 | { |
78376535 JL |
280 | unsigned char config; |
281 | ||
282 | config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION); | |
259fef35 | 283 | if (powerUp == 1) { |
78376535 JL |
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); | |
259fef35 | 288 | } else { |
78376535 JL |
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); | |
293 | } | |
81dee67e SM |
294 | } |
295 | ||
81dee67e SM |
296 | /* |
297 | * sii164SelectHotPlugDetectionMode | |
298 | * This function selects the mode of the hot plug detection. | |
299 | */ | |
c9750456 | 300 | static void sii164SelectHotPlugDetectionMode(sii164_hot_plug_mode_t hotPlugMode) |
81dee67e | 301 | { |
78376535 JL |
302 | unsigned char detectReg; |
303 | ||
c9750456 MD |
304 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & |
305 | ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG; | |
259fef35 | 306 | switch (hotPlugMode) { |
78376535 JL |
307 | case SII164_HOTPLUG_DISABLE: |
308 | detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH; | |
309 | break; | |
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; | |
314 | break; | |
315 | case SII164_HOTPLUG_USE_RSEN: | |
316 | detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN; | |
317 | break; | |
318 | case SII164_HOTPLUG_USE_HTPLG: | |
319 | detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG; | |
320 | break; | |
321 | } | |
322 | ||
323 | i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg); | |
81dee67e SM |
324 | } |
325 | ||
326 | /* | |
327 | * sii164EnableHotPlugDetection | |
328 | * This function enables the Hot Plug detection. | |
329 | * | |
330 | * enableHotPlug - Enable (=1) / disable (=0) Hot Plug detection | |
331 | */ | |
c9750456 | 332 | void sii164EnableHotPlugDetection(unsigned char enableHotPlug) |
81dee67e | 333 | { |
78376535 | 334 | unsigned char detectReg; |
40403c1b | 335 | |
78376535 JL |
336 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); |
337 | ||
338 | /* Depending on each DVI controller, need to enable the hot plug based on each | |
35e4d8ca EF |
339 | * individual chip design. |
340 | */ | |
78376535 JL |
341 | if (enableHotPlug != 0) |
342 | sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI); | |
343 | else | |
344 | sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE); | |
81dee67e SM |
345 | } |
346 | ||
347 | /* | |
348 | * sii164IsConnected | |
349 | * Check if the DVI Monitor is connected. | |
350 | * | |
351 | * Output: | |
352 | * 0 - Not Connected | |
353 | * 1 - Connected | |
354 | */ | |
6fa7db83 | 355 | unsigned char sii164IsConnected(void) |
81dee67e | 356 | { |
78376535 | 357 | unsigned char hotPlugValue; |
81dee67e | 358 | |
c9750456 MD |
359 | hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & |
360 | SII164_DETECT_HOT_PLUG_STATUS_MASK; | |
78376535 JL |
361 | if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON) |
362 | return 1; | |
363 | else | |
364 | return 0; | |
81dee67e SM |
365 | } |
366 | ||
367 | /* | |
368 | * sii164CheckInterrupt | |
69e98df7 | 369 | * Checks if interrupt has occurred. |
81dee67e SM |
370 | * |
371 | * Output: | |
372 | * 0 - No interrupt | |
373 | * 1 - Interrupt occurs | |
374 | */ | |
6fa7db83 | 375 | unsigned char sii164CheckInterrupt(void) |
81dee67e | 376 | { |
78376535 | 377 | unsigned char detectReg; |
81dee67e | 378 | |
c9750456 MD |
379 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & |
380 | SII164_DETECT_MONITOR_STATE_MASK; | |
78376535 JL |
381 | if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE) |
382 | return 1; | |
383 | else | |
384 | return 0; | |
81dee67e SM |
385 | } |
386 | ||
387 | /* | |
388 | * sii164ClearInterrupt | |
389 | * Clear the hot plug interrupt. | |
390 | */ | |
6fa7db83 | 391 | void sii164ClearInterrupt(void) |
81dee67e | 392 | { |
78376535 | 393 | unsigned char detectReg; |
81dee67e | 394 | |
78376535 JL |
395 | /* Clear the MDI interrupt */ |
396 | detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); | |
c9750456 MD |
397 | i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, |
398 | detectReg | SII164_DETECT_MONITOR_STATE_CLEAR); | |
81dee67e SM |
399 | } |
400 | ||
401 | #endif | |
402 | ||
403 | #endif | |
404 | ||
405 |