coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ast_dp501.c
Go to the documentation of this file.
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 
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 
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 
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 
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 
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 
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 
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);
80  do {
81  if (wait_ack(ast)) {
83  send_nack(ast);
84  return true;
85  }
86  } while (retry++ < 100);
87  }
89  send_nack(ast);
90  return false;
91 }
92 
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 
111 {
112  ast_write_cmd(dev, 0x40);
113  ast_write_data(dev, mode);
114 
115  msleep(10);
116 }
117 
119 {
120  return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
121 }
122 
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 
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 
150  if (ast->dp501_fw_addr) {
151  fw_addr = ast->dp501_fw_addr;
152  len = 32*1024;
153  } else {
154  if (!ast->dp501_fw)
155  return false;
156 
157  fw_addr = (u8 *)ast->dp501_fw->data;
158  len = ast->dp501_fw->size;
159  }
160  /* Get BootAddress */
161  ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
162  data = ast_mindwm(ast, 0x1e6e0004);
163  switch (data & 0x03) {
164  case 0:
165  boot_address = 0x44000000;
166  break;
167  default:
168  case 1:
169  boot_address = 0x48000000;
170  break;
171  case 2:
172  boot_address = 0x50000000;
173  break;
174  case 3:
175  boot_address = 0x60000000;
176  break;
177  }
178  boot_address -= 0x200000; /* -2MB */
179 
180  /* copy image to buffer */
181  for (i = 0; i < len; i += 4) {
182  data = *(u32 *)(fw_addr + i);
183  ast_moutdwm(ast, boot_address + i, data);
184  }
185 
186  /* Init SCU */
187  ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
188 
189  /* Launch FW */
190  ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
191  ast_moutdwm(ast, 0x1e6e2100, 1);
192 
193  /* Update Scratch */
194  data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff; /* D[11:9] = 100b: UEFI handling */
195  data |= 0x800;
196  ast_moutdwm(ast, 0x1e6e2040, data);
197 
198  jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */
199  jreg |= 0x02;
200  ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg);
201  }
202  return true;
203 }
204 
206 {
207  struct ast_private *ast = dev->dev_private;
208  u32 boot_address, offset, data;
209  u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
210 
211  boot_address = get_fw_base(ast);
212 
213  /* validate FW version */
214  offset = 0xf000;
215  data = ast_mindwm(ast, boot_address + offset);
216  if ((data & 0xf0) != 0x10) /* version: 1x */
217  return maxclk;
218 
219  /* Read Link Capability */
220  offset = 0xf014;
221  *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
222  if (linkcap[2] == 0) {
223  linkrate = linkcap[0];
224  linklanes = linkcap[1];
225  data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
226  if (data > 0xff)
227  data = 0xff;
228  maxclk = (u8)data;
229  }
230  return maxclk;
231 }
232 
233 bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
234 {
235  struct ast_private *ast = dev->dev_private;
236  u32 i, boot_address, offset, data;
237 
238  boot_address = get_fw_base(ast);
239 
240  /* validate FW version */
241  offset = 0xf000;
242  data = ast_mindwm(ast, boot_address + offset);
243  if ((data & 0xf0) != 0x10)
244  return false;
245 
246  /* validate PnP Monitor */
247  offset = 0xf010;
248  data = ast_mindwm(ast, boot_address + offset);
249  if (!(data & 0x01))
250  return false;
251 
252  /* Read EDID */
253  offset = 0xf020;
254  for (i = 0; i < 128; i += 4) {
255  data = ast_mindwm(ast, boot_address + offset + i);
256  *(u32 *)(ediddata + i) = data;
257  }
258 
259  return true;
260 }
261 
262 static bool ast_init_dvo(struct drm_device *dev)
263 {
264  struct ast_private *ast = dev->dev_private;
265  u8 jreg;
266  u32 data;
267  ast_write32(ast, 0xf004, 0x1e6e0000);
268  ast_write32(ast, 0xf000, 0x1);
269  ast_write32(ast, 0x12000, 0x1688a8a8);
270 
271  jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
272  if (!(jreg & 0x80)) {
273  /* Init SCU DVO Settings */
274  data = ast_read32(ast, 0x12008);
275  /* delay phase */
276  data &= 0xfffff8ff;
277  data |= 0x00000500;
278  ast_write32(ast, 0x12008, data);
279 
280  if (ast->chip == AST2300) {
281  data = ast_read32(ast, 0x12084);
282  /* multi-pins for DVO single-edge */
283  data |= 0xfffe0000;
284  ast_write32(ast, 0x12084, data);
285 
286  data = ast_read32(ast, 0x12088);
287  /* multi-pins for DVO single-edge */
288  data |= 0x000fffff;
289  ast_write32(ast, 0x12088, data);
290 
291  data = ast_read32(ast, 0x12090);
292  /* multi-pins for DVO single-edge */
293  data &= 0xffffffcf;
294  data |= 0x00000020;
295  ast_write32(ast, 0x12090, data);
296  } else { /* AST2400 */
297  data = ast_read32(ast, 0x12088);
298  /* multi-pins for DVO single-edge */
299  data |= 0x30000000;
300  ast_write32(ast, 0x12088, data);
301 
302  data = ast_read32(ast, 0x1208c);
303  /* multi-pins for DVO single-edge */
304  data |= 0x000000cf;
305  ast_write32(ast, 0x1208c, data);
306 
307  data = ast_read32(ast, 0x120a4);
308  /* multi-pins for DVO single-edge */
309  data |= 0xffff0000;
310  ast_write32(ast, 0x120a4, data);
311 
312  data = ast_read32(ast, 0x120a8);
313  /* multi-pins for DVO single-edge */
314  data |= 0x0000000f;
315  ast_write32(ast, 0x120a8, data);
316 
317  data = ast_read32(ast, 0x12094);
318  /* multi-pins for DVO single-edge */
319  data |= 0x00000002;
320  ast_write32(ast, 0x12094, data);
321  }
322  }
323 
324  /* Force to DVO */
325  data = ast_read32(ast, 0x1202c);
326  data &= 0xfffbffff;
327  ast_write32(ast, 0x1202c, data);
328 
329  /* Init VGA DVO Settings */
330  ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);
331  return true;
332 }
333 
334 static void ast_init_analog(struct drm_device *dev)
335 {
336  struct ast_private *ast = dev->dev_private;
337  u32 data;
338 
339  /*
340  * Set DAC source to VGA mode in SCU2C via the P2A
341  * bridge. First configure the P2U to target the SCU
342  * in case it isn't at this stage.
343  */
344  ast_write32(ast, 0xf004, 0x1e6e0000);
345  ast_write32(ast, 0xf000, 0x1);
346 
347  /* Then unlock the SCU with the magic password */
348  ast_write32(ast, 0x12000, 0x1688a8a8);
349  ast_write32(ast, 0x12000, 0x1688a8a8);
350  ast_write32(ast, 0x12000, 0x1688a8a8);
351 
352  /* Finally, clear bits [17:16] of SCU2c */
353  data = ast_read32(ast, 0x1202c);
354  data &= 0xfffcffff;
355  ast_write32(ast, 0, data);
356 
357  /* Disable DVO */
358  ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00);
359 }
360 
362 {
363  struct ast_private *ast = dev->dev_private;
364  u8 jreg;
365 
366  if (ast->chip == AST2300 || ast->chip == AST2400) {
367  jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
368  switch (jreg & 0x0e) {
369  case 0x04:
370  ast_init_dvo(dev);
371  break;
372  case 0x08:
374  break;
375  case 0x0c:
376  ast_init_dvo(dev);
377  break;
378  default:
380  ast_init_dvo(dev);
381  else
383  }
384  }
385 }
static void msleep(unsigned int msecs)
static void set_cmd_trigger(struct ast_private *ast)
Definition: ast_dp501.c:61
static bool ast_launch_m68k(struct drm_device *dev)
Definition: ast_dp501.c:139
static bool ast_write_cmd(struct drm_device *dev, u8 data)
Definition: ast_dp501.c:71
void ast_init_3rdtx(struct drm_device *dev)
Definition: ast_dp501.c:361
static bool ast_init_dvo(struct drm_device *dev)
Definition: ast_dp501.c:262
bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
Definition: ast_dp501.c:233
static u32 get_fw_base(struct ast_private *ast)
Definition: ast_dp501.c:118
static void send_ack(struct ast_private *ast)
Definition: ast_dp501.c:13
static void ast_init_analog(struct drm_device *dev)
Definition: ast_dp501.c:334
static bool ast_write_data(struct drm_device *dev, u8 data)
Definition: ast_dp501.c:93
static bool wait_ack(struct ast_private *ast)
Definition: ast_dp501.c:29
static void send_nack(struct ast_private *ast)
Definition: ast_dp501.c:21
static bool wait_nack(struct ast_private *ast)
Definition: ast_dp501.c:45
void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
Definition: ast_dp501.c:110
bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
Definition: ast_dp501.c:123
u8 ast_get_dp501_max_clk(struct drm_device *dev)
Definition: ast_dp501.c:205
static void clear_cmd_trigger(struct ast_private *ast)
Definition: ast_dp501.c:66
uint8_t ast_get_index_reg_mask(struct ast_private *ast, uint32_t base, uint8_t index, uint8_t mask)
Definition: ast_main.c:30
@ AST_TX_SIL164
Definition: ast_drv.h:28
#define AST_IO_CRTC_PORT
Definition: ast_drv.h:89
void ast_set_index_reg_mask(struct ast_private *ast, uint32_t base, uint8_t index, uint8_t mask, uint8_t val)
Definition: ast_main.c:11
void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)
Definition: ast_post.c:111
@ AST2400
Definition: ast_drv.h:21
@ AST2300
Definition: ast_drv.h:20
static void ast_set_index_reg(struct ast_private *ast, uint32_t base, uint8_t index, uint8_t val)
Definition: ast_drv.h:141
u32 ast_mindwm(struct ast_private *ast, u32 r)
Definition: ast_post.c:93
static struct ast_private * ast
Definition: ast_i2c.c:10
#define retry(attempts, condition,...)
Definition: helpers.h:126
static u32 addr
Definition: cirrus.c:14
static size_t offset
Definition: flashconsole.c:16
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
uint8_t u8
Definition: stdint.h:45
struct drm_device * dev
Definition: ast_drv.h:44
const struct firmware * dp501_fw
Definition: ast_drv.h:75
enum ast_chip chip
Definition: ast_drv.h:50
u8 * dp501_fw_addr
Definition: ast_drv.h:74
enum ast_tx_chip tx_chip_type
Definition: ast_drv.h:72
void * dev_private
size_t size
const u8 * data
void udelay(uint32_t us)
Definition: udelay.c:15