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