These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / sm750fb / ddk750_sii164.c
1 #define USE_DVICHIP
2 #ifdef USE_DVICHIP
3
4 #include "ddk750_sii164.h"
5 #include "ddk750_hwi2c.h"
6
7 /* I2C Address of each SII164 chip */
8 #define SII164_I2C_ADDRESS                  0x70
9
10 /* Define this definition to use hardware i2c. */
11 #define USE_HW_I2C
12
13 #ifdef USE_HW_I2C
14     #define i2cWriteReg sm750_hw_i2c_write_reg
15     #define i2cReadReg  sm750_hw_i2c_read_reg
16 #else
17     #define i2cWriteReg swI2CWriteReg
18     #define i2cReadReg  swI2CReadReg
19 #endif
20
21 /* SII164 Vendor and Device ID */
22 #define SII164_VENDOR_ID                    0x0001
23 #define SII164_DEVICE_ID                    0x0006
24
25 #ifdef SII164_FULL_FUNCTIONS
26 /* Name of the DVI Controller chip */
27 static char *gDviCtrlChipName = "Silicon Image SiI 164";
28 #endif
29
30 /*
31  *  sii164GetVendorID
32  *      This function gets the vendor ID of the DVI controller chip.
33  *
34  *  Output:
35  *      Vendor ID
36  */
37 unsigned short sii164GetVendorID(void)
38 {
39         unsigned short vendorID;
40
41         vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
42                     (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
43
44         return vendorID;
45 }
46
47 /*
48  *  sii164GetDeviceID
49  *      This function gets the device ID of the DVI controller chip.
50  *
51  *  Output:
52  *      Device ID
53  */
54 unsigned short sii164GetDeviceID(void)
55 {
56         unsigned short deviceID;
57
58         deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
59                     (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
60
61         return deviceID;
62 }
63
64
65
66 /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */
67
68 /*
69  *  sii164InitChip
70  *      This function initialize and detect the DVI controller chip.
71  *
72  *  Input:
73  *      edgeSelect          - Edge Select:
74  *                              0 = Input data is falling edge latched (falling edge
75  *                                  latched first in dual edge mode)
76  *                              1 = Input data is rising edge latched (rising edge
77  *                                  latched first in dual edge mode)
78  *      busSelect           - Input Bus Select:
79  *                              0 = Input data bus is 12-bits wide
80  *                              1 = Input data bus is 24-bits wide
81  *      dualEdgeClkSelect   - Dual Edge Clock Select
82  *                              0 = Input data is single edge latched
83  *                              1 = Input data is dual edge latched
84  *      hsyncEnable         - Horizontal Sync Enable:
85  *                              0 = HSYNC input is transmitted as fixed LOW
86  *                              1 = HSYNC input is transmitted as is
87  *      vsyncEnable         - Vertical Sync Enable:
88  *                              0 = VSYNC input is transmitted as fixed LOW
89  *                              1 = VSYNC input is transmitted as is
90  *      deskewEnable        - De-skewing Enable:
91  *                              0 = De-skew disabled
92  *                              1 = De-skew enabled
93  *      deskewSetting       - De-skewing Setting (increment of 260psec)
94  *                              0 = 1 step --> minimum setup / maximum hold
95  *                              1 = 2 step
96  *                              2 = 3 step
97  *                              3 = 4 step
98  *                              4 = 5 step
99  *                              5 = 6 step
100  *                              6 = 7 step
101  *                              7 = 8 step --> maximum setup / minimum hold
102  *      continuousSyncEnable- SYNC Continuous:
103  *                              0 = Disable
104  *                              1 = Enable
105  *      pllFilterEnable     - PLL Filter Enable
106  *                              0 = Disable PLL Filter
107  *                              1 = Enable PLL Filter
108  *      pllFilterValue      - PLL Filter characteristics:
109  *                              0~7 (recommended value is 4)
110  *
111  *  Output:
112  *      0   - Success
113  *     -1   - Fail.
114  */
115 long sii164InitChip(
116         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
126 )
127 {
128         unsigned char config;
129
130         /* Initialize the i2c bus */
131 #ifdef USE_HW_I2C
132         /* Use fast mode. */
133         sm750_hw_i2c_init(1);
134 #else
135         sm750_sw_i2c_init(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
136 #endif
137
138         /* Check if SII164 Chip exists */
139         if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
140                 /*
141                  *  Initialize SII164 controller chip.
142                  */
143
144                 /* Select the edge */
145                 if (edgeSelect == 0)
146                         config = SII164_CONFIGURATION_LATCH_FALLING;
147                 else
148                         config = SII164_CONFIGURATION_LATCH_RISING;
149
150                 /* Select bus wide */
151                 if (busSelect == 0)
152                         config |= SII164_CONFIGURATION_BUS_12BITS;
153                 else
154                         config |= SII164_CONFIGURATION_BUS_24BITS;
155
156                 /* Select Dual/Single Edge Clock */
157                 if (dualEdgeClkSelect == 0)
158                         config |= SII164_CONFIGURATION_CLOCK_SINGLE;
159                 else
160                         config |= SII164_CONFIGURATION_CLOCK_DUAL;
161
162                 /* Select HSync Enable */
163                 if (hsyncEnable == 0)
164                         config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
165                 else
166                         config |= SII164_CONFIGURATION_HSYNC_AS_IS;
167
168                 /* Select VSync Enable */
169                 if (vsyncEnable == 0)
170                         config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
171                 else
172                         config |= SII164_CONFIGURATION_VSYNC_AS_IS;
173
174                 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
175
176                 /* De-skew enabled with default 111b value.
177                    This will fix some artifacts problem in some mode on board 2.2.
178                    Somehow this fix does not affect board 2.1.
179                  */
180                 if (deskewEnable == 0)
181                         config = SII164_DESKEW_DISABLE;
182                 else
183                         config = SII164_DESKEW_ENABLE;
184
185                 switch (deskewSetting) {
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. */
239         return (-1);
240 }
241
242
243
244
245
246 /* below sii164 function is not necessary */
247
248 #ifdef SII164_FULL_FUNCTIONS
249
250 /*
251  *  sii164ResetChip
252  *      This function resets the DVI Controller Chip.
253  */
254 void sii164ResetChip(void)
255 {
256         /* Power down */
257         sii164SetPower(0);
258         sii164SetPower(1);
259 }
260
261
262 /*
263  * sii164GetChipString
264  *      This function returns a char string name of the current DVI Controller chip.
265  *      It's convenient for application need to display the chip name.
266  */
267 char *sii164GetChipString(void)
268 {
269         return gDviCtrlChipName;
270 }
271
272
273 /*
274  *  sii164SetPower
275  *      This function sets the power configuration of the DVI Controller Chip.
276  *
277  *  Input:
278  *      powerUp - Flag to set the power down or up
279  */
280 void sii164SetPower(
281         unsigned char powerUp
282 )
283 {
284         unsigned char config;
285
286         config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
287         if (powerUp == 1) {
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);
292         } else {
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         }
298 }
299
300
301 /*
302  *  sii164SelectHotPlugDetectionMode
303  *      This function selects the mode of the hot plug detection.
304  */
305 static void sii164SelectHotPlugDetectionMode(
306         sii164_hot_plug_mode_t hotPlugMode
307 )
308 {
309         unsigned char detectReg;
310
311         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
312         switch (hotPlugMode) {
313         case SII164_HOTPLUG_DISABLE:
314                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
315                 break;
316         case SII164_HOTPLUG_USE_MDI:
317                 detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
318                 detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
319                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
320                 break;
321         case SII164_HOTPLUG_USE_RSEN:
322                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
323                 break;
324         case SII164_HOTPLUG_USE_HTPLG:
325                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
326                 break;
327         }
328
329         i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
330 }
331
332 /*
333  *  sii164EnableHotPlugDetection
334  *      This function enables the Hot Plug detection.
335  *
336  *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
337  */
338 void sii164EnableHotPlugDetection(
339         unsigned char enableHotPlug
340 )
341 {
342         unsigned char detectReg;
343
344         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
345
346         /* Depending on each DVI controller, need to enable the hot plug based on each
347            individual chip design. */
348         if (enableHotPlug != 0)
349                 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
350         else
351                 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
352 }
353
354 /*
355  *  sii164IsConnected
356  *      Check if the DVI Monitor is connected.
357  *
358  *  Output:
359  *      0   - Not Connected
360  *      1   - Connected
361  */
362 unsigned char sii164IsConnected(void)
363 {
364         unsigned char hotPlugValue;
365
366         hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
367         if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
368                 return 1;
369         else
370                 return 0;
371 }
372
373 /*
374  *  sii164CheckInterrupt
375  *      Checks if interrupt has occurred.
376  *
377  *  Output:
378  *      0   - No interrupt
379  *      1   - Interrupt occurs
380  */
381 unsigned char sii164CheckInterrupt(void)
382 {
383         unsigned char detectReg;
384
385         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
386         if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
387                 return 1;
388         else
389                 return 0;
390 }
391
392 /*
393  *  sii164ClearInterrupt
394  *      Clear the hot plug interrupt.
395  */
396 void sii164ClearInterrupt(void)
397 {
398         unsigned char detectReg;
399
400         /* Clear the MDI interrupt */
401         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
402         i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
403 }
404
405 #endif
406
407 #endif
408
409