Add the rt linux 4.1.3-rt3 as base
[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 hwI2CWriteReg
15     #define i2cReadReg  hwI2CReadReg
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 ucRegIndex, ucRegValue;
129     //unsigned char ucDeviceAddress,
130         unsigned char config;
131     //unsigned long delayCount;
132
133     /* Initialize the i2c bus */
134 #ifdef USE_HW_I2C
135     /* Use fast mode. */
136     hwI2CInit(1);
137 #else
138     swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
139 #endif
140
141     /* Check if SII164 Chip exists */
142     if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID))
143     {
144
145 #ifdef DDKDEBUG
146         //sii164PrintRegisterValues();
147 #endif
148         /*
149          *  Initialize SII164 controller chip.
150          */
151
152         /* Select the edge */
153         if (edgeSelect == 0)
154             config = SII164_CONFIGURATION_LATCH_FALLING;
155         else
156             config = SII164_CONFIGURATION_LATCH_RISING;
157
158         /* Select bus wide */
159         if (busSelect == 0)
160             config |= SII164_CONFIGURATION_BUS_12BITS;
161         else
162             config |= SII164_CONFIGURATION_BUS_24BITS;
163
164         /* Select Dual/Single Edge Clock */
165         if (dualEdgeClkSelect == 0)
166             config |= SII164_CONFIGURATION_CLOCK_SINGLE;
167         else
168             config |= SII164_CONFIGURATION_CLOCK_DUAL;
169
170         /* Select HSync Enable */
171         if (hsyncEnable == 0)
172             config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
173         else
174             config |= SII164_CONFIGURATION_HSYNC_AS_IS;
175
176         /* Select VSync Enable */
177         if (vsyncEnable == 0)
178             config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
179         else
180             config |= SII164_CONFIGURATION_VSYNC_AS_IS;
181
182         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
183
184         /* De-skew enabled with default 111b value.
185            This will fix some artifacts problem in some mode on board 2.2.
186            Somehow this fix does not affect board 2.1.
187          */
188         if (deskewEnable == 0)
189             config = SII164_DESKEW_DISABLE;
190         else
191             config = SII164_DESKEW_ENABLE;
192
193         switch (deskewSetting)
194         {
195             case 0:
196                 config |= SII164_DESKEW_1_STEP;
197                 break;
198             case 1:
199                 config |= SII164_DESKEW_2_STEP;
200                 break;
201             case 2:
202                 config |= SII164_DESKEW_3_STEP;
203                 break;
204             case 3:
205                 config |= SII164_DESKEW_4_STEP;
206                 break;
207             case 4:
208                 config |= SII164_DESKEW_5_STEP;
209                 break;
210             case 5:
211                 config |= SII164_DESKEW_6_STEP;
212                 break;
213             case 6:
214                 config |= SII164_DESKEW_7_STEP;
215                 break;
216             case 7:
217                 config |= SII164_DESKEW_8_STEP;
218                 break;
219         }
220         i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
221
222         /* Enable/Disable Continuous Sync. */
223         if (continuousSyncEnable == 0)
224             config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
225         else
226             config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
227
228         /* Enable/Disable PLL Filter */
229         if (pllFilterEnable == 0)
230             config |= SII164_PLL_FILTER_DISABLE;
231         else
232             config |= SII164_PLL_FILTER_ENABLE;
233
234         /* Set the PLL Filter value */
235         config |= ((pllFilterValue & 0x07) << 1);
236
237         i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
238
239         /* Recover from Power Down and enable output. */
240         config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
241         config |= SII164_CONFIGURATION_POWER_NORMAL;
242         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
243
244 #ifdef DDKDEBUG
245         //sii164PrintRegisterValues();
246 #endif
247
248         return 0;
249     }
250
251     /* Return -1 if initialization fails. */
252     return (-1);
253 }
254
255
256
257
258
259 /* below sii164 function is not neccessary */
260
261 #ifdef SII164_FULL_FUNCTIONS
262
263 /*
264  *  sii164ResetChip
265  *      This function resets the DVI Controller Chip.
266  */
267 void sii164ResetChip(void)
268 {
269     /* Power down */
270     sii164SetPower(0);
271     sii164SetPower(1);
272 }
273
274
275 /*
276  * sii164GetChipString
277  *      This function returns a char string name of the current DVI Controller chip.
278  *      It's convenient for application need to display the chip name.
279  */
280 char *sii164GetChipString(void)
281 {
282     return gDviCtrlChipName;
283 }
284
285
286 /*
287  *  sii164SetPower
288  *      This function sets the power configuration of the DVI Controller Chip.
289  *
290  *  Input:
291  *      powerUp - Flag to set the power down or up
292  */
293 void sii164SetPower(
294     unsigned char powerUp
295 )
296 {
297     unsigned char config;
298
299     config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
300     if (powerUp == 1)
301     {
302         /* Power up the chip */
303         config &= ~SII164_CONFIGURATION_POWER_MASK;
304         config |= SII164_CONFIGURATION_POWER_NORMAL;
305         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
306     }
307     else
308     {
309         /* Power down the chip */
310         config &= ~SII164_CONFIGURATION_POWER_MASK;
311         config |= SII164_CONFIGURATION_POWER_DOWN;
312         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
313     }
314 }
315
316
317 /*
318  *  sii164SelectHotPlugDetectionMode
319  *      This function selects the mode of the hot plug detection.
320  */
321 static void sii164SelectHotPlugDetectionMode(
322     sii164_hot_plug_mode_t hotPlugMode
323 )
324 {
325     unsigned char detectReg;
326
327     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
328     switch (hotPlugMode)
329     {
330         case SII164_HOTPLUG_DISABLE:
331             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
332             break;
333         case SII164_HOTPLUG_USE_MDI:
334             detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
335             detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
336             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
337             break;
338         case SII164_HOTPLUG_USE_RSEN:
339             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
340             break;
341         case SII164_HOTPLUG_USE_HTPLG:
342             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
343             break;
344     }
345
346     i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
347 }
348
349 /*
350  *  sii164EnableHotPlugDetection
351  *      This function enables the Hot Plug detection.
352  *
353  *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
354  */
355 void sii164EnableHotPlugDetection(
356     unsigned char enableHotPlug
357 )
358 {
359     unsigned char detectReg;
360     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
361
362     /* Depending on each DVI controller, need to enable the hot plug based on each
363        individual chip design. */
364     if (enableHotPlug != 0)
365         sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
366     else
367         sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
368 }
369
370 /*
371  *  sii164IsConnected
372  *      Check if the DVI Monitor is connected.
373  *
374  *  Output:
375  *      0   - Not Connected
376  *      1   - Connected
377  */
378 unsigned char sii164IsConnected(void)
379 {
380     unsigned char hotPlugValue;
381
382     hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
383     if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
384         return 1;
385     else
386         return 0;
387 }
388
389 /*
390  *  sii164CheckInterrupt
391  *      Checks if interrupt has occured.
392  *
393  *  Output:
394  *      0   - No interrupt
395  *      1   - Interrupt occurs
396  */
397 unsigned char sii164CheckInterrupt(void)
398 {
399     unsigned char detectReg;
400
401     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
402     if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
403         return 1;
404     else
405         return 0;
406 }
407
408 /*
409  *  sii164ClearInterrupt
410  *      Clear the hot plug interrupt.
411  */
412 void sii164ClearInterrupt(void)
413 {
414     unsigned char detectReg;
415
416     /* Clear the MDI interrupt */
417     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
418     i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
419 }
420
421 #endif
422
423 #endif
424
425