These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[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 disp_state)
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                 ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
20                 /* Turn on/off the Panel display control */
21                 if (disp_state) {
22                         /* Timing should be enabled first before enabling the plane
23                          * because changing at the same time does not guarantee that
24                          * the plane will also enabled or disabled.
25                          */
26                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
27                                                                 PANEL_DISPLAY_CTRL, TIMING, ENABLE);
28                         POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
29
30                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
31                                                                 PANEL_DISPLAY_CTRL, PLANE, ENABLE);
32
33                         /* Added some masks to mask out the reserved bits.
34                          * Sometimes, the reserved bits are set/reset randomly when
35                          * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
36                          * reserved bits are needed to be masked out.
37                          */
38                         ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
39                                 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
40                                 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE);
41
42                         /* Somehow the register value on the plane is not set
43                          * until a few delay. Need to write
44                          * and read it a couple times
45                          */
46                         do {
47                                 cnt++;
48                                 POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
49                         } while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
50                                         (ulDisplayCtrlReg & ~ulReservedBits));
51                         printk("Set Panel Plane enbit:after tried %d times\n", cnt);
52                 } else {
53                         /* When turning off, there is no rule on the programming
54                          * sequence since whenever the clock is off, then it does not
55                          * matter whether the plane is enabled or disabled.
56                          * Note: Modifying the plane bit will take effect on the
57                          * next vertical sync. Need to find out if it is necessary to
58                          * wait for 1 vsync before modifying the timing enable bit.
59                          * */
60                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
61                                                                 PANEL_DISPLAY_CTRL, PLANE, DISABLE);
62                         POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
63
64                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
65                                                                 PANEL_DISPLAY_CTRL, TIMING, DISABLE);
66                         POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
67                 }
68
69         } else {
70                 /* Set the secondary display control */
71                 ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
72
73                 if (disp_state) {
74                         /* Timing should be enabled first before enabling the plane because changing at the
75                            same time does not guarantee that the plane will also enabled or disabled.
76                            */
77                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
78                                                                 CRT_DISPLAY_CTRL, TIMING, ENABLE);
79                         POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
80
81                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
82                                                                 CRT_DISPLAY_CTRL, PLANE, ENABLE);
83
84                         /* Added some masks to mask out the reserved bits.
85                          * Sometimes, the reserved bits are set/reset randomly when
86                          * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register
87                          * reserved bits are needed to be masked out.
88                          */
89
90                         ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
91                                 FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
92                                 FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
93                                 FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
94
95                         do {
96                                 cnt++;
97                                 POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
98                         } while ((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
99                                         (ulDisplayCtrlReg & ~ulReservedBits));
100                                 printk("Set Crt Plane enbit:after tried %d times\n", cnt);
101                 } else {
102                         /* When turning off, there is no rule on the programming
103                          * sequence since whenever the clock is off, then it does not
104                          * matter whether the plane is enabled or disabled.
105                          * Note: Modifying the plane bit will take effect on the next
106                          * vertical sync. Need to find out if it is necessary to
107                          * wait for 1 vsync before modifying the timing enable bit.
108                          */
109                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
110                                                                 CRT_DISPLAY_CTRL, PLANE, DISABLE);
111                         POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
112
113                         ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
114                                                                 CRT_DISPLAY_CTRL, TIMING, DISABLE);
115                         POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
116                 }
117         }
118 }
119
120 static void waitNextVerticalSync(int ctrl, int delay)
121 {
122         unsigned int status;
123
124         if (!ctrl) {
125                 /* primary controller */
126
127                 /* Do not wait when the Primary PLL is off or display control is already off.
128                    This will prevent the software to wait forever. */
129                 if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
130                          PANEL_PLL_CTRL_POWER_OFF) ||
131                         (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
132                          PANEL_DISPLAY_CTRL_TIMING_DISABLE)) {
133                         return;
134                 }
135
136                 while (delay-- > 0) {
137                         /* Wait for end of vsync. */
138                         do {
139                                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
140                                                    SYSTEM_CTRL,
141                                                    PANEL_VSYNC);
142                         } while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
143
144                         /* Wait for start of vsync. */
145                         do {
146                                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
147                                                    SYSTEM_CTRL,
148                                                    PANEL_VSYNC);
149                         } while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
150                 }
151
152         } else {
153
154                 /* Do not wait when the Primary PLL is off or display control is already off.
155                            This will prevent the software to wait forever. */
156                 if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
157                          CRT_PLL_CTRL_POWER_OFF) ||
158                         (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
159                          CRT_DISPLAY_CTRL_TIMING_DISABLE)) {
160                         return;
161                 }
162
163                 while (delay-- > 0) {
164                         /* Wait for end of vsync. */
165                         do {
166                                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
167                                                                    SYSTEM_CTRL,
168                                                                    CRT_VSYNC);
169                         } while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
170
171                         /* Wait for start of vsync. */
172                         do {
173                                 status = FIELD_GET(PEEK32(SYSTEM_CTRL),
174                                                                    SYSTEM_CTRL,
175                                                                    CRT_VSYNC);
176                         } while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
177                 }
178         }
179 }
180
181 static void swPanelPowerSequence(int disp, int delay)
182 {
183         unsigned int reg;
184
185         /* disp should be 1 to open sequence */
186         reg = PEEK32(PANEL_DISPLAY_CTRL);
187         reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp);
188         POKE32(PANEL_DISPLAY_CTRL, reg);
189         primaryWaitVerticalSync(delay);
190
191         reg = PEEK32(PANEL_DISPLAY_CTRL);
192         reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, DATA, disp);
193         POKE32(PANEL_DISPLAY_CTRL, reg);
194         primaryWaitVerticalSync(delay);
195
196         reg = PEEK32(PANEL_DISPLAY_CTRL);
197         reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, VBIASEN, disp);
198         POKE32(PANEL_DISPLAY_CTRL, reg);
199         primaryWaitVerticalSync(delay);
200
201         reg = PEEK32(PANEL_DISPLAY_CTRL);
202         reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp);
203         POKE32(PANEL_DISPLAY_CTRL, reg);
204         primaryWaitVerticalSync(delay);
205
206 }
207
208 void ddk750_setLogicalDispOut(disp_output_t output)
209 {
210         unsigned int reg;
211
212         if (output & PNL_2_USAGE) {
213                 /* set panel path controller select */
214                 reg = PEEK32(PANEL_DISPLAY_CTRL);
215                 reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, SELECT, (output & PNL_2_MASK)>>PNL_2_OFFSET);
216                 POKE32(PANEL_DISPLAY_CTRL, reg);
217         }
218
219         if (output & CRT_2_USAGE) {
220                 /* set crt path controller select */
221                 reg = PEEK32(CRT_DISPLAY_CTRL);
222                 reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET);
223                 /*se blank off */
224                 reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, BLANK, OFF);
225                 POKE32(CRT_DISPLAY_CTRL, reg);
226
227         }
228
229         if (output & PRI_TP_USAGE) {
230                 /* set primary timing and plane en_bit */
231                 setDisplayControl(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
232         }
233
234         if (output & SEC_TP_USAGE) {
235                 /* set secondary timing and plane en_bit*/
236                 setDisplayControl(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
237         }
238
239         if (output & PNL_SEQ_USAGE) {
240                 /* set  panel sequence */
241                 swPanelPowerSequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET, 4);
242         }
243
244         if (output & DAC_USAGE)
245                 setDAC((output & DAC_MASK) >> DAC_OFFSET);
246
247         if (output & DPMS_USAGE)
248                 ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
249 }