xref: /openbmc/linux/drivers/gpu/drm/ast/ast_post.c (revision 83c6620b)
1312fec14SDave Airlie /*
2312fec14SDave Airlie  * Copyright 2012 Red Hat Inc.
3312fec14SDave Airlie  *
4312fec14SDave Airlie  * Permission is hereby granted, free of charge, to any person obtaining a
5312fec14SDave Airlie  * copy of this software and associated documentation files (the
6312fec14SDave Airlie  * "Software"), to deal in the Software without restriction, including
7312fec14SDave Airlie  * without limitation the rights to use, copy, modify, merge, publish,
8312fec14SDave Airlie  * distribute, sub license, and/or sell copies of the Software, and to
9312fec14SDave Airlie  * permit persons to whom the Software is furnished to do so, subject to
10312fec14SDave Airlie  * the following conditions:
11312fec14SDave Airlie  *
12312fec14SDave Airlie  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13312fec14SDave Airlie  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14312fec14SDave Airlie  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15312fec14SDave Airlie  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16312fec14SDave Airlie  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17312fec14SDave Airlie  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18312fec14SDave Airlie  * USE OR OTHER DEALINGS IN THE SOFTWARE.
19312fec14SDave Airlie  *
20312fec14SDave Airlie  * The above copyright notice and this permission notice (including the
21312fec14SDave Airlie  * next paragraph) shall be included in all copies or substantial portions
22312fec14SDave Airlie  * of the Software.
23312fec14SDave Airlie  *
24312fec14SDave Airlie  */
25312fec14SDave Airlie /*
26312fec14SDave Airlie  * Authors: Dave Airlie <airlied@redhat.com>
27312fec14SDave Airlie  */
28312fec14SDave Airlie 
29760285e7SDavid Howells #include <drm/drmP.h>
30312fec14SDave Airlie #include "ast_drv.h"
31312fec14SDave Airlie 
32312fec14SDave Airlie #include "ast_dram_tables.h"
33312fec14SDave Airlie 
34312fec14SDave Airlie static void ast_init_dram_2300(struct drm_device *dev);
35312fec14SDave Airlie 
36312fec14SDave Airlie static void
37312fec14SDave Airlie ast_enable_vga(struct drm_device *dev)
38312fec14SDave Airlie {
39312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
40312fec14SDave Airlie 
41312fec14SDave Airlie 	ast_io_write8(ast, 0x43, 0x01);
42312fec14SDave Airlie 	ast_io_write8(ast, 0x42, 0x01);
43312fec14SDave Airlie }
44312fec14SDave Airlie 
45312fec14SDave Airlie #if 0 /* will use later */
46312fec14SDave Airlie static bool
47312fec14SDave Airlie ast_is_vga_enabled(struct drm_device *dev)
48312fec14SDave Airlie {
49312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
50312fec14SDave Airlie 	u8 ch;
51312fec14SDave Airlie 
52312fec14SDave Airlie 	if (ast->chip == AST1180) {
53312fec14SDave Airlie 		/* TODO 1180 */
54312fec14SDave Airlie 	} else {
55312fec14SDave Airlie 		ch = ast_io_read8(ast, 0x43);
56312fec14SDave Airlie 		if (ch) {
57312fec14SDave Airlie 			ast_open_key(ast);
58312fec14SDave Airlie 			ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff);
59312fec14SDave Airlie 			return ch & 0x04;
60312fec14SDave Airlie 		}
61312fec14SDave Airlie 	}
62312fec14SDave Airlie 	return 0;
63312fec14SDave Airlie }
64312fec14SDave Airlie #endif
65312fec14SDave Airlie 
66312fec14SDave Airlie static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
67312fec14SDave Airlie static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff };
68312fec14SDave Airlie static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };
69312fec14SDave Airlie 
70312fec14SDave Airlie static void
71312fec14SDave Airlie ast_set_def_ext_reg(struct drm_device *dev)
72312fec14SDave Airlie {
73312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
74312fec14SDave Airlie 	u8 i, index, reg;
75312fec14SDave Airlie 	const u8 *ext_reg_info;
76312fec14SDave Airlie 
77312fec14SDave Airlie 	/* reset scratch */
78312fec14SDave Airlie 	for (i = 0x81; i <= 0x8f; i++)
79312fec14SDave Airlie 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
80312fec14SDave Airlie 
811453bf4cSDave Airlie 	if (ast->chip == AST2300 || ast->chip == AST2400) {
82312fec14SDave Airlie 		if (dev->pdev->revision >= 0x20)
83312fec14SDave Airlie 			ext_reg_info = extreginfo_ast2300;
84312fec14SDave Airlie 		else
85312fec14SDave Airlie 			ext_reg_info = extreginfo_ast2300a0;
86312fec14SDave Airlie 	} else
87312fec14SDave Airlie 		ext_reg_info = extreginfo;
88312fec14SDave Airlie 
89312fec14SDave Airlie 	index = 0xa0;
90312fec14SDave Airlie 	while (*ext_reg_info != 0xff) {
91312fec14SDave Airlie 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info);
92312fec14SDave Airlie 		index++;
93312fec14SDave Airlie 		ext_reg_info++;
94312fec14SDave Airlie 	}
95312fec14SDave Airlie 
96312fec14SDave Airlie 	/* disable standard IO/MEM decode if secondary */
97312fec14SDave Airlie 	/* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */
98312fec14SDave Airlie 
99312fec14SDave Airlie 	/* Set Ext. Default */
100312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01);
101312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00);
102312fec14SDave Airlie 
103312fec14SDave Airlie 	/* Enable RAMDAC for A1 */
104312fec14SDave Airlie 	reg = 0x04;
1051453bf4cSDave Airlie 	if (ast->chip == AST2300 || ast->chip == AST2400)
106312fec14SDave Airlie 		reg |= 0x20;
107312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
108312fec14SDave Airlie }
109312fec14SDave Airlie 
11083c6620bSDave Airlie u32 ast_mindwm(struct ast_private *ast, u32 r)
111312fec14SDave Airlie {
112318cfa29SDave Airlie 	uint32_t data;
113318cfa29SDave Airlie 
114312fec14SDave Airlie 	ast_write32(ast, 0xf004, r & 0xffff0000);
115312fec14SDave Airlie 	ast_write32(ast, 0xf000, 0x1);
116312fec14SDave Airlie 
117318cfa29SDave Airlie 	do {
118318cfa29SDave Airlie 		data = ast_read32(ast, 0xf004) & 0xffff0000;
119318cfa29SDave Airlie 	} while (data != (r & 0xffff0000));
120312fec14SDave Airlie 	return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
121312fec14SDave Airlie }
122312fec14SDave Airlie 
12383c6620bSDave Airlie void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)
124312fec14SDave Airlie {
125318cfa29SDave Airlie 	uint32_t data;
126312fec14SDave Airlie 	ast_write32(ast, 0xf004, r & 0xffff0000);
127312fec14SDave Airlie 	ast_write32(ast, 0xf000, 0x1);
128318cfa29SDave Airlie 	do {
129318cfa29SDave Airlie 		data = ast_read32(ast, 0xf004) & 0xffff0000;
130318cfa29SDave Airlie 	} while (data != (r & 0xffff0000));
131312fec14SDave Airlie 	ast_write32(ast, 0x10000 + (r & 0x0000ffff), v);
132312fec14SDave Airlie }
133312fec14SDave Airlie 
134312fec14SDave Airlie /*
135312fec14SDave Airlie  * AST2100/2150 DLL CBR Setting
136312fec14SDave Airlie  */
137312fec14SDave Airlie #define CBR_SIZE_AST2150	     ((16 << 10) - 1)
138312fec14SDave Airlie #define CBR_PASSNUM_AST2150          5
139312fec14SDave Airlie #define CBR_THRESHOLD_AST2150        10
140312fec14SDave Airlie #define CBR_THRESHOLD2_AST2150       10
141312fec14SDave Airlie #define TIMEOUT_AST2150              5000000
142312fec14SDave Airlie 
143312fec14SDave Airlie #define CBR_PATNUM_AST2150           8
144312fec14SDave Airlie 
145312fec14SDave Airlie static const u32 pattern_AST2150[14] = {
146312fec14SDave Airlie 	0xFF00FF00,
147312fec14SDave Airlie 	0xCC33CC33,
148312fec14SDave Airlie 	0xAA55AA55,
149312fec14SDave Airlie 	0xFFFE0001,
150312fec14SDave Airlie 	0x683501FE,
151312fec14SDave Airlie 	0x0F1929B0,
152312fec14SDave Airlie 	0x2D0B4346,
153312fec14SDave Airlie 	0x60767F02,
154312fec14SDave Airlie 	0x6FBE36A6,
155312fec14SDave Airlie 	0x3A253035,
156312fec14SDave Airlie 	0x3019686D,
157312fec14SDave Airlie 	0x41C6167E,
158312fec14SDave Airlie 	0x620152BF,
159312fec14SDave Airlie 	0x20F050E0
160312fec14SDave Airlie };
161312fec14SDave Airlie 
162312fec14SDave Airlie static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen)
163312fec14SDave Airlie {
164312fec14SDave Airlie 	u32 data, timeout;
165312fec14SDave Airlie 
1660e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1670e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3));
168312fec14SDave Airlie 	timeout = 0;
169312fec14SDave Airlie 	do {
1700e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
171312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1720e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
173312fec14SDave Airlie 			return 0xffffffff;
174312fec14SDave Airlie 		}
175312fec14SDave Airlie 	} while (!data);
1760e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1770e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3));
178312fec14SDave Airlie 	timeout = 0;
179312fec14SDave Airlie 	do {
1800e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
181312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1820e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
183312fec14SDave Airlie 			return 0xffffffff;
184312fec14SDave Airlie 		}
185312fec14SDave Airlie 	} while (!data);
1860e5ce924SDave Airlie 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
1870e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
188312fec14SDave Airlie 	return data;
189312fec14SDave Airlie }
190312fec14SDave Airlie 
191312fec14SDave Airlie #if 0 /* unused in DDX driver - here for completeness */
192312fec14SDave Airlie static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen)
193312fec14SDave Airlie {
194312fec14SDave Airlie 	u32 data, timeout;
195312fec14SDave Airlie 
1960e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1970e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
198312fec14SDave Airlie 	timeout = 0;
199312fec14SDave Airlie 	do {
2000e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
201312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
2020e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
203312fec14SDave Airlie 			return 0xffffffff;
204312fec14SDave Airlie 		}
205312fec14SDave Airlie 	} while (!data);
2060e5ce924SDave Airlie 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
2070e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
208312fec14SDave Airlie 	return data;
209312fec14SDave Airlie }
210312fec14SDave Airlie #endif
211312fec14SDave Airlie 
212312fec14SDave Airlie static int cbrtest_ast2150(struct ast_private *ast)
213312fec14SDave Airlie {
214312fec14SDave Airlie 	int i;
215312fec14SDave Airlie 
216312fec14SDave Airlie 	for (i = 0; i < 8; i++)
217312fec14SDave Airlie 		if (mmctestburst2_ast2150(ast, i))
218312fec14SDave Airlie 			return 0;
219312fec14SDave Airlie 	return 1;
220312fec14SDave Airlie }
221312fec14SDave Airlie 
222312fec14SDave Airlie static int cbrscan_ast2150(struct ast_private *ast, int busw)
223312fec14SDave Airlie {
224312fec14SDave Airlie 	u32 patcnt, loop;
225312fec14SDave Airlie 
226312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
2270e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]);
228312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
229312fec14SDave Airlie 			if (cbrtest_ast2150(ast))
230312fec14SDave Airlie 				break;
231312fec14SDave Airlie 		}
232312fec14SDave Airlie 		if (loop == CBR_PASSNUM_AST2150)
233312fec14SDave Airlie 			return 0;
234312fec14SDave Airlie 	}
235312fec14SDave Airlie 	return 1;
236312fec14SDave Airlie }
237312fec14SDave Airlie 
238312fec14SDave Airlie 
239312fec14SDave Airlie static void cbrdlli_ast2150(struct ast_private *ast, int busw)
240312fec14SDave Airlie {
241312fec14SDave Airlie 	u32 dll_min[4], dll_max[4], dlli, data, passcnt;
242312fec14SDave Airlie 
243312fec14SDave Airlie cbr_start:
244312fec14SDave Airlie 	dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff;
245312fec14SDave Airlie 	dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0;
246312fec14SDave Airlie 	passcnt = 0;
247312fec14SDave Airlie 
248312fec14SDave Airlie 	for (dlli = 0; dlli < 100; dlli++) {
2490e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
250312fec14SDave Airlie 		data = cbrscan_ast2150(ast, busw);
251312fec14SDave Airlie 		if (data != 0) {
252312fec14SDave Airlie 			if (data & 0x1) {
253312fec14SDave Airlie 				if (dll_min[0] > dlli)
254312fec14SDave Airlie 					dll_min[0] = dlli;
255312fec14SDave Airlie 				if (dll_max[0] < dlli)
256312fec14SDave Airlie 					dll_max[0] = dlli;
257312fec14SDave Airlie 			}
258312fec14SDave Airlie 			passcnt++;
259312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD_AST2150)
260312fec14SDave Airlie 			goto cbr_start;
261312fec14SDave Airlie 	}
262312fec14SDave Airlie 	if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150)
263312fec14SDave Airlie 		goto cbr_start;
264312fec14SDave Airlie 
265312fec14SDave Airlie 	dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
2660e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
267312fec14SDave Airlie }
268312fec14SDave Airlie 
269312fec14SDave Airlie 
270312fec14SDave Airlie 
271312fec14SDave Airlie static void ast_init_dram_reg(struct drm_device *dev)
272312fec14SDave Airlie {
273312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
274312fec14SDave Airlie 	u8 j;
275312fec14SDave Airlie 	u32 data, temp, i;
276312fec14SDave Airlie 	const struct ast_dramstruct *dram_reg_info;
277312fec14SDave Airlie 
278312fec14SDave Airlie 	j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
279312fec14SDave Airlie 
280312fec14SDave Airlie 	if ((j & 0x80) == 0) { /* VGA only */
281312fec14SDave Airlie 		if (ast->chip == AST2000) {
282312fec14SDave Airlie 			dram_reg_info = ast2000_dram_table_data;
283312fec14SDave Airlie 			ast_write32(ast, 0xf004, 0x1e6e0000);
284312fec14SDave Airlie 			ast_write32(ast, 0xf000, 0x1);
285312fec14SDave Airlie 			ast_write32(ast, 0x10100, 0xa8);
286312fec14SDave Airlie 
287312fec14SDave Airlie 			do {
288312fec14SDave Airlie 				;
289312fec14SDave Airlie 			} while (ast_read32(ast, 0x10100) != 0xa8);
290312fec14SDave Airlie 		} else {/* AST2100/1100 */
291312fec14SDave Airlie 			if (ast->chip == AST2100 || ast->chip == 2200)
292312fec14SDave Airlie 				dram_reg_info = ast2100_dram_table_data;
293312fec14SDave Airlie 			else
294312fec14SDave Airlie 				dram_reg_info = ast1100_dram_table_data;
295312fec14SDave Airlie 
296312fec14SDave Airlie 			ast_write32(ast, 0xf004, 0x1e6e0000);
297312fec14SDave Airlie 			ast_write32(ast, 0xf000, 0x1);
298312fec14SDave Airlie 			ast_write32(ast, 0x12000, 0x1688A8A8);
299312fec14SDave Airlie 			do {
300312fec14SDave Airlie 				;
301312fec14SDave Airlie 			} while (ast_read32(ast, 0x12000) != 0x01);
302312fec14SDave Airlie 
303312fec14SDave Airlie 			ast_write32(ast, 0x10000, 0xfc600309);
304312fec14SDave Airlie 			do {
305312fec14SDave Airlie 				;
306312fec14SDave Airlie 			} while (ast_read32(ast, 0x10000) != 0x01);
307312fec14SDave Airlie 		}
308312fec14SDave Airlie 
309312fec14SDave Airlie 		while (dram_reg_info->index != 0xffff) {
310312fec14SDave Airlie 			if (dram_reg_info->index == 0xff00) {/* delay fn */
311312fec14SDave Airlie 				for (i = 0; i < 15; i++)
312312fec14SDave Airlie 					udelay(dram_reg_info->data);
313312fec14SDave Airlie 			} else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) {
314312fec14SDave Airlie 				data = dram_reg_info->data;
315312fec14SDave Airlie 				if (ast->dram_type == AST_DRAM_1Gx16)
316312fec14SDave Airlie 					data = 0x00000d89;
317312fec14SDave Airlie 				else if (ast->dram_type == AST_DRAM_1Gx32)
318312fec14SDave Airlie 					data = 0x00000c8d;
319312fec14SDave Airlie 
320312fec14SDave Airlie 				temp = ast_read32(ast, 0x12070);
321312fec14SDave Airlie 				temp &= 0xc;
322312fec14SDave Airlie 				temp <<= 2;
323312fec14SDave Airlie 				ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp);
324312fec14SDave Airlie 			} else
325312fec14SDave Airlie 				ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data);
326312fec14SDave Airlie 			dram_reg_info++;
327312fec14SDave Airlie 		}
328312fec14SDave Airlie 
329312fec14SDave Airlie 		/* AST 2100/2150 DRAM calibration */
330312fec14SDave Airlie 		data = ast_read32(ast, 0x10120);
331312fec14SDave Airlie 		if (data == 0x5061) { /* 266Mhz */
332312fec14SDave Airlie 			data = ast_read32(ast, 0x10004);
333312fec14SDave Airlie 			if (data & 0x40)
334312fec14SDave Airlie 				cbrdlli_ast2150(ast, 16); /* 16 bits */
335312fec14SDave Airlie 			else
336312fec14SDave Airlie 				cbrdlli_ast2150(ast, 32); /* 32 bits */
337312fec14SDave Airlie 		}
338312fec14SDave Airlie 
339312fec14SDave Airlie 		switch (ast->chip) {
340312fec14SDave Airlie 		case AST2000:
341312fec14SDave Airlie 			temp = ast_read32(ast, 0x10140);
342312fec14SDave Airlie 			ast_write32(ast, 0x10140, temp | 0x40);
343312fec14SDave Airlie 			break;
344312fec14SDave Airlie 		case AST1100:
345312fec14SDave Airlie 		case AST2100:
346312fec14SDave Airlie 		case AST2200:
347312fec14SDave Airlie 		case AST2150:
348312fec14SDave Airlie 			temp = ast_read32(ast, 0x1200c);
349312fec14SDave Airlie 			ast_write32(ast, 0x1200c, temp & 0xfffffffd);
350312fec14SDave Airlie 			temp = ast_read32(ast, 0x12040);
351312fec14SDave Airlie 			ast_write32(ast, 0x12040, temp | 0x40);
352312fec14SDave Airlie 			break;
353312fec14SDave Airlie 		default:
354312fec14SDave Airlie 			break;
355312fec14SDave Airlie 		}
356312fec14SDave Airlie 	}
357312fec14SDave Airlie 
358312fec14SDave Airlie 	/* wait ready */
359312fec14SDave Airlie 	do {
360312fec14SDave Airlie 		j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
361312fec14SDave Airlie 	} while ((j & 0x40) == 0);
362312fec14SDave Airlie }
363312fec14SDave Airlie 
364312fec14SDave Airlie void ast_post_gpu(struct drm_device *dev)
365312fec14SDave Airlie {
366312fec14SDave Airlie 	u32 reg;
367312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
368312fec14SDave Airlie 
369312fec14SDave Airlie 	pci_read_config_dword(ast->dev->pdev, 0x04, &reg);
370312fec14SDave Airlie 	reg |= 0x3;
371312fec14SDave Airlie 	pci_write_config_dword(ast->dev->pdev, 0x04, reg);
372312fec14SDave Airlie 
373312fec14SDave Airlie 	ast_enable_vga(dev);
374312fec14SDave Airlie 	ast_open_key(ast);
375312fec14SDave Airlie 	ast_set_def_ext_reg(dev);
376312fec14SDave Airlie 
3771453bf4cSDave Airlie 	if (ast->chip == AST2300 || ast->chip == AST2400)
378312fec14SDave Airlie 		ast_init_dram_2300(dev);
379312fec14SDave Airlie 	else
380312fec14SDave Airlie 		ast_init_dram_reg(dev);
38183c6620bSDave Airlie 
38283c6620bSDave Airlie 	ast_init_3rdtx(dev);
383312fec14SDave Airlie }
384312fec14SDave Airlie 
385312fec14SDave Airlie /* AST 2300 DRAM settings */
386312fec14SDave Airlie #define AST_DDR3 0
387312fec14SDave Airlie #define AST_DDR2 1
388312fec14SDave Airlie 
389312fec14SDave Airlie struct ast2300_dram_param {
390312fec14SDave Airlie 	u32 dram_type;
391312fec14SDave Airlie 	u32 dram_chipid;
392312fec14SDave Airlie 	u32 dram_freq;
393312fec14SDave Airlie 	u32 vram_size;
394312fec14SDave Airlie 	u32 odt;
395312fec14SDave Airlie 	u32 wodt;
396312fec14SDave Airlie 	u32 rodt;
397312fec14SDave Airlie 	u32 dram_config;
398312fec14SDave Airlie 	u32 reg_PERIOD;
399312fec14SDave Airlie 	u32 reg_MADJ;
400312fec14SDave Airlie 	u32 reg_SADJ;
401312fec14SDave Airlie 	u32 reg_MRS;
402312fec14SDave Airlie 	u32 reg_EMRS;
403312fec14SDave Airlie 	u32 reg_AC1;
404312fec14SDave Airlie 	u32 reg_AC2;
405312fec14SDave Airlie 	u32 reg_DQSIC;
406312fec14SDave Airlie 	u32 reg_DRV;
407312fec14SDave Airlie 	u32 reg_IOZ;
408312fec14SDave Airlie 	u32 reg_DQIDLY;
409312fec14SDave Airlie 	u32 reg_FREQ;
410312fec14SDave Airlie 	u32 madj_max;
411312fec14SDave Airlie 	u32 dll2_finetune_step;
412312fec14SDave Airlie };
413312fec14SDave Airlie 
414312fec14SDave Airlie /*
415312fec14SDave Airlie  * DQSI DLL CBR Setting
416312fec14SDave Airlie  */
417318cfa29SDave Airlie #define CBR_SIZE0            ((1  << 10) - 1)
418312fec14SDave Airlie #define CBR_SIZE1            ((4  << 10) - 1)
419312fec14SDave Airlie #define CBR_SIZE2            ((64 << 10) - 1)
420312fec14SDave Airlie #define CBR_PASSNUM          5
421312fec14SDave Airlie #define CBR_PASSNUM2         5
422312fec14SDave Airlie #define CBR_THRESHOLD        10
423312fec14SDave Airlie #define CBR_THRESHOLD2       10
424312fec14SDave Airlie #define TIMEOUT              5000000
425312fec14SDave Airlie #define CBR_PATNUM           8
426312fec14SDave Airlie 
427312fec14SDave Airlie static const u32 pattern[8] = {
428312fec14SDave Airlie 	0xFF00FF00,
429312fec14SDave Airlie 	0xCC33CC33,
430312fec14SDave Airlie 	0xAA55AA55,
431312fec14SDave Airlie 	0x88778877,
432312fec14SDave Airlie 	0x92CC4D6E,
433312fec14SDave Airlie 	0x543D3CDE,
434312fec14SDave Airlie 	0xF1E843C7,
435312fec14SDave Airlie 	0x7C61D253
436312fec14SDave Airlie };
437312fec14SDave Airlie 
438312fec14SDave Airlie static int mmc_test_burst(struct ast_private *ast, u32 datagen)
439312fec14SDave Airlie {
440312fec14SDave Airlie 	u32 data, timeout;
441312fec14SDave Airlie 
4420e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
4430e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3));
444312fec14SDave Airlie 	timeout = 0;
445312fec14SDave Airlie 	do {
4460e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
447312fec14SDave Airlie 		if (data & 0x2000) {
448312fec14SDave Airlie 			return 0;
449312fec14SDave Airlie 		}
450312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
4510e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
452312fec14SDave Airlie 			return 0;
453312fec14SDave Airlie 		}
454312fec14SDave Airlie 	} while (!data);
4550e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
456312fec14SDave Airlie 	return 1;
457312fec14SDave Airlie }
458312fec14SDave Airlie 
459312fec14SDave Airlie static int mmc_test_burst2(struct ast_private *ast, u32 datagen)
460312fec14SDave Airlie {
461312fec14SDave Airlie 	u32 data, timeout;
462312fec14SDave Airlie 
4630e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
4640e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3));
465312fec14SDave Airlie 	timeout = 0;
466312fec14SDave Airlie 	do {
4670e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
468312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
4690e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
470312fec14SDave Airlie 			return -1;
471312fec14SDave Airlie 		}
472312fec14SDave Airlie 	} while (!data);
4730e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1e6e0078);
474312fec14SDave Airlie 	data = (data | (data >> 16)) & 0xffff;
4750e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
476312fec14SDave Airlie 	return data;
477312fec14SDave Airlie }
478312fec14SDave Airlie 
479312fec14SDave Airlie static int mmc_test_single(struct ast_private *ast, u32 datagen)
480312fec14SDave Airlie {
481312fec14SDave Airlie 	u32 data, timeout;
482312fec14SDave Airlie 
4830e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
4840e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3));
485312fec14SDave Airlie 	timeout = 0;
486312fec14SDave Airlie 	do {
4870e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
488312fec14SDave Airlie 		if (data & 0x2000)
489312fec14SDave Airlie 			return 0;
490312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
4910e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
492312fec14SDave Airlie 			return 0;
493312fec14SDave Airlie 		}
494312fec14SDave Airlie 	} while (!data);
4950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
496312fec14SDave Airlie 	return 1;
497312fec14SDave Airlie }
498312fec14SDave Airlie 
499312fec14SDave Airlie static int mmc_test_single2(struct ast_private *ast, u32 datagen)
500312fec14SDave Airlie {
501312fec14SDave Airlie 	u32 data, timeout;
502312fec14SDave Airlie 
5030e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
5040e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
505312fec14SDave Airlie 	timeout = 0;
506312fec14SDave Airlie 	do {
5070e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
508312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
5090e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
510312fec14SDave Airlie 			return -1;
511312fec14SDave Airlie 		}
512312fec14SDave Airlie 	} while (!data);
5130e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1e6e0078);
514312fec14SDave Airlie 	data = (data | (data >> 16)) & 0xffff;
5150e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
516312fec14SDave Airlie 	return data;
517312fec14SDave Airlie }
518312fec14SDave Airlie 
519312fec14SDave Airlie static int cbr_test(struct ast_private *ast)
520312fec14SDave Airlie {
521312fec14SDave Airlie 	u32 data;
522312fec14SDave Airlie 	int i;
523312fec14SDave Airlie 	data = mmc_test_single2(ast, 0);
524312fec14SDave Airlie 	if ((data & 0xff) && (data & 0xff00))
525312fec14SDave Airlie 		return 0;
526312fec14SDave Airlie 	for (i = 0; i < 8; i++) {
527312fec14SDave Airlie 		data = mmc_test_burst2(ast, i);
528312fec14SDave Airlie 		if ((data & 0xff) && (data & 0xff00))
529312fec14SDave Airlie 			return 0;
530312fec14SDave Airlie 	}
531312fec14SDave Airlie 	if (!data)
532312fec14SDave Airlie 		return 3;
533312fec14SDave Airlie 	else if (data & 0xff)
534312fec14SDave Airlie 		return 2;
535312fec14SDave Airlie 	return 1;
536312fec14SDave Airlie }
537312fec14SDave Airlie 
538312fec14SDave Airlie static int cbr_scan(struct ast_private *ast)
539312fec14SDave Airlie {
540312fec14SDave Airlie 	u32 data, data2, patcnt, loop;
541312fec14SDave Airlie 
542312fec14SDave Airlie 	data2 = 3;
543312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5440e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
545312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
546312fec14SDave Airlie 			if ((data = cbr_test(ast)) != 0) {
547312fec14SDave Airlie 				data2 &= data;
548312fec14SDave Airlie 				if (!data2)
549312fec14SDave Airlie 					return 0;
550312fec14SDave Airlie 				break;
551312fec14SDave Airlie 			}
552312fec14SDave Airlie 		}
553312fec14SDave Airlie 		if (loop == CBR_PASSNUM2)
554312fec14SDave Airlie 			return 0;
555312fec14SDave Airlie 	}
556312fec14SDave Airlie 	return data2;
557312fec14SDave Airlie }
558312fec14SDave Airlie 
559312fec14SDave Airlie static u32 cbr_test2(struct ast_private *ast)
560312fec14SDave Airlie {
561312fec14SDave Airlie 	u32 data;
562312fec14SDave Airlie 
563312fec14SDave Airlie 	data = mmc_test_burst2(ast, 0);
564312fec14SDave Airlie 	if (data == 0xffff)
565312fec14SDave Airlie 		return 0;
566312fec14SDave Airlie 	data |= mmc_test_single2(ast, 0);
567312fec14SDave Airlie 	if (data == 0xffff)
568312fec14SDave Airlie 		return 0;
569312fec14SDave Airlie 
570312fec14SDave Airlie 	return ~data & 0xffff;
571312fec14SDave Airlie }
572312fec14SDave Airlie 
573312fec14SDave Airlie static u32 cbr_scan2(struct ast_private *ast)
574312fec14SDave Airlie {
575312fec14SDave Airlie 	u32 data, data2, patcnt, loop;
576312fec14SDave Airlie 
577312fec14SDave Airlie 	data2 = 0xffff;
578312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5790e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
580312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
581312fec14SDave Airlie 			if ((data = cbr_test2(ast)) != 0) {
582312fec14SDave Airlie 				data2 &= data;
583312fec14SDave Airlie 				if (!data)
584312fec14SDave Airlie 					return 0;
585312fec14SDave Airlie 				break;
586312fec14SDave Airlie 			}
587312fec14SDave Airlie 		}
588312fec14SDave Airlie 		if (loop == CBR_PASSNUM2)
589312fec14SDave Airlie 			return 0;
590312fec14SDave Airlie 	}
591312fec14SDave Airlie 	return data2;
592312fec14SDave Airlie }
593312fec14SDave Airlie 
594318cfa29SDave Airlie static u32 cbr_test3(struct ast_private *ast)
595312fec14SDave Airlie {
596318cfa29SDave Airlie 	if (!mmc_test_burst(ast, 0))
597318cfa29SDave Airlie 		return 0;
598318cfa29SDave Airlie 	if (!mmc_test_single(ast, 0))
599318cfa29SDave Airlie 		return 0;
600318cfa29SDave Airlie 	return 1;
601318cfa29SDave Airlie }
602312fec14SDave Airlie 
603318cfa29SDave Airlie static u32 cbr_scan3(struct ast_private *ast)
604318cfa29SDave Airlie {
605318cfa29SDave Airlie 	u32 patcnt, loop;
606312fec14SDave Airlie 
607318cfa29SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
6080e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
609318cfa29SDave Airlie 		for (loop = 0; loop < 2; loop++) {
610318cfa29SDave Airlie 			if (cbr_test3(ast))
611312fec14SDave Airlie 				break;
612312fec14SDave Airlie 		}
613318cfa29SDave Airlie 		if (loop == 2)
614318cfa29SDave Airlie 			return 0;
615312fec14SDave Airlie 	}
616318cfa29SDave Airlie 	return 1;
617312fec14SDave Airlie }
618312fec14SDave Airlie 
619318cfa29SDave Airlie static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param)
620312fec14SDave Airlie {
621318cfa29SDave Airlie 	u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
622318cfa29SDave Airlie 	bool status = false;
623312fec14SDave Airlie FINETUNE_START:
624312fec14SDave Airlie 	for (cnt = 0; cnt < 16; cnt++) {
625312fec14SDave Airlie 		dllmin[cnt] = 0xff;
626312fec14SDave Airlie 		dllmax[cnt] = 0x0;
627312fec14SDave Airlie 	}
628312fec14SDave Airlie 	passcnt = 0;
629312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
6300e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
6310e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
632312fec14SDave Airlie 		data = cbr_scan2(ast);
633312fec14SDave Airlie 		if (data != 0) {
634312fec14SDave Airlie 			mask = 0x00010001;
635312fec14SDave Airlie 			for (cnt = 0; cnt < 16; cnt++) {
636312fec14SDave Airlie 				if (data & mask) {
637312fec14SDave Airlie 					if (dllmin[cnt] > dlli) {
638312fec14SDave Airlie 						dllmin[cnt] = dlli;
639312fec14SDave Airlie 					}
640312fec14SDave Airlie 					if (dllmax[cnt] < dlli) {
641312fec14SDave Airlie 						dllmax[cnt] = dlli;
642312fec14SDave Airlie 					}
643312fec14SDave Airlie 				}
644312fec14SDave Airlie 				mask <<= 1;
645312fec14SDave Airlie 			}
646312fec14SDave Airlie 			passcnt++;
647312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD2) {
648312fec14SDave Airlie 			break;
649312fec14SDave Airlie 		}
650312fec14SDave Airlie 	}
651312fec14SDave Airlie 	gold_sadj[0] = 0x0;
652312fec14SDave Airlie 	passcnt = 0;
653312fec14SDave Airlie 	for (cnt = 0; cnt < 16; cnt++) {
654312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
655312fec14SDave Airlie 			gold_sadj[0] += dllmin[cnt];
656312fec14SDave Airlie 			passcnt++;
657312fec14SDave Airlie 		}
658312fec14SDave Airlie 	}
659318cfa29SDave Airlie 	if (retry++ > 10)
660318cfa29SDave Airlie 		goto FINETUNE_DONE;
661312fec14SDave Airlie 	if (passcnt != 16) {
662312fec14SDave Airlie 		goto FINETUNE_START;
663312fec14SDave Airlie 	}
664318cfa29SDave Airlie 	status = true;
665318cfa29SDave Airlie FINETUNE_DONE:
666312fec14SDave Airlie 	gold_sadj[0] = gold_sadj[0] >> 4;
667312fec14SDave Airlie 	gold_sadj[1] = gold_sadj[0];
668312fec14SDave Airlie 
669312fec14SDave Airlie 	data = 0;
670312fec14SDave Airlie 	for (cnt = 0; cnt < 8; cnt++) {
671312fec14SDave Airlie 		data >>= 3;
672312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
673312fec14SDave Airlie 			dlli = dllmin[cnt];
674312fec14SDave Airlie 			if (gold_sadj[0] >= dlli) {
675312fec14SDave Airlie 				dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
676312fec14SDave Airlie 				if (dlli > 3) {
677312fec14SDave Airlie 					dlli = 3;
678312fec14SDave Airlie 				}
679312fec14SDave Airlie 			} else {
680312fec14SDave Airlie 				dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
681312fec14SDave Airlie 				if (dlli > 4) {
682312fec14SDave Airlie 					dlli = 4;
683312fec14SDave Airlie 				}
684312fec14SDave Airlie 				dlli = (8 - dlli) & 0x7;
685312fec14SDave Airlie 			}
686312fec14SDave Airlie 			data |= dlli << 21;
687312fec14SDave Airlie 		}
688312fec14SDave Airlie 	}
6890e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, data);
690312fec14SDave Airlie 
691312fec14SDave Airlie 	data = 0;
692312fec14SDave Airlie 	for (cnt = 8; cnt < 16; cnt++) {
693312fec14SDave Airlie 		data >>= 3;
694312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
695312fec14SDave Airlie 			dlli = dllmin[cnt];
696312fec14SDave Airlie 			if (gold_sadj[1] >= dlli) {
697312fec14SDave Airlie 				dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
698312fec14SDave Airlie 				if (dlli > 3) {
699312fec14SDave Airlie 					dlli = 3;
700312fec14SDave Airlie 				} else {
701312fec14SDave Airlie 					dlli = (dlli - 1) & 0x7;
702312fec14SDave Airlie 				}
703312fec14SDave Airlie 			} else {
704312fec14SDave Airlie 				dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
705312fec14SDave Airlie 				dlli += 1;
706312fec14SDave Airlie 				if (dlli > 4) {
707312fec14SDave Airlie 					dlli = 4;
708312fec14SDave Airlie 				}
709312fec14SDave Airlie 				dlli = (8 - dlli) & 0x7;
710312fec14SDave Airlie 			}
711312fec14SDave Airlie 			data |= dlli << 21;
712312fec14SDave Airlie 		}
713312fec14SDave Airlie 	}
7140e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, data);
715318cfa29SDave Airlie 	return status;
716312fec14SDave Airlie } /* finetuneDQI_L */
717312fec14SDave Airlie 
718318cfa29SDave Airlie static void finetuneDQSI(struct ast_private *ast)
719312fec14SDave Airlie {
720318cfa29SDave Airlie 	u32 dlli, dqsip, dqidly;
721318cfa29SDave Airlie 	u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
722318cfa29SDave Airlie 	u32 g_dqidly, g_dqsip, g_margin, g_side;
723318cfa29SDave Airlie 	u16 pass[32][2][2];
724318cfa29SDave Airlie 	char tag[2][76];
725312fec14SDave Airlie 
726318cfa29SDave Airlie 	/* Disable DQI CBR */
7270e5ce924SDave Airlie 	reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
7280e5ce924SDave Airlie 	reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
729318cfa29SDave Airlie 	reg_mcr18 &= 0x0000ffff;
7300e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
731318cfa29SDave Airlie 
732312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
733318cfa29SDave Airlie 		tag[0][dlli] = 0x0;
734318cfa29SDave Airlie 		tag[1][dlli] = 0x0;
735312fec14SDave Airlie 	}
736318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
737318cfa29SDave Airlie 		pass[dqidly][0][0] = 0xff;
738318cfa29SDave Airlie 		pass[dqidly][0][1] = 0x0;
739318cfa29SDave Airlie 		pass[dqidly][1][0] = 0xff;
740318cfa29SDave Airlie 		pass[dqidly][1][1] = 0x0;
741312fec14SDave Airlie 	}
742318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
743318cfa29SDave Airlie 		passcnt[0] = passcnt[1] = 0;
744318cfa29SDave Airlie 		for (dqsip = 0; dqsip < 2; dqsip++) {
7450e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E000C, 0);
7460e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
7470e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
748318cfa29SDave Airlie 			for (dlli = 0; dlli < 76; dlli++) {
7490e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
7500e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0070, 0);
7510e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
752318cfa29SDave Airlie 				if (cbr_scan3(ast)) {
753318cfa29SDave Airlie 					if (dlli == 0)
754312fec14SDave Airlie 						break;
755318cfa29SDave Airlie 					passcnt[dqsip]++;
756318cfa29SDave Airlie 					tag[dqsip][dlli] = 'P';
757318cfa29SDave Airlie 					if (dlli < pass[dqidly][dqsip][0])
758318cfa29SDave Airlie 						pass[dqidly][dqsip][0] = (u16) dlli;
759318cfa29SDave Airlie 					if (dlli > pass[dqidly][dqsip][1])
760318cfa29SDave Airlie 						pass[dqidly][dqsip][1] = (u16) dlli;
761318cfa29SDave Airlie 				} else if (passcnt[dqsip] >= 5)
762318cfa29SDave Airlie 					break;
763318cfa29SDave Airlie 				else {
764318cfa29SDave Airlie 					pass[dqidly][dqsip][0] = 0xff;
765318cfa29SDave Airlie 					pass[dqidly][dqsip][1] = 0x0;
766312fec14SDave Airlie 				}
767312fec14SDave Airlie 			}
768312fec14SDave Airlie 		}
769318cfa29SDave Airlie 		if (passcnt[0] == 0 && passcnt[1] == 0)
770318cfa29SDave Airlie 			dqidly++;
771318cfa29SDave Airlie 	}
772318cfa29SDave Airlie 	/* Search margin */
773318cfa29SDave Airlie 	g_dqidly = g_dqsip = g_margin = g_side = 0;
774312fec14SDave Airlie 
775318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
776318cfa29SDave Airlie 		for (dqsip = 0; dqsip < 2; dqsip++) {
777318cfa29SDave Airlie 			if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
778318cfa29SDave Airlie 				continue;
779318cfa29SDave Airlie 			diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
780318cfa29SDave Airlie 			if ((diff+2) < g_margin)
781318cfa29SDave Airlie 				continue;
782318cfa29SDave Airlie 			passcnt[0] = passcnt[1] = 0;
783318cfa29SDave Airlie 			for (dlli = pass[dqidly][dqsip][0]; dlli > 0  && tag[dqsip][dlli] != 0; dlli--, passcnt[0]++);
784318cfa29SDave Airlie 			for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && tag[dqsip][dlli] != 0; dlli++, passcnt[1]++);
785318cfa29SDave Airlie 			if (passcnt[0] > passcnt[1])
786318cfa29SDave Airlie 				passcnt[0] = passcnt[1];
787318cfa29SDave Airlie 			passcnt[1] = 0;
788318cfa29SDave Airlie 			if (passcnt[0] > g_side)
789318cfa29SDave Airlie 				passcnt[1] = passcnt[0] - g_side;
790318cfa29SDave Airlie 			if (diff > (g_margin+1) && (passcnt[1] > 0 || passcnt[0] > 8)) {
791318cfa29SDave Airlie 				g_margin = diff;
792318cfa29SDave Airlie 				g_dqidly = dqidly;
793318cfa29SDave Airlie 				g_dqsip  = dqsip;
794318cfa29SDave Airlie 				g_side   = passcnt[0];
795318cfa29SDave Airlie 			} else if (passcnt[1] > 1 && g_side < 8) {
796318cfa29SDave Airlie 				if (diff > g_margin)
797318cfa29SDave Airlie 					g_margin = diff;
798318cfa29SDave Airlie 				g_dqidly = dqidly;
799318cfa29SDave Airlie 				g_dqsip  = dqsip;
800318cfa29SDave Airlie 				g_side   = passcnt[0];
801312fec14SDave Airlie 			}
802312fec14SDave Airlie 		}
803312fec14SDave Airlie 	}
804318cfa29SDave Airlie 	reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
8050e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
806312fec14SDave Airlie 
807312fec14SDave Airlie }
808318cfa29SDave Airlie static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param)
809312fec14SDave Airlie {
810318cfa29SDave Airlie 	u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
811318cfa29SDave Airlie 	bool status = false;
812312fec14SDave Airlie 
813318cfa29SDave Airlie 	finetuneDQSI(ast);
814318cfa29SDave Airlie 	if (finetuneDQI_L(ast, param) == false)
815318cfa29SDave Airlie 		return status;
816312fec14SDave Airlie 
817312fec14SDave Airlie CBR_START2:
818312fec14SDave Airlie 	dllmin[0] = dllmin[1] = 0xff;
819312fec14SDave Airlie 	dllmax[0] = dllmax[1] = 0x0;
820312fec14SDave Airlie 	passcnt = 0;
821312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
8220e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
8230e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
824312fec14SDave Airlie 		data = cbr_scan(ast);
825312fec14SDave Airlie 		if (data != 0) {
826312fec14SDave Airlie 			if (data & 0x1) {
827312fec14SDave Airlie 				if (dllmin[0] > dlli) {
828312fec14SDave Airlie 					dllmin[0] = dlli;
829312fec14SDave Airlie 				}
830312fec14SDave Airlie 				if (dllmax[0] < dlli) {
831312fec14SDave Airlie 					dllmax[0] = dlli;
832312fec14SDave Airlie 				}
833312fec14SDave Airlie 			}
834312fec14SDave Airlie 			if (data & 0x2) {
835312fec14SDave Airlie 				if (dllmin[1] > dlli) {
836312fec14SDave Airlie 					dllmin[1] = dlli;
837312fec14SDave Airlie 				}
838312fec14SDave Airlie 				if (dllmax[1] < dlli) {
839312fec14SDave Airlie 					dllmax[1] = dlli;
840312fec14SDave Airlie 				}
841312fec14SDave Airlie 			}
842312fec14SDave Airlie 			passcnt++;
843312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD) {
844312fec14SDave Airlie 			break;
845312fec14SDave Airlie 		}
846312fec14SDave Airlie 	}
847318cfa29SDave Airlie 	if (retry++ > 10)
848318cfa29SDave Airlie 		goto CBR_DONE2;
849312fec14SDave Airlie 	if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) {
850312fec14SDave Airlie 		goto CBR_START2;
851312fec14SDave Airlie 	}
852312fec14SDave Airlie 	if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) {
853312fec14SDave Airlie 		goto CBR_START2;
854312fec14SDave Airlie 	}
855318cfa29SDave Airlie 	status = true;
856318cfa29SDave Airlie CBR_DONE2:
857312fec14SDave Airlie 	dlli  = (dllmin[1] + dllmax[1]) >> 1;
858312fec14SDave Airlie 	dlli <<= 8;
859312fec14SDave Airlie 	dlli += (dllmin[0] + dllmax[0]) >> 1;
8600e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16));
861318cfa29SDave Airlie 	return status;
862312fec14SDave Airlie } /* CBRDLL2 */
863312fec14SDave Airlie 
864312fec14SDave Airlie static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param)
865312fec14SDave Airlie {
866312fec14SDave Airlie 	u32 trap, trap_AC2, trap_MRS;
867312fec14SDave Airlie 
8680e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
869312fec14SDave Airlie 
870312fec14SDave Airlie 	/* Ger trap info */
8710e5ce924SDave Airlie 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
872312fec14SDave Airlie 	trap_AC2  = 0x00020000 + (trap << 16);
873312fec14SDave Airlie 	trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
874312fec14SDave Airlie 	trap_MRS  = 0x00000010 + (trap << 4);
875312fec14SDave Airlie 	trap_MRS |= ((trap & 0x2) << 18);
876312fec14SDave Airlie 
877312fec14SDave Airlie 	param->reg_MADJ       = 0x00034C4C;
878312fec14SDave Airlie 	param->reg_SADJ       = 0x00001800;
879312fec14SDave Airlie 	param->reg_DRV        = 0x000000F0;
880312fec14SDave Airlie 	param->reg_PERIOD     = param->dram_freq;
881312fec14SDave Airlie 	param->rodt           = 0;
882312fec14SDave Airlie 
883312fec14SDave Airlie 	switch (param->dram_freq) {
884312fec14SDave Airlie 	case 336:
8850e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
886312fec14SDave Airlie 		param->wodt          = 0;
887312fec14SDave Airlie 		param->reg_AC1       = 0x22202725;
888312fec14SDave Airlie 		param->reg_AC2       = 0xAA007613 | trap_AC2;
889312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000BA;
890312fec14SDave Airlie 		param->reg_MRS       = 0x04001400 | trap_MRS;
891312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
892318cfa29SDave Airlie 		param->reg_IOZ       = 0x00000023;
893312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000074;
894312fec14SDave Airlie 		param->reg_FREQ      = 0x00004DC0;
895312fec14SDave Airlie 		param->madj_max      = 96;
896312fec14SDave Airlie 		param->dll2_finetune_step = 3;
897318cfa29SDave Airlie 		switch (param->dram_chipid) {
898318cfa29SDave Airlie 		default:
899318cfa29SDave Airlie 		case AST_DRAM_512Mx16:
900318cfa29SDave Airlie 		case AST_DRAM_1Gx16:
901318cfa29SDave Airlie 			param->reg_AC2   = 0xAA007613 | trap_AC2;
902318cfa29SDave Airlie 			break;
903318cfa29SDave Airlie 		case AST_DRAM_2Gx16:
904318cfa29SDave Airlie 			param->reg_AC2   = 0xAA00761C | trap_AC2;
905318cfa29SDave Airlie 			break;
906318cfa29SDave Airlie 		case AST_DRAM_4Gx16:
907318cfa29SDave Airlie 			param->reg_AC2   = 0xAA007636 | trap_AC2;
908318cfa29SDave Airlie 			break;
909318cfa29SDave Airlie 		}
910312fec14SDave Airlie 		break;
911312fec14SDave Airlie 	default:
912312fec14SDave Airlie 	case 396:
9130e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
914312fec14SDave Airlie 		param->wodt          = 1;
915312fec14SDave Airlie 		param->reg_AC1       = 0x33302825;
916312fec14SDave Airlie 		param->reg_AC2       = 0xCC009617 | trap_AC2;
917312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
918312fec14SDave Airlie 		param->reg_MRS       = 0x04001600 | trap_MRS;
919312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
920312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
921312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
922312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
923318cfa29SDave Airlie 		param->reg_FREQ      = 0x00005040;
924312fec14SDave Airlie 		param->madj_max      = 96;
925312fec14SDave Airlie 		param->dll2_finetune_step = 4;
926312fec14SDave Airlie 
927312fec14SDave Airlie 		switch (param->dram_chipid) {
928312fec14SDave Airlie 		default:
929312fec14SDave Airlie 		case AST_DRAM_512Mx16:
930312fec14SDave Airlie 		case AST_DRAM_1Gx16:
931312fec14SDave Airlie 			param->reg_AC2   = 0xCC009617 | trap_AC2;
932312fec14SDave Airlie 			break;
933312fec14SDave Airlie 		case AST_DRAM_2Gx16:
934312fec14SDave Airlie 			param->reg_AC2   = 0xCC009622 | trap_AC2;
935312fec14SDave Airlie 			break;
936312fec14SDave Airlie 		case AST_DRAM_4Gx16:
937312fec14SDave Airlie 			param->reg_AC2   = 0xCC00963F | trap_AC2;
938312fec14SDave Airlie 			break;
939312fec14SDave Airlie 		}
940312fec14SDave Airlie 		break;
941312fec14SDave Airlie 
942312fec14SDave Airlie 	case 408:
9430e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
944312fec14SDave Airlie 		param->wodt          = 1;
945312fec14SDave Airlie 		param->reg_AC1       = 0x33302825;
946312fec14SDave Airlie 		param->reg_AC2       = 0xCC009617 | trap_AC2;
947312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
948312fec14SDave Airlie 		param->reg_MRS       = 0x04001600 | trap_MRS;
949312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
950318cfa29SDave Airlie 		param->reg_IOZ       = 0x00000023;
951312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
952312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
953312fec14SDave Airlie 		param->reg_FREQ      = 0x000050C0;
954312fec14SDave Airlie 		param->madj_max      = 96;
955312fec14SDave Airlie 		param->dll2_finetune_step = 4;
956312fec14SDave Airlie 
957312fec14SDave Airlie 		switch (param->dram_chipid) {
958312fec14SDave Airlie 		default:
959312fec14SDave Airlie 		case AST_DRAM_512Mx16:
960312fec14SDave Airlie 		case AST_DRAM_1Gx16:
961312fec14SDave Airlie 			param->reg_AC2   = 0xCC009617 | trap_AC2;
962312fec14SDave Airlie 			break;
963312fec14SDave Airlie 		case AST_DRAM_2Gx16:
964312fec14SDave Airlie 			param->reg_AC2   = 0xCC009622 | trap_AC2;
965312fec14SDave Airlie 			break;
966312fec14SDave Airlie 		case AST_DRAM_4Gx16:
967312fec14SDave Airlie 			param->reg_AC2   = 0xCC00963F | trap_AC2;
968312fec14SDave Airlie 			break;
969312fec14SDave Airlie 		}
970312fec14SDave Airlie 
971312fec14SDave Airlie 		break;
972312fec14SDave Airlie 	case 456:
9730e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
974312fec14SDave Airlie 		param->wodt          = 0;
975312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
976312fec14SDave Airlie 		param->reg_AC2       = 0xCD44961A;
977312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000FC;
978312fec14SDave Airlie 		param->reg_MRS       = 0x00081830;
979312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
980312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
981312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000097;
982312fec14SDave Airlie 		param->reg_FREQ      = 0x000052C0;
983312fec14SDave Airlie 		param->madj_max      = 88;
984312fec14SDave Airlie 		param->dll2_finetune_step = 4;
985312fec14SDave Airlie 		break;
986312fec14SDave Airlie 	case 504:
9870e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0270);
988312fec14SDave Airlie 		param->wodt          = 1;
989312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
990312fec14SDave Airlie 		param->reg_AC2       = 0xDE44A61D;
991312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000117;
992312fec14SDave Airlie 		param->reg_MRS       = 0x00081A30;
993312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
994312fec14SDave Airlie 		param->reg_IOZ       = 0x070000BB;
995312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A0;
996312fec14SDave Airlie 		param->reg_FREQ      = 0x000054C0;
997312fec14SDave Airlie 		param->madj_max      = 79;
998312fec14SDave Airlie 		param->dll2_finetune_step = 4;
999312fec14SDave Airlie 		break;
1000312fec14SDave Airlie 	case 528:
10010e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0290);
1002312fec14SDave Airlie 		param->wodt          = 1;
1003312fec14SDave Airlie 		param->rodt          = 1;
1004312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
1005312fec14SDave Airlie 		param->reg_AC2       = 0xEF44B61E;
1006312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000125;
1007312fec14SDave Airlie 		param->reg_MRS       = 0x00081A30;
1008312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1009312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1010312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1011312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000088;
1012312fec14SDave Airlie 		param->reg_FREQ      = 0x000055C0;
1013312fec14SDave Airlie 		param->madj_max      = 76;
1014312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1015312fec14SDave Airlie 		break;
1016312fec14SDave Airlie 	case 576:
10170e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1018312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1019312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1020312fec14SDave Airlie 		param->wodt          = 1;
1021312fec14SDave Airlie 		param->rodt          = 1;
1022312fec14SDave Airlie 		param->reg_AC1       = 0x33302A37;
1023312fec14SDave Airlie 		param->reg_AC2       = 0xEF56B61E;
1024312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000013F;
1025312fec14SDave Airlie 		param->reg_MRS       = 0x00101A50;
1026312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1027312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1028312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1029312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1030312fec14SDave Airlie 		param->reg_FREQ      = 0x000057C0;
1031312fec14SDave Airlie 		param->madj_max      = 136;
1032312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1033312fec14SDave Airlie 		break;
1034312fec14SDave Airlie 	case 600:
10350e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
1036312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1037312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1038312fec14SDave Airlie 		param->wodt          = 1;
1039312fec14SDave Airlie 		param->rodt          = 1;
1040312fec14SDave Airlie 		param->reg_AC1       = 0x32302A37;
1041312fec14SDave Airlie 		param->reg_AC2       = 0xDF56B61F;
1042312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000014D;
1043312fec14SDave Airlie 		param->reg_MRS       = 0x00101A50;
1044312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1045312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1046312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1047312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1048312fec14SDave Airlie 		param->reg_FREQ      = 0x000058C0;
1049312fec14SDave Airlie 		param->madj_max      = 132;
1050312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1051312fec14SDave Airlie 		break;
1052312fec14SDave Airlie 	case 624:
10530e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0160);
1054312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1055312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1056312fec14SDave Airlie 		param->wodt          = 1;
1057312fec14SDave Airlie 		param->rodt          = 1;
1058312fec14SDave Airlie 		param->reg_AC1       = 0x32302A37;
1059312fec14SDave Airlie 		param->reg_AC2       = 0xEF56B621;
1060312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000015A;
1061312fec14SDave Airlie 		param->reg_MRS       = 0x02101A50;
1062312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1063312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1064312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1065312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1066312fec14SDave Airlie 		param->reg_FREQ      = 0x000059C0;
1067312fec14SDave Airlie 		param->madj_max      = 128;
1068312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1069312fec14SDave Airlie 		break;
1070312fec14SDave Airlie 	} /* switch freq */
1071312fec14SDave Airlie 
1072312fec14SDave Airlie 	switch (param->dram_chipid) {
1073312fec14SDave Airlie 	case AST_DRAM_512Mx16:
1074312fec14SDave Airlie 		param->dram_config = 0x130;
1075312fec14SDave Airlie 		break;
1076312fec14SDave Airlie 	default:
1077312fec14SDave Airlie 	case AST_DRAM_1Gx16:
1078312fec14SDave Airlie 		param->dram_config = 0x131;
1079312fec14SDave Airlie 		break;
1080312fec14SDave Airlie 	case AST_DRAM_2Gx16:
1081312fec14SDave Airlie 		param->dram_config = 0x132;
1082312fec14SDave Airlie 		break;
1083312fec14SDave Airlie 	case AST_DRAM_4Gx16:
1084312fec14SDave Airlie 		param->dram_config = 0x133;
1085312fec14SDave Airlie 		break;
1086312fec14SDave Airlie 	}; /* switch size */
1087312fec14SDave Airlie 
1088312fec14SDave Airlie 	switch (param->vram_size) {
1089312fec14SDave Airlie 	default:
1090312fec14SDave Airlie 	case AST_VIDMEM_SIZE_8M:
1091312fec14SDave Airlie 		param->dram_config |= 0x00;
1092312fec14SDave Airlie 		break;
1093312fec14SDave Airlie 	case AST_VIDMEM_SIZE_16M:
1094312fec14SDave Airlie 		param->dram_config |= 0x04;
1095312fec14SDave Airlie 		break;
1096312fec14SDave Airlie 	case AST_VIDMEM_SIZE_32M:
1097312fec14SDave Airlie 		param->dram_config |= 0x08;
1098312fec14SDave Airlie 		break;
1099312fec14SDave Airlie 	case AST_VIDMEM_SIZE_64M:
1100312fec14SDave Airlie 		param->dram_config |= 0x0c;
1101312fec14SDave Airlie 		break;
1102312fec14SDave Airlie 	}
1103312fec14SDave Airlie 
1104312fec14SDave Airlie }
1105312fec14SDave Airlie 
1106312fec14SDave Airlie static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param)
1107312fec14SDave Airlie {
1108318cfa29SDave Airlie 	u32 data, data2, retry = 0;
1109312fec14SDave Airlie 
1110318cfa29SDave Airlie ddr3_init_start:
11110e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
11120e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
11130e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
11140e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
1115312fec14SDave Airlie 	udelay(10);
11160e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
11170e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1118312fec14SDave Airlie 	udelay(10);
11190e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1120312fec14SDave Airlie 	udelay(10);
1121312fec14SDave Airlie 
11220e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
11230e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
11240e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
11250e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
11260e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
11270e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
11280e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
11290e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
11300e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
11310e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
11320e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
11330e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
11340e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
11350e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
11360e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
11370e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
11380e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
11390e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0054, 0);
11400e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
11410e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
11420e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
11430e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
11440e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
11450e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1146312fec14SDave Airlie 	/* Wait MCLK2X lock to MCLK */
1147312fec14SDave Airlie 	do {
11480e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1149312fec14SDave Airlie 	} while (!(data & 0x08000000));
11500e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E001C);
1151312fec14SDave Airlie 	data = (data >> 8) & 0xff;
1152312fec14SDave Airlie 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
11530e5ce924SDave Airlie 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1154312fec14SDave Airlie 		if ((data2 & 0xff) > param->madj_max) {
1155312fec14SDave Airlie 			break;
1156312fec14SDave Airlie 		}
11570e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, data2);
1158312fec14SDave Airlie 		if (data2 & 0x00100000) {
1159312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 3) + 3;
1160312fec14SDave Airlie 		} else {
1161312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 2) + 5;
1162312fec14SDave Airlie 		}
11630e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1164312fec14SDave Airlie 		data2 += data & 0xff;
1165312fec14SDave Airlie 		data = data | (data2 << 8);
11660e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, data);
1167312fec14SDave Airlie 		udelay(10);
11680e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1169312fec14SDave Airlie 		udelay(10);
11700e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
11710e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1172312fec14SDave Airlie 		data = data | 0x200;
11730e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1174312fec14SDave Airlie 		do {
11750e5ce924SDave Airlie 			data = ast_mindwm(ast, 0x1E6E001C);
1176312fec14SDave Airlie 		} while (!(data & 0x08000000));
1177312fec14SDave Airlie 
11780e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1179312fec14SDave Airlie 		data = (data >> 8) & 0xff;
1180312fec14SDave Airlie 	}
11810e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
11820e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
11830e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, data);
1184312fec14SDave Airlie 
11850e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
11860e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
1187312fec14SDave Airlie 	udelay(50);
1188312fec14SDave Airlie 	/* Mode Register Setting */
11890e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
11900e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
11910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
11920e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
11930e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
11940e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
11950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
11960e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
11970e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1198312fec14SDave Airlie 
11990e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
1200312fec14SDave Airlie 	data = 0;
1201312fec14SDave Airlie 	if (param->wodt) {
1202312fec14SDave Airlie 		data = 0x300;
1203312fec14SDave Airlie 	}
1204312fec14SDave Airlie 	if (param->rodt) {
1205312fec14SDave Airlie 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1206312fec14SDave Airlie 	}
12070e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1208312fec14SDave Airlie 
1209312fec14SDave Airlie 	/* Calibrate the DQSI delay */
1210318cfa29SDave Airlie 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1211318cfa29SDave Airlie 		goto ddr3_init_start;
1212312fec14SDave Airlie 
12130e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1214312fec14SDave Airlie 	/* ECC Memory Initialization */
1215312fec14SDave Airlie #ifdef ECC
12160e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
12170e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1218312fec14SDave Airlie 	do {
12190e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0070);
1220312fec14SDave Airlie 	} while (!(data & 0x00001000));
12210e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
12220e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
12230e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1224312fec14SDave Airlie #endif
1225312fec14SDave Airlie 
1226312fec14SDave Airlie 
1227312fec14SDave Airlie }
1228312fec14SDave Airlie 
1229312fec14SDave Airlie static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param)
1230312fec14SDave Airlie {
1231312fec14SDave Airlie 	u32 trap, trap_AC2, trap_MRS;
1232312fec14SDave Airlie 
12330e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
1234312fec14SDave Airlie 
1235312fec14SDave Airlie 	/* Ger trap info */
12360e5ce924SDave Airlie 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
1237312fec14SDave Airlie 	trap_AC2  = (trap << 20) | (trap << 16);
1238312fec14SDave Airlie 	trap_AC2 += 0x00110000;
1239312fec14SDave Airlie 	trap_MRS  = 0x00000040 | (trap << 4);
1240312fec14SDave Airlie 
1241312fec14SDave Airlie 
1242312fec14SDave Airlie 	param->reg_MADJ       = 0x00034C4C;
1243312fec14SDave Airlie 	param->reg_SADJ       = 0x00001800;
1244312fec14SDave Airlie 	param->reg_DRV        = 0x000000F0;
1245312fec14SDave Airlie 	param->reg_PERIOD     = param->dram_freq;
1246312fec14SDave Airlie 	param->rodt           = 0;
1247312fec14SDave Airlie 
1248312fec14SDave Airlie 	switch (param->dram_freq) {
1249312fec14SDave Airlie 	case 264:
12500e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0130);
1251312fec14SDave Airlie 		param->wodt          = 0;
1252312fec14SDave Airlie 		param->reg_AC1       = 0x11101513;
1253312fec14SDave Airlie 		param->reg_AC2       = 0x78117011;
1254312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000092;
1255312fec14SDave Airlie 		param->reg_MRS       = 0x00000842;
1256312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1257312fec14SDave Airlie 		param->reg_DRV       = 0x000000F0;
1258312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1259312fec14SDave Airlie 		param->reg_DQIDLY    = 0x0000005A;
1260312fec14SDave Airlie 		param->reg_FREQ      = 0x00004AC0;
1261312fec14SDave Airlie 		param->madj_max      = 138;
1262312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1263312fec14SDave Airlie 		break;
1264312fec14SDave Airlie 	case 336:
12650e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
1266312fec14SDave Airlie 		param->wodt          = 1;
1267312fec14SDave Airlie 		param->reg_AC1       = 0x22202613;
1268312fec14SDave Airlie 		param->reg_AC2       = 0xAA009016 | trap_AC2;
1269312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000BA;
1270312fec14SDave Airlie 		param->reg_MRS       = 0x00000A02 | trap_MRS;
1271312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1272312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1273312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1274312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000074;
1275312fec14SDave Airlie 		param->reg_FREQ      = 0x00004DC0;
1276312fec14SDave Airlie 		param->madj_max      = 96;
1277312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1278318cfa29SDave Airlie 		switch (param->dram_chipid) {
1279318cfa29SDave Airlie 		default:
1280318cfa29SDave Airlie 		case AST_DRAM_512Mx16:
1281318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009012 | trap_AC2;
1282318cfa29SDave Airlie 			break;
1283318cfa29SDave Airlie 		case AST_DRAM_1Gx16:
1284318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009016 | trap_AC2;
1285318cfa29SDave Airlie 			break;
1286318cfa29SDave Airlie 		case AST_DRAM_2Gx16:
1287318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009023 | trap_AC2;
1288318cfa29SDave Airlie 			break;
1289318cfa29SDave Airlie 		case AST_DRAM_4Gx16:
1290318cfa29SDave Airlie 			param->reg_AC2   = 0xAA00903B | trap_AC2;
1291318cfa29SDave Airlie 			break;
1292318cfa29SDave Airlie 		}
1293312fec14SDave Airlie 		break;
1294312fec14SDave Airlie 	default:
1295312fec14SDave Airlie 	case 396:
12960e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
1297312fec14SDave Airlie 		param->wodt          = 1;
1298312fec14SDave Airlie 		param->rodt          = 0;
1299312fec14SDave Airlie 		param->reg_AC1       = 0x33302714;
1300312fec14SDave Airlie 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1301312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
1302312fec14SDave Airlie 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1303312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1304312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1305312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1306312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
1307318cfa29SDave Airlie 		param->reg_FREQ      = 0x00005040;
1308312fec14SDave Airlie 		param->madj_max      = 96;
1309312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1310312fec14SDave Airlie 
1311312fec14SDave Airlie 		switch (param->dram_chipid) {
1312312fec14SDave Airlie 		case AST_DRAM_512Mx16:
1313312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1314312fec14SDave Airlie 			break;
1315312fec14SDave Airlie 		default:
1316312fec14SDave Airlie 		case AST_DRAM_1Gx16:
1317312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1318312fec14SDave Airlie 			break;
1319312fec14SDave Airlie 		case AST_DRAM_2Gx16:
1320312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1321312fec14SDave Airlie 			break;
1322312fec14SDave Airlie 		case AST_DRAM_4Gx16:
1323312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1324312fec14SDave Airlie 			break;
1325312fec14SDave Airlie 		}
1326312fec14SDave Airlie 
1327312fec14SDave Airlie 		break;
1328312fec14SDave Airlie 
1329312fec14SDave Airlie 	case 408:
13300e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
1331312fec14SDave Airlie 		param->wodt          = 1;
1332312fec14SDave Airlie 		param->rodt          = 0;
1333312fec14SDave Airlie 		param->reg_AC1       = 0x33302714;
1334312fec14SDave Airlie 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1335312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
1336312fec14SDave Airlie 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1337312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1338312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1339312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1340312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
1341312fec14SDave Airlie 		param->reg_FREQ      = 0x000050C0;
1342312fec14SDave Airlie 		param->madj_max      = 96;
1343312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1344312fec14SDave Airlie 
1345312fec14SDave Airlie 		switch (param->dram_chipid) {
1346312fec14SDave Airlie 		case AST_DRAM_512Mx16:
1347312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1348312fec14SDave Airlie 			break;
1349312fec14SDave Airlie 		default:
1350312fec14SDave Airlie 		case AST_DRAM_1Gx16:
1351312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1352312fec14SDave Airlie 			break;
1353312fec14SDave Airlie 		case AST_DRAM_2Gx16:
1354312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1355312fec14SDave Airlie 			break;
1356312fec14SDave Airlie 		case AST_DRAM_4Gx16:
1357312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1358312fec14SDave Airlie 			break;
1359312fec14SDave Airlie 		}
1360312fec14SDave Airlie 
1361312fec14SDave Airlie 		break;
1362312fec14SDave Airlie 	case 456:
13630e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
1364312fec14SDave Airlie 		param->wodt          = 0;
1365312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1366312fec14SDave Airlie 		param->reg_AC2       = 0xCD44B01E;
1367312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000FC;
1368312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1369312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1370312fec14SDave Airlie 		param->reg_DRV       = 0x00000000;
1371312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1372312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000097;
1373312fec14SDave Airlie 		param->reg_FREQ      = 0x000052C0;
1374312fec14SDave Airlie 		param->madj_max      = 88;
1375312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1376312fec14SDave Airlie 		break;
1377312fec14SDave Airlie 	case 504:
13780e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0261);
1379312fec14SDave Airlie 		param->wodt          = 1;
1380312fec14SDave Airlie 		param->rodt          = 1;
1381312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1382312fec14SDave Airlie 		param->reg_AC2       = 0xDE44C022;
1383312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000117;
1384312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1385312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1386312fec14SDave Airlie 		param->reg_DRV       = 0x0000000A;
1387312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1388312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A0;
1389312fec14SDave Airlie 		param->reg_FREQ      = 0x000054C0;
1390312fec14SDave Airlie 		param->madj_max      = 79;
1391312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1392312fec14SDave Airlie 		break;
1393312fec14SDave Airlie 	case 528:
13940e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0120);
1395312fec14SDave Airlie 		param->wodt          = 1;
1396312fec14SDave Airlie 		param->rodt          = 1;
1397312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1398312fec14SDave Airlie 		param->reg_AC2       = 0xEF44D024;
1399312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000125;
1400312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1401312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1402312fec14SDave Airlie 		param->reg_DRV       = 0x000000F9;
1403312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1404312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A7;
1405312fec14SDave Airlie 		param->reg_FREQ      = 0x000055C0;
1406312fec14SDave Airlie 		param->madj_max      = 76;
1407312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1408312fec14SDave Airlie 		break;
1409312fec14SDave Airlie 	case 552:
14100e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
1411312fec14SDave Airlie 		param->wodt          = 1;
1412312fec14SDave Airlie 		param->rodt          = 1;
1413312fec14SDave Airlie 		param->reg_AC1       = 0x43402915;
1414312fec14SDave Airlie 		param->reg_AC2       = 0xFF44E025;
1415312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000132;
1416312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1417312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1418312fec14SDave Airlie 		param->reg_DRV       = 0x0000000A;
1419312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1420312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000AD;
1421312fec14SDave Airlie 		param->reg_FREQ      = 0x000056C0;
1422312fec14SDave Airlie 		param->madj_max      = 76;
1423312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1424312fec14SDave Airlie 		break;
1425312fec14SDave Airlie 	case 576:
14260e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1427312fec14SDave Airlie 		param->wodt          = 1;
1428312fec14SDave Airlie 		param->rodt          = 1;
1429312fec14SDave Airlie 		param->reg_AC1       = 0x43402915;
1430312fec14SDave Airlie 		param->reg_AC2       = 0xFF44E027;
1431312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000013F;
1432312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1433312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1434312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1435312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1436312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000B3;
1437312fec14SDave Airlie 		param->reg_FREQ      = 0x000057C0;
1438312fec14SDave Airlie 		param->madj_max      = 76;
1439312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1440312fec14SDave Airlie 		break;
1441312fec14SDave Airlie 	}
1442312fec14SDave Airlie 
1443312fec14SDave Airlie 	switch (param->dram_chipid) {
1444312fec14SDave Airlie 	case AST_DRAM_512Mx16:
1445312fec14SDave Airlie 		param->dram_config = 0x100;
1446312fec14SDave Airlie 		break;
1447312fec14SDave Airlie 	default:
1448312fec14SDave Airlie 	case AST_DRAM_1Gx16:
1449312fec14SDave Airlie 		param->dram_config = 0x121;
1450312fec14SDave Airlie 		break;
1451312fec14SDave Airlie 	case AST_DRAM_2Gx16:
1452312fec14SDave Airlie 		param->dram_config = 0x122;
1453312fec14SDave Airlie 		break;
1454312fec14SDave Airlie 	case AST_DRAM_4Gx16:
1455312fec14SDave Airlie 		param->dram_config = 0x123;
1456312fec14SDave Airlie 		break;
1457312fec14SDave Airlie 	}; /* switch size */
1458312fec14SDave Airlie 
1459312fec14SDave Airlie 	switch (param->vram_size) {
1460312fec14SDave Airlie 	default:
1461312fec14SDave Airlie 	case AST_VIDMEM_SIZE_8M:
1462312fec14SDave Airlie 		param->dram_config |= 0x00;
1463312fec14SDave Airlie 		break;
1464312fec14SDave Airlie 	case AST_VIDMEM_SIZE_16M:
1465312fec14SDave Airlie 		param->dram_config |= 0x04;
1466312fec14SDave Airlie 		break;
1467312fec14SDave Airlie 	case AST_VIDMEM_SIZE_32M:
1468312fec14SDave Airlie 		param->dram_config |= 0x08;
1469312fec14SDave Airlie 		break;
1470312fec14SDave Airlie 	case AST_VIDMEM_SIZE_64M:
1471312fec14SDave Airlie 		param->dram_config |= 0x0c;
1472312fec14SDave Airlie 		break;
1473312fec14SDave Airlie 	}
1474312fec14SDave Airlie }
1475312fec14SDave Airlie 
1476312fec14SDave Airlie static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param)
1477312fec14SDave Airlie {
1478318cfa29SDave Airlie 	u32 data, data2, retry = 0;
1479312fec14SDave Airlie 
1480318cfa29SDave Airlie ddr2_init_start:
14810e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
14820e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
14830e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
14840e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
14850e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1486312fec14SDave Airlie 	udelay(10);
14870e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1488312fec14SDave Airlie 	udelay(10);
1489312fec14SDave Airlie 
14900e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
14910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
14920e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
14930e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
14940e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
14950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
14960e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
14970e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
14980e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
14990e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
15000e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
15010e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
15020e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
15030e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
15040e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
15050e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
15060e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
15070e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0054, 0);
15080e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
15090e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
15100e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
15110e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
15120e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
15130e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1514312fec14SDave Airlie 
1515312fec14SDave Airlie 	/* Wait MCLK2X lock to MCLK */
1516312fec14SDave Airlie 	do {
15170e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1518312fec14SDave Airlie 	} while (!(data & 0x08000000));
15190e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E001C);
1520312fec14SDave Airlie 	data = (data >> 8) & 0xff;
1521312fec14SDave Airlie 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
15220e5ce924SDave Airlie 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1523312fec14SDave Airlie 		if ((data2 & 0xff) > param->madj_max) {
1524312fec14SDave Airlie 			break;
1525312fec14SDave Airlie 		}
15260e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, data2);
1527312fec14SDave Airlie 		if (data2 & 0x00100000) {
1528312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 3) + 3;
1529312fec14SDave Airlie 		} else {
1530312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 2) + 5;
1531312fec14SDave Airlie 		}
15320e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1533312fec14SDave Airlie 		data2 += data & 0xff;
1534312fec14SDave Airlie 		data = data | (data2 << 8);
15350e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, data);
1536312fec14SDave Airlie 		udelay(10);
15370e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1538312fec14SDave Airlie 		udelay(10);
15390e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
15400e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1541312fec14SDave Airlie 		data = data | 0x200;
15420e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1543312fec14SDave Airlie 		do {
15440e5ce924SDave Airlie 			data = ast_mindwm(ast, 0x1E6E001C);
1545312fec14SDave Airlie 		} while (!(data & 0x08000000));
1546312fec14SDave Airlie 
15470e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1548312fec14SDave Airlie 		data = (data >> 8) & 0xff;
1549312fec14SDave Airlie 	}
15500e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
15510e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
15520e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, data);
1553312fec14SDave Airlie 
15540e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
15550e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1556312fec14SDave Airlie 	udelay(50);
1557312fec14SDave Airlie 	/* Mode Register Setting */
15580e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
15590e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
15600e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
15610e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
15620e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
15630e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1564312fec14SDave Airlie 
15650e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
15660e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
15670e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
15680e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
15690e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
15700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
15710e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1572312fec14SDave Airlie 
15730e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
1574312fec14SDave Airlie 	data = 0;
1575312fec14SDave Airlie 	if (param->wodt) {
1576312fec14SDave Airlie 		data = 0x500;
1577312fec14SDave Airlie 	}
1578312fec14SDave Airlie 	if (param->rodt) {
1579312fec14SDave Airlie 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1580312fec14SDave Airlie 	}
15810e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
15820e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1583312fec14SDave Airlie 
1584312fec14SDave Airlie 	/* Calibrate the DQSI delay */
1585318cfa29SDave Airlie 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1586318cfa29SDave Airlie 		goto ddr2_init_start;
1587312fec14SDave Airlie 
1588312fec14SDave Airlie 	/* ECC Memory Initialization */
1589312fec14SDave Airlie #ifdef ECC
15900e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
15910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1592312fec14SDave Airlie 	do {
15930e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0070);
1594312fec14SDave Airlie 	} while (!(data & 0x00001000));
15950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
15960e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
15970e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1598312fec14SDave Airlie #endif
1599312fec14SDave Airlie 
1600312fec14SDave Airlie }
1601312fec14SDave Airlie 
1602312fec14SDave Airlie static void ast_init_dram_2300(struct drm_device *dev)
1603312fec14SDave Airlie {
1604312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
1605312fec14SDave Airlie 	struct ast2300_dram_param param;
1606312fec14SDave Airlie 	u32 temp;
1607312fec14SDave Airlie 	u8 reg;
1608312fec14SDave Airlie 
1609312fec14SDave Airlie 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1610312fec14SDave Airlie 	if ((reg & 0x80) == 0) {/* vga only */
1611312fec14SDave Airlie 		ast_write32(ast, 0xf004, 0x1e6e0000);
1612312fec14SDave Airlie 		ast_write32(ast, 0xf000, 0x1);
1613312fec14SDave Airlie 		ast_write32(ast, 0x12000, 0x1688a8a8);
1614312fec14SDave Airlie 		do {
1615312fec14SDave Airlie 			;
1616312fec14SDave Airlie 		} while (ast_read32(ast, 0x12000) != 0x1);
1617312fec14SDave Airlie 
1618312fec14SDave Airlie 		ast_write32(ast, 0x10000, 0xfc600309);
1619312fec14SDave Airlie 		do {
1620312fec14SDave Airlie 			;
1621312fec14SDave Airlie 		} while (ast_read32(ast, 0x10000) != 0x1);
1622312fec14SDave Airlie 
1623312fec14SDave Airlie 		/* Slow down CPU/AHB CLK in VGA only mode */
1624312fec14SDave Airlie 		temp = ast_read32(ast, 0x12008);
1625312fec14SDave Airlie 		temp |= 0x73;
1626312fec14SDave Airlie 		ast_write32(ast, 0x12008, temp);
1627312fec14SDave Airlie 
1628312fec14SDave Airlie 		param.dram_type = AST_DDR3;
1629312fec14SDave Airlie 		if (temp & 0x01000000)
1630312fec14SDave Airlie 			param.dram_type = AST_DDR2;
1631312fec14SDave Airlie 		param.dram_chipid = ast->dram_type;
1632312fec14SDave Airlie 		param.dram_freq = ast->mclk;
1633312fec14SDave Airlie 		param.vram_size = ast->vram_size;
1634312fec14SDave Airlie 
1635312fec14SDave Airlie 		if (param.dram_type == AST_DDR3) {
1636312fec14SDave Airlie 			get_ddr3_info(ast, &param);
1637312fec14SDave Airlie 			ddr3_init(ast, &param);
1638312fec14SDave Airlie 		} else {
1639312fec14SDave Airlie 			get_ddr2_info(ast, &param);
1640312fec14SDave Airlie 			ddr2_init(ast, &param);
1641312fec14SDave Airlie 		}
1642312fec14SDave Airlie 
16430e5ce924SDave Airlie 		temp = ast_mindwm(ast, 0x1e6e2040);
16440e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
1645312fec14SDave Airlie 	}
1646312fec14SDave Airlie 
1647312fec14SDave Airlie 	/* wait ready */
1648312fec14SDave Airlie 	do {
1649312fec14SDave Airlie 		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1650312fec14SDave Airlie 	} while ((reg & 0x40) == 0);
1651312fec14SDave Airlie }
1652312fec14SDave Airlie 
1653