1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 /*
4 * File taken from the Linux ast driver (v3.18.5)
5 * coreboot-specific includes added at top and/or contents modified
6 * as needed to function within the coreboot environment.
7 */
8
9 #include <delay.h>
10
11 #include "ast_drv.h"
12
send_ack(struct ast_private * ast)13 static void send_ack(struct ast_private *ast)
14 {
15 u8 sendack;
16 sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
17 sendack |= 0x80;
18 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
19 }
20
send_nack(struct ast_private * ast)21 static void send_nack(struct ast_private *ast)
22 {
23 u8 sendack;
24 sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
25 sendack &= ~0x80;
26 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
27 }
28
wait_ack(struct ast_private * ast)29 static bool wait_ack(struct ast_private *ast)
30 {
31 u8 waitack;
32 u32 retry = 0;
33 do {
34 waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff);
35 waitack &= 0x80;
36 udelay(100);
37 } while ((!waitack) && (retry++ < 1000));
38
39 if (retry < 1000)
40 return true;
41 else
42 return false;
43 }
44
wait_nack(struct ast_private * ast)45 static bool wait_nack(struct ast_private *ast)
46 {
47 u8 waitack;
48 u32 retry = 0;
49 do {
50 waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff);
51 waitack &= 0x80;
52 udelay(100);
53 } while ((waitack) && (retry++ < 1000));
54
55 if (retry < 1000)
56 return true;
57 else
58 return false;
59 }
60
set_cmd_trigger(struct ast_private * ast)61 static void set_cmd_trigger(struct ast_private *ast)
62 {
63 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40);
64 }
65
clear_cmd_trigger(struct ast_private * ast)66 static void clear_cmd_trigger(struct ast_private *ast)
67 {
68 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00);
69 }
70
ast_write_cmd(struct drm_device * dev,u8 data)71 static bool ast_write_cmd(struct drm_device *dev, u8 data)
72 {
73 struct ast_private *ast = dev->dev_private;
74 int retry = 0;
75 if (wait_nack(ast)) {
76 send_nack(ast);
77 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
78 send_ack(ast);
79 set_cmd_trigger(ast);
80 do {
81 if (wait_ack(ast)) {
82 clear_cmd_trigger(ast);
83 send_nack(ast);
84 return true;
85 }
86 } while (retry++ < 100);
87 }
88 clear_cmd_trigger(ast);
89 send_nack(ast);
90 return false;
91 }
92
ast_write_data(struct drm_device * dev,u8 data)93 static bool ast_write_data(struct drm_device *dev, u8 data)
94 {
95 struct ast_private *ast = dev->dev_private;
96
97 if (wait_nack(ast)) {
98 send_nack(ast);
99 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
100 send_ack(ast);
101 if (wait_ack(ast)) {
102 send_nack(ast);
103 return true;
104 }
105 }
106 send_nack(ast);
107 return false;
108 }
109
ast_set_dp501_video_output(struct drm_device * dev,u8 mode)110 void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
111 {
112 ast_write_cmd(dev, 0x40);
113 ast_write_data(dev, mode);
114
115 msleep(10);
116 }
117
get_fw_base(struct ast_private * ast)118 static u32 get_fw_base(struct ast_private *ast)
119 {
120 return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
121 }
122
ast_backup_fw(struct drm_device * dev,u8 * addr,u32 size)123 bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
124 {
125 struct ast_private *ast = dev->dev_private;
126 u32 i, data;
127 u32 boot_address;
128
129 data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
130 if (data) {
131 boot_address = get_fw_base(ast);
132 for (i = 0; i < size; i += 4)
133 *(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);
134 return true;
135 }
136 return false;
137 }
138
ast_launch_m68k(struct drm_device * dev)139 static bool ast_launch_m68k(struct drm_device *dev)
140 {
141 struct ast_private *ast = dev->dev_private;
142 u32 i, data, len = 0;
143 u32 boot_address;
144 u8 *fw_addr = NULL;
145 u8 jreg;
146
147 data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
148 if (!data) {
149 if (ast->dp501_fw_addr) {
150 fw_addr = ast->dp501_fw_addr;
151 len = 32*1024;
152 } else {
153 if (!ast->dp501_fw)
154 return false;
155
156 fw_addr = (u8 *)ast->dp501_fw->data;
157 len = ast->dp501_fw->size;
158 }
159 /* Get BootAddress */
160 ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
161 data = ast_mindwm(ast, 0x1e6e0004);
162 switch (data & 0x03) {
163 case 0:
164 boot_address = 0x44000000;
165 break;
166 default:
167 case 1:
168 boot_address = 0x48000000;
169 break;
170 case 2:
171 boot_address = 0x50000000;
172 break;
173 case 3:
174 boot_address = 0x60000000;
175 break;
176 }
177 boot_address -= 0x200000; /* -2MB */
178
179 /* copy image to buffer */
180 for (i = 0; i < len; i += 4) {
181 data = *(u32 *)(fw_addr + i);
182 ast_moutdwm(ast, boot_address + i, data);
183 }
184
185 /* Init SCU */
186 ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
187
188 /* Launch FW */
189 ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
190 ast_moutdwm(ast, 0x1e6e2100, 1);
191
192 /* Update Scratch */
193 data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff; /* D[11:9] = 100b: UEFI handling */
194 data |= 0x800;
195 ast_moutdwm(ast, 0x1e6e2040, data);
196
197 jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */
198 jreg |= 0x02;
199 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg);
200 }
201 return true;
202 }
203
ast_get_dp501_max_clk(struct drm_device * dev)204 u8 ast_get_dp501_max_clk(struct drm_device *dev)
205 {
206 struct ast_private *ast = dev->dev_private;
207 u32 boot_address, offset, data;
208 u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
209
210 boot_address = get_fw_base(ast);
211
212 /* validate FW version */
213 offset = 0xf000;
214 data = ast_mindwm(ast, boot_address + offset);
215 if ((data & 0xf0) != 0x10) /* version: 1x */
216 return maxclk;
217
218 /* Read Link Capability */
219 offset = 0xf014;
220 *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
221 if (linkcap[2] == 0) {
222 linkrate = linkcap[0];
223 linklanes = linkcap[1];
224 data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
225 if (data > 0xff)
226 data = 0xff;
227 maxclk = (u8)data;
228 }
229 return maxclk;
230 }
231
ast_dp501_read_edid(struct drm_device * dev,u8 * ediddata)232 bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
233 {
234 struct ast_private *ast = dev->dev_private;
235 u32 i, boot_address, offset, data;
236
237 boot_address = get_fw_base(ast);
238
239 /* validate FW version */
240 offset = 0xf000;
241 data = ast_mindwm(ast, boot_address + offset);
242 if ((data & 0xf0) != 0x10)
243 return false;
244
245 /* validate PnP Monitor */
246 offset = 0xf010;
247 data = ast_mindwm(ast, boot_address + offset);
248 if (!(data & 0x01))
249 return false;
250
251 /* Read EDID */
252 offset = 0xf020;
253 for (i = 0; i < 128; i += 4) {
254 data = ast_mindwm(ast, boot_address + offset + i);
255 *(u32 *)(ediddata + i) = data;
256 }
257
258 return true;
259 }
260
ast_init_dvo(struct drm_device * dev)261 static bool ast_init_dvo(struct drm_device *dev)
262 {
263 struct ast_private *ast = dev->dev_private;
264 u8 jreg;
265 u32 data;
266 ast_write32(ast, 0xf004, 0x1e6e0000);
267 ast_write32(ast, 0xf000, 0x1);
268 ast_write32(ast, 0x12000, 0x1688a8a8);
269
270 jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
271 if (!(jreg & 0x80)) {
272 /* Init SCU DVO Settings */
273 data = ast_read32(ast, 0x12008);
274 /* delay phase */
275 data &= 0xfffff8ff;
276 data |= 0x00000500;
277 ast_write32(ast, 0x12008, data);
278
279 if (ast->chip == AST2300) {
280 data = ast_read32(ast, 0x12084);
281 /* multi-pins for DVO single-edge */
282 data |= 0xfffe0000;
283 ast_write32(ast, 0x12084, data);
284
285 data = ast_read32(ast, 0x12088);
286 /* multi-pins for DVO single-edge */
287 data |= 0x000fffff;
288 ast_write32(ast, 0x12088, data);
289
290 data = ast_read32(ast, 0x12090);
291 /* multi-pins for DVO single-edge */
292 data &= 0xffffffcf;
293 data |= 0x00000020;
294 ast_write32(ast, 0x12090, data);
295 } else { /* AST2400 */
296 data = ast_read32(ast, 0x12088);
297 /* multi-pins for DVO single-edge */
298 data |= 0x30000000;
299 ast_write32(ast, 0x12088, data);
300
301 data = ast_read32(ast, 0x1208c);
302 /* multi-pins for DVO single-edge */
303 data |= 0x000000cf;
304 ast_write32(ast, 0x1208c, data);
305
306 data = ast_read32(ast, 0x120a4);
307 /* multi-pins for DVO single-edge */
308 data |= 0xffff0000;
309 ast_write32(ast, 0x120a4, data);
310
311 data = ast_read32(ast, 0x120a8);
312 /* multi-pins for DVO single-edge */
313 data |= 0x0000000f;
314 ast_write32(ast, 0x120a8, data);
315
316 data = ast_read32(ast, 0x12094);
317 /* multi-pins for DVO single-edge */
318 data |= 0x00000002;
319 ast_write32(ast, 0x12094, data);
320 }
321 }
322
323 /* Force to DVO */
324 data = ast_read32(ast, 0x1202c);
325 data &= 0xfffbffff;
326 ast_write32(ast, 0x1202c, data);
327
328 /* Init VGA DVO Settings */
329 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);
330 return true;
331 }
332
ast_init_analog(struct drm_device * dev)333 static void ast_init_analog(struct drm_device *dev)
334 {
335 struct ast_private *ast = dev->dev_private;
336 u32 data;
337
338 /*
339 * Set DAC source to VGA mode in SCU2C via the P2A
340 * bridge. First configure the P2U to target the SCU
341 * in case it isn't at this stage.
342 */
343 ast_write32(ast, 0xf004, 0x1e6e0000);
344 ast_write32(ast, 0xf000, 0x1);
345
346 /* Then unlock the SCU with the magic password */
347 ast_write32(ast, 0x12000, 0x1688a8a8);
348 ast_write32(ast, 0x12000, 0x1688a8a8);
349 ast_write32(ast, 0x12000, 0x1688a8a8);
350
351 /* Finally, clear bits [17:16] of SCU2c */
352 data = ast_read32(ast, 0x1202c);
353 data &= 0xfffcffff;
354 ast_write32(ast, 0, data);
355
356 /* Disable DVO */
357 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00);
358 }
359
ast_init_3rdtx(struct drm_device * dev)360 void ast_init_3rdtx(struct drm_device *dev)
361 {
362 struct ast_private *ast = dev->dev_private;
363 u8 jreg;
364
365 if (ast->chip == AST2300 || ast->chip == AST2400) {
366 jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
367 switch (jreg & 0x0e) {
368 case 0x04:
369 ast_init_dvo(dev);
370 break;
371 case 0x08:
372 ast_launch_m68k(dev);
373 break;
374 case 0x0c:
375 ast_init_dvo(dev);
376 break;
377 default:
378 if (ast->tx_chip_type == AST_TX_SIL164)
379 ast_init_dvo(dev);
380 else
381 ast_init_analog(dev);
382 }
383 }
384 }
385