File Index
Files and directories
Sign in
FILE

ast_2300.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/ast/ast_2300.c C
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright 2012 Red Hat Inc.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining a
   6 * copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sub license, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
  20 *
  21 * The above copyright notice and this permission notice (including the
  22 * next paragraph) shall be included in all copies or substantial portions
  23 * of the Software.
  24 */
  25/*
  26 * Authors: Dave Airlie <airlied@redhat.com>
  27 */
  28
  29#include <linux/delay.h>
  30#include <linux/pci.h>
  31#include <linux/sizes.h>
  32
  33#include <drm/drm_drv.h>
  34#include <drm/drm_managed.h>
  35#include <drm/drm_print.h>
  36
  37#include "ast_drv.h"
  38#include "ast_post.h"
  39
  40/*
  41 *  POST
  42 */
  43
  44void ast_2300_set_def_ext_reg(struct ast_device *ast)
  45{
  46	static const u8 extreginfo[] = { 0x0f, 0x04, 0x1f, 0xff };
  47	u8 i, index, reg;
  48	const u8 *ext_reg_info;
  49
  50	/* reset scratch */
  51	for (i = 0x81; i <= 0x9f; i++)
  52		ast_set_index_reg(ast, AST_IO_VGACRI, i, 0x00);
  53
  54	ext_reg_info = extreginfo;
  55	index = 0xa0;
  56	while (*ext_reg_info != 0xff) {
  57		ast_set_index_reg_mask(ast, AST_IO_VGACRI, index, 0x00, *ext_reg_info);
  58		index++;
  59		ext_reg_info++;
  60	}
  61
  62	/* disable standard IO/MEM decode if secondary */
  63	/* ast_set_index_reg-mask(ast, AST_IO_VGACRI, 0xa1, 0xff, 0x3); */
  64
  65	/* Set Ext. Default */
  66	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x8c, 0x00, 0x01);
  67	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x00, 0x00);
  68
  69	/* Enable RAMDAC for A1 */
  70	reg = 0x04;
  71	reg |= 0x20;
  72	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xff, reg);
  73}
  74
  75/* AST 2300 DRAM settings */
  76#define AST_DDR3 0
  77#define AST_DDR2 1
  78
  79struct ast2300_dram_param {
  80	u32 dram_type;
  81	u32 dram_chipid;
  82	u32 dram_freq;
  83	u32 vram_size;
  84	u32 odt;
  85	u32 wodt;
  86	u32 rodt;
  87	u32 dram_config;
  88	u32 reg_PERIOD;
  89	u32 reg_MADJ;
  90	u32 reg_SADJ;
  91	u32 reg_MRS;
  92	u32 reg_EMRS;
  93	u32 reg_AC1;
  94	u32 reg_AC2;
  95	u32 reg_DQSIC;
  96	u32 reg_DRV;
  97	u32 reg_IOZ;
  98	u32 reg_DQIDLY;
  99	u32 reg_FREQ;
 100	u32 madj_max;
 101	u32 dll2_finetune_step;
 102};
 103
 104/*
 105 * DQSI DLL CBR Setting
 106 */
 107#define CBR_SIZE0            ((1  << 10) - 1)
 108#define CBR_SIZE1            ((4  << 10) - 1)
 109#define CBR_SIZE2            ((64 << 10) - 1)
 110#define CBR_PASSNUM          5
 111#define CBR_PASSNUM2         5
 112#define CBR_THRESHOLD        10
 113#define CBR_THRESHOLD2       10
 114#define TIMEOUT              5000000
 115#define CBR_PATNUM           8
 116
 117static const u32 pattern[8] = {
 118	0xFF00FF00,
 119	0xCC33CC33,
 120	0xAA55AA55,
 121	0x88778877,
 122	0x92CC4D6E,
 123	0x543D3CDE,
 124	0xF1E843C7,
 125	0x7C61D253
 126};
 127
 128static u32 mmc_test2(struct ast_device *ast, u32 datagen, u8 test_ctl)
 129{
 130	u32 data, timeout;
 131
 132	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
 133	ast_moutdwm(ast, 0x1e6e0070, (datagen << 3) | test_ctl);
 134	timeout = 0;
 135	do {
 136		data = ast_mindwm(ast, 0x1e6e0070) & 0x1000;
 137		if (++timeout > TIMEOUT) {
 138			ast_moutdwm(ast, 0x1e6e0070, 0x0);
 139			return 0xffffffff;
 140		}
 141	} while (!data);
 142	data = ast_mindwm(ast, 0x1e6e0078);
 143	data = (data | (data >> 16)) & 0xffff;
 144	ast_moutdwm(ast, 0x1e6e0070, 0x00000000);
 145	return data;
 146}
 147
 148static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen)
 149{
 150	return mmc_test2(ast, datagen, 0x41);
 151}
 152
 153static bool mmc_test_single(struct ast_device *ast, u32 datagen)
 154{
 155	return mmc_test(ast, datagen, 0xc5);
 156}
 157
 158static u32 mmc_test_single2(struct ast_device *ast, u32 datagen)
 159{
 160	return mmc_test2(ast, datagen, 0x05);
 161}
 162
 163static int cbr_test(struct ast_device *ast)
 164{
 165	u32 data;
 166	int i;
 167
 168	data = mmc_test_single2(ast, 0);
 169	if ((data & 0xff) && (data & 0xff00))
 170		return 0;
 171	for (i = 0; i < 8; i++) {
 172		data = mmc_test_burst2(ast, i);
 173		if ((data & 0xff) && (data & 0xff00))
 174			return 0;
 175	}
 176	if (!data)
 177		return 3;
 178	else if (data & 0xff)
 179		return 2;
 180	return 1;
 181}
 182
 183static int cbr_scan(struct ast_device *ast)
 184{
 185	u32 data, data2, patcnt, loop;
 186
 187	data2 = 3;
 188	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
 189		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
 190		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
 191			data = cbr_test(ast);
 192			if (data != 0) {
 193				data2 &= data;
 194				if (!data2)
 195					return 0;
 196				break;
 197			}
 198		}
 199		if (loop == CBR_PASSNUM2)
 200			return 0;
 201	}
 202	return data2;
 203}
 204
 205static u32 cbr_test2(struct ast_device *ast)
 206{
 207	u32 data;
 208
 209	data = mmc_test_burst2(ast, 0);
 210	if (data == 0xffff)
 211		return 0;
 212	data |= mmc_test_single2(ast, 0);
 213	if (data == 0xffff)
 214		return 0;
 215
 216	return ~data & 0xffff;
 217}
 218
 219static u32 cbr_scan2(struct ast_device *ast)
 220{
 221	u32 data, data2, patcnt, loop;
 222
 223	data2 = 0xffff;
 224	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
 225		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
 226		for (loop = 0; loop < CBR_PASSNUM2; loop++) {
 227			data = cbr_test2(ast);
 228			if (data != 0) {
 229				data2 &= data;
 230				if (!data2)
 231					return 0;
 232				break;
 233			}
 234		}
 235		if (loop == CBR_PASSNUM2)
 236			return 0;
 237	}
 238	return data2;
 239}
 240
 241static bool cbr_test3(struct ast_device *ast)
 242{
 243	if (!mmc_test_burst(ast, 0))
 244		return false;
 245	if (!mmc_test_single(ast, 0))
 246		return false;
 247	return true;
 248}
 249
 250static bool cbr_scan3(struct ast_device *ast)
 251{
 252	u32 patcnt, loop;
 253
 254	for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) {
 255		ast_moutdwm(ast, 0x1e6e007c, pattern[patcnt]);
 256		for (loop = 0; loop < 2; loop++) {
 257			if (cbr_test3(ast))
 258				break;
 259		}
 260		if (loop == 2)
 261			return false;
 262	}
 263	return true;
 264}
 265
 266static bool finetuneDQI_L(struct ast_device *ast, struct ast2300_dram_param *param)
 267{
 268	u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, retry = 0;
 269	bool status = false;
 270FINETUNE_START:
 271	for (cnt = 0; cnt < 16; cnt++) {
 272		dllmin[cnt] = 0xff;
 273		dllmax[cnt] = 0x0;
 274	}
 275	passcnt = 0;
 276	for (dlli = 0; dlli < 76; dlli++) {
 277		ast_moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24));
 278		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE1);
 279		data = cbr_scan2(ast);
 280		if (data != 0) {
 281			mask = 0x00010001;
 282			for (cnt = 0; cnt < 16; cnt++) {
 283				if (data & mask) {
 284					if (dllmin[cnt] > dlli)
 285						dllmin[cnt] = dlli;
 286					if (dllmax[cnt] < dlli)
 287						dllmax[cnt] = dlli;
 288				}
 289				mask <<= 1;
 290			}
 291			passcnt++;
 292		} else if (passcnt >= CBR_THRESHOLD2) {
 293			break;
 294		}
 295	}
 296	gold_sadj[0] = 0x0;
 297	passcnt = 0;
 298	for (cnt = 0; cnt < 16; cnt++) {
 299		if ((dllmax[cnt] > dllmin[cnt]) &&
 300		    ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
 301			gold_sadj[0] += dllmin[cnt];
 302			passcnt++;
 303		}
 304	}
 305	if (retry++ > 10)
 306		goto FINETUNE_DONE;
 307	if (passcnt != 16)
 308		goto FINETUNE_START;
 309	status = true;
 310FINETUNE_DONE:
 311	gold_sadj[0] = gold_sadj[0] >> 4;
 312	gold_sadj[1] = gold_sadj[0];
 313
 314	data = 0;
 315	for (cnt = 0; cnt < 8; cnt++) {
 316		data >>= 3;
 317		if ((dllmax[cnt] > dllmin[cnt]) &&
 318		    ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
 319			dlli = dllmin[cnt];
 320			if (gold_sadj[0] >= dlli) {
 321				dlli = ((gold_sadj[0] - dlli) * 19) >> 5;
 322				if (dlli > 3)
 323					dlli = 3;
 324			} else {
 325				dlli = ((dlli - gold_sadj[0]) * 19) >> 5;
 326				if (dlli > 4)
 327					dlli = 4;
 328				dlli = (8 - dlli) & 0x7;
 329			}
 330			data |= dlli << 21;
 331		}
 332	}
 333	ast_moutdwm(ast, 0x1E6E0080, data);
 334
 335	data = 0;
 336	for (cnt = 8; cnt < 16; cnt++) {
 337		data >>= 3;
 338		if ((dllmax[cnt] > dllmin[cnt]) &&
 339		    ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) {
 340			dlli = dllmin[cnt];
 341			if (gold_sadj[1] >= dlli) {
 342				dlli = ((gold_sadj[1] - dlli) * 19) >> 5;
 343				if (dlli > 3)
 344					dlli = 3;
 345				else
 346					dlli = (dlli - 1) & 0x7;
 347			} else {
 348				dlli = ((dlli - gold_sadj[1]) * 19) >> 5;
 349				dlli += 1;
 350				if (dlli > 4)
 351					dlli = 4;
 352				dlli = (8 - dlli) & 0x7;
 353			}
 354			data |= dlli << 21;
 355		}
 356	}
 357	ast_moutdwm(ast, 0x1E6E0084, data);
 358	return status;
 359} /* finetuneDQI_L */
 360
 361static void finetuneDQSI(struct ast_device *ast)
 362{
 363	u32 dlli, dqsip, dqidly;
 364	u32 reg_mcr18, reg_mcr0c, passcnt[2], diff;
 365	u32 g_dqidly, g_dqsip, g_margin, g_side;
 366	u16 pass[32][2][2];
 367	char tag[2][76];
 368
 369	/* Disable DQI CBR */
 370	reg_mcr0c  = ast_mindwm(ast, 0x1E6E000C);
 371	reg_mcr18  = ast_mindwm(ast, 0x1E6E0018);
 372	reg_mcr18 &= 0x0000ffff;
 373	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
 374
 375	for (dlli = 0; dlli < 76; dlli++) {
 376		tag[0][dlli] = 0x0;
 377		tag[1][dlli] = 0x0;
 378	}
 379	for (dqidly = 0; dqidly < 32; dqidly++) {
 380		pass[dqidly][0][0] = 0xff;
 381		pass[dqidly][0][1] = 0x0;
 382		pass[dqidly][1][0] = 0xff;
 383		pass[dqidly][1][1] = 0x0;
 384	}
 385	for (dqidly = 0; dqidly < 32; dqidly++) {
 386		passcnt[0] = 0;
 387		passcnt[1] = 0;
 388		for (dqsip = 0; dqsip < 2; dqsip++) {
 389			ast_moutdwm(ast, 0x1E6E000C, 0);
 390			ast_moutdwm(ast, 0x1E6E0018, reg_mcr18 | (dqidly << 16) | (dqsip << 23));
 391			ast_moutdwm(ast, 0x1E6E000C, reg_mcr0c);
 392			for (dlli = 0; dlli < 76; dlli++) {
 393				ast_moutdwm(ast, 0x1E6E0068,
 394					    0x00001300 | (dlli << 16) | (dlli << 24));
 395				ast_moutdwm(ast, 0x1E6E0070, 0);
 396				ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE0);
 397				if (cbr_scan3(ast)) {
 398					if (dlli == 0)
 399						break;
 400					passcnt[dqsip]++;
 401					tag[dqsip][dlli] = 'P';
 402					if (dlli < pass[dqidly][dqsip][0])
 403						pass[dqidly][dqsip][0] = (u16)dlli;
 404					if (dlli > pass[dqidly][dqsip][1])
 405						pass[dqidly][dqsip][1] = (u16)dlli;
 406				} else if (passcnt[dqsip] >= 5) {
 407					break;
 408				} else {
 409					pass[dqidly][dqsip][0] = 0xff;
 410					pass[dqidly][dqsip][1] = 0x0;
 411				}
 412			}
 413		}
 414		if (passcnt[0] == 0 && passcnt[1] == 0)
 415			dqidly++;
 416	}
 417	/* Search margin */
 418	g_dqidly = 0;
 419	g_dqsip = 0;
 420	g_margin = 0;
 421	g_side = 0;
 422
 423	for (dqidly = 0; dqidly < 32; dqidly++) {
 424		for (dqsip = 0; dqsip < 2; dqsip++) {
 425			if (pass[dqidly][dqsip][0] > pass[dqidly][dqsip][1])
 426				continue;
 427			diff = pass[dqidly][dqsip][1] - pass[dqidly][dqsip][0];
 428			if ((diff + 2) < g_margin)
 429				continue;
 430			passcnt[0] = 0;
 431			passcnt[1] = 0;
 432			for (dlli = pass[dqidly][dqsip][0];
 433			     dlli > 0 && tag[dqsip][dlli] != 0;
 434			     dlli--, passcnt[0]++) {
 435			}
 436			for (dlli = pass[dqidly][dqsip][1];
 437			     dlli < 76 && tag[dqsip][dlli] != 0;
 438			     dlli++, passcnt[1]++) {
 439			}
 440			if (passcnt[0] > passcnt[1])
 441				passcnt[0] = passcnt[1];
 442			passcnt[1] = 0;
 443			if (passcnt[0] > g_side)
 444				passcnt[1] = passcnt[0] - g_side;
 445			if (diff > (g_margin + 1) && (passcnt[1] > 0 || passcnt[0] > 8)) {
 446				g_margin = diff;
 447				g_dqidly = dqidly;
 448				g_dqsip  = dqsip;
 449				g_side   = passcnt[0];
 450			} else if (passcnt[1] > 1 && g_side < 8) {
 451				if (diff > g_margin)
 452					g_margin = diff;
 453				g_dqidly = dqidly;
 454				g_dqsip  = dqsip;
 455				g_side   = passcnt[0];
 456			}
 457		}
 458	}
 459	reg_mcr18 = reg_mcr18 | (g_dqidly << 16) | (g_dqsip << 23);
 460	ast_moutdwm(ast, 0x1E6E0018, reg_mcr18);
 461}
 462
 463static bool cbr_dll2(struct ast_device *ast, struct ast2300_dram_param *param)
 464{
 465	u32 dllmin[2], dllmax[2], dlli, data, passcnt, retry = 0;
 466	bool status = false;
 467
 468	finetuneDQSI(ast);
 469	if (finetuneDQI_L(ast, param) == false)
 470		return status;
 471
 472CBR_START2:
 473	dllmin[0] = 0xff;
 474	dllmin[1] = 0xff;
 475	dllmax[0] = 0x0;
 476	dllmax[1] = 0x0;
 477	passcnt = 0;
 478	for (dlli = 0; dlli < 76; dlli++) {
 479		ast_moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24));
 480		ast_moutdwm(ast, 0x1E6E0074, CBR_SIZE2);
 481		data = cbr_scan(ast);
 482		if (data != 0) {
 483			if (data & 0x1) {
 484				if (dllmin[0] > dlli)
 485					dllmin[0] = dlli;
 486				if (dllmax[0] < dlli)
 487					dllmax[0] = dlli;
 488			}
 489			if (data & 0x2) {
 490				if (dllmin[1] > dlli)
 491					dllmin[1] = dlli;
 492				if (dllmax[1] < dlli)
 493					dllmax[1] = dlli;
 494			}
 495			passcnt++;
 496		} else if (passcnt >= CBR_THRESHOLD) {
 497			break;
 498		}
 499	}
 500	if (retry++ > 10)
 501		goto CBR_DONE2;
 502	if (dllmax[0] == 0 || (dllmax[0] - dllmin[0]) < CBR_THRESHOLD)
 503		goto CBR_START2;
 504	if (dllmax[1] == 0 || (dllmax[1] - dllmin[1]) < CBR_THRESHOLD)
 505		goto CBR_START2;
 506	status = true;
 507CBR_DONE2:
 508	dlli  = (dllmin[1] + dllmax[1]) >> 1;
 509	dlli <<= 8;
 510	dlli += (dllmin[0] + dllmax[0]) >> 1;
 511	ast_moutdwm(ast, 0x1E6E0068, ast_mindwm(ast, 0x1E720058) | (dlli << 16));
 512	return status;
 513} /* CBRDLL2 */
 514
 515static void get_ddr3_info(struct ast_device *ast, struct ast2300_dram_param *param)
 516{
 517	u32 trap, trap_AC2, trap_MRS;
 518
 519	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
 520
 521	/* Ger trap info */
 522	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
 523	trap_AC2  = 0x00020000 + (trap << 16);
 524	trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19);
 525	trap_MRS  = 0x00000010 + (trap << 4);
 526	trap_MRS |= ((trap & 0x2) << 18);
 527
 528	param->reg_MADJ       = 0x00034C4C;
 529	param->reg_SADJ       = 0x00001800;
 530	param->reg_DRV        = 0x000000F0;
 531	param->reg_PERIOD     = param->dram_freq;
 532	param->rodt           = 0;
 533
 534	switch (param->dram_freq) {
 535	case 336:
 536		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
 537		param->wodt          = 0;
 538		param->reg_AC1       = 0x22202725;
 539		param->reg_AC2       = 0xAA007613 | trap_AC2;
 540		param->reg_DQSIC     = 0x000000BA;
 541		param->reg_MRS       = 0x04001400 | trap_MRS;
 542		param->reg_EMRS      = 0x00000000;
 543		param->reg_IOZ       = 0x00000023;
 544		param->reg_DQIDLY    = 0x00000074;
 545		param->reg_FREQ      = 0x00004DC0;
 546		param->madj_max      = 96;
 547		param->dll2_finetune_step = 3;
 548		switch (param->dram_chipid) {
 549		default:
 550		case AST_DRAM_512Mx16:
 551		case AST_DRAM_1Gx16:
 552			param->reg_AC2   = 0xAA007613 | trap_AC2;
 553			break;
 554		case AST_DRAM_2Gx16:
 555			param->reg_AC2   = 0xAA00761C | trap_AC2;
 556			break;
 557		case AST_DRAM_4Gx16:
 558			param->reg_AC2   = 0xAA007636 | trap_AC2;
 559			break;
 560		}
 561		break;
 562	default:
 563	case 396:
 564		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
 565		param->wodt          = 1;
 566		param->reg_AC1       = 0x33302825;
 567		param->reg_AC2       = 0xCC009617 | trap_AC2;
 568		param->reg_DQSIC     = 0x000000E2;
 569		param->reg_MRS       = 0x04001600 | trap_MRS;
 570		param->reg_EMRS      = 0x00000000;
 571		param->reg_IOZ       = 0x00000034;
 572		param->reg_DRV       = 0x000000FA;
 573		param->reg_DQIDLY    = 0x00000089;
 574		param->reg_FREQ      = 0x00005040;
 575		param->madj_max      = 96;
 576		param->dll2_finetune_step = 4;
 577
 578		switch (param->dram_chipid) {
 579		default:
 580		case AST_DRAM_512Mx16:
 581		case AST_DRAM_1Gx16:
 582			param->reg_AC2   = 0xCC009617 | trap_AC2;
 583			break;
 584		case AST_DRAM_2Gx16:
 585			param->reg_AC2   = 0xCC009622 | trap_AC2;
 586			break;
 587		case AST_DRAM_4Gx16:
 588			param->reg_AC2   = 0xCC00963F | trap_AC2;
 589			break;
 590		}
 591		break;
 592
 593	case 408:
 594		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
 595		param->wodt          = 1;
 596		param->reg_AC1       = 0x33302825;
 597		param->reg_AC2       = 0xCC009617 | trap_AC2;
 598		param->reg_DQSIC     = 0x000000E2;
 599		param->reg_MRS       = 0x04001600 | trap_MRS;
 600		param->reg_EMRS      = 0x00000000;
 601		param->reg_IOZ       = 0x00000023;
 602		param->reg_DRV       = 0x000000FA;
 603		param->reg_DQIDLY    = 0x00000089;
 604		param->reg_FREQ      = 0x000050C0;
 605		param->madj_max      = 96;
 606		param->dll2_finetune_step = 4;
 607
 608		switch (param->dram_chipid) {
 609		default:
 610		case AST_DRAM_512Mx16:
 611		case AST_DRAM_1Gx16:
 612			param->reg_AC2   = 0xCC009617 | trap_AC2;
 613			break;
 614		case AST_DRAM_2Gx16:
 615			param->reg_AC2   = 0xCC009622 | trap_AC2;
 616			break;
 617		case AST_DRAM_4Gx16:
 618			param->reg_AC2   = 0xCC00963F | trap_AC2;
 619			break;
 620		}
 621
 622		break;
 623	case 456:
 624		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
 625		param->wodt          = 0;
 626		param->reg_AC1       = 0x33302926;
 627		param->reg_AC2       = 0xCD44961A;
 628		param->reg_DQSIC     = 0x000000FC;
 629		param->reg_MRS       = 0x00081830;
 630		param->reg_EMRS      = 0x00000000;
 631		param->reg_IOZ       = 0x00000045;
 632		param->reg_DQIDLY    = 0x00000097;
 633		param->reg_FREQ      = 0x000052C0;
 634		param->madj_max      = 88;
 635		param->dll2_finetune_step = 4;
 636		break;
 637	case 504:
 638		ast_moutdwm(ast, 0x1E6E2020, 0x0270);
 639		param->wodt          = 1;
 640		param->reg_AC1       = 0x33302926;
 641		param->reg_AC2       = 0xDE44A61D;
 642		param->reg_DQSIC     = 0x00000117;
 643		param->reg_MRS       = 0x00081A30;
 644		param->reg_EMRS      = 0x00000000;
 645		param->reg_IOZ       = 0x070000BB;
 646		param->reg_DQIDLY    = 0x000000A0;
 647		param->reg_FREQ      = 0x000054C0;
 648		param->madj_max      = 79;
 649		param->dll2_finetune_step = 4;
 650		break;
 651	case 528:
 652		ast_moutdwm(ast, 0x1E6E2020, 0x0290);
 653		param->wodt          = 1;
 654		param->rodt          = 1;
 655		param->reg_AC1       = 0x33302926;
 656		param->reg_AC2       = 0xEF44B61E;
 657		param->reg_DQSIC     = 0x00000125;
 658		param->reg_MRS       = 0x00081A30;
 659		param->reg_EMRS      = 0x00000040;
 660		param->reg_DRV       = 0x000000F5;
 661		param->reg_IOZ       = 0x00000023;
 662		param->reg_DQIDLY    = 0x00000088;
 663		param->reg_FREQ      = 0x000055C0;
 664		param->madj_max      = 76;
 665		param->dll2_finetune_step = 3;
 666		break;
 667	case 576:
 668		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
 669		param->reg_MADJ      = 0x00136868;
 670		param->reg_SADJ      = 0x00004534;
 671		param->wodt          = 1;
 672		param->rodt          = 1;
 673		param->reg_AC1       = 0x33302A37;
 674		param->reg_AC2       = 0xEF56B61E;
 675		param->reg_DQSIC     = 0x0000013F;
 676		param->reg_MRS       = 0x00101A50;
 677		param->reg_EMRS      = 0x00000040;
 678		param->reg_DRV       = 0x000000FA;
 679		param->reg_IOZ       = 0x00000023;
 680		param->reg_DQIDLY    = 0x00000078;
 681		param->reg_FREQ      = 0x000057C0;
 682		param->madj_max      = 136;
 683		param->dll2_finetune_step = 3;
 684		break;
 685	case 600:
 686		ast_moutdwm(ast, 0x1E6E2020, 0x02E1);
 687		param->reg_MADJ      = 0x00136868;
 688		param->reg_SADJ      = 0x00004534;
 689		param->wodt          = 1;
 690		param->rodt          = 1;
 691		param->reg_AC1       = 0x32302A37;
 692		param->reg_AC2       = 0xDF56B61F;
 693		param->reg_DQSIC     = 0x0000014D;
 694		param->reg_MRS       = 0x00101A50;
 695		param->reg_EMRS      = 0x00000004;
 696		param->reg_DRV       = 0x000000F5;
 697		param->reg_IOZ       = 0x00000023;
 698		param->reg_DQIDLY    = 0x00000078;
 699		param->reg_FREQ      = 0x000058C0;
 700		param->madj_max      = 132;
 701		param->dll2_finetune_step = 3;
 702		break;
 703	case 624:
 704		ast_moutdwm(ast, 0x1E6E2020, 0x0160);
 705		param->reg_MADJ      = 0x00136868;
 706		param->reg_SADJ      = 0x00004534;
 707		param->wodt          = 1;
 708		param->rodt          = 1;
 709		param->reg_AC1       = 0x32302A37;
 710		param->reg_AC2       = 0xEF56B621;
 711		param->reg_DQSIC     = 0x0000015A;
 712		param->reg_MRS       = 0x02101A50;
 713		param->reg_EMRS      = 0x00000004;
 714		param->reg_DRV       = 0x000000F5;
 715		param->reg_IOZ       = 0x00000034;
 716		param->reg_DQIDLY    = 0x00000078;
 717		param->reg_FREQ      = 0x000059C0;
 718		param->madj_max      = 128;
 719		param->dll2_finetune_step = 3;
 720		break;
 721	} /* switch freq */
 722
 723	switch (param->dram_chipid) {
 724	case AST_DRAM_512Mx16:
 725		param->dram_config = 0x130;
 726		break;
 727	default:
 728	case AST_DRAM_1Gx16:
 729		param->dram_config = 0x131;
 730		break;
 731	case AST_DRAM_2Gx16:
 732		param->dram_config = 0x132;
 733		break;
 734	case AST_DRAM_4Gx16:
 735		param->dram_config = 0x133;
 736		break;
 737	} /* switch size */
 738
 739	switch (param->vram_size) {
 740	default:
 741	case SZ_8M:
 742		param->dram_config |= 0x00;
 743		break;
 744	case SZ_16M:
 745		param->dram_config |= 0x04;
 746		break;
 747	case SZ_32M:
 748		param->dram_config |= 0x08;
 749		break;
 750	case SZ_64M:
 751		param->dram_config |= 0x0c;
 752		break;
 753	}
 754}
 755
 756static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param)
 757{
 758	u32 data, data2, retry = 0;
 759
 760ddr3_init_start:
 761	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
 762	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
 763	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
 764	ast_moutdwm(ast, 0x1E6E0034, 0x00000000);
 765	udelay(10);
 766	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
 767	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
 768	udelay(10);
 769	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
 770	udelay(10);
 771
 772	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
 773	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
 774	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
 775	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
 776	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
 777	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
 778	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
 779	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
 780	ast_moutdwm(ast, 0x1E6E0018, 0x4000A170);
 781	ast_moutdwm(ast, 0x1E6E0018, 0x00002370);
 782	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
 783	ast_moutdwm(ast, 0x1E6E0040, 0xFF444444);
 784	ast_moutdwm(ast, 0x1E6E0044, 0x22222222);
 785	ast_moutdwm(ast, 0x1E6E0048, 0x22222222);
 786	ast_moutdwm(ast, 0x1E6E004C, 0x00000002);
 787	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
 788	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
 789	ast_moutdwm(ast, 0x1E6E0054, 0);
 790	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
 791	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
 792	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
 793	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
 794	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
 795	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
 796	/* Wait MCLK2X lock to MCLK */
 797	do {
 798		data = ast_mindwm(ast, 0x1E6E001C);
 799	} while (!(data & 0x08000000));
 800	data = ast_mindwm(ast, 0x1E6E001C);
 801	data = (data >> 8) & 0xff;
 802	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
 803		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
 804		if ((data2 & 0xff) > param->madj_max)
 805			break;
 806		ast_moutdwm(ast, 0x1E6E0064, data2);
 807		if (data2 & 0x00100000)
 808			data2 = ((data2 & 0xff) >> 3) + 3;
 809		else
 810			data2 = ((data2 & 0xff) >> 2) + 5;
 811		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
 812		data2 += data & 0xff;
 813		data = data | (data2 << 8);
 814		ast_moutdwm(ast, 0x1E6E0068, data);
 815		udelay(10);
 816		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
 817		udelay(10);
 818		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
 819		ast_moutdwm(ast, 0x1E6E0018, data);
 820		data = data | 0x200;
 821		ast_moutdwm(ast, 0x1E6E0018, data);
 822		do {
 823			data = ast_mindwm(ast, 0x1E6E001C);
 824		} while (!(data & 0x08000000));
 825
 826		data = ast_mindwm(ast, 0x1E6E001C);
 827		data = (data >> 8) & 0xff;
 828	}
 829	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0068) & 0xffff);
 830	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
 831	ast_moutdwm(ast, 0x1E6E0018, data);
 832
 833	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
 834	ast_moutdwm(ast, 0x1E6E000C, 0x00000040);
 835	udelay(50);
 836	/* Mode Register Setting */
 837	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
 838	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
 839	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
 840	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
 841	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
 842	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
 843	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
 844	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
 845	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
 846
 847	ast_moutdwm(ast, 0x1E6E000C, 0x00005C01);
 848	data = 0;
 849	if (param->wodt)
 850		data = 0x300;
 851	if (param->rodt)
 852		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
 853	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
 854
 855	/* Calibrate the DQSI delay */
 856	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
 857		goto ddr3_init_start;
 858
 859	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
 860	/* ECC Memory Initialization */
 861#ifdef ECC
 862	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
 863	ast_moutdwm(ast, 0x1E6E0070, 0x221);
 864	do {
 865		data = ast_mindwm(ast, 0x1E6E0070);
 866	} while (!(data & 0x00001000));
 867	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
 868	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
 869	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
 870#endif
 871}
 872
 873static void get_ddr2_info(struct ast_device *ast, struct ast2300_dram_param *param)
 874{
 875	u32 trap, trap_AC2, trap_MRS;
 876
 877	ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
 878
 879	/* Ger trap info */
 880	trap = (ast_mindwm(ast, 0x1E6E2070) >> 25) & 0x3;
 881	trap_AC2  = (trap << 20) | (trap << 16);
 882	trap_AC2 += 0x00110000;
 883	trap_MRS  = 0x00000040 | (trap << 4);
 884
 885	param->reg_MADJ       = 0x00034C4C;
 886	param->reg_SADJ       = 0x00001800;
 887	param->reg_DRV        = 0x000000F0;
 888	param->reg_PERIOD     = param->dram_freq;
 889	param->rodt           = 0;
 890
 891	switch (param->dram_freq) {
 892	case 264:
 893		ast_moutdwm(ast, 0x1E6E2020, 0x0130);
 894		param->wodt          = 0;
 895		param->reg_AC1       = 0x11101513;
 896		param->reg_AC2       = 0x78117011;
 897		param->reg_DQSIC     = 0x00000092;
 898		param->reg_MRS       = 0x00000842;
 899		param->reg_EMRS      = 0x00000000;
 900		param->reg_DRV       = 0x000000F0;
 901		param->reg_IOZ       = 0x00000034;
 902		param->reg_DQIDLY    = 0x0000005A;
 903		param->reg_FREQ      = 0x00004AC0;
 904		param->madj_max      = 138;
 905		param->dll2_finetune_step = 3;
 906		break;
 907	case 336:
 908		ast_moutdwm(ast, 0x1E6E2020, 0x0190);
 909		param->wodt          = 1;
 910		param->reg_AC1       = 0x22202613;
 911		param->reg_AC2       = 0xAA009016 | trap_AC2;
 912		param->reg_DQSIC     = 0x000000BA;
 913		param->reg_MRS       = 0x00000A02 | trap_MRS;
 914		param->reg_EMRS      = 0x00000040;
 915		param->reg_DRV       = 0x000000FA;
 916		param->reg_IOZ       = 0x00000034;
 917		param->reg_DQIDLY    = 0x00000074;
 918		param->reg_FREQ      = 0x00004DC0;
 919		param->madj_max      = 96;
 920		param->dll2_finetune_step = 3;
 921		switch (param->dram_chipid) {
 922		default:
 923		case AST_DRAM_512Mx16:
 924			param->reg_AC2   = 0xAA009012 | trap_AC2;
 925			break;
 926		case AST_DRAM_1Gx16:
 927			param->reg_AC2   = 0xAA009016 | trap_AC2;
 928			break;
 929		case AST_DRAM_2Gx16:
 930			param->reg_AC2   = 0xAA009023 | trap_AC2;
 931			break;
 932		case AST_DRAM_4Gx16:
 933			param->reg_AC2   = 0xAA00903B | trap_AC2;
 934			break;
 935		}
 936		break;
 937	default:
 938	case 396:
 939		ast_moutdwm(ast, 0x1E6E2020, 0x03F1);
 940		param->wodt          = 1;
 941		param->rodt          = 0;
 942		param->reg_AC1       = 0x33302714;
 943		param->reg_AC2       = 0xCC00B01B | trap_AC2;
 944		param->reg_DQSIC     = 0x000000E2;
 945		param->reg_MRS       = 0x00000C02 | trap_MRS;
 946		param->reg_EMRS      = 0x00000040;
 947		param->reg_DRV       = 0x000000FA;
 948		param->reg_IOZ       = 0x00000034;
 949		param->reg_DQIDLY    = 0x00000089;
 950		param->reg_FREQ      = 0x00005040;
 951		param->madj_max      = 96;
 952		param->dll2_finetune_step = 4;
 953
 954		switch (param->dram_chipid) {
 955		case AST_DRAM_512Mx16:
 956			param->reg_AC2   = 0xCC00B016 | trap_AC2;
 957			break;
 958		default:
 959		case AST_DRAM_1Gx16:
 960			param->reg_AC2   = 0xCC00B01B | trap_AC2;
 961			break;
 962		case AST_DRAM_2Gx16:
 963			param->reg_AC2   = 0xCC00B02B | trap_AC2;
 964			break;
 965		case AST_DRAM_4Gx16:
 966			param->reg_AC2   = 0xCC00B03F | trap_AC2;
 967			break;
 968		}
 969
 970		break;
 971
 972	case 408:
 973		ast_moutdwm(ast, 0x1E6E2020, 0x01F0);
 974		param->wodt          = 1;
 975		param->rodt          = 0;
 976		param->reg_AC1       = 0x33302714;
 977		param->reg_AC2       = 0xCC00B01B | trap_AC2;
 978		param->reg_DQSIC     = 0x000000E2;
 979		param->reg_MRS       = 0x00000C02 | trap_MRS;
 980		param->reg_EMRS      = 0x00000040;
 981		param->reg_DRV       = 0x000000FA;
 982		param->reg_IOZ       = 0x00000034;
 983		param->reg_DQIDLY    = 0x00000089;
 984		param->reg_FREQ      = 0x000050C0;
 985		param->madj_max      = 96;
 986		param->dll2_finetune_step = 4;
 987
 988		switch (param->dram_chipid) {
 989		case AST_DRAM_512Mx16:
 990			param->reg_AC2   = 0xCC00B016 | trap_AC2;
 991			break;
 992		default:
 993		case AST_DRAM_1Gx16:
 994			param->reg_AC2   = 0xCC00B01B | trap_AC2;
 995			break;
 996		case AST_DRAM_2Gx16:
 997			param->reg_AC2   = 0xCC00B02B | trap_AC2;
 998			break;
 999		case AST_DRAM_4Gx16:
1000			param->reg_AC2   = 0xCC00B03F | trap_AC2;
1001			break;
1002		}
1003
1004		break;
1005	case 456:
1006		ast_moutdwm(ast, 0x1E6E2020, 0x0230);
1007		param->wodt          = 0;
1008		param->reg_AC1       = 0x33302815;
1009		param->reg_AC2       = 0xCD44B01E;
1010		param->reg_DQSIC     = 0x000000FC;
1011		param->reg_MRS       = 0x00000E72;
1012		param->reg_EMRS      = 0x00000000;
1013		param->reg_DRV       = 0x00000000;
1014		param->reg_IOZ       = 0x00000034;
1015		param->reg_DQIDLY    = 0x00000097;
1016		param->reg_FREQ      = 0x000052C0;
1017		param->madj_max      = 88;
1018		param->dll2_finetune_step = 3;
1019		break;
1020	case 504:
1021		ast_moutdwm(ast, 0x1E6E2020, 0x0261);
1022		param->wodt          = 1;
1023		param->rodt          = 1;
1024		param->reg_AC1       = 0x33302815;
1025		param->reg_AC2       = 0xDE44C022;
1026		param->reg_DQSIC     = 0x00000117;
1027		param->reg_MRS       = 0x00000E72;
1028		param->reg_EMRS      = 0x00000040;
1029		param->reg_DRV       = 0x0000000A;
1030		param->reg_IOZ       = 0x00000045;
1031		param->reg_DQIDLY    = 0x000000A0;
1032		param->reg_FREQ      = 0x000054C0;
1033		param->madj_max      = 79;
1034		param->dll2_finetune_step = 3;
1035		break;
1036	case 528:
1037		ast_moutdwm(ast, 0x1E6E2020, 0x0120);
1038		param->wodt          = 1;
1039		param->rodt          = 1;
1040		param->reg_AC1       = 0x33302815;
1041		param->reg_AC2       = 0xEF44D024;
1042		param->reg_DQSIC     = 0x00000125;
1043		param->reg_MRS       = 0x00000E72;
1044		param->reg_EMRS      = 0x00000004;
1045		param->reg_DRV       = 0x000000F9;
1046		param->reg_IOZ       = 0x00000045;
1047		param->reg_DQIDLY    = 0x000000A7;
1048		param->reg_FREQ      = 0x000055C0;
1049		param->madj_max      = 76;
1050		param->dll2_finetune_step = 3;
1051		break;
1052	case 552:
1053		ast_moutdwm(ast, 0x1E6E2020, 0x02A1);
1054		param->wodt          = 1;
1055		param->rodt          = 1;
1056		param->reg_AC1       = 0x43402915;
1057		param->reg_AC2       = 0xFF44E025;
1058		param->reg_DQSIC     = 0x00000132;
1059		param->reg_MRS       = 0x00000E72;
1060		param->reg_EMRS      = 0x00000040;
1061		param->reg_DRV       = 0x0000000A;
1062		param->reg_IOZ       = 0x00000045;
1063		param->reg_DQIDLY    = 0x000000AD;
1064		param->reg_FREQ      = 0x000056C0;
1065		param->madj_max      = 76;
1066		param->dll2_finetune_step = 3;
1067		break;
1068	case 576:
1069		ast_moutdwm(ast, 0x1E6E2020, 0x0140);
1070		param->wodt          = 1;
1071		param->rodt          = 1;
1072		param->reg_AC1       = 0x43402915;
1073		param->reg_AC2       = 0xFF44E027;
1074		param->reg_DQSIC     = 0x0000013F;
1075		param->reg_MRS       = 0x00000E72;
1076		param->reg_EMRS      = 0x00000004;
1077		param->reg_DRV       = 0x000000F5;
1078		param->reg_IOZ       = 0x00000045;
1079		param->reg_DQIDLY    = 0x000000B3;
1080		param->reg_FREQ      = 0x000057C0;
1081		param->madj_max      = 76;
1082		param->dll2_finetune_step = 3;
1083		break;
1084	}
1085
1086	switch (param->dram_chipid) {
1087	case AST_DRAM_512Mx16:
1088		param->dram_config = 0x100;
1089		break;
1090	default:
1091	case AST_DRAM_1Gx16:
1092		param->dram_config = 0x121;
1093		break;
1094	case AST_DRAM_2Gx16:
1095		param->dram_config = 0x122;
1096		break;
1097	case AST_DRAM_4Gx16:
1098		param->dram_config = 0x123;
1099		break;
1100	} /* switch size */
1101
1102	switch (param->vram_size) {
1103	default:
1104	case SZ_8M:
1105		param->dram_config |= 0x00;
1106		break;
1107	case SZ_16M:
1108		param->dram_config |= 0x04;
1109		break;
1110	case SZ_32M:
1111		param->dram_config |= 0x08;
1112		break;
1113	case SZ_64M:
1114		param->dram_config |= 0x0c;
1115		break;
1116	}
1117}
1118
1119static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param)
1120{
1121	u32 data, data2, retry = 0;
1122
1123ddr2_init_start:
1124	ast_moutdwm(ast, 0x1E6E0000, 0xFC600309);
1125	ast_moutdwm(ast, 0x1E6E0018, 0x00000100);
1126	ast_moutdwm(ast, 0x1E6E0024, 0x00000000);
1127	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ);
1128	ast_moutdwm(ast, 0x1E6E0068, param->reg_SADJ);
1129	udelay(10);
1130	ast_moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000);
1131	udelay(10);
1132
1133	ast_moutdwm(ast, 0x1E6E0004, param->dram_config);
1134	ast_moutdwm(ast, 0x1E6E0008, 0x90040f);
1135	ast_moutdwm(ast, 0x1E6E0010, param->reg_AC1);
1136	ast_moutdwm(ast, 0x1E6E0014, param->reg_AC2);
1137	ast_moutdwm(ast, 0x1E6E0020, param->reg_DQSIC);
1138	ast_moutdwm(ast, 0x1E6E0080, 0x00000000);
1139	ast_moutdwm(ast, 0x1E6E0084, 0x00000000);
1140	ast_moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY);
1141	ast_moutdwm(ast, 0x1E6E0018, 0x4000A130);
1142	ast_moutdwm(ast, 0x1E6E0018, 0x00002330);
1143	ast_moutdwm(ast, 0x1E6E0038, 0x00000000);
1144	ast_moutdwm(ast, 0x1E6E0040, 0xFF808000);
1145	ast_moutdwm(ast, 0x1E6E0044, 0x88848466);
1146	ast_moutdwm(ast, 0x1E6E0048, 0x44440008);
1147	ast_moutdwm(ast, 0x1E6E004C, 0x00000000);
1148	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1149	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1150	ast_moutdwm(ast, 0x1E6E0054, 0);
1151	ast_moutdwm(ast, 0x1E6E0060, param->reg_DRV);
1152	ast_moutdwm(ast, 0x1E6E006C, param->reg_IOZ);
1153	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1154	ast_moutdwm(ast, 0x1E6E0074, 0x00000000);
1155	ast_moutdwm(ast, 0x1E6E0078, 0x00000000);
1156	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1157
1158	/* Wait MCLK2X lock to MCLK */
1159	do {
1160		data = ast_mindwm(ast, 0x1E6E001C);
1161	} while (!(data & 0x08000000));
1162	data = ast_mindwm(ast, 0x1E6E001C);
1163	data = (data >> 8) & 0xff;
1164	while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) {
1165		data2 = (ast_mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4;
1166		if ((data2 & 0xff) > param->madj_max)
1167			break;
1168		ast_moutdwm(ast, 0x1E6E0064, data2);
1169		if (data2 & 0x00100000)
1170			data2 = ((data2 & 0xff) >> 3) + 3;
1171		else
1172			data2 = ((data2 & 0xff) >> 2) + 5;
1173		data = ast_mindwm(ast, 0x1E6E0068) & 0xffff00ff;
1174		data2 += data & 0xff;
1175		data = data | (data2 << 8);
1176		ast_moutdwm(ast, 0x1E6E0068, data);
1177		udelay(10);
1178		ast_moutdwm(ast, 0x1E6E0064, ast_mindwm(ast, 0x1E6E0064) | 0xC0000);
1179		udelay(10);
1180		data = ast_mindwm(ast, 0x1E6E0018) & 0xfffff1ff;
1181		ast_moutdwm(ast, 0x1E6E0018, data);
1182		data = data | 0x200;
1183		ast_moutdwm(ast, 0x1E6E0018, data);
1184		do {
1185			data = ast_mindwm(ast, 0x1E6E001C);
1186		} while (!(data & 0x08000000));
1187
1188		data = ast_mindwm(ast, 0x1E6E001C);
1189		data = (data >> 8) & 0xff;
1190	}
1191	ast_moutdwm(ast, 0x1E720058, ast_mindwm(ast, 0x1E6E0008) & 0xffff);
1192	data = ast_mindwm(ast, 0x1E6E0018) | 0xC00;
1193	ast_moutdwm(ast, 0x1E6E0018, data);
1194
1195	ast_moutdwm(ast, 0x1E6E0034, 0x00000001);
1196	ast_moutdwm(ast, 0x1E6E000C, 0x00000000);
1197	udelay(50);
1198	/* Mode Register Setting */
1199	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100);
1200	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1201	ast_moutdwm(ast, 0x1E6E0028, 0x00000005);
1202	ast_moutdwm(ast, 0x1E6E0028, 0x00000007);
1203	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1204	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1205
1206	ast_moutdwm(ast, 0x1E6E000C, 0x00005C08);
1207	ast_moutdwm(ast, 0x1E6E002C, param->reg_MRS);
1208	ast_moutdwm(ast, 0x1E6E0028, 0x00000001);
1209	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380);
1210	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1211	ast_moutdwm(ast, 0x1E6E0030, param->reg_EMRS);
1212	ast_moutdwm(ast, 0x1E6E0028, 0x00000003);
1213
1214	ast_moutdwm(ast, 0x1E6E000C, 0x7FFF5C01);
1215	data = 0;
1216	if (param->wodt)
1217		data = 0x500;
1218	if (param->rodt)
1219		data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3);
1220	ast_moutdwm(ast, 0x1E6E0034, data | 0x3);
1221	ast_moutdwm(ast, 0x1E6E0120, param->reg_FREQ);
1222
1223	/* Calibrate the DQSI delay */
1224	if ((cbr_dll2(ast, param) == false) && (retry++ < 10))
1225		goto ddr2_init_start;
1226
1227	/* ECC Memory Initialization */
1228#ifdef ECC
1229	ast_moutdwm(ast, 0x1E6E007C, 0x00000000);
1230	ast_moutdwm(ast, 0x1E6E0070, 0x221);
1231	do {
1232		data = ast_mindwm(ast, 0x1E6E0070);
1233	} while (!(data & 0x00001000));
1234	ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
1235	ast_moutdwm(ast, 0x1E6E0050, 0x80000000);
1236	ast_moutdwm(ast, 0x1E6E0050, 0x00000000);
1237#endif
1238}
1239
1240static void ast_post_chip_2300(struct ast_device *ast)
1241{
1242	struct ast2300_dram_param param;
1243	u32 temp;
1244	u8 reg;
1245
1246	reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
1247	if ((reg & 0x80) == 0) {/* vga only */
1248		ast_write32(ast, 0xf004, 0x1e6e0000);
1249		ast_write32(ast, 0xf000, 0x1);
1250		ast_write32(ast, 0x12000, 0x1688a8a8);
1251		do {
1252			;
1253		} while (ast_read32(ast, 0x12000) != 0x1);
1254
1255		ast_write32(ast, 0x10000, 0xfc600309);
1256		do {
1257			;
1258		} while (ast_read32(ast, 0x10000) != 0x1);
1259
1260		/* Slow down CPU/AHB CLK in VGA only mode */
1261		temp = ast_read32(ast, 0x12008);
1262		temp |= 0x73;
1263		ast_write32(ast, 0x12008, temp);
1264
1265		param.dram_freq = 396;
1266		param.dram_type = AST_DDR3;
1267		temp = ast_mindwm(ast, 0x1e6e2070);
1268		if (temp & 0x01000000)
1269			param.dram_type = AST_DDR2;
1270		switch (temp & 0x18000000) {
1271		case 0:
1272			param.dram_chipid = AST_DRAM_512Mx16;
1273			break;
1274		default:
1275		case 0x08000000:
1276			param.dram_chipid = AST_DRAM_1Gx16;
1277			break;
1278		case 0x10000000:
1279			param.dram_chipid = AST_DRAM_2Gx16;
1280			break;
1281		case 0x18000000:
1282			param.dram_chipid = AST_DRAM_4Gx16;
1283			break;
1284		}
1285		switch (temp & 0x0c) {
1286		default:
1287		case 0x00:
1288			param.vram_size = SZ_8M;
1289			break;
1290		case 0x04:
1291			param.vram_size = SZ_16M;
1292			break;
1293		case 0x08:
1294			param.vram_size = SZ_32M;
1295			break;
1296		case 0x0c:
1297			param.vram_size = SZ_64M;
1298			break;
1299		}
1300
1301		if (param.dram_type == AST_DDR3) {
1302			get_ddr3_info(ast, &param);
1303			ddr3_init(ast, &param);
1304		} else {
1305			get_ddr2_info(ast, &param);
1306			ddr2_init(ast, &param);
1307		}
1308
1309		temp = ast_mindwm(ast, 0x1e6e2040);
1310		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
1311	}
1312
1313	/* wait ready */
1314	do {
1315		reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
1316	} while ((reg & 0x40) == 0);
1317}
1318
1319int ast_2300_post(struct ast_device *ast)
1320{
1321	ast_2300_set_def_ext_reg(ast);
1322
1323	if (ast->config_mode == ast_use_p2a) {
1324		ast_post_chip_2300(ast);
1325		ast_init_3rdtx(ast);
1326	} else {
1327		if (ast->tx_chip == AST_TX_SIL164) {
1328			/* Enable DVO */
1329			ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);
1330		}
1331	}
1332
1333	return 0;
1334}
1335
1336/*
1337 * Device initialization
1338 */
1339
1340void ast_2300_detect_tx_chip(struct ast_device *ast)
1341{
1342	enum ast_tx_chip tx_chip = AST_TX_NONE;
1343	struct drm_device *dev = &ast->base;
1344	u8 vgacrd1;
1345
1346	/*
1347	 * On AST GEN4+, look at the configuration set by the SoC in
1348	 * the SOC scratch register #1 bits 11:8 (interestingly marked
1349	 * as "reserved" in the spec)
1350	 */
1351	vgacrd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1,
1352					 AST_IO_VGACRD1_TX_TYPE_MASK);
1353	switch (vgacrd1) {
1354	/*
1355	 * GEN4 to GEN6
1356	 */
1357	case AST_IO_VGACRD1_TX_SIL164_VBIOS:
1358		tx_chip = AST_TX_SIL164;
1359		break;
1360	case AST_IO_VGACRD1_TX_DP501_VBIOS:
1361		ast->dp501_fw_addr = drmm_kzalloc(dev, SZ_32K, GFP_KERNEL);
1362		if (ast->dp501_fw_addr) {
1363			/* backup firmware */
1364			if (ast_backup_fw(ast, ast->dp501_fw_addr, SZ_32K)) {
1365				drmm_kfree(dev, ast->dp501_fw_addr);
1366				ast->dp501_fw_addr = NULL;
1367			}
1368		}
1369		fallthrough;
1370	case AST_IO_VGACRD1_TX_FW_EMBEDDED_FW:
1371		tx_chip = AST_TX_DP501;
1372		break;
1373	/*
1374	 * GEN7+
1375	 */
1376	case AST_IO_VGACRD1_TX_ASTDP:
1377		tx_chip = AST_TX_ASTDP;
1378		break;
1379	/*
1380	 * Several of the listed TX chips are not explicitly supported
1381	 * by the ast driver. If these exist in real-world devices, they
1382	 * are most likely reported as VGA or SIL164 outputs. We warn here
1383	 * to get bug reports for these devices. If none come in for some
1384	 * time, we can begin to fail device probing on these values.
1385	 */
1386	case AST_IO_VGACRD1_TX_ITE66121_VBIOS:
1387		drm_warn(dev, "ITE IT66121 detected, 0x%x, Gen%lu\n", vgacrd1, AST_GEN(ast));
1388		break;
1389	case AST_IO_VGACRD1_TX_CH7003_VBIOS:
1390		drm_warn(dev, "Chrontel CH7003 detected, 0x%x, Gen%lu\n", vgacrd1, AST_GEN(ast));
1391		break;
1392	case AST_IO_VGACRD1_TX_ANX9807_VBIOS:
1393		drm_warn(dev, "Analogix ANX9807 detected, 0x%x, Gen%lu\n", vgacrd1, AST_GEN(ast));
1394		break;
1395	}
1396
1397	__ast_device_set_tx_chip(ast, tx_chip);
1398}
1399
1400static void ast_2300_detect_widescreen(struct ast_device *ast)
1401{
1402	if (__ast_2100_detect_wsxga_p(ast) || ast->chip == AST1300) {
1403		ast->support_wsxga_p = true;
1404		ast->support_fullhd = true;
1405	}
1406	if (__ast_2100_detect_wuxga(ast))
1407		ast->support_wuxga = true;
1408}
1409
1410static const struct ast_device_quirks ast_2300_device_quirks = {
1411	.crtc_mem_req_threshold_low = 96,
1412	.crtc_mem_req_threshold_high = 120,
1413};
1414
1415struct drm_device *ast_2300_device_create(struct pci_dev *pdev,
1416					  const struct drm_driver *drv,
1417					  enum ast_chip chip,
1418					  enum ast_config_mode config_mode,
1419					  void __iomem *regs,
1420					  void __iomem *ioregs,
1421					  bool need_post)
1422{
1423	struct drm_device *dev;
1424	struct ast_device *ast;
1425	int ret;
1426
1427	ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
1428	if (IS_ERR(ast))
1429		return ERR_CAST(ast);
1430	dev = &ast->base;
1431
1432	ast_device_init(ast, chip, config_mode, regs, ioregs, &ast_2300_device_quirks);
1433
1434	ast->dclk_table = ast_2000_dclk_table;
1435
1436	ast_2300_detect_tx_chip(ast);
1437
1438	if (need_post) {
1439		ret = ast_post_gpu(ast);
1440		if (ret)
1441			return ERR_PTR(ret);
1442	}
1443
1444	ret = ast_mm_init(ast);
1445	if (ret)
1446		return ERR_PTR(ret);
1447
1448	/* map reserved buffer */
1449	ast->dp501_fw_buf = NULL;
1450	if (ast->vram_size < pci_resource_len(pdev, 0)) {
1451		ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);
1452		if (!ast->dp501_fw_buf)
1453			drm_info(dev, "failed to map reserved buffer!\n");
1454	}
1455
1456	ast_2300_detect_widescreen(ast);
1457
1458	ret = ast_mode_config_init(ast);
1459	if (ret)
1460		return ERR_PTR(ret);
1461
1462	return dev;
1463}
~/ Read-only file preview.