xref: /aosp_15_r20/external/coreboot/src/drivers/aspeed/common/ast_dp501.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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