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
displayControlAdjust_SM750LE(struct mode_parameter * pModeParam,unsigned long dispControl)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 */
programModeRegisters(struct mode_parameter * pModeParam,struct pll_value * pll)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
ddk750_setModeTiming(struct mode_parameter * parm,enum clock_type clock)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 }
226