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