xref: /openbmc/linux/drivers/gpu/drm/ast/ast_post.c (revision 71f677a9)
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 
36d1b98557SBenjamin Herrenschmidt void ast_enable_vga(struct drm_device *dev)
37312fec14SDave Airlie {
38312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
39312fec14SDave Airlie 
40d1b98557SBenjamin Herrenschmidt 	ast_io_write8(ast, AST_IO_VGA_ENABLE_PORT, 0x01);
41d1b98557SBenjamin Herrenschmidt 	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, 0x01);
42312fec14SDave Airlie }
43312fec14SDave Airlie 
44d1b98557SBenjamin Herrenschmidt void ast_enable_mmio(struct drm_device *dev)
45d1b98557SBenjamin Herrenschmidt {
46d1b98557SBenjamin Herrenschmidt 	struct ast_private *ast = dev->dev_private;
47d1b98557SBenjamin Herrenschmidt 
48d1b98557SBenjamin Herrenschmidt 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
49d1b98557SBenjamin Herrenschmidt }
50d1b98557SBenjamin Herrenschmidt 
51d1b98557SBenjamin Herrenschmidt 
52d1b98557SBenjamin Herrenschmidt bool ast_is_vga_enabled(struct drm_device *dev)
53312fec14SDave Airlie {
54312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
55312fec14SDave Airlie 	u8 ch;
56312fec14SDave Airlie 
57312fec14SDave Airlie 	if (ast->chip == AST1180) {
58312fec14SDave Airlie 		/* TODO 1180 */
59312fec14SDave Airlie 	} else {
60d1b98557SBenjamin Herrenschmidt 		ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
61312fec14SDave Airlie 		if (ch) {
62312fec14SDave Airlie 			ast_open_key(ast);
63312fec14SDave Airlie 			ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff);
64312fec14SDave Airlie 			return ch & 0x04;
65312fec14SDave Airlie 		}
66312fec14SDave Airlie 	}
67312fec14SDave Airlie 	return 0;
68312fec14SDave Airlie }
69312fec14SDave Airlie 
70312fec14SDave Airlie static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
71312fec14SDave Airlie static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff };
72312fec14SDave Airlie static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff };
73312fec14SDave Airlie 
74312fec14SDave Airlie static void
75312fec14SDave Airlie ast_set_def_ext_reg(struct drm_device *dev)
76312fec14SDave Airlie {
77312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
78312fec14SDave Airlie 	u8 i, index, reg;
79312fec14SDave Airlie 	const u8 *ext_reg_info;
80312fec14SDave Airlie 
81312fec14SDave Airlie 	/* reset scratch */
82312fec14SDave Airlie 	for (i = 0x81; i <= 0x8f; i++)
83312fec14SDave Airlie 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
84312fec14SDave Airlie 
851453bf4cSDave Airlie 	if (ast->chip == AST2300 || ast->chip == AST2400) {
86312fec14SDave Airlie 		if (dev->pdev->revision >= 0x20)
87312fec14SDave Airlie 			ext_reg_info = extreginfo_ast2300;
88312fec14SDave Airlie 		else
89312fec14SDave Airlie 			ext_reg_info = extreginfo_ast2300a0;
90312fec14SDave Airlie 	} else
91312fec14SDave Airlie 		ext_reg_info = extreginfo;
92312fec14SDave Airlie 
93312fec14SDave Airlie 	index = 0xa0;
94312fec14SDave Airlie 	while (*ext_reg_info != 0xff) {
95312fec14SDave Airlie 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info);
96312fec14SDave Airlie 		index++;
97312fec14SDave Airlie 		ext_reg_info++;
98312fec14SDave Airlie 	}
99312fec14SDave Airlie 
100312fec14SDave Airlie 	/* disable standard IO/MEM decode if secondary */
101312fec14SDave Airlie 	/* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */
102312fec14SDave Airlie 
103312fec14SDave Airlie 	/* Set Ext. Default */
104312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01);
105312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00);
106312fec14SDave Airlie 
107312fec14SDave Airlie 	/* Enable RAMDAC for A1 */
108312fec14SDave Airlie 	reg = 0x04;
1091453bf4cSDave Airlie 	if (ast->chip == AST2300 || ast->chip == AST2400)
110312fec14SDave Airlie 		reg |= 0x20;
111312fec14SDave Airlie 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
112312fec14SDave Airlie }
113312fec14SDave Airlie 
11483c6620bSDave Airlie u32 ast_mindwm(struct ast_private *ast, u32 r)
115312fec14SDave Airlie {
116318cfa29SDave Airlie 	uint32_t data;
117318cfa29SDave Airlie 
118312fec14SDave Airlie 	ast_write32(ast, 0xf004, r & 0xffff0000);
119312fec14SDave Airlie 	ast_write32(ast, 0xf000, 0x1);
120312fec14SDave Airlie 
121318cfa29SDave Airlie 	do {
122318cfa29SDave Airlie 		data = ast_read32(ast, 0xf004) & 0xffff0000;
123318cfa29SDave Airlie 	} while (data != (r & 0xffff0000));
124312fec14SDave Airlie 	return ast_read32(ast, 0x10000 + (r & 0x0000ffff));
125312fec14SDave Airlie }
126312fec14SDave Airlie 
12783c6620bSDave Airlie void ast_moutdwm(struct ast_private *ast, u32 r, u32 v)
128312fec14SDave Airlie {
129318cfa29SDave Airlie 	uint32_t data;
130312fec14SDave Airlie 	ast_write32(ast, 0xf004, r & 0xffff0000);
131312fec14SDave Airlie 	ast_write32(ast, 0xf000, 0x1);
132318cfa29SDave Airlie 	do {
133318cfa29SDave Airlie 		data = ast_read32(ast, 0xf004) & 0xffff0000;
134318cfa29SDave Airlie 	} while (data != (r & 0xffff0000));
135312fec14SDave Airlie 	ast_write32(ast, 0x10000 + (r & 0x0000ffff), v);
136312fec14SDave Airlie }
137312fec14SDave Airlie 
138312fec14SDave Airlie /*
139312fec14SDave Airlie  * AST2100/2150 DLL CBR Setting
140312fec14SDave Airlie  */
141312fec14SDave Airlie #define CBR_SIZE_AST2150	     ((16 << 10) - 1)
142312fec14SDave Airlie #define CBR_PASSNUM_AST2150          5
143312fec14SDave Airlie #define CBR_THRESHOLD_AST2150        10
144312fec14SDave Airlie #define CBR_THRESHOLD2_AST2150       10
145312fec14SDave Airlie #define TIMEOUT_AST2150              5000000
146312fec14SDave Airlie 
147312fec14SDave Airlie #define CBR_PATNUM_AST2150           8
148312fec14SDave Airlie 
149312fec14SDave Airlie static const u32 pattern_AST2150[14] = {
150312fec14SDave Airlie 	0xFF00FF00,
151312fec14SDave Airlie 	0xCC33CC33,
152312fec14SDave Airlie 	0xAA55AA55,
153312fec14SDave Airlie 	0xFFFE0001,
154312fec14SDave Airlie 	0x683501FE,
155312fec14SDave Airlie 	0x0F1929B0,
156312fec14SDave Airlie 	0x2D0B4346,
157312fec14SDave Airlie 	0x60767F02,
158312fec14SDave Airlie 	0x6FBE36A6,
159312fec14SDave Airlie 	0x3A253035,
160312fec14SDave Airlie 	0x3019686D,
161312fec14SDave Airlie 	0x41C6167E,
162312fec14SDave Airlie 	0x620152BF,
163312fec14SDave Airlie 	0x20F050E0
164312fec14SDave Airlie };
165312fec14SDave Airlie 
166312fec14SDave Airlie static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen)
167312fec14SDave Airlie {
168312fec14SDave Airlie 	u32 data, timeout;
169312fec14SDave Airlie 
1700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1710e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3));
172312fec14SDave Airlie 	timeout = 0;
173312fec14SDave Airlie 	do {
1740e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
175312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1760e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
177312fec14SDave Airlie 			return 0xffffffff;
178312fec14SDave Airlie 		}
179312fec14SDave Airlie 	} while (!data);
1800e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
1810e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3));
182312fec14SDave Airlie 	timeout = 0;
183312fec14SDave Airlie 	do {
1840e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
185312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
1860e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
187312fec14SDave Airlie 			return 0xffffffff;
188312fec14SDave Airlie 		}
189312fec14SDave Airlie 	} while (!data);
1900e5ce924SDave Airlie 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
1910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
192312fec14SDave Airlie 	return data;
193312fec14SDave Airlie }
194312fec14SDave Airlie 
195312fec14SDave Airlie #if 0 /* unused in DDX driver - here for completeness */
196312fec14SDave Airlie static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen)
197312fec14SDave Airlie {
198312fec14SDave Airlie 	u32 data, timeout;
199312fec14SDave Airlie 
2000e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
2010e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
202312fec14SDave Airlie 	timeout = 0;
203312fec14SDave Airlie 	do {
2040e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x40;
205312fec14SDave Airlie 		if (++timeout > TIMEOUT_AST2150) {
2060e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
207312fec14SDave Airlie 			return 0xffffffff;
208312fec14SDave Airlie 		}
209312fec14SDave Airlie 	} while (!data);
2100e5ce924SDave Airlie 	data = (ast_mindwm(ast, 0x1e6e0070) & 0x80) >> 7;
2110e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
212312fec14SDave Airlie 	return data;
213312fec14SDave Airlie }
214312fec14SDave Airlie #endif
215312fec14SDave Airlie 
216312fec14SDave Airlie static int cbrtest_ast2150(struct ast_private *ast)
217312fec14SDave Airlie {
218312fec14SDave Airlie 	int i;
219312fec14SDave Airlie 
220312fec14SDave Airlie 	for (i = 0; i < 8; i++)
221312fec14SDave Airlie 		if (mmctestburst2_ast2150(ast, i))
222312fec14SDave Airlie 			return 0;
223312fec14SDave Airlie 	return 1;
224312fec14SDave Airlie }
225312fec14SDave Airlie 
226312fec14SDave Airlie static int cbrscan_ast2150(struct ast_private *ast, int busw)
227312fec14SDave Airlie {
228312fec14SDave Airlie 	u32 patcnt, loop;
229312fec14SDave Airlie 
230312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) {
2310e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]);
232312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) {
233312fec14SDave Airlie 			if (cbrtest_ast2150(ast))
234312fec14SDave Airlie 				break;
235312fec14SDave Airlie 		}
236312fec14SDave Airlie 		if (loop == CBR_PASSNUM_AST2150)
237312fec14SDave Airlie 			return 0;
238312fec14SDave Airlie 	}
239312fec14SDave Airlie 	return 1;
240312fec14SDave Airlie }
241312fec14SDave Airlie 
242312fec14SDave Airlie 
243312fec14SDave Airlie static void cbrdlli_ast2150(struct ast_private *ast, int busw)
244312fec14SDave Airlie {
245312fec14SDave Airlie 	u32 dll_min[4], dll_max[4], dlli, data, passcnt;
246312fec14SDave Airlie 
247312fec14SDave Airlie cbr_start:
248312fec14SDave Airlie 	dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff;
249312fec14SDave Airlie 	dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0;
250312fec14SDave Airlie 	passcnt = 0;
251312fec14SDave Airlie 
252312fec14SDave Airlie 	for (dlli = 0; dlli < 100; dlli++) {
2530e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
254312fec14SDave Airlie 		data = cbrscan_ast2150(ast, busw);
255312fec14SDave Airlie 		if (data != 0) {
256312fec14SDave Airlie 			if (data & 0x1) {
257312fec14SDave Airlie 				if (dll_min[0] > dlli)
258312fec14SDave Airlie 					dll_min[0] = dlli;
259312fec14SDave Airlie 				if (dll_max[0] < dlli)
260312fec14SDave Airlie 					dll_max[0] = dlli;
261312fec14SDave Airlie 			}
262312fec14SDave Airlie 			passcnt++;
263312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD_AST2150)
264312fec14SDave Airlie 			goto cbr_start;
265312fec14SDave Airlie 	}
266312fec14SDave Airlie 	if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150)
267312fec14SDave Airlie 		goto cbr_start;
268312fec14SDave Airlie 
269312fec14SDave Airlie 	dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4);
2700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24));
271312fec14SDave Airlie }
272312fec14SDave Airlie 
273312fec14SDave Airlie 
274312fec14SDave Airlie 
275312fec14SDave Airlie static void ast_init_dram_reg(struct drm_device *dev)
276312fec14SDave Airlie {
277312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
278312fec14SDave Airlie 	u8 j;
279312fec14SDave Airlie 	u32 data, temp, i;
280312fec14SDave Airlie 	const struct ast_dramstruct *dram_reg_info;
281312fec14SDave Airlie 
282312fec14SDave Airlie 	j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
283312fec14SDave Airlie 
284312fec14SDave Airlie 	if ((j & 0x80) == 0) { /* VGA only */
285312fec14SDave Airlie 		if (ast->chip == AST2000) {
286312fec14SDave Airlie 			dram_reg_info = ast2000_dram_table_data;
287312fec14SDave Airlie 			ast_write32(ast, 0xf004, 0x1e6e0000);
288312fec14SDave Airlie 			ast_write32(ast, 0xf000, 0x1);
289312fec14SDave Airlie 			ast_write32(ast, 0x10100, 0xa8);
290312fec14SDave Airlie 
291312fec14SDave Airlie 			do {
292312fec14SDave Airlie 				;
293312fec14SDave Airlie 			} while (ast_read32(ast, 0x10100) != 0xa8);
294312fec14SDave Airlie 		} else {/* AST2100/1100 */
295312fec14SDave Airlie 			if (ast->chip == AST2100 || ast->chip == 2200)
296312fec14SDave Airlie 				dram_reg_info = ast2100_dram_table_data;
297312fec14SDave Airlie 			else
298312fec14SDave Airlie 				dram_reg_info = ast1100_dram_table_data;
299312fec14SDave Airlie 
300312fec14SDave Airlie 			ast_write32(ast, 0xf004, 0x1e6e0000);
301312fec14SDave Airlie 			ast_write32(ast, 0xf000, 0x1);
302312fec14SDave Airlie 			ast_write32(ast, 0x12000, 0x1688A8A8);
303312fec14SDave Airlie 			do {
304312fec14SDave Airlie 				;
305312fec14SDave Airlie 			} while (ast_read32(ast, 0x12000) != 0x01);
306312fec14SDave Airlie 
307312fec14SDave Airlie 			ast_write32(ast, 0x10000, 0xfc600309);
308312fec14SDave Airlie 			do {
309312fec14SDave Airlie 				;
310312fec14SDave Airlie 			} while (ast_read32(ast, 0x10000) != 0x01);
311312fec14SDave Airlie 		}
312312fec14SDave Airlie 
313312fec14SDave Airlie 		while (dram_reg_info->index != 0xffff) {
314312fec14SDave Airlie 			if (dram_reg_info->index == 0xff00) {/* delay fn */
315312fec14SDave Airlie 				for (i = 0; i < 15; i++)
316312fec14SDave Airlie 					udelay(dram_reg_info->data);
317312fec14SDave Airlie 			} else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) {
318312fec14SDave Airlie 				data = dram_reg_info->data;
319312fec14SDave Airlie 				if (ast->dram_type == AST_DRAM_1Gx16)
320312fec14SDave Airlie 					data = 0x00000d89;
321312fec14SDave Airlie 				else if (ast->dram_type == AST_DRAM_1Gx32)
322312fec14SDave Airlie 					data = 0x00000c8d;
323312fec14SDave Airlie 
324312fec14SDave Airlie 				temp = ast_read32(ast, 0x12070);
325312fec14SDave Airlie 				temp &= 0xc;
326312fec14SDave Airlie 				temp <<= 2;
327312fec14SDave Airlie 				ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp);
328312fec14SDave Airlie 			} else
329312fec14SDave Airlie 				ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data);
330312fec14SDave Airlie 			dram_reg_info++;
331312fec14SDave Airlie 		}
332312fec14SDave Airlie 
333312fec14SDave Airlie 		/* AST 2100/2150 DRAM calibration */
334312fec14SDave Airlie 		data = ast_read32(ast, 0x10120);
335312fec14SDave Airlie 		if (data == 0x5061) { /* 266Mhz */
336312fec14SDave Airlie 			data = ast_read32(ast, 0x10004);
337312fec14SDave Airlie 			if (data & 0x40)
338312fec14SDave Airlie 				cbrdlli_ast2150(ast, 16); /* 16 bits */
339312fec14SDave Airlie 			else
340312fec14SDave Airlie 				cbrdlli_ast2150(ast, 32); /* 32 bits */
341312fec14SDave Airlie 		}
342312fec14SDave Airlie 
343312fec14SDave Airlie 		switch (ast->chip) {
344312fec14SDave Airlie 		case AST2000:
345312fec14SDave Airlie 			temp = ast_read32(ast, 0x10140);
346312fec14SDave Airlie 			ast_write32(ast, 0x10140, temp | 0x40);
347312fec14SDave Airlie 			break;
348312fec14SDave Airlie 		case AST1100:
349312fec14SDave Airlie 		case AST2100:
350312fec14SDave Airlie 		case AST2200:
351312fec14SDave Airlie 		case AST2150:
352312fec14SDave Airlie 			temp = ast_read32(ast, 0x1200c);
353312fec14SDave Airlie 			ast_write32(ast, 0x1200c, temp & 0xfffffffd);
354312fec14SDave Airlie 			temp = ast_read32(ast, 0x12040);
355312fec14SDave Airlie 			ast_write32(ast, 0x12040, temp | 0x40);
356312fec14SDave Airlie 			break;
357312fec14SDave Airlie 		default:
358312fec14SDave Airlie 			break;
359312fec14SDave Airlie 		}
360312fec14SDave Airlie 	}
361312fec14SDave Airlie 
362312fec14SDave Airlie 	/* wait ready */
363312fec14SDave Airlie 	do {
364312fec14SDave Airlie 		j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
365312fec14SDave Airlie 	} while ((j & 0x40) == 0);
366312fec14SDave Airlie }
367312fec14SDave Airlie 
368312fec14SDave Airlie void ast_post_gpu(struct drm_device *dev)
369312fec14SDave Airlie {
370312fec14SDave Airlie 	u32 reg;
371312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
372312fec14SDave Airlie 
373312fec14SDave Airlie 	pci_read_config_dword(ast->dev->pdev, 0x04, &reg);
374312fec14SDave Airlie 	reg |= 0x3;
375312fec14SDave Airlie 	pci_write_config_dword(ast->dev->pdev, 0x04, reg);
376312fec14SDave Airlie 
377312fec14SDave Airlie 	ast_enable_vga(dev);
378d1b98557SBenjamin Herrenschmidt 	ast_enable_mmio(dev);
379312fec14SDave Airlie 	ast_open_key(ast);
380312fec14SDave Airlie 	ast_set_def_ext_reg(dev);
381312fec14SDave Airlie 
38271f677a9SRussell Currey 	if (ast->config_mode == ast_use_p2a) {
3831453bf4cSDave Airlie 		if (ast->chip == AST2300 || ast->chip == AST2400)
384312fec14SDave Airlie 			ast_init_dram_2300(dev);
385312fec14SDave Airlie 		else
386312fec14SDave Airlie 			ast_init_dram_reg(dev);
38783c6620bSDave Airlie 
38883c6620bSDave Airlie 		ast_init_3rdtx(dev);
38971f677a9SRussell Currey 	} else {
3906c971c09SY.C. Chen 		if (ast->tx_chip_type != AST_TX_NONE)
3916c971c09SY.C. Chen 			ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);	/* Enable DVO */
3926c971c09SY.C. Chen 	}
3936c971c09SY.C. Chen }
394312fec14SDave Airlie 
395312fec14SDave Airlie /* AST 2300 DRAM settings */
396312fec14SDave Airlie #define AST_DDR3 0
397312fec14SDave Airlie #define AST_DDR2 1
398312fec14SDave Airlie 
399312fec14SDave Airlie struct ast2300_dram_param {
400312fec14SDave Airlie 	u32 dram_type;
401312fec14SDave Airlie 	u32 dram_chipid;
402312fec14SDave Airlie 	u32 dram_freq;
403312fec14SDave Airlie 	u32 vram_size;
404312fec14SDave Airlie 	u32 odt;
405312fec14SDave Airlie 	u32 wodt;
406312fec14SDave Airlie 	u32 rodt;
407312fec14SDave Airlie 	u32 dram_config;
408312fec14SDave Airlie 	u32 reg_PERIOD;
409312fec14SDave Airlie 	u32 reg_MADJ;
410312fec14SDave Airlie 	u32 reg_SADJ;
411312fec14SDave Airlie 	u32 reg_MRS;
412312fec14SDave Airlie 	u32 reg_EMRS;
413312fec14SDave Airlie 	u32 reg_AC1;
414312fec14SDave Airlie 	u32 reg_AC2;
415312fec14SDave Airlie 	u32 reg_DQSIC;
416312fec14SDave Airlie 	u32 reg_DRV;
417312fec14SDave Airlie 	u32 reg_IOZ;
418312fec14SDave Airlie 	u32 reg_DQIDLY;
419312fec14SDave Airlie 	u32 reg_FREQ;
420312fec14SDave Airlie 	u32 madj_max;
421312fec14SDave Airlie 	u32 dll2_finetune_step;
422312fec14SDave Airlie };
423312fec14SDave Airlie 
424312fec14SDave Airlie /*
425312fec14SDave Airlie  * DQSI DLL CBR Setting
426312fec14SDave Airlie  */
427318cfa29SDave Airlie #define CBR_SIZE0            ((1  << 10) - 1)
428312fec14SDave Airlie #define CBR_SIZE1            ((4  << 10) - 1)
429312fec14SDave Airlie #define CBR_SIZE2            ((64 << 10) - 1)
430312fec14SDave Airlie #define CBR_PASSNUM          5
431312fec14SDave Airlie #define CBR_PASSNUM2         5
432312fec14SDave Airlie #define CBR_THRESHOLD        10
433312fec14SDave Airlie #define CBR_THRESHOLD2       10
434312fec14SDave Airlie #define TIMEOUT              5000000
435312fec14SDave Airlie #define CBR_PATNUM           8
436312fec14SDave Airlie 
437312fec14SDave Airlie static const u32 pattern[8] = {
438312fec14SDave Airlie 	0xFF00FF00,
439312fec14SDave Airlie 	0xCC33CC33,
440312fec14SDave Airlie 	0xAA55AA55,
441312fec14SDave Airlie 	0x88778877,
442312fec14SDave Airlie 	0x92CC4D6E,
443312fec14SDave Airlie 	0x543D3CDE,
444312fec14SDave Airlie 	0xF1E843C7,
445312fec14SDave Airlie 	0x7C61D253
446312fec14SDave Airlie };
447312fec14SDave Airlie 
448312fec14SDave Airlie static int mmc_test_burst(struct ast_private *ast, u32 datagen)
449312fec14SDave Airlie {
450312fec14SDave Airlie 	u32 data, timeout;
451312fec14SDave Airlie 
4520e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
4530e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3));
454312fec14SDave Airlie 	timeout = 0;
455312fec14SDave Airlie 	do {
4560e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
457312fec14SDave Airlie 		if (data & 0x2000) {
458312fec14SDave Airlie 			return 0;
459312fec14SDave Airlie 		}
460312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
4610e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
462312fec14SDave Airlie 			return 0;
463312fec14SDave Airlie 		}
464312fec14SDave Airlie 	} while (!data);
4650e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
466312fec14SDave Airlie 	return 1;
467312fec14SDave Airlie }
468312fec14SDave Airlie 
469312fec14SDave Airlie static int mmc_test_burst2(struct ast_private *ast, u32 datagen)
470312fec14SDave Airlie {
471312fec14SDave Airlie 	u32 data, timeout;
472312fec14SDave Airlie 
4730e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
4740e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3));
475312fec14SDave Airlie 	timeout = 0;
476312fec14SDave Airlie 	do {
4770e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
478312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
4790e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
480312fec14SDave Airlie 			return -1;
481312fec14SDave Airlie 		}
482312fec14SDave Airlie 	} while (!data);
4830e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1e6e0078);
484312fec14SDave Airlie 	data = (data | (data >> 16)) & 0xffff;
4850e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
486312fec14SDave Airlie 	return data;
487312fec14SDave Airlie }
488312fec14SDave Airlie 
489312fec14SDave Airlie static int mmc_test_single(struct ast_private *ast, u32 datagen)
490312fec14SDave Airlie {
491312fec14SDave Airlie 	u32 data, timeout;
492312fec14SDave Airlie 
4930e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
4940e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3));
495312fec14SDave Airlie 	timeout = 0;
496312fec14SDave Airlie 	do {
4970e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x3000;
498312fec14SDave Airlie 		if (data & 0x2000)
499312fec14SDave Airlie 			return 0;
500312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
5010e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
502312fec14SDave Airlie 			return 0;
503312fec14SDave Airlie 		}
504312fec14SDave Airlie 	} while (!data);
5050e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
506312fec14SDave Airlie 	return 1;
507312fec14SDave Airlie }
508312fec14SDave Airlie 
509312fec14SDave Airlie static int mmc_test_single2(struct ast_private *ast, u32 datagen)
510312fec14SDave Airlie {
511312fec14SDave Airlie 	u32 data, timeout;
512312fec14SDave Airlie 
5130e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
5140e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3));
515312fec14SDave Airlie 	timeout = 0;
516312fec14SDave Airlie 	do {
5170e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
518312fec14SDave Airlie 		if (++timeout > TIMEOUT) {
5190e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1e6e0070, 0x0);
520312fec14SDave Airlie 			return -1;
521312fec14SDave Airlie 		}
522312fec14SDave Airlie 	} while (!data);
5230e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1e6e0078);
524312fec14SDave Airlie 	data = (data | (data >> 16)) & 0xffff;
5250e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1e6e0070, 0x0);
526312fec14SDave Airlie 	return data;
527312fec14SDave Airlie }
528312fec14SDave Airlie 
529312fec14SDave Airlie static int cbr_test(struct ast_private *ast)
530312fec14SDave Airlie {
531312fec14SDave Airlie 	u32 data;
532312fec14SDave Airlie 	int i;
533312fec14SDave Airlie 	data = mmc_test_single2(ast, 0);
534312fec14SDave Airlie 	if ((data & 0xff) && (data & 0xff00))
535312fec14SDave Airlie 		return 0;
536312fec14SDave Airlie 	for (i = 0; i < 8; i++) {
537312fec14SDave Airlie 		data = mmc_test_burst2(ast, i);
538312fec14SDave Airlie 		if ((data & 0xff) && (data & 0xff00))
539312fec14SDave Airlie 			return 0;
540312fec14SDave Airlie 	}
541312fec14SDave Airlie 	if (!data)
542312fec14SDave Airlie 		return 3;
543312fec14SDave Airlie 	else if (data & 0xff)
544312fec14SDave Airlie 		return 2;
545312fec14SDave Airlie 	return 1;
546312fec14SDave Airlie }
547312fec14SDave Airlie 
548312fec14SDave Airlie static int cbr_scan(struct ast_private *ast)
549312fec14SDave Airlie {
550312fec14SDave Airlie 	u32 data, data2, patcnt, loop;
551312fec14SDave Airlie 
552312fec14SDave Airlie 	data2 = 3;
553312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5540e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
555312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
556312fec14SDave Airlie 			if ((data = cbr_test(ast)) != 0) {
557312fec14SDave Airlie 				data2 &= data;
558312fec14SDave Airlie 				if (!data2)
559312fec14SDave Airlie 					return 0;
560312fec14SDave Airlie 				break;
561312fec14SDave Airlie 			}
562312fec14SDave Airlie 		}
563312fec14SDave Airlie 		if (loop == CBR_PASSNUM2)
564312fec14SDave Airlie 			return 0;
565312fec14SDave Airlie 	}
566312fec14SDave Airlie 	return data2;
567312fec14SDave Airlie }
568312fec14SDave Airlie 
569312fec14SDave Airlie static u32 cbr_test2(struct ast_private *ast)
570312fec14SDave Airlie {
571312fec14SDave Airlie 	u32 data;
572312fec14SDave Airlie 
573312fec14SDave Airlie 	data = mmc_test_burst2(ast, 0);
574312fec14SDave Airlie 	if (data == 0xffff)
575312fec14SDave Airlie 		return 0;
576312fec14SDave Airlie 	data |= mmc_test_single2(ast, 0);
577312fec14SDave Airlie 	if (data == 0xffff)
578312fec14SDave Airlie 		return 0;
579312fec14SDave Airlie 
580312fec14SDave Airlie 	return ~data & 0xffff;
581312fec14SDave Airlie }
582312fec14SDave Airlie 
583312fec14SDave Airlie static u32 cbr_scan2(struct ast_private *ast)
584312fec14SDave Airlie {
585312fec14SDave Airlie 	u32 data, data2, patcnt, loop;
586312fec14SDave Airlie 
587312fec14SDave Airlie 	data2 = 0xffff;
588312fec14SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
5890e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
590312fec14SDave Airlie 		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
591312fec14SDave Airlie 			if ((data = cbr_test2(ast)) != 0) {
592312fec14SDave Airlie 				data2 &= data;
593a82049b1SDave Airlie 				if (!data2)
594312fec14SDave Airlie 					return 0;
595312fec14SDave Airlie 				break;
596312fec14SDave Airlie 			}
597312fec14SDave Airlie 		}
598312fec14SDave Airlie 		if (loop == CBR_PASSNUM2)
599312fec14SDave Airlie 			return 0;
600312fec14SDave Airlie 	}
601312fec14SDave Airlie 	return data2;
602312fec14SDave Airlie }
603312fec14SDave Airlie 
604318cfa29SDave Airlie static u32 cbr_test3(struct ast_private *ast)
605312fec14SDave Airlie {
606318cfa29SDave Airlie 	if (!mmc_test_burst(ast, 0))
607318cfa29SDave Airlie 		return 0;
608318cfa29SDave Airlie 	if (!mmc_test_single(ast, 0))
609318cfa29SDave Airlie 		return 0;
610318cfa29SDave Airlie 	return 1;
611318cfa29SDave Airlie }
612312fec14SDave Airlie 
613318cfa29SDave Airlie static u32 cbr_scan3(struct ast_private *ast)
614318cfa29SDave Airlie {
615318cfa29SDave Airlie 	u32 patcnt, loop;
616312fec14SDave Airlie 
617318cfa29SDave Airlie 	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
6180e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
619318cfa29SDave Airlie 		for (loop = 0; loop < 2; loop++) {
620318cfa29SDave Airlie 			if (cbr_test3(ast))
621312fec14SDave Airlie 				break;
622312fec14SDave Airlie 		}
623318cfa29SDave Airlie 		if (loop == 2)
624318cfa29SDave Airlie 			return 0;
625312fec14SDave Airlie 	}
626318cfa29SDave Airlie 	return 1;
627312fec14SDave Airlie }
628312fec14SDave Airlie 
629318cfa29SDave Airlie static bool finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param)
630312fec14SDave Airlie {
631318cfa29SDave Airlie 	u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
632318cfa29SDave Airlie 	bool status = false;
633312fec14SDave Airlie FINETUNE_START:
634312fec14SDave Airlie 	for (cnt = 0; cnt < 16; cnt++) {
635312fec14SDave Airlie 		dllmin[cnt] = 0xff;
636312fec14SDave Airlie 		dllmax[cnt] = 0x0;
637312fec14SDave Airlie 	}
638312fec14SDave Airlie 	passcnt = 0;
639312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
6400e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
6410e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
642312fec14SDave Airlie 		data = cbr_scan2(ast);
643312fec14SDave Airlie 		if (data != 0) {
644312fec14SDave Airlie 			mask = 0x00010001;
645312fec14SDave Airlie 			for (cnt = 0; cnt < 16; cnt++) {
646312fec14SDave Airlie 				if (data & mask) {
647312fec14SDave Airlie 					if (dllmin[cnt] > dlli) {
648312fec14SDave Airlie 						dllmin[cnt] = dlli;
649312fec14SDave Airlie 					}
650312fec14SDave Airlie 					if (dllmax[cnt] < dlli) {
651312fec14SDave Airlie 						dllmax[cnt] = dlli;
652312fec14SDave Airlie 					}
653312fec14SDave Airlie 				}
654312fec14SDave Airlie 				mask <<= 1;
655312fec14SDave Airlie 			}
656312fec14SDave Airlie 			passcnt++;
657312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD2) {
658312fec14SDave Airlie 			break;
659312fec14SDave Airlie 		}
660312fec14SDave Airlie 	}
661312fec14SDave Airlie 	gold_sadj[0] = 0x0;
662312fec14SDave Airlie 	passcnt = 0;
663312fec14SDave Airlie 	for (cnt = 0; cnt < 16; cnt++) {
664312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
665312fec14SDave Airlie 			gold_sadj[0] += dllmin[cnt];
666312fec14SDave Airlie 			passcnt++;
667312fec14SDave Airlie 		}
668312fec14SDave Airlie 	}
669318cfa29SDave Airlie 	if (retry++ > 10)
670318cfa29SDave Airlie 		goto FINETUNE_DONE;
671312fec14SDave Airlie 	if (passcnt != 16) {
672312fec14SDave Airlie 		goto FINETUNE_START;
673312fec14SDave Airlie 	}
674318cfa29SDave Airlie 	status = true;
675318cfa29SDave Airlie FINETUNE_DONE:
676312fec14SDave Airlie 	gold_sadj[0] = gold_sadj[0] >> 4;
677312fec14SDave Airlie 	gold_sadj[1] = gold_sadj[0];
678312fec14SDave Airlie 
679312fec14SDave Airlie 	data = 0;
680312fec14SDave Airlie 	for (cnt = 0; cnt < 8; cnt++) {
681312fec14SDave Airlie 		data >>= 3;
682312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
683312fec14SDave Airlie 			dlli = dllmin[cnt];
684312fec14SDave Airlie 			if (gold_sadj[0] >= dlli) {
685312fec14SDave Airlie 				dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
686312fec14SDave Airlie 				if (dlli > 3) {
687312fec14SDave Airlie 					dlli = 3;
688312fec14SDave Airlie 				}
689312fec14SDave Airlie 			} else {
690312fec14SDave Airlie 				dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
691312fec14SDave Airlie 				if (dlli > 4) {
692312fec14SDave Airlie 					dlli = 4;
693312fec14SDave Airlie 				}
694312fec14SDave Airlie 				dlli = (8 - dlli) & 0x7;
695312fec14SDave Airlie 			}
696312fec14SDave Airlie 			data |= dlli << 21;
697312fec14SDave Airlie 		}
698312fec14SDave Airlie 	}
6990e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, data);
700312fec14SDave Airlie 
701312fec14SDave Airlie 	data = 0;
702312fec14SDave Airlie 	for (cnt = 8; cnt < 16; cnt++) {
703312fec14SDave Airlie 		data >>= 3;
704312fec14SDave Airlie 		if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
705312fec14SDave Airlie 			dlli = dllmin[cnt];
706312fec14SDave Airlie 			if (gold_sadj[1] >= dlli) {
707312fec14SDave Airlie 				dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
708312fec14SDave Airlie 				if (dlli > 3) {
709312fec14SDave Airlie 					dlli = 3;
710312fec14SDave Airlie 				} else {
711312fec14SDave Airlie 					dlli = (dlli - 1) & 0x7;
712312fec14SDave Airlie 				}
713312fec14SDave Airlie 			} else {
714312fec14SDave Airlie 				dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
715312fec14SDave Airlie 				dlli += 1;
716312fec14SDave Airlie 				if (dlli > 4) {
717312fec14SDave Airlie 					dlli = 4;
718312fec14SDave Airlie 				}
719312fec14SDave Airlie 				dlli = (8 - dlli) & 0x7;
720312fec14SDave Airlie 			}
721312fec14SDave Airlie 			data |= dlli << 21;
722312fec14SDave Airlie 		}
723312fec14SDave Airlie 	}
7240e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, data);
725318cfa29SDave Airlie 	return status;
726312fec14SDave Airlie } /* finetuneDQI_L */
727312fec14SDave Airlie 
728318cfa29SDave Airlie static void finetuneDQSI(struct ast_private *ast)
729312fec14SDave Airlie {
730318cfa29SDave Airlie 	u32 dlli, dqsip, dqidly;
731318cfa29SDave Airlie 	u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
732318cfa29SDave Airlie 	u32 g_dqidly, g_dqsip, g_margin, g_side;
733318cfa29SDave Airlie 	u16 pass[32][2][2];
734318cfa29SDave Airlie 	char tag[2][76];
735312fec14SDave Airlie 
736318cfa29SDave Airlie 	/* Disable DQI CBR */
7370e5ce924SDave Airlie 	reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
7380e5ce924SDave Airlie 	reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
739318cfa29SDave Airlie 	reg_mcr18 &= 0x0000ffff;
7400e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
741318cfa29SDave Airlie 
742312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
743318cfa29SDave Airlie 		tag[0][dlli] = 0x0;
744318cfa29SDave Airlie 		tag[1][dlli] = 0x0;
745312fec14SDave Airlie 	}
746318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
747318cfa29SDave Airlie 		pass[dqidly][0][0] = 0xff;
748318cfa29SDave Airlie 		pass[dqidly][0][1] = 0x0;
749318cfa29SDave Airlie 		pass[dqidly][1][0] = 0xff;
750318cfa29SDave Airlie 		pass[dqidly][1][1] = 0x0;
751312fec14SDave Airlie 	}
752318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
753318cfa29SDave Airlie 		passcnt[0] = passcnt[1] = 0;
754318cfa29SDave Airlie 		for (dqsip = 0; dqsip < 2; dqsip++) {
7550e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E000C, 0);
7560e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
7570e5ce924SDave Airlie 			ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
758318cfa29SDave Airlie 			for (dlli = 0; dlli < 76; dlli++) {
7590e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
7600e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0070, 0);
7610e5ce924SDave Airlie 				ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
762318cfa29SDave Airlie 				if (cbr_scan3(ast)) {
763318cfa29SDave Airlie 					if (dlli == 0)
764312fec14SDave Airlie 						break;
765318cfa29SDave Airlie 					passcnt[dqsip]++;
766318cfa29SDave Airlie 					tag[dqsip][dlli] = 'P';
767318cfa29SDave Airlie 					if (dlli < pass[dqidly][dqsip][0])
768318cfa29SDave Airlie 						pass[dqidly][dqsip][0] = (u16) dlli;
769318cfa29SDave Airlie 					if (dlli > pass[dqidly][dqsip][1])
770318cfa29SDave Airlie 						pass[dqidly][dqsip][1] = (u16) dlli;
771318cfa29SDave Airlie 				} else if (passcnt[dqsip] >= 5)
772318cfa29SDave Airlie 					break;
773318cfa29SDave Airlie 				else {
774318cfa29SDave Airlie 					pass[dqidly][dqsip][0] = 0xff;
775318cfa29SDave Airlie 					pass[dqidly][dqsip][1] = 0x0;
776312fec14SDave Airlie 				}
777312fec14SDave Airlie 			}
778312fec14SDave Airlie 		}
779318cfa29SDave Airlie 		if (passcnt[0] == 0 && passcnt[1] == 0)
780318cfa29SDave Airlie 			dqidly++;
781318cfa29SDave Airlie 	}
782318cfa29SDave Airlie 	/* Search margin */
783318cfa29SDave Airlie 	g_dqidly = g_dqsip = g_margin = g_side = 0;
784312fec14SDave Airlie 
785318cfa29SDave Airlie 	for (dqidly = 0; dqidly < 32; dqidly++) {
786318cfa29SDave Airlie 		for (dqsip = 0; dqsip < 2; dqsip++) {
787318cfa29SDave Airlie 			if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
788318cfa29SDave Airlie 				continue;
789318cfa29SDave Airlie 			diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
790318cfa29SDave Airlie 			if ((diff+2) < g_margin)
791318cfa29SDave Airlie 				continue;
792318cfa29SDave Airlie 			passcnt[0] = passcnt[1] = 0;
793318cfa29SDave Airlie 			for (dlli = pass[dqidly][dqsip][0]; dlli > 0  && tag[dqsip][dlli] != 0; dlli--, passcnt[0]++);
794318cfa29SDave Airlie 			for (dlli = pass[dqidly][dqsip][1]; dlli < 76 && tag[dqsip][dlli] != 0; dlli++, passcnt[1]++);
795318cfa29SDave Airlie 			if (passcnt[0] > passcnt[1])
796318cfa29SDave Airlie 				passcnt[0] = passcnt[1];
797318cfa29SDave Airlie 			passcnt[1] = 0;
798318cfa29SDave Airlie 			if (passcnt[0] > g_side)
799318cfa29SDave Airlie 				passcnt[1] = passcnt[0] - g_side;
800318cfa29SDave Airlie 			if (diff > (g_margin+1) && (passcnt[1] > 0 || passcnt[0] > 8)) {
801318cfa29SDave Airlie 				g_margin = diff;
802318cfa29SDave Airlie 				g_dqidly = dqidly;
803318cfa29SDave Airlie 				g_dqsip  = dqsip;
804318cfa29SDave Airlie 				g_side   = passcnt[0];
805318cfa29SDave Airlie 			} else if (passcnt[1] > 1 && g_side < 8) {
806318cfa29SDave Airlie 				if (diff > g_margin)
807318cfa29SDave Airlie 					g_margin = diff;
808318cfa29SDave Airlie 				g_dqidly = dqidly;
809318cfa29SDave Airlie 				g_dqsip  = dqsip;
810318cfa29SDave Airlie 				g_side   = passcnt[0];
811312fec14SDave Airlie 			}
812312fec14SDave Airlie 		}
813312fec14SDave Airlie 	}
814318cfa29SDave Airlie 	reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
8150e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
816312fec14SDave Airlie 
817312fec14SDave Airlie }
818318cfa29SDave Airlie static bool cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param)
819312fec14SDave Airlie {
820318cfa29SDave Airlie 	u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
821318cfa29SDave Airlie 	bool status = false;
822312fec14SDave Airlie 
823318cfa29SDave Airlie 	finetuneDQSI(ast);
824318cfa29SDave Airlie 	if (finetuneDQI_L(ast, param) == false)
825318cfa29SDave Airlie 		return status;
826312fec14SDave Airlie 
827312fec14SDave Airlie CBR_START2:
828312fec14SDave Airlie 	dllmin[0] = dllmin[1] = 0xff;
829312fec14SDave Airlie 	dllmax[0] = dllmax[1] = 0x0;
830312fec14SDave Airlie 	passcnt = 0;
831312fec14SDave Airlie 	for (dlli = 0; dlli < 76; dlli++) {
8320e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
8330e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
834312fec14SDave Airlie 		data = cbr_scan(ast);
835312fec14SDave Airlie 		if (data != 0) {
836312fec14SDave Airlie 			if (data & 0x1) {
837312fec14SDave Airlie 				if (dllmin[0] > dlli) {
838312fec14SDave Airlie 					dllmin[0] = dlli;
839312fec14SDave Airlie 				}
840312fec14SDave Airlie 				if (dllmax[0] < dlli) {
841312fec14SDave Airlie 					dllmax[0] = dlli;
842312fec14SDave Airlie 				}
843312fec14SDave Airlie 			}
844312fec14SDave Airlie 			if (data & 0x2) {
845312fec14SDave Airlie 				if (dllmin[1] > dlli) {
846312fec14SDave Airlie 					dllmin[1] = dlli;
847312fec14SDave Airlie 				}
848312fec14SDave Airlie 				if (dllmax[1] < dlli) {
849312fec14SDave Airlie 					dllmax[1] = dlli;
850312fec14SDave Airlie 				}
851312fec14SDave Airlie 			}
852312fec14SDave Airlie 			passcnt++;
853312fec14SDave Airlie 		} else if (passcnt >= CBR_THRESHOLD) {
854312fec14SDave Airlie 			break;
855312fec14SDave Airlie 		}
856312fec14SDave Airlie 	}
857318cfa29SDave Airlie 	if (retry++ > 10)
858318cfa29SDave Airlie 		goto CBR_DONE2;
859312fec14SDave Airlie 	if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) {
860312fec14SDave Airlie 		goto CBR_START2;
861312fec14SDave Airlie 	}
862312fec14SDave Airlie 	if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) {
863312fec14SDave Airlie 		goto CBR_START2;
864312fec14SDave Airlie 	}
865318cfa29SDave Airlie 	status = true;
866318cfa29SDave Airlie CBR_DONE2:
867312fec14SDave Airlie 	dlli  = (dllmin[1] + dllmax[1]) >> 1;
868312fec14SDave Airlie 	dlli <<= 8;
869312fec14SDave Airlie 	dlli += (dllmin[0] + dllmax[0]) >> 1;
8700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16));
871318cfa29SDave Airlie 	return status;
872312fec14SDave Airlie } /* CBRDLL2 */
873312fec14SDave Airlie 
874312fec14SDave Airlie static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param)
875312fec14SDave Airlie {
876312fec14SDave Airlie 	u32 trap, trap_AC2, trap_MRS;
877312fec14SDave Airlie 
8780e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
879312fec14SDave Airlie 
880312fec14SDave Airlie 	/* Ger trap info */
8810e5ce924SDave Airlie 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
882312fec14SDave Airlie 	trap_AC2  = 0x00020000 + (trap << 16);
883312fec14SDave Airlie 	trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
884312fec14SDave Airlie 	trap_MRS  = 0x00000010 + (trap << 4);
885312fec14SDave Airlie 	trap_MRS |= ((trap & 0x2) << 18);
886312fec14SDave Airlie 
887312fec14SDave Airlie 	param->reg_MADJ       = 0x00034C4C;
888312fec14SDave Airlie 	param->reg_SADJ       = 0x00001800;
889312fec14SDave Airlie 	param->reg_DRV        = 0x000000F0;
890312fec14SDave Airlie 	param->reg_PERIOD     = param->dram_freq;
891312fec14SDave Airlie 	param->rodt           = 0;
892312fec14SDave Airlie 
893312fec14SDave Airlie 	switch (param->dram_freq) {
894312fec14SDave Airlie 	case 336:
8950e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
896312fec14SDave Airlie 		param->wodt          = 0;
897312fec14SDave Airlie 		param->reg_AC1       = 0x22202725;
898312fec14SDave Airlie 		param->reg_AC2       = 0xAA007613 | trap_AC2;
899312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000BA;
900312fec14SDave Airlie 		param->reg_MRS       = 0x04001400 | trap_MRS;
901312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
902318cfa29SDave Airlie 		param->reg_IOZ       = 0x00000023;
903312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000074;
904312fec14SDave Airlie 		param->reg_FREQ      = 0x00004DC0;
905312fec14SDave Airlie 		param->madj_max      = 96;
906312fec14SDave Airlie 		param->dll2_finetune_step = 3;
907318cfa29SDave Airlie 		switch (param->dram_chipid) {
908318cfa29SDave Airlie 		default:
909318cfa29SDave Airlie 		case AST_DRAM_512Mx16:
910318cfa29SDave Airlie 		case AST_DRAM_1Gx16:
911318cfa29SDave Airlie 			param->reg_AC2   = 0xAA007613 | trap_AC2;
912318cfa29SDave Airlie 			break;
913318cfa29SDave Airlie 		case AST_DRAM_2Gx16:
914318cfa29SDave Airlie 			param->reg_AC2   = 0xAA00761C | trap_AC2;
915318cfa29SDave Airlie 			break;
916318cfa29SDave Airlie 		case AST_DRAM_4Gx16:
917318cfa29SDave Airlie 			param->reg_AC2   = 0xAA007636 | trap_AC2;
918318cfa29SDave Airlie 			break;
919318cfa29SDave Airlie 		}
920312fec14SDave Airlie 		break;
921312fec14SDave Airlie 	default:
922312fec14SDave Airlie 	case 396:
9230e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
924312fec14SDave Airlie 		param->wodt          = 1;
925312fec14SDave Airlie 		param->reg_AC1       = 0x33302825;
926312fec14SDave Airlie 		param->reg_AC2       = 0xCC009617 | trap_AC2;
927312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
928312fec14SDave Airlie 		param->reg_MRS       = 0x04001600 | trap_MRS;
929312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
930312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
931312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
932312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
933318cfa29SDave Airlie 		param->reg_FREQ      = 0x00005040;
934312fec14SDave Airlie 		param->madj_max      = 96;
935312fec14SDave Airlie 		param->dll2_finetune_step = 4;
936312fec14SDave Airlie 
937312fec14SDave Airlie 		switch (param->dram_chipid) {
938312fec14SDave Airlie 		default:
939312fec14SDave Airlie 		case AST_DRAM_512Mx16:
940312fec14SDave Airlie 		case AST_DRAM_1Gx16:
941312fec14SDave Airlie 			param->reg_AC2   = 0xCC009617 | trap_AC2;
942312fec14SDave Airlie 			break;
943312fec14SDave Airlie 		case AST_DRAM_2Gx16:
944312fec14SDave Airlie 			param->reg_AC2   = 0xCC009622 | trap_AC2;
945312fec14SDave Airlie 			break;
946312fec14SDave Airlie 		case AST_DRAM_4Gx16:
947312fec14SDave Airlie 			param->reg_AC2   = 0xCC00963F | trap_AC2;
948312fec14SDave Airlie 			break;
949312fec14SDave Airlie 		}
950312fec14SDave Airlie 		break;
951312fec14SDave Airlie 
952312fec14SDave Airlie 	case 408:
9530e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
954312fec14SDave Airlie 		param->wodt          = 1;
955312fec14SDave Airlie 		param->reg_AC1       = 0x33302825;
956312fec14SDave Airlie 		param->reg_AC2       = 0xCC009617 | trap_AC2;
957312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
958312fec14SDave Airlie 		param->reg_MRS       = 0x04001600 | trap_MRS;
959312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
960318cfa29SDave Airlie 		param->reg_IOZ       = 0x00000023;
961312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
962312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
963312fec14SDave Airlie 		param->reg_FREQ      = 0x000050C0;
964312fec14SDave Airlie 		param->madj_max      = 96;
965312fec14SDave Airlie 		param->dll2_finetune_step = 4;
966312fec14SDave Airlie 
967312fec14SDave Airlie 		switch (param->dram_chipid) {
968312fec14SDave Airlie 		default:
969312fec14SDave Airlie 		case AST_DRAM_512Mx16:
970312fec14SDave Airlie 		case AST_DRAM_1Gx16:
971312fec14SDave Airlie 			param->reg_AC2   = 0xCC009617 | trap_AC2;
972312fec14SDave Airlie 			break;
973312fec14SDave Airlie 		case AST_DRAM_2Gx16:
974312fec14SDave Airlie 			param->reg_AC2   = 0xCC009622 | trap_AC2;
975312fec14SDave Airlie 			break;
976312fec14SDave Airlie 		case AST_DRAM_4Gx16:
977312fec14SDave Airlie 			param->reg_AC2   = 0xCC00963F | trap_AC2;
978312fec14SDave Airlie 			break;
979312fec14SDave Airlie 		}
980312fec14SDave Airlie 
981312fec14SDave Airlie 		break;
982312fec14SDave Airlie 	case 456:
9830e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
984312fec14SDave Airlie 		param->wodt          = 0;
985312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
986312fec14SDave Airlie 		param->reg_AC2       = 0xCD44961A;
987312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000FC;
988312fec14SDave Airlie 		param->reg_MRS       = 0x00081830;
989312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
990312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
991312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000097;
992312fec14SDave Airlie 		param->reg_FREQ      = 0x000052C0;
993312fec14SDave Airlie 		param->madj_max      = 88;
994312fec14SDave Airlie 		param->dll2_finetune_step = 4;
995312fec14SDave Airlie 		break;
996312fec14SDave Airlie 	case 504:
9970e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0270);
998312fec14SDave Airlie 		param->wodt          = 1;
999312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
1000312fec14SDave Airlie 		param->reg_AC2       = 0xDE44A61D;
1001312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000117;
1002312fec14SDave Airlie 		param->reg_MRS       = 0x00081A30;
1003312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1004312fec14SDave Airlie 		param->reg_IOZ       = 0x070000BB;
1005312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A0;
1006312fec14SDave Airlie 		param->reg_FREQ      = 0x000054C0;
1007312fec14SDave Airlie 		param->madj_max      = 79;
1008312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1009312fec14SDave Airlie 		break;
1010312fec14SDave Airlie 	case 528:
10110e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0290);
1012312fec14SDave Airlie 		param->wodt          = 1;
1013312fec14SDave Airlie 		param->rodt          = 1;
1014312fec14SDave Airlie 		param->reg_AC1       = 0x33302926;
1015312fec14SDave Airlie 		param->reg_AC2       = 0xEF44B61E;
1016312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000125;
1017312fec14SDave Airlie 		param->reg_MRS       = 0x00081A30;
1018312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1019312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1020312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1021312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000088;
1022312fec14SDave Airlie 		param->reg_FREQ      = 0x000055C0;
1023312fec14SDave Airlie 		param->madj_max      = 76;
1024312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1025312fec14SDave Airlie 		break;
1026312fec14SDave Airlie 	case 576:
10270e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1028312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1029312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1030312fec14SDave Airlie 		param->wodt          = 1;
1031312fec14SDave Airlie 		param->rodt          = 1;
1032312fec14SDave Airlie 		param->reg_AC1       = 0x33302A37;
1033312fec14SDave Airlie 		param->reg_AC2       = 0xEF56B61E;
1034312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000013F;
1035312fec14SDave Airlie 		param->reg_MRS       = 0x00101A50;
1036312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1037312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1038312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1039312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1040312fec14SDave Airlie 		param->reg_FREQ      = 0x000057C0;
1041312fec14SDave Airlie 		param->madj_max      = 136;
1042312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1043312fec14SDave Airlie 		break;
1044312fec14SDave Airlie 	case 600:
10450e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
1046312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1047312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1048312fec14SDave Airlie 		param->wodt          = 1;
1049312fec14SDave Airlie 		param->rodt          = 1;
1050312fec14SDave Airlie 		param->reg_AC1       = 0x32302A37;
1051312fec14SDave Airlie 		param->reg_AC2       = 0xDF56B61F;
1052312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000014D;
1053312fec14SDave Airlie 		param->reg_MRS       = 0x00101A50;
1054312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1055312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1056312fec14SDave Airlie 		param->reg_IOZ       = 0x00000023;
1057312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1058312fec14SDave Airlie 		param->reg_FREQ      = 0x000058C0;
1059312fec14SDave Airlie 		param->madj_max      = 132;
1060312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1061312fec14SDave Airlie 		break;
1062312fec14SDave Airlie 	case 624:
10630e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0160);
1064312fec14SDave Airlie 		param->reg_MADJ      = 0x00136868;
1065312fec14SDave Airlie 		param->reg_SADJ      = 0x00004534;
1066312fec14SDave Airlie 		param->wodt          = 1;
1067312fec14SDave Airlie 		param->rodt          = 1;
1068312fec14SDave Airlie 		param->reg_AC1       = 0x32302A37;
1069312fec14SDave Airlie 		param->reg_AC2       = 0xEF56B621;
1070312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000015A;
1071312fec14SDave Airlie 		param->reg_MRS       = 0x02101A50;
1072312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1073312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1074312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1075312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000078;
1076312fec14SDave Airlie 		param->reg_FREQ      = 0x000059C0;
1077312fec14SDave Airlie 		param->madj_max      = 128;
1078312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1079312fec14SDave Airlie 		break;
1080312fec14SDave Airlie 	} /* switch freq */
1081312fec14SDave Airlie 
1082312fec14SDave Airlie 	switch (param->dram_chipid) {
1083312fec14SDave Airlie 	case AST_DRAM_512Mx16:
1084312fec14SDave Airlie 		param->dram_config = 0x130;
1085312fec14SDave Airlie 		break;
1086312fec14SDave Airlie 	default:
1087312fec14SDave Airlie 	case AST_DRAM_1Gx16:
1088312fec14SDave Airlie 		param->dram_config = 0x131;
1089312fec14SDave Airlie 		break;
1090312fec14SDave Airlie 	case AST_DRAM_2Gx16:
1091312fec14SDave Airlie 		param->dram_config = 0x132;
1092312fec14SDave Airlie 		break;
1093312fec14SDave Airlie 	case AST_DRAM_4Gx16:
1094312fec14SDave Airlie 		param->dram_config = 0x133;
1095312fec14SDave Airlie 		break;
109610d9b4edSDamien Lespiau 	} /* switch size */
1097312fec14SDave Airlie 
1098312fec14SDave Airlie 	switch (param->vram_size) {
1099312fec14SDave Airlie 	default:
1100312fec14SDave Airlie 	case AST_VIDMEM_SIZE_8M:
1101312fec14SDave Airlie 		param->dram_config |= 0x00;
1102312fec14SDave Airlie 		break;
1103312fec14SDave Airlie 	case AST_VIDMEM_SIZE_16M:
1104312fec14SDave Airlie 		param->dram_config |= 0x04;
1105312fec14SDave Airlie 		break;
1106312fec14SDave Airlie 	case AST_VIDMEM_SIZE_32M:
1107312fec14SDave Airlie 		param->dram_config |= 0x08;
1108312fec14SDave Airlie 		break;
1109312fec14SDave Airlie 	case AST_VIDMEM_SIZE_64M:
1110312fec14SDave Airlie 		param->dram_config |= 0x0c;
1111312fec14SDave Airlie 		break;
1112312fec14SDave Airlie 	}
1113312fec14SDave Airlie 
1114312fec14SDave Airlie }
1115312fec14SDave Airlie 
1116312fec14SDave Airlie static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param)
1117312fec14SDave Airlie {
1118318cfa29SDave Airlie 	u32 data, data2, retry = 0;
1119312fec14SDave Airlie 
1120318cfa29SDave Airlie ddr3_init_start:
11210e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
11220e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
11230e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
11240e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
1125312fec14SDave Airlie 	udelay(10);
11260e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
11270e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1128312fec14SDave Airlie 	udelay(10);
11290e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1130312fec14SDave Airlie 	udelay(10);
1131312fec14SDave Airlie 
11320e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
11330e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
11340e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
11350e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
11360e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
11370e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
11380e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
11390e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
11400e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
11410e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
11420e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
11430e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
11440e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
11450e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
11460e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
11470e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
11480e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
11490e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0054, 0);
11500e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
11510e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
11520e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
11530e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
11540e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
11550e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1156312fec14SDave Airlie 	/* Wait MCLK2X lock to MCLK */
1157312fec14SDave Airlie 	do {
11580e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1159312fec14SDave Airlie 	} while (!(data & 0x08000000));
11600e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E001C);
1161312fec14SDave Airlie 	data = (data >> 8) & 0xff;
1162312fec14SDave Airlie 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
11630e5ce924SDave Airlie 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1164312fec14SDave Airlie 		if ((data2 & 0xff) > param->madj_max) {
1165312fec14SDave Airlie 			break;
1166312fec14SDave Airlie 		}
11670e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, data2);
1168312fec14SDave Airlie 		if (data2 & 0x00100000) {
1169312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 3) + 3;
1170312fec14SDave Airlie 		} else {
1171312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 2) + 5;
1172312fec14SDave Airlie 		}
11730e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1174312fec14SDave Airlie 		data2 += data & 0xff;
1175312fec14SDave Airlie 		data = data | (data2 << 8);
11760e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, data);
1177312fec14SDave Airlie 		udelay(10);
11780e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1179312fec14SDave Airlie 		udelay(10);
11800e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
11810e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1182312fec14SDave Airlie 		data = data | 0x200;
11830e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1184312fec14SDave Airlie 		do {
11850e5ce924SDave Airlie 			data = ast_mindwm(ast, 0x1E6E001C);
1186312fec14SDave Airlie 		} while (!(data & 0x08000000));
1187312fec14SDave Airlie 
11880e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1189312fec14SDave Airlie 		data = (data >> 8) & 0xff;
1190312fec14SDave Airlie 	}
11910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
11920e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
11930e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, data);
1194312fec14SDave Airlie 
11950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
11960e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
1197312fec14SDave Airlie 	udelay(50);
1198312fec14SDave Airlie 	/* Mode Register Setting */
11990e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
12000e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
12010e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
12020e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
12030e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
12040e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
12050e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
12060e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
12070e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1208312fec14SDave Airlie 
12090e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
1210312fec14SDave Airlie 	data = 0;
1211312fec14SDave Airlie 	if (param->wodt) {
1212312fec14SDave Airlie 		data = 0x300;
1213312fec14SDave Airlie 	}
1214312fec14SDave Airlie 	if (param->rodt) {
1215312fec14SDave Airlie 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1216312fec14SDave Airlie 	}
12170e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1218312fec14SDave Airlie 
1219312fec14SDave Airlie 	/* Calibrate the DQSI delay */
1220318cfa29SDave Airlie 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1221318cfa29SDave Airlie 		goto ddr3_init_start;
1222312fec14SDave Airlie 
12230e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1224312fec14SDave Airlie 	/* ECC Memory Initialization */
1225312fec14SDave Airlie #ifdef ECC
12260e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
12270e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1228312fec14SDave Airlie 	do {
12290e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0070);
1230312fec14SDave Airlie 	} while (!(data & 0x00001000));
12310e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
12320e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
12330e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1234312fec14SDave Airlie #endif
1235312fec14SDave Airlie 
1236312fec14SDave Airlie 
1237312fec14SDave Airlie }
1238312fec14SDave Airlie 
1239312fec14SDave Airlie static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param)
1240312fec14SDave Airlie {
1241312fec14SDave Airlie 	u32 trap, trap_AC2, trap_MRS;
1242312fec14SDave Airlie 
12430e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
1244312fec14SDave Airlie 
1245312fec14SDave Airlie 	/* Ger trap info */
12460e5ce924SDave Airlie 	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
1247312fec14SDave Airlie 	trap_AC2  = (trap << 20) | (trap << 16);
1248312fec14SDave Airlie 	trap_AC2 += 0x00110000;
1249312fec14SDave Airlie 	trap_MRS  = 0x00000040 | (trap << 4);
1250312fec14SDave Airlie 
1251312fec14SDave Airlie 
1252312fec14SDave Airlie 	param->reg_MADJ       = 0x00034C4C;
1253312fec14SDave Airlie 	param->reg_SADJ       = 0x00001800;
1254312fec14SDave Airlie 	param->reg_DRV        = 0x000000F0;
1255312fec14SDave Airlie 	param->reg_PERIOD     = param->dram_freq;
1256312fec14SDave Airlie 	param->rodt           = 0;
1257312fec14SDave Airlie 
1258312fec14SDave Airlie 	switch (param->dram_freq) {
1259312fec14SDave Airlie 	case 264:
12600e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0130);
1261312fec14SDave Airlie 		param->wodt          = 0;
1262312fec14SDave Airlie 		param->reg_AC1       = 0x11101513;
1263312fec14SDave Airlie 		param->reg_AC2       = 0x78117011;
1264312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000092;
1265312fec14SDave Airlie 		param->reg_MRS       = 0x00000842;
1266312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1267312fec14SDave Airlie 		param->reg_DRV       = 0x000000F0;
1268312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1269312fec14SDave Airlie 		param->reg_DQIDLY    = 0x0000005A;
1270312fec14SDave Airlie 		param->reg_FREQ      = 0x00004AC0;
1271312fec14SDave Airlie 		param->madj_max      = 138;
1272312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1273312fec14SDave Airlie 		break;
1274312fec14SDave Airlie 	case 336:
12750e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
1276312fec14SDave Airlie 		param->wodt          = 1;
1277312fec14SDave Airlie 		param->reg_AC1       = 0x22202613;
1278312fec14SDave Airlie 		param->reg_AC2       = 0xAA009016 | trap_AC2;
1279312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000BA;
1280312fec14SDave Airlie 		param->reg_MRS       = 0x00000A02 | trap_MRS;
1281312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1282312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1283312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1284312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000074;
1285312fec14SDave Airlie 		param->reg_FREQ      = 0x00004DC0;
1286312fec14SDave Airlie 		param->madj_max      = 96;
1287312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1288318cfa29SDave Airlie 		switch (param->dram_chipid) {
1289318cfa29SDave Airlie 		default:
1290318cfa29SDave Airlie 		case AST_DRAM_512Mx16:
1291318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009012 | trap_AC2;
1292318cfa29SDave Airlie 			break;
1293318cfa29SDave Airlie 		case AST_DRAM_1Gx16:
1294318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009016 | trap_AC2;
1295318cfa29SDave Airlie 			break;
1296318cfa29SDave Airlie 		case AST_DRAM_2Gx16:
1297318cfa29SDave Airlie 			param->reg_AC2   = 0xAA009023 | trap_AC2;
1298318cfa29SDave Airlie 			break;
1299318cfa29SDave Airlie 		case AST_DRAM_4Gx16:
1300318cfa29SDave Airlie 			param->reg_AC2   = 0xAA00903B | trap_AC2;
1301318cfa29SDave Airlie 			break;
1302318cfa29SDave Airlie 		}
1303312fec14SDave Airlie 		break;
1304312fec14SDave Airlie 	default:
1305312fec14SDave Airlie 	case 396:
13060e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
1307312fec14SDave Airlie 		param->wodt          = 1;
1308312fec14SDave Airlie 		param->rodt          = 0;
1309312fec14SDave Airlie 		param->reg_AC1       = 0x33302714;
1310312fec14SDave Airlie 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1311312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
1312312fec14SDave Airlie 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1313312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1314312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1315312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1316312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
1317318cfa29SDave Airlie 		param->reg_FREQ      = 0x00005040;
1318312fec14SDave Airlie 		param->madj_max      = 96;
1319312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1320312fec14SDave Airlie 
1321312fec14SDave Airlie 		switch (param->dram_chipid) {
1322312fec14SDave Airlie 		case AST_DRAM_512Mx16:
1323312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1324312fec14SDave Airlie 			break;
1325312fec14SDave Airlie 		default:
1326312fec14SDave Airlie 		case AST_DRAM_1Gx16:
1327312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1328312fec14SDave Airlie 			break;
1329312fec14SDave Airlie 		case AST_DRAM_2Gx16:
1330312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1331312fec14SDave Airlie 			break;
1332312fec14SDave Airlie 		case AST_DRAM_4Gx16:
1333312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1334312fec14SDave Airlie 			break;
1335312fec14SDave Airlie 		}
1336312fec14SDave Airlie 
1337312fec14SDave Airlie 		break;
1338312fec14SDave Airlie 
1339312fec14SDave Airlie 	case 408:
13400e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
1341312fec14SDave Airlie 		param->wodt          = 1;
1342312fec14SDave Airlie 		param->rodt          = 0;
1343312fec14SDave Airlie 		param->reg_AC1       = 0x33302714;
1344312fec14SDave Airlie 		param->reg_AC2       = 0xCC00B01B | trap_AC2;
1345312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000E2;
1346312fec14SDave Airlie 		param->reg_MRS       = 0x00000C02 | trap_MRS;
1347312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1348312fec14SDave Airlie 		param->reg_DRV       = 0x000000FA;
1349312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1350312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000089;
1351312fec14SDave Airlie 		param->reg_FREQ      = 0x000050C0;
1352312fec14SDave Airlie 		param->madj_max      = 96;
1353312fec14SDave Airlie 		param->dll2_finetune_step = 4;
1354312fec14SDave Airlie 
1355312fec14SDave Airlie 		switch (param->dram_chipid) {
1356312fec14SDave Airlie 		case AST_DRAM_512Mx16:
1357312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B016 | trap_AC2;
1358312fec14SDave Airlie 			break;
1359312fec14SDave Airlie 		default:
1360312fec14SDave Airlie 		case AST_DRAM_1Gx16:
1361312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B01B | trap_AC2;
1362312fec14SDave Airlie 			break;
1363312fec14SDave Airlie 		case AST_DRAM_2Gx16:
1364312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B02B | trap_AC2;
1365312fec14SDave Airlie 			break;
1366312fec14SDave Airlie 		case AST_DRAM_4Gx16:
1367312fec14SDave Airlie 			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1368312fec14SDave Airlie 			break;
1369312fec14SDave Airlie 		}
1370312fec14SDave Airlie 
1371312fec14SDave Airlie 		break;
1372312fec14SDave Airlie 	case 456:
13730e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
1374312fec14SDave Airlie 		param->wodt          = 0;
1375312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1376312fec14SDave Airlie 		param->reg_AC2       = 0xCD44B01E;
1377312fec14SDave Airlie 		param->reg_DQSIC     = 0x000000FC;
1378312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1379312fec14SDave Airlie 		param->reg_EMRS      = 0x00000000;
1380312fec14SDave Airlie 		param->reg_DRV       = 0x00000000;
1381312fec14SDave Airlie 		param->reg_IOZ       = 0x00000034;
1382312fec14SDave Airlie 		param->reg_DQIDLY    = 0x00000097;
1383312fec14SDave Airlie 		param->reg_FREQ      = 0x000052C0;
1384312fec14SDave Airlie 		param->madj_max      = 88;
1385312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1386312fec14SDave Airlie 		break;
1387312fec14SDave Airlie 	case 504:
13880e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0261);
1389312fec14SDave Airlie 		param->wodt          = 1;
1390312fec14SDave Airlie 		param->rodt          = 1;
1391312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1392312fec14SDave Airlie 		param->reg_AC2       = 0xDE44C022;
1393312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000117;
1394312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1395312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1396312fec14SDave Airlie 		param->reg_DRV       = 0x0000000A;
1397312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1398312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A0;
1399312fec14SDave Airlie 		param->reg_FREQ      = 0x000054C0;
1400312fec14SDave Airlie 		param->madj_max      = 79;
1401312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1402312fec14SDave Airlie 		break;
1403312fec14SDave Airlie 	case 528:
14040e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0120);
1405312fec14SDave Airlie 		param->wodt          = 1;
1406312fec14SDave Airlie 		param->rodt          = 1;
1407312fec14SDave Airlie 		param->reg_AC1       = 0x33302815;
1408312fec14SDave Airlie 		param->reg_AC2       = 0xEF44D024;
1409312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000125;
1410312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1411312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1412312fec14SDave Airlie 		param->reg_DRV       = 0x000000F9;
1413312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1414312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000A7;
1415312fec14SDave Airlie 		param->reg_FREQ      = 0x000055C0;
1416312fec14SDave Airlie 		param->madj_max      = 76;
1417312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1418312fec14SDave Airlie 		break;
1419312fec14SDave Airlie 	case 552:
14200e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
1421312fec14SDave Airlie 		param->wodt          = 1;
1422312fec14SDave Airlie 		param->rodt          = 1;
1423312fec14SDave Airlie 		param->reg_AC1       = 0x43402915;
1424312fec14SDave Airlie 		param->reg_AC2       = 0xFF44E025;
1425312fec14SDave Airlie 		param->reg_DQSIC     = 0x00000132;
1426312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1427312fec14SDave Airlie 		param->reg_EMRS      = 0x00000040;
1428312fec14SDave Airlie 		param->reg_DRV       = 0x0000000A;
1429312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1430312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000AD;
1431312fec14SDave Airlie 		param->reg_FREQ      = 0x000056C0;
1432312fec14SDave Airlie 		param->madj_max      = 76;
1433312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1434312fec14SDave Airlie 		break;
1435312fec14SDave Airlie 	case 576:
14360e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1437312fec14SDave Airlie 		param->wodt          = 1;
1438312fec14SDave Airlie 		param->rodt          = 1;
1439312fec14SDave Airlie 		param->reg_AC1       = 0x43402915;
1440312fec14SDave Airlie 		param->reg_AC2       = 0xFF44E027;
1441312fec14SDave Airlie 		param->reg_DQSIC     = 0x0000013F;
1442312fec14SDave Airlie 		param->reg_MRS       = 0x00000E72;
1443312fec14SDave Airlie 		param->reg_EMRS      = 0x00000004;
1444312fec14SDave Airlie 		param->reg_DRV       = 0x000000F5;
1445312fec14SDave Airlie 		param->reg_IOZ       = 0x00000045;
1446312fec14SDave Airlie 		param->reg_DQIDLY    = 0x000000B3;
1447312fec14SDave Airlie 		param->reg_FREQ      = 0x000057C0;
1448312fec14SDave Airlie 		param->madj_max      = 76;
1449312fec14SDave Airlie 		param->dll2_finetune_step = 3;
1450312fec14SDave Airlie 		break;
1451312fec14SDave Airlie 	}
1452312fec14SDave Airlie 
1453312fec14SDave Airlie 	switch (param->dram_chipid) {
1454312fec14SDave Airlie 	case AST_DRAM_512Mx16:
1455312fec14SDave Airlie 		param->dram_config = 0x100;
1456312fec14SDave Airlie 		break;
1457312fec14SDave Airlie 	default:
1458312fec14SDave Airlie 	case AST_DRAM_1Gx16:
1459312fec14SDave Airlie 		param->dram_config = 0x121;
1460312fec14SDave Airlie 		break;
1461312fec14SDave Airlie 	case AST_DRAM_2Gx16:
1462312fec14SDave Airlie 		param->dram_config = 0x122;
1463312fec14SDave Airlie 		break;
1464312fec14SDave Airlie 	case AST_DRAM_4Gx16:
1465312fec14SDave Airlie 		param->dram_config = 0x123;
1466312fec14SDave Airlie 		break;
146710d9b4edSDamien Lespiau 	} /* switch size */
1468312fec14SDave Airlie 
1469312fec14SDave Airlie 	switch (param->vram_size) {
1470312fec14SDave Airlie 	default:
1471312fec14SDave Airlie 	case AST_VIDMEM_SIZE_8M:
1472312fec14SDave Airlie 		param->dram_config |= 0x00;
1473312fec14SDave Airlie 		break;
1474312fec14SDave Airlie 	case AST_VIDMEM_SIZE_16M:
1475312fec14SDave Airlie 		param->dram_config |= 0x04;
1476312fec14SDave Airlie 		break;
1477312fec14SDave Airlie 	case AST_VIDMEM_SIZE_32M:
1478312fec14SDave Airlie 		param->dram_config |= 0x08;
1479312fec14SDave Airlie 		break;
1480312fec14SDave Airlie 	case AST_VIDMEM_SIZE_64M:
1481312fec14SDave Airlie 		param->dram_config |= 0x0c;
1482312fec14SDave Airlie 		break;
1483312fec14SDave Airlie 	}
1484312fec14SDave Airlie }
1485312fec14SDave Airlie 
1486312fec14SDave Airlie static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param)
1487312fec14SDave Airlie {
1488318cfa29SDave Airlie 	u32 data, data2, retry = 0;
1489312fec14SDave Airlie 
1490318cfa29SDave Airlie ddr2_init_start:
14910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
14920e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
14930e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
14940e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
14950e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1496312fec14SDave Airlie 	udelay(10);
14970e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1498312fec14SDave Airlie 	udelay(10);
1499312fec14SDave Airlie 
15000e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
15010e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
15020e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
15030e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
15040e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
15050e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
15060e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
15070e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
15080e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
15090e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
15100e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
15110e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
15120e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
15130e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
15140e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
15150e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
15160e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
15170e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0054, 0);
15180e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
15190e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
15200e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
15210e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
15220e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
15230e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1524312fec14SDave Airlie 
1525312fec14SDave Airlie 	/* Wait MCLK2X lock to MCLK */
1526312fec14SDave Airlie 	do {
15270e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1528312fec14SDave Airlie 	} while (!(data & 0x08000000));
15290e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E001C);
1530312fec14SDave Airlie 	data = (data >> 8) & 0xff;
1531312fec14SDave Airlie 	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
15320e5ce924SDave Airlie 		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1533312fec14SDave Airlie 		if ((data2 & 0xff) > param->madj_max) {
1534312fec14SDave Airlie 			break;
1535312fec14SDave Airlie 		}
15360e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, data2);
1537312fec14SDave Airlie 		if (data2 & 0x00100000) {
1538312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 3) + 3;
1539312fec14SDave Airlie 		} else {
1540312fec14SDave Airlie 			data2 = ((data2 & 0xff) >> 2) + 5;
1541312fec14SDave Airlie 		}
15420e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1543312fec14SDave Airlie 		data2 += data & 0xff;
1544312fec14SDave Airlie 		data = data | (data2 << 8);
15450e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0068, data);
1546312fec14SDave Airlie 		udelay(10);
15470e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1548312fec14SDave Airlie 		udelay(10);
15490e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
15500e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1551312fec14SDave Airlie 		data = data | 0x200;
15520e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1E6E0018, data);
1553312fec14SDave Airlie 		do {
15540e5ce924SDave Airlie 			data = ast_mindwm(ast, 0x1E6E001C);
1555312fec14SDave Airlie 		} while (!(data & 0x08000000));
1556312fec14SDave Airlie 
15570e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E001C);
1558312fec14SDave Airlie 		data = (data >> 8) & 0xff;
1559312fec14SDave Airlie 	}
15600e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
15610e5ce924SDave Airlie 	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
15620e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0018, data);
1563312fec14SDave Airlie 
15640e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
15650e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1566312fec14SDave Airlie 	udelay(50);
1567312fec14SDave Airlie 	/* Mode Register Setting */
15680e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
15690e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
15700e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
15710e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
15720e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
15730e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1574312fec14SDave Airlie 
15750e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
15760e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
15770e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
15780e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
15790e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
15800e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
15810e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1582312fec14SDave Airlie 
15830e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
1584312fec14SDave Airlie 	data = 0;
1585312fec14SDave Airlie 	if (param->wodt) {
1586312fec14SDave Airlie 		data = 0x500;
1587312fec14SDave Airlie 	}
1588312fec14SDave Airlie 	if (param->rodt) {
1589312fec14SDave Airlie 		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1590312fec14SDave Airlie 	}
15910e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
15920e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1593312fec14SDave Airlie 
1594312fec14SDave Airlie 	/* Calibrate the DQSI delay */
1595318cfa29SDave Airlie 	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1596318cfa29SDave Airlie 		goto ddr2_init_start;
1597312fec14SDave Airlie 
1598312fec14SDave Airlie 	/* ECC Memory Initialization */
1599312fec14SDave Airlie #ifdef ECC
16000e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
16010e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1602312fec14SDave Airlie 	do {
16030e5ce924SDave Airlie 		data = ast_mindwm(ast, 0x1E6E0070);
1604312fec14SDave Airlie 	} while (!(data & 0x00001000));
16050e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
16060e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
16070e5ce924SDave Airlie 	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1608312fec14SDave Airlie #endif
1609312fec14SDave Airlie 
1610312fec14SDave Airlie }
1611312fec14SDave Airlie 
1612312fec14SDave Airlie static void ast_init_dram_2300(struct drm_device *dev)
1613312fec14SDave Airlie {
1614312fec14SDave Airlie 	struct ast_private *ast = dev->dev_private;
1615312fec14SDave Airlie 	struct ast2300_dram_param param;
1616312fec14SDave Airlie 	u32 temp;
1617312fec14SDave Airlie 	u8 reg;
1618312fec14SDave Airlie 
1619312fec14SDave Airlie 	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1620312fec14SDave Airlie 	if ((reg & 0x80) == 0) {/* vga only */
1621312fec14SDave Airlie 		ast_write32(ast, 0xf004, 0x1e6e0000);
1622312fec14SDave Airlie 		ast_write32(ast, 0xf000, 0x1);
1623312fec14SDave Airlie 		ast_write32(ast, 0x12000, 0x1688a8a8);
1624312fec14SDave Airlie 		do {
1625312fec14SDave Airlie 			;
1626312fec14SDave Airlie 		} while (ast_read32(ast, 0x12000) != 0x1);
1627312fec14SDave Airlie 
1628312fec14SDave Airlie 		ast_write32(ast, 0x10000, 0xfc600309);
1629312fec14SDave Airlie 		do {
1630312fec14SDave Airlie 			;
1631312fec14SDave Airlie 		} while (ast_read32(ast, 0x10000) != 0x1);
1632312fec14SDave Airlie 
1633312fec14SDave Airlie 		/* Slow down CPU/AHB CLK in VGA only mode */
1634312fec14SDave Airlie 		temp = ast_read32(ast, 0x12008);
1635312fec14SDave Airlie 		temp |= 0x73;
1636312fec14SDave Airlie 		ast_write32(ast, 0x12008, temp);
1637312fec14SDave Airlie 
16383856081eSY.C. Chen 		param.dram_freq = 396;
1639312fec14SDave Airlie 		param.dram_type = AST_DDR3;
16403856081eSY.C. Chen 		temp = ast_mindwm(ast, 0x1e6e2070);
1641312fec14SDave Airlie 		if (temp & 0x01000000)
1642312fec14SDave Airlie 			param.dram_type = AST_DDR2;
16433856081eSY.C. Chen                 switch (temp & 0x18000000) {
16443856081eSY.C. Chen 		case 0:
16453856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_512Mx16;
16463856081eSY.C. Chen 			break;
16473856081eSY.C. Chen 		default:
16483856081eSY.C. Chen 		case 0x08000000:
16493856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_1Gx16;
16503856081eSY.C. Chen 			break;
16513856081eSY.C. Chen 		case 0x10000000:
16523856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_2Gx16;
16533856081eSY.C. Chen 			break;
16543856081eSY.C. Chen 		case 0x18000000:
16553856081eSY.C. Chen 			param.dram_chipid = AST_DRAM_4Gx16;
16563856081eSY.C. Chen 			break;
16573856081eSY.C. Chen 		}
16583856081eSY.C. Chen                 switch (temp & 0x0c) {
16593856081eSY.C. Chen                 default:
16603856081eSY.C. Chen 		case 0x00:
16613856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_8M;
16623856081eSY.C. Chen 			break;
16633856081eSY.C. Chen 
16643856081eSY.C. Chen 		case 0x04:
16653856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_16M;
16663856081eSY.C. Chen 			break;
16673856081eSY.C. Chen 
16683856081eSY.C. Chen 		case 0x08:
16693856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_32M;
16703856081eSY.C. Chen 			break;
16713856081eSY.C. Chen 
16723856081eSY.C. Chen 		case 0x0c:
16733856081eSY.C. Chen 			param.vram_size = AST_VIDMEM_SIZE_64M;
16743856081eSY.C. Chen 			break;
16753856081eSY.C. Chen 		}
1676312fec14SDave Airlie 
1677312fec14SDave Airlie 		if (param.dram_type == AST_DDR3) {
1678312fec14SDave Airlie 			get_ddr3_info(ast, &param);
1679312fec14SDave Airlie 			ddr3_init(ast, &param);
1680312fec14SDave Airlie 		} else {
1681312fec14SDave Airlie 			get_ddr2_info(ast, &param);
1682312fec14SDave Airlie 			ddr2_init(ast, &param);
1683312fec14SDave Airlie 		}
1684312fec14SDave Airlie 
16850e5ce924SDave Airlie 		temp = ast_mindwm(ast, 0x1e6e2040);
16860e5ce924SDave Airlie 		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
1687312fec14SDave Airlie 	}
1688312fec14SDave Airlie 
1689312fec14SDave Airlie 	/* wait ready */
1690312fec14SDave Airlie 	do {
1691312fec14SDave Airlie 		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
1692312fec14SDave Airlie 	} while ((reg & 0x40) == 0);
1693312fec14SDave Airlie }
1694312fec14SDave Airlie 
1695