1
2
3#include <linux/delay.h>
4
5#include "mgag200_drv.h"
6
7
8
9
10
11static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
12 struct mgag200_pll_values *pixpllc)
13{
14 struct mga_device *mdev = pixpll->mdev;
15 struct drm_device *dev = &mdev->base;
16 const int post_div_max = 7;
17 const int in_div_min = 1;
18 const int in_div_max = 6;
19 const int feed_div_min = 7;
20 const int feed_div_max = 127;
21 u8 testp, testm, testn;
22 u8 n = 0, m = 0, p, s;
23 long f_vco;
24 long computed;
25 long delta, tmp_delta;
26 long ref_clk = mdev->model.g200.ref_clk;
27 long p_clk_min = mdev->model.g200.pclk_min;
28 long p_clk_max = mdev->model.g200.pclk_max;
29
30 if (clock > p_clk_max) {
31 drm_err(dev, "Pixel Clock %ld too high\n", clock);
32 return -EINVAL;
33 }
34
35 if (clock < p_clk_min >> 3)
36 clock = p_clk_min >> 3;
37
38 f_vco = clock;
39 for (testp = 0;
40 testp <= post_div_max && f_vco < p_clk_min;
41 testp = (testp << 1) + 1, f_vco <<= 1)
42 ;
43 p = testp + 1;
44
45 delta = clock;
46
47 for (testm = in_div_min; testm <= in_div_max; testm++) {
48 for (testn = feed_div_min; testn <= feed_div_max; testn++) {
49 computed = ref_clk * (testn + 1) / (testm + 1);
50 if (computed < f_vco)
51 tmp_delta = f_vco - computed;
52 else
53 tmp_delta = computed - f_vco;
54 if (tmp_delta < delta) {
55 delta = tmp_delta;
56 m = testm + 1;
57 n = testn + 1;
58 }
59 }
60 }
61 f_vco = ref_clk * n / m;
62 if (f_vco < 100000)
63 s = 0;
64 else if (f_vco < 140000)
65 s = 1;
66 else if (f_vco < 180000)
67 s = 2;
68 else
69 s = 3;
70
71 drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
72 clock, f_vco, m, n, p, s);
73
74 pixpllc->m = m;
75 pixpllc->n = n;
76 pixpllc->p = p;
77 pixpllc->s = s;
78
79 return 0;
80}
81
82static void
83mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
84{
85 struct mga_device *mdev = pixpll->mdev;
86 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
87 u8 xpixpllcm, xpixpllcn, xpixpllcp;
88
89 pixpllcm = pixpllc->m - 1;
90 pixpllcn = pixpllc->n - 1;
91 pixpllcp = pixpllc->p - 1;
92 pixpllcs = pixpllc->s;
93
94 xpixpllcm = pixpllcm;
95 xpixpllcn = pixpllcn;
96 xpixpllcp = (pixpllcs << 3) | pixpllcp;
97
98 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
99
100 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
101 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
102 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
103}
104
105static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = {
106 .compute = mgag200_pixpll_compute_g200,
107 .update = mgag200_pixpll_update_g200,
108};
109
110
111
112
113
114static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock,
115 struct mgag200_pll_values *pixpllc)
116{
117 static const unsigned int vcomax = 320000;
118 static const unsigned int vcomin = 160000;
119 static const unsigned int pllreffreq = 25000;
120
121 unsigned int delta, tmpdelta, permitteddelta;
122 unsigned int testp, testm, testn;
123 unsigned int p, m, n, s;
124 unsigned int computed;
125
126 m = n = p = s = 0;
127 delta = 0xffffffff;
128 permitteddelta = clock * 5 / 1000;
129
130 for (testp = 8; testp > 0; testp /= 2) {
131 if (clock * testp > vcomax)
132 continue;
133 if (clock * testp < vcomin)
134 continue;
135
136 for (testn = 17; testn < 256; testn++) {
137 for (testm = 1; testm < 32; testm++) {
138 computed = (pllreffreq * testn) / (testm * testp);
139 if (computed > clock)
140 tmpdelta = computed - clock;
141 else
142 tmpdelta = clock - computed;
143 if (tmpdelta < delta) {
144 delta = tmpdelta;
145 m = testm;
146 n = testn;
147 p = testp;
148 }
149 }
150 }
151 }
152
153 if (delta > permitteddelta) {
154 pr_warn("PLL delta too large\n");
155 return -EINVAL;
156 }
157
158 pixpllc->m = m;
159 pixpllc->n = n;
160 pixpllc->p = p;
161 pixpllc->s = s;
162
163 return 0;
164}
165
166static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
167 const struct mgag200_pll_values *pixpllc)
168{
169 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
170 u8 xpixpllcm, xpixpllcn, xpixpllcp;
171 struct mga_device *mdev = pixpll->mdev;
172
173 pixpllcm = pixpllc->m - 1;
174 pixpllcn = pixpllc->n - 1;
175 pixpllcp = pixpllc->p - 1;
176 pixpllcs = pixpllc->s;
177
178 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
179 xpixpllcn = pixpllcn;
180 xpixpllcp = (pixpllcs << 3) | pixpllcp;
181
182 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
183
184 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
185 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
186 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
187}
188
189static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
190 struct mgag200_pll_values *pixpllc)
191{
192 static const unsigned int vcomax = 1600000;
193 static const unsigned int vcomin = 800000;
194 static const unsigned int pllreffreq = 25000;
195 static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
196
197 unsigned int delta, tmpdelta, permitteddelta;
198 unsigned int testp, testm, testn;
199 unsigned int p, m, n, s;
200 unsigned int computed;
201 unsigned int fvv;
202 unsigned int i;
203
204 m = n = p = s = 0;
205 delta = 0xffffffff;
206
207 if (clock < 25000)
208 clock = 25000;
209 clock = clock * 2;
210
211
212 permitteddelta = clock * 5 / 1000;
213
214 for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
215 testp = pvalues_e4[i];
216
217 if ((clock * testp) > vcomax)
218 continue;
219 if ((clock * testp) < vcomin)
220 continue;
221
222 for (testn = 50; testn <= 256; testn++) {
223 for (testm = 1; testm <= 32; testm++) {
224 computed = (pllreffreq * testn) / (testm * testp);
225 if (computed > clock)
226 tmpdelta = computed - clock;
227 else
228 tmpdelta = clock - computed;
229
230 if (tmpdelta < delta) {
231 delta = tmpdelta;
232 m = testm;
233 n = testn;
234 p = testp;
235 }
236 }
237 }
238 }
239
240 fvv = pllreffreq * n / m;
241 fvv = (fvv - 800000) / 50000;
242 if (fvv > 15)
243 fvv = 15;
244 s = fvv << 1;
245
246 if (delta > permitteddelta) {
247 pr_warn("PLL delta too large\n");
248 return -EINVAL;
249 }
250
251 pixpllc->m = m;
252 pixpllc->n = n;
253 pixpllc->p = p;
254 pixpllc->s = s;
255
256 return 0;
257}
258
259static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
260 const struct mgag200_pll_values *pixpllc)
261{
262 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
263 u8 xpixpllcm, xpixpllcn, xpixpllcp;
264 struct mga_device *mdev = pixpll->mdev;
265
266 pixpllcm = pixpllc->m - 1;
267 pixpllcn = pixpllc->n - 1;
268 pixpllcp = pixpllc->p - 1;
269 pixpllcs = pixpllc->s;
270
271 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
272 xpixpllcn = pixpllcn;
273 xpixpllcp = (pixpllcs << 3) | pixpllcp;
274
275 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
276
277 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
278 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
279 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
280
281 WREG_DAC(0x1a, 0x09);
282 msleep(20);
283 WREG_DAC(0x1a, 0x01);
284}
285
286static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
287 .compute = mgag200_pixpll_compute_g200se_00,
288 .update = mgag200_pixpll_update_g200se_00,
289};
290
291static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
292 .compute = mgag200_pixpll_compute_g200se_04,
293 .update = mgag200_pixpll_update_g200se_04,
294};
295
296
297
298
299
300static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
301 struct mgag200_pll_values *pixpllc)
302{
303 static const unsigned int vcomax = 550000;
304 static const unsigned int vcomin = 150000;
305 static const unsigned int pllreffreq = 48000;
306
307 unsigned int delta, tmpdelta;
308 unsigned int testp, testm, testn;
309 unsigned int p, m, n, s;
310 unsigned int computed;
311
312 m = n = p = s = 0;
313 delta = 0xffffffff;
314
315 for (testp = 1; testp < 9; testp++) {
316 if (clock * testp > vcomax)
317 continue;
318 if (clock * testp < vcomin)
319 continue;
320
321 for (testm = 1; testm < 17; testm++) {
322 for (testn = 1; testn < 151; testn++) {
323 computed = (pllreffreq * testn) / (testm * testp);
324 if (computed > clock)
325 tmpdelta = computed - clock;
326 else
327 tmpdelta = clock - computed;
328 if (tmpdelta < delta) {
329 delta = tmpdelta;
330 n = testn;
331 m = testm;
332 p = testp;
333 s = 0;
334 }
335 }
336 }
337 }
338
339 pixpllc->m = m;
340 pixpllc->n = n;
341 pixpllc->p = p;
342 pixpllc->s = s;
343
344 return 0;
345}
346
347static void
348mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
349{
350 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
351 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
352 int i, j, tmpcount, vcount;
353 struct mga_device *mdev = pixpll->mdev;
354 bool pll_locked = false;
355
356 pixpllcm = pixpllc->m - 1;
357 pixpllcn = pixpllc->n - 1;
358 pixpllcp = pixpllc->p - 1;
359 pixpllcs = pixpllc->s;
360
361 xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
362 xpixpllcn = pixpllcn;
363 xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
364
365 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
366
367 for (i = 0; i <= 32 && pll_locked == false; i++) {
368 if (i > 0) {
369 WREG8(MGAREG_CRTC_INDEX, 0x1e);
370 tmp = RREG8(MGAREG_CRTC_DATA);
371 if (tmp < 0xff)
372 WREG8(MGAREG_CRTC_DATA, tmp+1);
373 }
374
375
376 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
377 tmp = RREG8(DAC_DATA);
378 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
379 WREG8(DAC_DATA, tmp);
380
381 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
382 tmp = RREG8(DAC_DATA);
383 tmp |= MGA1064_REMHEADCTL_CLKDIS;
384 WREG8(DAC_DATA, tmp);
385
386
387 tmp = RREG8(MGAREG_MEM_MISC_READ);
388 tmp |= 0x3 << 2;
389 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
390
391 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
392 tmp = RREG8(DAC_DATA);
393 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
394 WREG8(DAC_DATA, tmp);
395
396 udelay(500);
397
398
399 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
400 tmp = RREG8(DAC_DATA);
401 tmp &= ~0x04;
402 WREG8(DAC_DATA, tmp);
403
404 udelay(50);
405
406
407 WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
408 WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
409 WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
410
411 udelay(50);
412
413
414 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
415 tmp = RREG8(DAC_DATA);
416 tmp |= 0x04;
417 WREG_DAC(MGA1064_VREF_CTL, tmp);
418
419 udelay(500);
420
421
422 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
423 tmp = RREG8(DAC_DATA);
424 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
425 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
426 WREG8(DAC_DATA, tmp);
427
428 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
429 tmp = RREG8(DAC_DATA);
430 tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
431 tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
432 WREG8(DAC_DATA, tmp);
433
434
435 WREG8(MGAREG_SEQ_INDEX, 1);
436 tmp = RREG8(MGAREG_SEQ_DATA);
437 tmp &= ~0x8;
438 WREG8(MGAREG_SEQ_DATA, tmp);
439
440 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
441 tmp = RREG8(DAC_DATA);
442 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
443 WREG8(DAC_DATA, tmp);
444
445 vcount = RREG8(MGAREG_VCOUNT);
446
447 for (j = 0; j < 30 && pll_locked == false; j++) {
448 tmpcount = RREG8(MGAREG_VCOUNT);
449 if (tmpcount < vcount)
450 vcount = 0;
451 if ((tmpcount - vcount) > 2)
452 pll_locked = true;
453 else
454 udelay(5);
455 }
456 }
457
458 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
459 tmp = RREG8(DAC_DATA);
460 tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
461 WREG_DAC(MGA1064_REMHEADCTL, tmp);
462}
463
464static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
465 .compute = mgag200_pixpll_compute_g200wb,
466 .update = mgag200_pixpll_update_g200wb,
467};
468
469
470
471
472
473static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
474 struct mgag200_pll_values *pixpllc)
475{
476 static const unsigned int vcomax = 550000;
477 static const unsigned int vcomin = 150000;
478 static const unsigned int pllreffreq = 50000;
479
480 unsigned int delta, tmpdelta;
481 unsigned int testp, testm, testn;
482 unsigned int p, m, n, s;
483 unsigned int computed;
484
485 m = n = p = s = 0;
486 delta = 0xffffffff;
487
488 for (testp = 16; testp > 0; testp--) {
489 if (clock * testp > vcomax)
490 continue;
491 if (clock * testp < vcomin)
492 continue;
493
494 for (testn = 1; testn < 257; testn++) {
495 for (testm = 1; testm < 17; testm++) {
496 computed = (pllreffreq * testn) /
497 (testm * testp);
498 if (computed > clock)
499 tmpdelta = computed - clock;
500 else
501 tmpdelta = clock - computed;
502 if (tmpdelta < delta) {
503 delta = tmpdelta;
504 n = testn;
505 m = testm;
506 p = testp;
507 }
508 }
509 }
510 }
511
512 pixpllc->m = m;
513 pixpllc->n = n;
514 pixpllc->p = p;
515 pixpllc->s = s;
516
517 return 0;
518}
519
520static void
521mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
522{
523 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
524 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
525 struct mga_device *mdev = pixpll->mdev;
526
527 pixpllcm = pixpllc->m - 1;
528 pixpllcn = pixpllc->n - 1;
529 pixpllcp = pixpllc->p - 1;
530 pixpllcs = pixpllc->s;
531
532 xpixpllcm = pixpllcm;
533 xpixpllcn = pixpllcn;
534 xpixpllcp = (pixpllcs << 3) | pixpllcp;
535
536 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
537
538 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
539 tmp = RREG8(DAC_DATA);
540 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
541 WREG8(DAC_DATA, tmp);
542
543 tmp = RREG8(MGAREG_MEM_MISC_READ);
544 tmp |= 0x3 << 2;
545 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
546
547 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
548 tmp = RREG8(DAC_DATA);
549 WREG8(DAC_DATA, tmp & ~0x40);
550
551 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
552 tmp = RREG8(DAC_DATA);
553 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
554 WREG8(DAC_DATA, tmp);
555
556 WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
557 WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
558 WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
559
560 udelay(50);
561
562 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
563 tmp = RREG8(DAC_DATA);
564 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
565 WREG8(DAC_DATA, tmp);
566
567 udelay(500);
568
569 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
570 tmp = RREG8(DAC_DATA);
571 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
572 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
573 WREG8(DAC_DATA, tmp);
574
575 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
576 tmp = RREG8(DAC_DATA);
577 WREG8(DAC_DATA, tmp | 0x40);
578
579 tmp = RREG8(MGAREG_MEM_MISC_READ);
580 tmp |= (0x3 << 2);
581 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
582
583 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
584 tmp = RREG8(DAC_DATA);
585 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
586 WREG8(DAC_DATA, tmp);
587}
588
589static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
590 .compute = mgag200_pixpll_compute_g200ev,
591 .update = mgag200_pixpll_update_g200ev,
592};
593
594
595
596
597
598static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
599 struct mgag200_pll_values *pixpllc)
600{
601 static const unsigned int vcomax = 800000;
602 static const unsigned int vcomin = 400000;
603 static const unsigned int pllreffreq = 33333;
604
605 unsigned int delta, tmpdelta;
606 unsigned int testp, testm, testn;
607 unsigned int p, m, n, s;
608 unsigned int computed;
609
610 m = n = p = s = 0;
611 delta = 0xffffffff;
612
613 for (testp = 16; testp > 0; testp >>= 1) {
614 if (clock * testp > vcomax)
615 continue;
616 if (clock * testp < vcomin)
617 continue;
618
619 for (testm = 1; testm < 33; testm++) {
620 for (testn = 17; testn < 257; testn++) {
621 computed = (pllreffreq * testn) / (testm * testp);
622 if (computed > clock)
623 tmpdelta = computed - clock;
624 else
625 tmpdelta = clock - computed;
626 if (tmpdelta < delta) {
627 delta = tmpdelta;
628 n = testn;
629 m = testm;
630 p = testp;
631 }
632 }
633 }
634 }
635
636 pixpllc->m = m;
637 pixpllc->n = n;
638 pixpllc->p = p;
639 pixpllc->s = s;
640
641 return 0;
642}
643
644static void
645mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
646{
647 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
648 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
649 int i, j, tmpcount, vcount;
650 struct mga_device *mdev = pixpll->mdev;
651 bool pll_locked = false;
652
653 pixpllcm = pixpllc->m - 1;
654 pixpllcn = pixpllc->n - 1;
655 pixpllcp = pixpllc->p - 1;
656 pixpllcs = pixpllc->s;
657
658 xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
659 xpixpllcn = pixpllcn;
660 xpixpllcp = (pixpllcs << 3) | pixpllcp;
661
662 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
663
664 for (i = 0; i <= 32 && pll_locked == false; i++) {
665 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
666 tmp = RREG8(DAC_DATA);
667 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
668 WREG8(DAC_DATA, tmp);
669
670 tmp = RREG8(MGAREG_MEM_MISC_READ);
671 tmp |= 0x3 << 2;
672 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
673
674 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
675 tmp = RREG8(DAC_DATA);
676 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
677 WREG8(DAC_DATA, tmp);
678
679 udelay(500);
680
681 WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
682 WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
683 WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
684
685 udelay(500);
686
687 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
688 tmp = RREG8(DAC_DATA);
689 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
690 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
691 WREG8(DAC_DATA, tmp);
692
693 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
694 tmp = RREG8(DAC_DATA);
695 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
696 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
697 WREG8(DAC_DATA, tmp);
698
699 vcount = RREG8(MGAREG_VCOUNT);
700
701 for (j = 0; j < 30 && pll_locked == false; j++) {
702 tmpcount = RREG8(MGAREG_VCOUNT);
703 if (tmpcount < vcount)
704 vcount = 0;
705 if ((tmpcount - vcount) > 2)
706 pll_locked = true;
707 else
708 udelay(5);
709 }
710 }
711}
712
713static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
714 .compute = mgag200_pixpll_compute_g200eh,
715 .update = mgag200_pixpll_update_g200eh,
716};
717
718
719
720
721
722static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
723 struct mgag200_pll_values *pixpllc)
724{
725 static const unsigned int vcomax = 3000000;
726 static const unsigned int vcomin = 1500000;
727 static const unsigned int pllreffreq = 25000;
728
729 unsigned int delta, tmpdelta;
730 unsigned int testp, testm, testn;
731 unsigned int p, m, n, s;
732 unsigned int computed;
733
734 m = n = p = s = 0;
735 delta = 0xffffffff;
736 testp = 0;
737
738 for (testm = 150; testm >= 6; testm--) {
739 if (clock * testm > vcomax)
740 continue;
741 if (clock * testm < vcomin)
742 continue;
743 for (testn = 120; testn >= 60; testn--) {
744 computed = (pllreffreq * testn) / testm;
745 if (computed > clock)
746 tmpdelta = computed - clock;
747 else
748 tmpdelta = clock - computed;
749 if (tmpdelta < delta) {
750 delta = tmpdelta;
751 n = testn + 1;
752 m = testm + 1;
753 p = testp + 1;
754 }
755 if (delta == 0)
756 break;
757 }
758 if (delta == 0)
759 break;
760 }
761
762 pixpllc->m = m;
763 pixpllc->n = n;
764 pixpllc->p = p;
765 pixpllc->s = s;
766
767 return 0;
768}
769
770static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
771 .compute = mgag200_pixpll_compute_g200eh3,
772 .update = mgag200_pixpll_update_g200eh,
773};
774
775
776
777
778
779static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
780 struct mgag200_pll_values *pixpllc)
781{
782 static const unsigned int vcomax = 1488000;
783 static const unsigned int vcomin = 1056000;
784 static const unsigned int pllreffreq = 48000;
785 static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
786
787 unsigned int delta, tmpdelta;
788 int testr, testn, testm, testo;
789 unsigned int p, m, n, s;
790 unsigned int computed, vco;
791
792 m = n = p = s = 0;
793 delta = 0xffffffff;
794
795 for (testr = 0; testr < 4; testr++) {
796 if (delta == 0)
797 break;
798 for (testn = 5; testn < 129; testn++) {
799 if (delta == 0)
800 break;
801 for (testm = 3; testm >= 0; testm--) {
802 if (delta == 0)
803 break;
804 for (testo = 5; testo < 33; testo++) {
805 vco = pllreffreq * (testn + 1) /
806 (testr + 1);
807 if (vco < vcomin)
808 continue;
809 if (vco > vcomax)
810 continue;
811 computed = vco / (m_div_val[testm] * (testo + 1));
812 if (computed > clock)
813 tmpdelta = computed - clock;
814 else
815 tmpdelta = clock - computed;
816 if (tmpdelta < delta) {
817 delta = tmpdelta;
818 m = (testm | (testo << 3)) + 1;
819 n = testn + 1;
820 p = testr + 1;
821 s = testr;
822 }
823 }
824 }
825 }
826 }
827
828 pixpllc->m = m;
829 pixpllc->n = n;
830 pixpllc->p = p;
831 pixpllc->s = s;
832
833 return 0;
834}
835
836static void
837mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
838{
839 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
840 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
841 struct mga_device *mdev = pixpll->mdev;
842
843 pixpllcm = pixpllc->m - 1;
844 pixpllcn = pixpllc->n - 1;
845 pixpllcp = pixpllc->p - 1;
846 pixpllcs = pixpllc->s;
847
848 xpixpllcm = pixpllcm;
849 xpixpllcn = pixpllcn;
850 xpixpllcp = (pixpllcs << 3) | pixpllcp;
851
852 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
853
854 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
855 tmp = RREG8(DAC_DATA);
856 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
857 WREG8(DAC_DATA, tmp);
858
859 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
860 tmp = RREG8(DAC_DATA);
861 tmp |= MGA1064_REMHEADCTL_CLKDIS;
862 WREG8(DAC_DATA, tmp);
863
864 tmp = RREG8(MGAREG_MEM_MISC_READ);
865 tmp |= (0x3<<2) | 0xc0;
866 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
867
868 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
869 tmp = RREG8(DAC_DATA);
870 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
871 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
872 WREG8(DAC_DATA, tmp);
873
874 udelay(500);
875
876 WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
877 WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
878 WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
879
880 udelay(50);
881}
882
883static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
884 .compute = mgag200_pixpll_compute_g200er,
885 .update = mgag200_pixpll_update_g200er,
886};
887
888
889
890
891
892static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
893 struct mgag200_pll_values *pixpllc)
894{
895 static const unsigned int vcomax = 800000;
896 static const unsigned int vcomin = 400000;
897 static const unsigned int pllreffreq = 25000;
898
899 unsigned int delta, tmpdelta;
900 unsigned int testp, testm, testn, testp2;
901 unsigned int p, m, n, s;
902 unsigned int computed;
903
904 m = n = p = s = 0;
905 delta = 0xffffffff;
906
907 for (testp = 1; testp < 8; testp++) {
908 for (testp2 = 1; testp2 < 8; testp2++) {
909 if (testp < testp2)
910 continue;
911 if ((clock * testp * testp2) > vcomax)
912 continue;
913 if ((clock * testp * testp2) < vcomin)
914 continue;
915 for (testm = 1; testm < 26; testm++) {
916 for (testn = 32; testn < 2048 ; testn++) {
917 computed = (pllreffreq * testn) / (testm * testp * testp2);
918 if (computed > clock)
919 tmpdelta = computed - clock;
920 else
921 tmpdelta = clock - computed;
922 if (tmpdelta < delta) {
923 delta = tmpdelta;
924 m = testm + 1;
925 n = testn + 1;
926 p = testp + 1;
927 s = testp2;
928 }
929 }
930 }
931 }
932 }
933
934 pixpllc->m = m;
935 pixpllc->n = n;
936 pixpllc->p = p;
937 pixpllc->s = s;
938
939 return 0;
940}
941
942static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
943 .compute = mgag200_pixpll_compute_g200ew3,
944 .update = mgag200_pixpll_update_g200wb,
945};
946
947
948
949
950
951int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
952{
953 struct drm_device *dev = &mdev->base;
954
955 pixpll->mdev = mdev;
956
957 switch (mdev->type) {
958 case G200_PCI:
959 case G200_AGP:
960 pixpll->funcs = &mgag200_pixpll_funcs_g200;
961 break;
962 case G200_SE_A:
963 case G200_SE_B:
964 if (mdev->model.g200se.unique_rev_id >= 0x04)
965 pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
966 else
967 pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
968 break;
969 case G200_WB:
970 pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
971 break;
972 case G200_EV:
973 pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
974 break;
975 case G200_EH:
976 pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
977 break;
978 case G200_EH3:
979 pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
980 break;
981 case G200_ER:
982 pixpll->funcs = &mgag200_pixpll_funcs_g200er;
983 break;
984 case G200_EW3:
985 pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
986 break;
987 default:
988 drm_err(dev, "unknown device type %d\n", mdev->type);
989 return -ENODEV;
990 }
991
992 return 0;
993}
994