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