]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/staging/sm750fb/ddk750_sii164.c
drm/amdgpu: fix gfx hang during suspend with video playback (v2)
[mirror_ubuntu-jammy-kernel.git] / drivers / staging / sm750fb / ddk750_sii164.c
CommitLineData
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 */
28static 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 38unsigned 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 57unsigned 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
121long 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 256void 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 270char *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 282void 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
304static
305void 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 337void 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 360unsigned 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 380unsigned 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 396void 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