xref: /linux/drivers/gpu/drm/ast/ast_2100.c (revision 2b109eccd80b660e58d4523e8b80ce11bc3e532e)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2012 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * The above copyright notice and this permission notice (including the
22  * next paragraph) shall be included in all copies or substantial portions
23  * of the Software.
24  */
25 /*
26  * Authors: Dave Airlie <airlied@redhat.com>
27  */
28 
29 #include <linux/delay.h>
30 #include <linux/pci.h>
31 
32 #include <drm/drm_drv.h>
33 
34 #include "ast_drv.h"
35 #include "ast_post.h"
36 
37 /*
38  * DRAM type
39  */
40 
41 static enum ast_dram_layout ast_2100_get_dram_layout_p2a(struct ast_device *ast)
42 {
43 	u32 mcr04;
44 	enum ast_dram_layout dram_layout;
45 
46 	mcr04 = ast_mindwm(ast, AST_REG_MCR04);
47 
48 	switch (mcr04 & GENMASK(3, 2)) {
49 	case 0:
50 	case 4:
51 	default:
52 		dram_layout = AST_DRAM_512Mx16;
53 		break;
54 	case 8:
55 		if (mcr04 & 0x40)
56 			dram_layout = AST_DRAM_1Gx16;
57 		else
58 			dram_layout = AST_DRAM_512Mx32;
59 		break;
60 	case 0xc:
61 		dram_layout = AST_DRAM_1Gx32;
62 		break;
63 	}
64 
65 	return dram_layout;
66 }
67 
68 /*
69  * POST
70  */
71 
72 static const struct ast_dramstruct ast1100_dram_table_data[] = {
73 	AST_DRAMSTRUCT_REG(AST_REG_SCU000, AST_REG_SCU000_PROTECTION_KEY),
74 	AST_DRAMSTRUCT_REG(AST_REG_SCU020, 0x000041f0),
75 	AST_DRAMSTRUCT_UDELAY(67u),
76 	AST_DRAMSTRUCT_REG(AST_REG_MCR00, AST_REG_MCR00_PROTECTION_KEY),
77 	AST_DRAMSTRUCT_REG(AST_REG_MCR6C, 0x00909090),
78 	AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x00050000),
79 	AST_DRAMSTRUCT_REG(AST_REG_MCR04, 0x00000585), // DRAM type
80 	AST_DRAMSTRUCT_REG(AST_REG_MCR08, 0x0011030f),
81 	AST_DRAMSTRUCT_REG(AST_REG_MCR10, 0x22201724),
82 	AST_DRAMSTRUCT_REG(AST_REG_MCR18, 0x1e29011a),
83 	AST_DRAMSTRUCT_REG(AST_REG_MCR20, 0x00c82222),
84 	AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x01001523),
85 	AST_DRAMSTRUCT_REG(AST_REG_MCR1C, 0x1024010d),
86 	AST_DRAMSTRUCT_REG(AST_REG_MCR24, 0x00cb2522),
87 	AST_DRAMSTRUCT_REG(AST_REG_MCR38, 0xffffff82),
88 	AST_DRAMSTRUCT_REG(AST_REG_MCR3C, 0x00000000),
89 	AST_DRAMSTRUCT_REG(AST_REG_MCR40, 0x00000000),
90 	AST_DRAMSTRUCT_REG(AST_REG_MCR44, 0x00000000),
91 	AST_DRAMSTRUCT_REG(AST_REG_MCR48, 0x00000000),
92 	AST_DRAMSTRUCT_REG(AST_REG_MCR4C, 0x00000000),
93 	AST_DRAMSTRUCT_REG(AST_REG_MCR50, 0x00000000),
94 	AST_DRAMSTRUCT_REG(AST_REG_MCR54, 0x00000000),
95 	AST_DRAMSTRUCT_REG(AST_REG_MCR58, 0x00000000),
96 	AST_DRAMSTRUCT_REG(AST_REG_MCR5C, 0x00000000),
97 	AST_DRAMSTRUCT_REG(AST_REG_MCR60, 0x032aa02a),
98 	AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x002d3000),
99 	AST_DRAMSTRUCT_REG(AST_REG_MCR68, 0x00000000),
100 	AST_DRAMSTRUCT_REG(AST_REG_MCR70, 0x00000000),
101 	AST_DRAMSTRUCT_REG(AST_REG_MCR74, 0x00000000),
102 	AST_DRAMSTRUCT_REG(AST_REG_MCR78, 0x00000000),
103 	AST_DRAMSTRUCT_REG(AST_REG_MCR7C, 0x00000000),
104 	AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00000001),
105 	AST_DRAMSTRUCT_UDELAY(67u),
106 	AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000732),
107 	AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040),
108 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000005),
109 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000007),
110 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003),
111 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001),
112 	AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a08),
113 	AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000632),
114 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001),
115 	AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x000003c0),
116 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003),
117 	AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040),
118 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003),
119 	AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a21),
120 	AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00007c03),
121 	AST_DRAMSTRUCT_REG(AST_REG_MCR120, 0x00004c41),
122 	AST_DRAMSTRUCT_INVALID,
123 };
124 
125 static const struct ast_dramstruct ast2100_dram_table_data[] = {
126 	AST_DRAMSTRUCT_REG(AST_REG_SCU000, AST_REG_SCU000_PROTECTION_KEY),
127 	AST_DRAMSTRUCT_REG(AST_REG_SCU020, 0x00004120),
128 	AST_DRAMSTRUCT_UDELAY(67u),
129 	AST_DRAMSTRUCT_REG(AST_REG_MCR00, AST_REG_MCR00_PROTECTION_KEY),
130 	AST_DRAMSTRUCT_REG(AST_REG_MCR6C, 0x00909090),
131 	AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x00070000),
132 	AST_DRAMSTRUCT_REG(AST_REG_MCR04, 0x00000489), // DRAM type
133 	AST_DRAMSTRUCT_REG(AST_REG_MCR08, 0x0011030f),
134 	AST_DRAMSTRUCT_REG(AST_REG_MCR10, 0x32302926),
135 	AST_DRAMSTRUCT_REG(AST_REG_MCR18, 0x274c0122),
136 	AST_DRAMSTRUCT_REG(AST_REG_MCR20, 0x00ce2222),
137 	AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x01001523),
138 	AST_DRAMSTRUCT_REG(AST_REG_MCR1C, 0x1024010d),
139 	AST_DRAMSTRUCT_REG(AST_REG_MCR24, 0x00cb2522),
140 	AST_DRAMSTRUCT_REG(AST_REG_MCR38, 0xffffff82),
141 	AST_DRAMSTRUCT_REG(AST_REG_MCR3C, 0x00000000),
142 	AST_DRAMSTRUCT_REG(AST_REG_MCR40, 0x00000000),
143 	AST_DRAMSTRUCT_REG(AST_REG_MCR44, 0x00000000),
144 	AST_DRAMSTRUCT_REG(AST_REG_MCR48, 0x00000000),
145 	AST_DRAMSTRUCT_REG(AST_REG_MCR4C, 0x00000000),
146 	AST_DRAMSTRUCT_REG(AST_REG_MCR50, 0x00000000),
147 	AST_DRAMSTRUCT_REG(AST_REG_MCR54, 0x00000000),
148 	AST_DRAMSTRUCT_REG(AST_REG_MCR58, 0x00000000),
149 	AST_DRAMSTRUCT_REG(AST_REG_MCR5C, 0x00000000),
150 	AST_DRAMSTRUCT_REG(AST_REG_MCR60, 0x0f2aa02a),
151 	AST_DRAMSTRUCT_REG(AST_REG_MCR64, 0x003f3005),
152 	AST_DRAMSTRUCT_REG(AST_REG_MCR68, 0x02020202),
153 	AST_DRAMSTRUCT_REG(AST_REG_MCR70, 0x00000000),
154 	AST_DRAMSTRUCT_REG(AST_REG_MCR74, 0x00000000),
155 	AST_DRAMSTRUCT_REG(AST_REG_MCR78, 0x00000000),
156 	AST_DRAMSTRUCT_REG(AST_REG_MCR7C, 0x00000000),
157 	AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00000001),
158 	AST_DRAMSTRUCT_UDELAY(67u),
159 	AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000942),
160 	AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040),
161 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000005),
162 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000007),
163 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003),
164 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001),
165 	AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a08),
166 	AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x00000842),
167 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000001),
168 	AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x000003c0),
169 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003),
170 	AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0x00000040),
171 	AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x00000003),
172 	AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x00005a21),
173 	AST_DRAMSTRUCT_REG(AST_REG_MCR34, 0x00007c03),
174 	AST_DRAMSTRUCT_REG(AST_REG_MCR120, 0x00005061),
175 	AST_DRAMSTRUCT_INVALID,
176 };
177 
178 /*
179  * AST2100/2150 DLL CBR Setting
180  */
181 #define CBR_SIZE_AST2150	     ((16 << 10) - 1)
182 #define CBR_PASSNUM_AST2150          5
183 #define CBR_THRESHOLD_AST2150        10
184 #define CBR_THRESHOLD2_AST2150       10
185 #define TIMEOUT_AST2150              5000000
186 
187 #define CBR_PATNUM_AST2150           8
188 
189 static const u32 pattern_AST2150[14] = {
190 	0xFF00FF00,
191 	0xCC33CC33,
192 	0xAA55AA55,
193 	0xFFFE0001,
194 	0x683501FE,
195 	0x0F1929B0,
196 	0x2D0B4346,
197 	0x60767F02,
198 	0x6FBE36A6,
199 	0x3A253035,
200 	0x3019686D,
201 	0x41C6167E,
202 	0x620152BF,
203 	0x20F050E0
204 };
205 
206 static u32 mmctestburst2_ast2150(struct ast_device *ast, u32 datagen)
207 {
208 	u32 data, timeout;
209 
210 	ast_moutdwm(ast, AST_REG_MCR70, 0x00000000);
211 	ast_moutdwm(ast, AST_REG_MCR70, 0x00000001 | (datagen << 3));
212 	timeout = 0;
213 	do {
214 		data = ast_mindwm(ast, AST_REG_MCR70) & 0x40;
215 		if (++timeout > TIMEOUT_AST2150) {
216 			ast_moutdwm(ast, AST_REG_MCR70, 0x00000000);
217 			return 0xffffffff;
218 		}
219 	} while (!data);
220 	ast_moutdwm(ast, AST_REG_MCR70, 0x00000000);
221 	ast_moutdwm(ast, AST_REG_MCR70, 0x00000003 | (datagen << 3));
222 	timeout = 0;
223 	do {
224 		data = ast_mindwm(ast, AST_REG_MCR70) & 0x40;
225 		if (++timeout > TIMEOUT_AST2150) {
226 			ast_moutdwm(ast, AST_REG_MCR70, 0x00000000);
227 			return 0xffffffff;
228 		}
229 	} while (!data);
230 	data = (ast_mindwm(ast, AST_REG_MCR70) & 0x80) >> 7;
231 	ast_moutdwm(ast, AST_REG_MCR70, 0x00000000);
232 	return data;
233 }
234 
235 static int cbrtest_ast2150(struct ast_device *ast)
236 {
237 	int i;
238 
239 	for (i = 0; i < 8; i++)
240 		if (mmctestburst2_ast2150(ast, i))
241 			return 0;
242 	return 1;
243 }
244 
245 static int cbrscan_ast2150(struct ast_device *ast, int busw)
246 {
247 	u32 patcnt, loop;
248 
249 	for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
250 		ast_moutdwm(ast, AST_REG_MCR7C, pattern_AST2150[patcnt]);
251 		for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
252 			if (cbrtest_ast2150(ast))
253 				break;
254 		}
255 		if (loop == CBR_PASSNUM_AST2150)
256 			return 0;
257 	}
258 	return 1;
259 }
260 
261 static void cbrdlli_ast2150(struct ast_device *ast, int busw)
262 {
263 	u32 dll_min[4], dll_max[4], dlli, data, passcnt;
264 
265 cbr_start:
266 	dll_min[0] = 0xff;
267 	dll_min[1] = 0xff;
268 	dll_min[2] = 0xff;
269 	dll_min[3] = 0xff;
270 	dll_max[0] = 0x00;
271 	dll_max[1] = 0x00;
272 	dll_max[2] = 0x00;
273 	dll_max[3] = 0x00;
274 	passcnt = 0;
275 
276 	for (dlli = 0; dlli < 100; dlli++) {
277 		ast_moutdwm(ast, AST_REG_MCR68, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
278 		data = cbrscan_ast2150(ast, busw);
279 		if (data != 0) {
280 			if (data & 0x1) {
281 				if (dll_min[0] > dlli)
282 					dll_min[0] = dlli;
283 				if (dll_max[0] < dlli)
284 					dll_max[0] = dlli;
285 			}
286 			passcnt++;
287 		} else if (passcnt >= CBR_THRESHOLD_AST2150) {
288 			goto cbr_start;
289 		}
290 	}
291 	if (dll_max[0] == 0 || (dll_max[0] - dll_min[0]) < CBR_THRESHOLD_AST2150)
292 		goto cbr_start;
293 
294 	dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
295 	ast_moutdwm(ast, AST_REG_MCR68, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
296 }
297 
298 static void ast_post_chip_2100(struct ast_device *ast)
299 {
300 	u8 j;
301 	u32 i;
302 	enum ast_dram_layout dram_layout = ast_2100_get_dram_layout_p2a(ast);
303 	u32 mcr120;
304 	u32 scu00c, scu040;
305 
306 	j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
307 
308 	if ((j & 0x80) == 0) { /* VGA only */
309 		const struct ast_dramstruct *dram_reg_info;
310 
311 		if (ast->chip == AST2100 || ast->chip == AST2200)
312 			dram_reg_info = ast2100_dram_table_data;
313 		else
314 			dram_reg_info = ast1100_dram_table_data;
315 
316 		ast_moutdwm_poll(ast, AST_REG_SCU000, AST_REG_SCU000_PROTECTION_KEY, 0x01);
317 		ast_moutdwm_poll(ast, AST_REG_MCR00, AST_REG_MCR00_PROTECTION_KEY, 0x01);
318 
319 		while (!AST_DRAMSTRUCT_IS(dram_reg_info, INVALID)) {
320 			if (AST_DRAMSTRUCT_IS(dram_reg_info, UDELAY)) {
321 				for (i = 0; i < 15; i++)
322 					udelay(dram_reg_info->data);
323 			} else if (AST_DRAMSTRUCT_IS_REG(dram_reg_info, AST_REG_MCR04)) {
324 				u32 mcr04;
325 				u32 scu070;
326 
327 				switch (dram_layout) {
328 				case AST_DRAM_1Gx16:
329 					mcr04 = 0x00000d89;
330 					break;
331 				case AST_DRAM_1Gx32:
332 					mcr04 = 0x00000c8d;
333 					break;
334 				default:
335 					mcr04 = dram_reg_info->data;
336 					break;
337 				}
338 
339 				/*
340 				 * FIXME: There might be bits already in MCR04[5:4]. Should
341 				 *        we only do this in the default case?
342 				 */
343 				scu070 = ast_mindwm(ast, AST_REG_SCU070);
344 				mcr04 |= (scu070 & GENMASK(3, 2)) << 2;
345 
346 				ast_moutdwm(ast, dram_reg_info->index, mcr04);
347 			} else {
348 				ast_moutdwm(ast, dram_reg_info->index, dram_reg_info->data);
349 			}
350 			dram_reg_info++;
351 		}
352 
353 		/* AST 2100/2150 DRAM calibration */
354 		mcr120 = ast_mindwm(ast, AST_REG_MCR120);
355 		if (mcr120 == 0x5061) { /* 266Mhz */
356 			u32 mcr04 = ast_mindwm(ast, AST_REG_MCR04);
357 
358 			if (mcr04 & 0x40)
359 				cbrdlli_ast2150(ast, 16); /* 16 bits */
360 			else
361 				cbrdlli_ast2150(ast, 32); /* 32 bits */
362 		}
363 
364 		scu00c = ast_mindwm(ast, AST_REG_SCU00C);
365 		scu00c &= 0xfffffffd;
366 		ast_moutdwm(ast, AST_REG_SCU00C, scu00c);
367 
368 		scu040 = ast_mindwm(ast, AST_REG_SCU040);
369 		scu040 |= 0x00000040;
370 		ast_moutdwm(ast, AST_REG_SCU040, scu040);
371 	}
372 
373 	/* wait ready */
374 	do {
375 		j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
376 	} while ((j & 0x40) == 0);
377 }
378 
379 int ast_2100_post(struct ast_device *ast)
380 {
381 	ast_2000_set_def_ext_reg(ast);
382 
383 	if (ast->config_mode == ast_use_p2a) {
384 		ast_post_chip_2100(ast);
385 	} else {
386 		if (ast->tx_chip == AST_TX_SIL164) {
387 			/* Enable DVO */
388 			ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);
389 		}
390 	}
391 
392 	return 0;
393 }
394 
395 /*
396  * Widescreen detection
397  */
398 
399 /* Try to detect WSXGA+ on Gen2+ */
400 bool __ast_2100_detect_wsxga_p(struct ast_device *ast)
401 {
402 	u8 vgacrd0 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd0);
403 
404 	if (!(vgacrd0 & AST_IO_VGACRD0_VRAM_INIT_BY_BMC))
405 		return true;
406 	if (vgacrd0 & AST_IO_VGACRD0_IKVM_WIDESCREEN)
407 		return true;
408 
409 	return false;
410 }
411 
412 /* Try to detect WUXGA on Gen2+ */
413 bool __ast_2100_detect_wuxga(struct ast_device *ast)
414 {
415 	u8 vgacrd1;
416 
417 	if (ast->support_fullhd) {
418 		vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1);
419 		if (!(vgacrd1 & AST_IO_VGACRD1_SUPPORTS_WUXGA))
420 			return true;
421 	}
422 
423 	return false;
424 }
425 
426 static void ast_2100_detect_widescreen(struct ast_device *ast)
427 {
428 	if (__ast_2100_detect_wsxga_p(ast)) {
429 		ast->support_wsxga_p = true;
430 		if (ast->chip == AST2100)
431 			ast->support_fullhd = true;
432 	}
433 	if (__ast_2100_detect_wuxga(ast))
434 		ast->support_wuxga = true;
435 }
436 
437 static const struct ast_device_quirks ast_2100_device_quirks = {
438 	.crtc_mem_req_threshold_low = 47,
439 	.crtc_mem_req_threshold_high = 63,
440 };
441 
442 struct drm_device *ast_2100_device_create(struct pci_dev *pdev,
443 					  const struct drm_driver *drv,
444 					  enum ast_chip chip,
445 					  enum ast_config_mode config_mode,
446 					  void __iomem *regs,
447 					  void __iomem *ioregs,
448 					  bool need_post)
449 {
450 	struct drm_device *dev;
451 	struct ast_device *ast;
452 	int ret;
453 
454 	ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
455 	if (IS_ERR(ast))
456 		return ERR_CAST(ast);
457 	dev = &ast->base;
458 
459 	ast_device_init(ast, chip, config_mode, regs, ioregs, &ast_2100_device_quirks);
460 
461 	ast->dclk_table = ast_2000_dclk_table;
462 
463 	ast_2000_detect_tx_chip(ast, need_post);
464 
465 	if (need_post) {
466 		ret = ast_post_gpu(ast);
467 		if (ret)
468 			return ERR_PTR(ret);
469 	}
470 
471 	ret = ast_mm_init(ast);
472 	if (ret)
473 		return ERR_PTR(ret);
474 
475 	ast_2100_detect_widescreen(ast);
476 
477 	ret = ast_mode_config_init(ast);
478 	if (ret)
479 		return ERR_PTR(ret);
480 
481 	return dev;
482 }
483