Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/ast/ast_2300.c
50622 views
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 <[email protected]>
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
44
void 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
79
struct 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
117
static const u32 pattern[8] = {
118
0xFF00FF00,
119
0xCC33CC33,
120
0xAA55AA55,
121
0x88778877,
122
0x92CC4D6E,
123
0x543D3CDE,
124
0xF1E843C7,
125
0x7C61D253
126
};
127
128
static 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
148
static u32 mmc_test_burst2(struct ast_device *ast, u32 datagen)
149
{
150
return mmc_test2(ast, datagen, 0x41);
151
}
152
153
static bool mmc_test_single(struct ast_device *ast, u32 datagen)
154
{
155
return mmc_test(ast, datagen, 0xc5);
156
}
157
158
static u32 mmc_test_single2(struct ast_device *ast, u32 datagen)
159
{
160
return mmc_test2(ast, datagen, 0x05);
161
}
162
163
static 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
183
static 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
205
static 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
219
static 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
241
static 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
250
static 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
266
static 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;
270
FINETUNE_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;
310
FINETUNE_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
361
static 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
463
static 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
472
CBR_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;
507
CBR_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
515
static 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
756
static void ddr3_init(struct ast_device *ast, struct ast2300_dram_param *param)
757
{
758
u32 data, data2, retry = 0;
759
760
ddr3_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
873
static 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
1119
static void ddr2_init(struct ast_device *ast, struct ast2300_dram_param *param)
1120
{
1121
u32 data, data2, retry = 0;
1122
1123
ddr2_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
1240
static 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
1319
int 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
1340
void 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
1400
static 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
1410
static 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
1415
struct 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
}
1464
1465