Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / sm750fb / ddk750_display.c
1 #include "ddk750_reg.h"
2 #include "ddk750_help.h"
3 #include "ddk750_display.h"
4 #include "ddk750_power.h"
5 #include "ddk750_dvi.h"
6
7 #define primaryWaitVerticalSync(delay) waitNextVerticalSync(0,delay)
8
9 static void setDisplayControl(int ctrl,int dispState)
10 {
11         /* state != 0 means turn on both timing & plane en_bit */
12         unsigned long ulDisplayCtrlReg, ulReservedBits;
13         int cnt;
14
15         cnt = 0;
16
17         /* Set the primary display control */
18         if (!ctrl)
19         {
20                 ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
21                 /* Turn on/off the Panel display control */
22                 if (dispState)
23                 {
24                         /* Timing should be enabled first before enabling the plane
25                          * because changing at the same time does not guarantee that
26                          * the plane will also enabled or disabled.
27              */
28                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
29                                                                 PANEL_DISPLAY_CTRL, TIMING, ENABLE);
30                         POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
31
32                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
33                                                                 PANEL_DISPLAY_CTRL, PLANE, ENABLE);
34
35                         /* Added some masks to mask out the reserved bits.
36                          * Sometimes, the reserved bits are set/reset randomly when
37                          * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
38                          * reserved bits are needed to be masked out.
39                          */
40                         ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
41                                 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
42                                 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE);
43
44                         /* Somehow the register value on the plane is not set
45                          * until a few delay. Need to write
46                          * and read it a couple times
47                          */
48                         do
49                         {
50                                 cnt++;
51                                 POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
52                         } while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
53                                         (ulDisplayCtrlReg & ~ulReservedBits));
54                         printk("Set Panel Plane enbit:after tried %d times\n",cnt);
55                 }
56                 else
57                 {
58                         /* When turning off, there is no rule on the programming
59                          * sequence since whenever the clock is off, then it does not
60                          * matter whether the plane is enabled or disabled.
61                          * Note: Modifying the plane bit will take effect on the
62                          * next vertical sync. Need to find out if it is necessary to
63                          * wait for 1 vsync before modifying the timing enable bit.
64                          * */
65                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
66                                                                 PANEL_DISPLAY_CTRL, PLANE, DISABLE);
67                         POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
68
69                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
70                                                                 PANEL_DISPLAY_CTRL, TIMING, DISABLE);
71                         POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
72                 }
73
74         }
75         /* Set the secondary display control */
76         else
77         {
78                 ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
79
80                 if (dispState)
81                 {
82                         /* Timing should be enabled first before enabling the plane because changing at the
83                            same time does not guarantee that the plane will also enabled or disabled.
84                            */
85                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
86                                                                 CRT_DISPLAY_CTRL, TIMING, ENABLE);
87                         POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
88
89                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
90                                                                 CRT_DISPLAY_CTRL, PLANE, ENABLE);
91
92                         /* Added some masks to mask out the reserved bits.
93                          * Sometimes, the reserved bits are set/reset randomly when
94                          * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
95                          * reserved bits are needed to be masked out.
96                          */
97
98                         ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
99                                 FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
100                                 FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
101                                 FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
102
103                         do
104                         {
105                                 cnt++;
106                                 POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
107                         } while((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
108                                         (ulDisplayCtrlReg & ~ulReservedBits));
109                                 printk("Set Crt Plane enbit:after tried %d times\n",cnt);
110                 }
111                 else
112                 {
113                         /* When turning off, there is no rule on the programming
114                          * sequence since whenever the clock is off, then it does not
115                          * matter whether the plane is enabled or disabled.
116                          * Note: Modifying the plane bit will take effect on the next
117                          * vertical sync. Need to find out if it is necessary to
118                          * wait for 1 vsync before modifying the timing enable bit.
119                          */
120                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
121                                                                 CRT_DISPLAY_CTRL, PLANE, DISABLE);
122                         POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
123
124                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
125                                                                 CRT_DISPLAY_CTRL, TIMING, DISABLE);
126                         POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
127                 }
128         }
129 }
130
131
132 static void waitNextVerticalSync(int ctrl,int delay)
133 {
134         unsigned int status;
135         if(!ctrl){
136                 /* primary controller */
137
138         /* Do not wait when the Primary PLL is off or display control is already off.
139                    This will prevent the software to wait forever. */
140                 if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
141                          PANEL_PLL_CTRL_POWER_OFF) ||
142                         (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
143                          PANEL_DISPLAY_CTRL_TIMING_DISABLE))
144                 {
145                         return;
146                 }
147
148         while (delay-- > 0)
149         {
150             /* Wait for end of vsync. */
151             do
152             {
153                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
154                                    SYSTEM_CTRL,
155                                    PANEL_VSYNC);
156             }
157             while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
158
159             /* Wait for start of vsync. */
160             do
161             {
162                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
163                                    SYSTEM_CTRL,
164                                    PANEL_VSYNC);
165             }
166             while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
167         }
168
169         }else{
170
171                 /* Do not wait when the Primary PLL is off or display control is already off.
172                            This will prevent the software to wait forever. */
173                 if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
174                          CRT_PLL_CTRL_POWER_OFF) ||
175                         (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
176                          CRT_DISPLAY_CTRL_TIMING_DISABLE))
177                 {
178                         return;
179                 }
180
181                 while (delay-- > 0)
182                 {
183                         /* Wait for end of vsync. */
184                         do
185                         {
186                                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
187                                                                    SYSTEM_CTRL,
188                                                                    CRT_VSYNC);
189                         }
190                         while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
191
192                         /* Wait for start of vsync. */
193                         do
194                         {
195                                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
196                                                                    SYSTEM_CTRL,
197                                                                    CRT_VSYNC);
198                         }
199                         while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
200                 }
201         }
202 }
203
204 static void swPanelPowerSequence(int disp,int delay)
205 {
206         unsigned int reg;
207
208         /* disp should be 1 to open sequence */
209         reg = PEEK32(PANEL_DISPLAY_CTRL);
210         reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp);
211         POKE32(PANEL_DISPLAY_CTRL,reg);
212         primaryWaitVerticalSync(delay);
213
214
215         reg = PEEK32(PANEL_DISPLAY_CTRL);
216         reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,DATA,disp);
217         POKE32(PANEL_DISPLAY_CTRL,reg);
218         primaryWaitVerticalSync(delay);
219
220         reg = PEEK32(PANEL_DISPLAY_CTRL);
221         reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,VBIASEN,disp);
222         POKE32(PANEL_DISPLAY_CTRL,reg);
223         primaryWaitVerticalSync(delay);
224
225
226         reg = PEEK32(PANEL_DISPLAY_CTRL);
227         reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp);
228         POKE32(PANEL_DISPLAY_CTRL,reg);
229         primaryWaitVerticalSync(delay);
230
231 }
232
233 void ddk750_setLogicalDispOut(disp_output_t output)
234 {
235         unsigned int reg;
236         if(output & PNL_2_USAGE){
237                 /* set panel path controller select */
238                 reg = PEEK32(PANEL_DISPLAY_CTRL);
239                 reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,SELECT,(output & PNL_2_MASK)>>PNL_2_OFFSET);
240                 POKE32(PANEL_DISPLAY_CTRL,reg);
241         }
242
243         if(output & CRT_2_USAGE){
244                 /* set crt path controller select */
245                 reg = PEEK32(CRT_DISPLAY_CTRL);
246                 reg = FIELD_VALUE(reg,CRT_DISPLAY_CTRL,SELECT,(output & CRT_2_MASK)>>CRT_2_OFFSET);
247                 /*se blank off */
248                 reg = FIELD_SET(reg,CRT_DISPLAY_CTRL,BLANK,OFF);
249                 POKE32(CRT_DISPLAY_CTRL,reg);
250
251         }
252
253         if(output & PRI_TP_USAGE){
254                 /* set primary timing and plane en_bit */
255                 setDisplayControl(0,(output&PRI_TP_MASK)>>PRI_TP_OFFSET);
256         }
257
258         if(output & SEC_TP_USAGE){
259                 /* set secondary timing and plane en_bit*/
260                 setDisplayControl(1,(output&SEC_TP_MASK)>>SEC_TP_OFFSET);
261         }
262
263         if(output & PNL_SEQ_USAGE){
264                 /* set  panel sequence */
265                 swPanelPowerSequence((output&PNL_SEQ_MASK)>>PNL_SEQ_OFFSET,4);
266         }
267
268         if(output & DAC_USAGE)
269                 setDAC((output & DAC_MASK)>>DAC_OFFSET);
270
271         if(output & DPMS_USAGE)
272                 ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
273 }
274
275
276 int ddk750_initDVIDisp(void)
277 {
278     /* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
279        not zeroed, then set the failure flag. If it is zeroe, it might mean
280        that the system is in Dual CRT Monitor configuration. */
281
282     /* De-skew enabled with default 111b value.
283        This will fix some artifacts problem in some mode on board 2.2.
284        Somehow this fix does not affect board 2.1.
285      */
286     if ((dviInit(1,  /* Select Rising Edge */
287                 1,  /* Select 24-bit bus */
288                 0,  /* Select Single Edge clock */
289                 1,  /* Enable HSync as is */
290                 1,  /* Enable VSync as is */
291                 1,  /* Enable De-skew */
292                 7,  /* Set the de-skew setting to maximum setup */
293                 1,  /* Enable continuous Sync */
294                 1,  /* Enable PLL Filter */
295                 4   /* Use the recommended value for PLL Filter value */
296         ) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000))
297     {
298         return (-1);
299     }
300
301     /* TODO: Initialize other display component */
302
303     /* Success */
304     return 0;
305
306 }
307