ACPI / DPTF: constify attribute_group structures
[sfrench/cifs-2.6.git] / 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 sm750_sw_i2c_write_reg
18     #define i2cReadReg  sm750_sw_i2c_read_reg
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                 /*
177                  * De-skew enabled with default 111b value.
178                  * This fixes some artifacts problem in some mode on board 2.2.
179                  * Somehow this fix does not affect board 2.1.
180                  */
181                 if (deskewEnable == 0)
182                         config = SII164_DESKEW_DISABLE;
183                 else
184                         config = SII164_DESKEW_ENABLE;
185
186                 switch (deskewSetting) {
187                 case 0:
188                         config |= SII164_DESKEW_1_STEP;
189                         break;
190                 case 1:
191                         config |= SII164_DESKEW_2_STEP;
192                         break;
193                 case 2:
194                         config |= SII164_DESKEW_3_STEP;
195                         break;
196                 case 3:
197                         config |= SII164_DESKEW_4_STEP;
198                         break;
199                 case 4:
200                         config |= SII164_DESKEW_5_STEP;
201                         break;
202                 case 5:
203                         config |= SII164_DESKEW_6_STEP;
204                         break;
205                 case 6:
206                         config |= SII164_DESKEW_7_STEP;
207                         break;
208                 case 7:
209                         config |= SII164_DESKEW_8_STEP;
210                         break;
211                 }
212                 i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
213
214                 /* Enable/Disable Continuous Sync. */
215                 if (continuousSyncEnable == 0)
216                         config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
217                 else
218                         config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
219
220                 /* Enable/Disable PLL Filter */
221                 if (pllFilterEnable == 0)
222                         config |= SII164_PLL_FILTER_DISABLE;
223                 else
224                         config |= SII164_PLL_FILTER_ENABLE;
225
226                 /* Set the PLL Filter value */
227                 config |= ((pllFilterValue & 0x07) << 1);
228
229                 i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
230
231                 /* Recover from Power Down and enable output. */
232                 config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
233                 config |= SII164_CONFIGURATION_POWER_NORMAL;
234                 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
235
236                 return 0;
237         }
238
239         /* Return -1 if initialization fails. */
240         return -1;
241 }
242
243
244
245
246
247 /* below sii164 function is not necessary */
248
249 #ifdef SII164_FULL_FUNCTIONS
250
251 /*
252  *  sii164ResetChip
253  *      This function resets the DVI Controller Chip.
254  */
255 void sii164ResetChip(void)
256 {
257         /* Power down */
258         sii164SetPower(0);
259         sii164SetPower(1);
260 }
261
262
263 /*
264  * sii164GetChipString
265  *      This function returns a char string name of the current DVI Controller chip.
266  *      It's convenient for application need to display the chip name.
267  */
268 char *sii164GetChipString(void)
269 {
270         return gDviCtrlChipName;
271 }
272
273
274 /*
275  *  sii164SetPower
276  *      This function sets the power configuration of the DVI Controller Chip.
277  *
278  *  Input:
279  *      powerUp - Flag to set the power down or up
280  */
281 void sii164SetPower(
282         unsigned char powerUp
283 )
284 {
285         unsigned char config;
286
287         config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
288         if (powerUp == 1) {
289                 /* Power up the chip */
290                 config &= ~SII164_CONFIGURATION_POWER_MASK;
291                 config |= SII164_CONFIGURATION_POWER_NORMAL;
292                 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
293         } else {
294                 /* Power down the chip */
295                 config &= ~SII164_CONFIGURATION_POWER_MASK;
296                 config |= SII164_CONFIGURATION_POWER_DOWN;
297                 i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
298         }
299 }
300
301
302 /*
303  *  sii164SelectHotPlugDetectionMode
304  *      This function selects the mode of the hot plug detection.
305  */
306 static void sii164SelectHotPlugDetectionMode(
307         sii164_hot_plug_mode_t hotPlugMode
308 )
309 {
310         unsigned char detectReg;
311
312         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
313         switch (hotPlugMode) {
314         case SII164_HOTPLUG_DISABLE:
315                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
316                 break;
317         case SII164_HOTPLUG_USE_MDI:
318                 detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
319                 detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
320                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
321                 break;
322         case SII164_HOTPLUG_USE_RSEN:
323                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
324                 break;
325         case SII164_HOTPLUG_USE_HTPLG:
326                 detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
327                 break;
328         }
329
330         i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
331 }
332
333 /*
334  *  sii164EnableHotPlugDetection
335  *      This function enables the Hot Plug detection.
336  *
337  *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection
338  */
339 void sii164EnableHotPlugDetection(
340         unsigned char enableHotPlug
341 )
342 {
343         unsigned char detectReg;
344
345         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
346
347         /* Depending on each DVI controller, need to enable the hot plug based on each
348          * individual chip design.
349          */
350         if (enableHotPlug != 0)
351                 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
352         else
353                 sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
354 }
355
356 /*
357  *  sii164IsConnected
358  *      Check if the DVI Monitor is connected.
359  *
360  *  Output:
361  *      0   - Not Connected
362  *      1   - Connected
363  */
364 unsigned char sii164IsConnected(void)
365 {
366         unsigned char hotPlugValue;
367
368         hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
369         if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
370                 return 1;
371         else
372                 return 0;
373 }
374
375 /*
376  *  sii164CheckInterrupt
377  *      Checks if interrupt has occurred.
378  *
379  *  Output:
380  *      0   - No interrupt
381  *      1   - Interrupt occurs
382  */
383 unsigned char sii164CheckInterrupt(void)
384 {
385         unsigned char detectReg;
386
387         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
388         if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
389                 return 1;
390         else
391                 return 0;
392 }
393
394 /*
395  *  sii164ClearInterrupt
396  *      Clear the hot plug interrupt.
397  */
398 void sii164ClearInterrupt(void)
399 {
400         unsigned char detectReg;
401
402         /* Clear the MDI interrupt */
403         detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
404         i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
405 }
406
407 #endif
408
409 #endif
410
411