Merge tag 'for-5.13-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / staging / sm750fb / ddk750_mode.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include "ddk750_reg.h"
4 #include "ddk750_mode.h"
5 #include "ddk750_chip.h"
6
7 /*
8  * SM750LE only:
9  * This function takes care extra registers and bit fields required to set
10  * up a mode in SM750LE
11  *
12  * Explanation about Display Control register:
13  * HW only supports 7 predefined pixel clocks, and clock select is
14  * in bit 29:27 of Display Control register.
15  */
16 static unsigned long
17 displayControlAdjust_SM750LE(struct mode_parameter *pModeParam,
18                              unsigned long dispControl)
19 {
20         unsigned long x, y;
21
22         x = pModeParam->horizontal_display_end;
23         y = pModeParam->vertical_display_end;
24
25         /*
26          * SM750LE has to set up the top-left and bottom-right
27          * registers as well.
28          * Note that normal SM750/SM718 only use those two register for
29          * auto-centering mode.
30          */
31         poke32(CRT_AUTO_CENTERING_TL, 0);
32
33         poke32(CRT_AUTO_CENTERING_BR,
34                (((y - 1) << CRT_AUTO_CENTERING_BR_BOTTOM_SHIFT) &
35                 CRT_AUTO_CENTERING_BR_BOTTOM_MASK) |
36                ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK));
37
38         /*
39          * Assume common fields in dispControl have been properly set before
40          * calling this function.
41          * This function only sets the extra fields in dispControl.
42          */
43
44         /* Clear bit 29:27 of display control register */
45         dispControl &= ~CRT_DISPLAY_CTRL_CLK_MASK;
46
47         /* Set bit 29:27 of display control register for the right clock */
48         /* Note that SM750LE only need to supported 7 resolutions. */
49         if (x == 800 && y == 600)
50                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL41;
51         else if (x == 1024 && y == 768)
52                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL65;
53         else if (x == 1152 && y == 864)
54                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80;
55         else if (x == 1280 && y == 768)
56                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80;
57         else if (x == 1280 && y == 720)
58                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL74;
59         else if (x == 1280 && y == 960)
60                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108;
61         else if (x == 1280 && y == 1024)
62                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108;
63         else /* default to VGA clock */
64                 dispControl |= CRT_DISPLAY_CTRL_CLK_PLL25;
65
66         /* Set bit 25:24 of display controller */
67         dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT);
68
69         /* Set bit 14 of display controller */
70         dispControl |= DISPLAY_CTRL_CLOCK_PHASE;
71
72         poke32(CRT_DISPLAY_CTRL, dispControl);
73
74         return dispControl;
75 }
76
77 /* only timing related registers will be  programed */
78 static int programModeRegisters(struct mode_parameter *pModeParam,
79                                 struct pll_value *pll)
80 {
81         int ret = 0;
82         int cnt = 0;
83         unsigned int tmp, reg;
84
85         if (pll->clock_type == SECONDARY_PLL) {
86                 /* programe secondary pixel clock */
87                 poke32(CRT_PLL_CTRL, sm750_format_pll_reg(pll));
88
89                 tmp = ((pModeParam->horizontal_total - 1) <<
90                        CRT_HORIZONTAL_TOTAL_TOTAL_SHIFT) &
91                      CRT_HORIZONTAL_TOTAL_TOTAL_MASK;
92                 tmp |= (pModeParam->horizontal_display_end - 1) &
93                       CRT_HORIZONTAL_TOTAL_DISPLAY_END_MASK;
94
95                 poke32(CRT_HORIZONTAL_TOTAL, tmp);
96
97                 tmp = (pModeParam->horizontal_sync_width <<
98                        CRT_HORIZONTAL_SYNC_WIDTH_SHIFT) &
99                      CRT_HORIZONTAL_SYNC_WIDTH_MASK;
100                 tmp |= (pModeParam->horizontal_sync_start - 1) &
101                       CRT_HORIZONTAL_SYNC_START_MASK;
102
103                 poke32(CRT_HORIZONTAL_SYNC, tmp);
104
105                 tmp = ((pModeParam->vertical_total - 1) <<
106                        CRT_VERTICAL_TOTAL_TOTAL_SHIFT) &
107                      CRT_VERTICAL_TOTAL_TOTAL_MASK;
108                 tmp |= (pModeParam->vertical_display_end - 1) &
109                       CRT_VERTICAL_TOTAL_DISPLAY_END_MASK;
110
111                 poke32(CRT_VERTICAL_TOTAL, tmp);
112
113                 tmp = ((pModeParam->vertical_sync_height <<
114                        CRT_VERTICAL_SYNC_HEIGHT_SHIFT)) &
115                      CRT_VERTICAL_SYNC_HEIGHT_MASK;
116                 tmp |= (pModeParam->vertical_sync_start - 1) &
117                       CRT_VERTICAL_SYNC_START_MASK;
118
119                 poke32(CRT_VERTICAL_SYNC, tmp);
120
121                 tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE;
122                 if (pModeParam->vertical_sync_polarity)
123                         tmp |= DISPLAY_CTRL_VSYNC_PHASE;
124                 if (pModeParam->horizontal_sync_polarity)
125                         tmp |= DISPLAY_CTRL_HSYNC_PHASE;
126
127                 if (sm750_get_chip_type() == SM750LE) {
128                         displayControlAdjust_SM750LE(pModeParam, tmp);
129                 } else {
130                         reg = peek32(CRT_DISPLAY_CTRL) &
131                                 ~(DISPLAY_CTRL_VSYNC_PHASE |
132                                   DISPLAY_CTRL_HSYNC_PHASE |
133                                   DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE);
134
135                         poke32(CRT_DISPLAY_CTRL, tmp | reg);
136                 }
137
138         } else if (pll->clock_type == PRIMARY_PLL) {
139                 unsigned int reserved;
140
141                 poke32(PANEL_PLL_CTRL, sm750_format_pll_reg(pll));
142
143                 reg = ((pModeParam->horizontal_total - 1) <<
144                         PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT) &
145                         PANEL_HORIZONTAL_TOTAL_TOTAL_MASK;
146                 reg |= ((pModeParam->horizontal_display_end - 1) &
147                         PANEL_HORIZONTAL_TOTAL_DISPLAY_END_MASK);
148                 poke32(PANEL_HORIZONTAL_TOTAL, reg);
149
150                 poke32(PANEL_HORIZONTAL_SYNC,
151                        ((pModeParam->horizontal_sync_width <<
152                          PANEL_HORIZONTAL_SYNC_WIDTH_SHIFT) &
153                         PANEL_HORIZONTAL_SYNC_WIDTH_MASK) |
154                        ((pModeParam->horizontal_sync_start - 1) &
155                         PANEL_HORIZONTAL_SYNC_START_MASK));
156
157                 poke32(PANEL_VERTICAL_TOTAL,
158                        (((pModeParam->vertical_total - 1) <<
159                          PANEL_VERTICAL_TOTAL_TOTAL_SHIFT) &
160                         PANEL_VERTICAL_TOTAL_TOTAL_MASK) |
161                        ((pModeParam->vertical_display_end - 1) &
162                         PANEL_VERTICAL_TOTAL_DISPLAY_END_MASK));
163
164                 poke32(PANEL_VERTICAL_SYNC,
165                        ((pModeParam->vertical_sync_height <<
166                          PANEL_VERTICAL_SYNC_HEIGHT_SHIFT) &
167                         PANEL_VERTICAL_SYNC_HEIGHT_MASK) |
168                        ((pModeParam->vertical_sync_start - 1) &
169                         PANEL_VERTICAL_SYNC_START_MASK));
170
171                 tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE;
172                 if (pModeParam->vertical_sync_polarity)
173                         tmp |= DISPLAY_CTRL_VSYNC_PHASE;
174                 if (pModeParam->horizontal_sync_polarity)
175                         tmp |= DISPLAY_CTRL_HSYNC_PHASE;
176                 if (pModeParam->clock_phase_polarity)
177                         tmp |= DISPLAY_CTRL_CLOCK_PHASE;
178
179                 reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK |
180                         PANEL_DISPLAY_CTRL_VSYNC;
181
182                 reg = (peek32(PANEL_DISPLAY_CTRL) & ~reserved) &
183                         ~(DISPLAY_CTRL_CLOCK_PHASE | DISPLAY_CTRL_VSYNC_PHASE |
184                           DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING |
185                           DISPLAY_CTRL_PLANE);
186
187                 /*
188                  * May a hardware bug or just my test chip (not confirmed).
189                  * PANEL_DISPLAY_CTRL register seems requiring few writes
190                  * before a value can be successfully written in.
191                  * Added some masks to mask out the reserved bits.
192                  * Note: This problem happens by design. The hardware will wait
193                  *       for the next vertical sync to turn on/off the plane.
194                  */
195                 poke32(PANEL_DISPLAY_CTRL, tmp | reg);
196
197                 while ((peek32(PANEL_DISPLAY_CTRL) & ~reserved) !=
198                         (tmp | reg)) {
199                         cnt++;
200                         if (cnt > 1000)
201                                 break;
202                         poke32(PANEL_DISPLAY_CTRL, tmp | reg);
203                 }
204         } else {
205                 ret = -1;
206         }
207         return ret;
208 }
209
210 int ddk750_setModeTiming(struct mode_parameter *parm, enum clock_type clock)
211 {
212         struct pll_value pll;
213
214         pll.input_freq = DEFAULT_INPUT_CLOCK;
215         pll.clock_type = clock;
216
217         sm750_calc_pll_value(parm->pixel_clock, &pll);
218         if (sm750_get_chip_type() == SM750LE) {
219                 /* set graphic mode via IO method */
220                 outb_p(0x88, 0x3d4);
221                 outb_p(0x06, 0x3d5);
222         }
223         programModeRegisters(parm, &pll);
224         return 0;
225 }