1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/delay.h>
5 #include "mgag200_drv.h"
11 static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
12 struct mgag200_pll_values *pixpllc)
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;
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;
30 if (clock > p_clk_max) {
31 drm_err(dev, "Pixel Clock %ld too high\n", clock);
35 if (clock < p_clk_min >> 3)
36 clock = p_clk_min >> 3;
40 testp <= post_div_max && f_vco < p_clk_min;
41 testp = (testp << 1) + 1, f_vco <<= 1)
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);
51 tmp_delta = f_vco - computed;
53 tmp_delta = computed - f_vco;
54 if (tmp_delta < delta) {
61 f_vco = ref_clk * n / m;
64 else if (f_vco < 140000)
66 else if (f_vco < 180000)
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);
83 mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
85 struct mga_device *mdev = pixpll->mdev;
86 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
87 u8 xpixpllcm, xpixpllcn, xpixpllcp;
89 pixpllcm = pixpllc->m - 1;
90 pixpllcn = pixpllc->n - 1;
91 pixpllcp = pixpllc->p - 1;
92 pixpllcs = pixpllc->s;
96 xpixpllcp = (pixpllcs << 3) | pixpllcp;
98 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
100 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
101 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
102 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
105 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = {
106 .compute = mgag200_pixpll_compute_g200,
107 .update = mgag200_pixpll_update_g200,
114 static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock,
115 struct mgag200_pll_values *pixpllc)
117 static const unsigned int vcomax = 320000;
118 static const unsigned int vcomin = 160000;
119 static const unsigned int pllreffreq = 25000;
121 unsigned int delta, tmpdelta, permitteddelta;
122 unsigned int testp, testm, testn;
123 unsigned int p, m, n, s;
124 unsigned int computed;
127 permitteddelta = clock * 5 / 1000;
129 for (testp = 8; testp > 0; testp /= 2) {
130 if (clock * testp > vcomax)
132 if (clock * testp < vcomin)
135 for (testn = 17; testn < 256; testn++) {
136 for (testm = 1; testm < 32; testm++) {
137 computed = (pllreffreq * testn) / (testm * testp);
138 if (computed > clock)
139 tmpdelta = computed - clock;
141 tmpdelta = clock - computed;
142 if (tmpdelta < delta) {
152 if (delta > permitteddelta) {
153 pr_warn("PLL delta too large\n");
165 static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
166 const struct mgag200_pll_values *pixpllc)
168 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
169 u8 xpixpllcm, xpixpllcn, xpixpllcp;
170 struct mga_device *mdev = pixpll->mdev;
172 pixpllcm = pixpllc->m - 1;
173 pixpllcn = pixpllc->n - 1;
174 pixpllcp = pixpllc->p - 1;
175 pixpllcs = pixpllc->s;
177 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
178 xpixpllcn = pixpllcn;
179 xpixpllcp = (pixpllcs << 3) | pixpllcp;
181 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
183 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
184 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
185 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
188 static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
189 struct mgag200_pll_values *pixpllc)
191 static const unsigned int vcomax = 1600000;
192 static const unsigned int vcomin = 800000;
193 static const unsigned int pllreffreq = 25000;
194 static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
196 unsigned int delta, tmpdelta, permitteddelta;
197 unsigned int testp, testm, testn;
198 unsigned int p, m, n, s;
199 unsigned int computed;
210 /* Permited delta is 0.5% as VESA Specification */
211 permitteddelta = clock * 5 / 1000;
213 for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
214 testp = pvalues_e4[i];
216 if ((clock * testp) > vcomax)
218 if ((clock * testp) < vcomin)
221 for (testn = 50; testn <= 256; testn++) {
222 for (testm = 1; testm <= 32; testm++) {
223 computed = (pllreffreq * testn) / (testm * testp);
224 if (computed > clock)
225 tmpdelta = computed - clock;
227 tmpdelta = clock - computed;
229 if (tmpdelta < delta) {
239 fvv = pllreffreq * n / m;
240 fvv = (fvv - 800000) / 50000;
245 if (delta > permitteddelta) {
246 pr_warn("PLL delta too large\n");
258 static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
259 const struct mgag200_pll_values *pixpllc)
261 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
262 u8 xpixpllcm, xpixpllcn, xpixpllcp;
263 struct mga_device *mdev = pixpll->mdev;
265 pixpllcm = pixpllc->m - 1;
266 pixpllcn = pixpllc->n - 1;
267 pixpllcp = pixpllc->p - 1;
268 pixpllcs = pixpllc->s;
270 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
271 xpixpllcn = pixpllcn;
272 xpixpllcp = (pixpllcs << 3) | pixpllcp;
274 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
276 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
277 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
278 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
280 WREG_DAC(0x1a, 0x09);
282 WREG_DAC(0x1a, 0x01);
285 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
286 .compute = mgag200_pixpll_compute_g200se_00,
287 .update = mgag200_pixpll_update_g200se_00,
290 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
291 .compute = mgag200_pixpll_compute_g200se_04,
292 .update = mgag200_pixpll_update_g200se_04,
299 static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
300 struct mgag200_pll_values *pixpllc)
302 static const unsigned int vcomax = 550000;
303 static const unsigned int vcomin = 150000;
304 static const unsigned int pllreffreq = 48000;
306 unsigned int delta, tmpdelta;
307 unsigned int testp, testm, testn;
308 unsigned int p, m, n, s;
309 unsigned int computed;
314 for (testp = 1; testp < 9; testp++) {
315 if (clock * testp > vcomax)
317 if (clock * testp < vcomin)
320 for (testm = 1; testm < 17; testm++) {
321 for (testn = 1; testn < 151; testn++) {
322 computed = (pllreffreq * testn) / (testm * testp);
323 if (computed > clock)
324 tmpdelta = computed - clock;
326 tmpdelta = clock - computed;
327 if (tmpdelta < delta) {
347 mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
349 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
350 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
351 int i, j, tmpcount, vcount;
352 struct mga_device *mdev = pixpll->mdev;
353 bool pll_locked = false;
355 pixpllcm = pixpllc->m - 1;
356 pixpllcn = pixpllc->n - 1;
357 pixpllcp = pixpllc->p - 1;
358 pixpllcs = pixpllc->s;
360 xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
361 xpixpllcn = pixpllcn;
362 xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
364 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
366 for (i = 0; i <= 32 && pll_locked == false; i++) {
368 WREG8(MGAREG_CRTC_INDEX, 0x1e);
369 tmp = RREG8(MGAREG_CRTC_DATA);
371 WREG8(MGAREG_CRTC_DATA, tmp+1);
374 /* set pixclkdis to 1 */
375 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
376 tmp = RREG8(DAC_DATA);
377 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
378 WREG8(DAC_DATA, tmp);
380 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
381 tmp = RREG8(DAC_DATA);
382 tmp |= MGA1064_REMHEADCTL_CLKDIS;
383 WREG8(DAC_DATA, tmp);
385 /* select PLL Set C */
386 tmp = RREG8(MGAREG_MEM_MISC_READ);
388 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
390 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
391 tmp = RREG8(DAC_DATA);
392 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
393 WREG8(DAC_DATA, tmp);
398 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
399 tmp = RREG8(DAC_DATA);
401 WREG8(DAC_DATA, tmp);
405 /* program pixel pll register */
406 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
407 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
408 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
413 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
414 tmp = RREG8(DAC_DATA);
416 WREG_DAC(MGA1064_VREF_CTL, tmp);
420 /* select the pixel pll */
421 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
422 tmp = RREG8(DAC_DATA);
423 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
424 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
425 WREG8(DAC_DATA, tmp);
427 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
428 tmp = RREG8(DAC_DATA);
429 tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
430 tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
431 WREG8(DAC_DATA, tmp);
433 /* reset dotclock rate bit */
434 WREG8(MGAREG_SEQ_INDEX, 1);
435 tmp = RREG8(MGAREG_SEQ_DATA);
437 WREG8(MGAREG_SEQ_DATA, tmp);
439 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
440 tmp = RREG8(DAC_DATA);
441 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
442 WREG8(DAC_DATA, tmp);
444 vcount = RREG8(MGAREG_VCOUNT);
446 for (j = 0; j < 30 && pll_locked == false; j++) {
447 tmpcount = RREG8(MGAREG_VCOUNT);
448 if (tmpcount < vcount)
450 if ((tmpcount - vcount) > 2)
457 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
458 tmp = RREG8(DAC_DATA);
459 tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
460 WREG_DAC(MGA1064_REMHEADCTL, tmp);
463 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
464 .compute = mgag200_pixpll_compute_g200wb,
465 .update = mgag200_pixpll_update_g200wb,
472 static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
473 struct mgag200_pll_values *pixpllc)
475 static const unsigned int vcomax = 550000;
476 static const unsigned int vcomin = 150000;
477 static const unsigned int pllreffreq = 50000;
479 unsigned int delta, tmpdelta;
480 unsigned int testp, testm, testn;
481 unsigned int p, m, n, s;
482 unsigned int computed;
487 for (testp = 16; testp > 0; testp--) {
488 if (clock * testp > vcomax)
490 if (clock * testp < vcomin)
493 for (testn = 1; testn < 257; testn++) {
494 for (testm = 1; testm < 17; testm++) {
495 computed = (pllreffreq * testn) /
497 if (computed > clock)
498 tmpdelta = computed - clock;
500 tmpdelta = clock - computed;
501 if (tmpdelta < delta) {
520 mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
522 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
523 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
524 struct mga_device *mdev = pixpll->mdev;
526 pixpllcm = pixpllc->m - 1;
527 pixpllcn = pixpllc->n - 1;
528 pixpllcp = pixpllc->p - 1;
529 pixpllcs = pixpllc->s;
531 xpixpllcm = pixpllcm;
532 xpixpllcn = pixpllcn;
533 xpixpllcp = (pixpllcs << 3) | pixpllcp;
535 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
537 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
538 tmp = RREG8(DAC_DATA);
539 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
540 WREG8(DAC_DATA, tmp);
542 tmp = RREG8(MGAREG_MEM_MISC_READ);
544 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
546 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
547 tmp = RREG8(DAC_DATA);
548 WREG8(DAC_DATA, tmp & ~0x40);
550 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
551 tmp = RREG8(DAC_DATA);
552 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
553 WREG8(DAC_DATA, tmp);
555 WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
556 WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
557 WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
561 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
562 tmp = RREG8(DAC_DATA);
563 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
564 WREG8(DAC_DATA, tmp);
568 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
569 tmp = RREG8(DAC_DATA);
570 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
571 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
572 WREG8(DAC_DATA, tmp);
574 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
575 tmp = RREG8(DAC_DATA);
576 WREG8(DAC_DATA, tmp | 0x40);
578 tmp = RREG8(MGAREG_MEM_MISC_READ);
580 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
582 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
583 tmp = RREG8(DAC_DATA);
584 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
585 WREG8(DAC_DATA, tmp);
588 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
589 .compute = mgag200_pixpll_compute_g200ev,
590 .update = mgag200_pixpll_update_g200ev,
597 static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
598 struct mgag200_pll_values *pixpllc)
600 static const unsigned int vcomax = 800000;
601 static const unsigned int vcomin = 400000;
602 static const unsigned int pllreffreq = 33333;
604 unsigned int delta, tmpdelta;
605 unsigned int testp, testm, testn;
606 unsigned int p, m, n, s;
607 unsigned int computed;
612 for (testp = 16; testp > 0; testp >>= 1) {
613 if (clock * testp > vcomax)
615 if (clock * testp < vcomin)
618 for (testm = 1; testm < 33; testm++) {
619 for (testn = 17; testn < 257; testn++) {
620 computed = (pllreffreq * testn) / (testm * testp);
621 if (computed > clock)
622 tmpdelta = computed - clock;
624 tmpdelta = clock - computed;
625 if (tmpdelta < delta) {
644 mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
646 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
647 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
648 int i, j, tmpcount, vcount;
649 struct mga_device *mdev = pixpll->mdev;
650 bool pll_locked = false;
652 pixpllcm = pixpllc->m - 1;
653 pixpllcn = pixpllc->n - 1;
654 pixpllcp = pixpllc->p - 1;
655 pixpllcs = pixpllc->s;
657 xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
658 xpixpllcn = pixpllcn;
659 xpixpllcp = (pixpllcs << 3) | pixpllcp;
661 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
663 for (i = 0; i <= 32 && pll_locked == false; i++) {
664 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
665 tmp = RREG8(DAC_DATA);
666 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
667 WREG8(DAC_DATA, tmp);
669 tmp = RREG8(MGAREG_MEM_MISC_READ);
671 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
673 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
674 tmp = RREG8(DAC_DATA);
675 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
676 WREG8(DAC_DATA, tmp);
680 WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
681 WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
682 WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
686 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
687 tmp = RREG8(DAC_DATA);
688 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
689 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
690 WREG8(DAC_DATA, tmp);
692 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
693 tmp = RREG8(DAC_DATA);
694 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
695 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
696 WREG8(DAC_DATA, tmp);
698 vcount = RREG8(MGAREG_VCOUNT);
700 for (j = 0; j < 30 && pll_locked == false; j++) {
701 tmpcount = RREG8(MGAREG_VCOUNT);
702 if (tmpcount < vcount)
704 if ((tmpcount - vcount) > 2)
712 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
713 .compute = mgag200_pixpll_compute_g200eh,
714 .update = mgag200_pixpll_update_g200eh,
721 static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
722 struct mgag200_pll_values *pixpllc)
724 static const unsigned int vcomax = 3000000;
725 static const unsigned int vcomin = 1500000;
726 static const unsigned int pllreffreq = 25000;
728 unsigned int delta, tmpdelta;
729 unsigned int testp, testm, testn;
730 unsigned int p, m, n, s;
731 unsigned int computed;
737 for (testm = 150; testm >= 6; testm--) {
738 if (clock * testm > vcomax)
740 if (clock * testm < vcomin)
742 for (testn = 120; testn >= 60; testn--) {
743 computed = (pllreffreq * testn) / testm;
744 if (computed > clock)
745 tmpdelta = computed - clock;
747 tmpdelta = clock - computed;
748 if (tmpdelta < delta) {
769 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
770 .compute = mgag200_pixpll_compute_g200eh3,
771 .update = mgag200_pixpll_update_g200eh, // same as G200EH
778 static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
779 struct mgag200_pll_values *pixpllc)
781 static const unsigned int vcomax = 1488000;
782 static const unsigned int vcomin = 1056000;
783 static const unsigned int pllreffreq = 48000;
784 static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
786 unsigned int delta, tmpdelta;
787 int testr, testn, testm, testo;
788 unsigned int p, m, n, s;
789 unsigned int computed, vco;
794 for (testr = 0; testr < 4; testr++) {
797 for (testn = 5; testn < 129; testn++) {
800 for (testm = 3; testm >= 0; testm--) {
803 for (testo = 5; testo < 33; testo++) {
804 vco = pllreffreq * (testn + 1) /
810 computed = vco / (m_div_val[testm] * (testo + 1));
811 if (computed > clock)
812 tmpdelta = computed - clock;
814 tmpdelta = clock - computed;
815 if (tmpdelta < delta) {
817 m = (testm | (testo << 3)) + 1;
836 mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
838 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
839 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
840 struct mga_device *mdev = pixpll->mdev;
842 pixpllcm = pixpllc->m - 1;
843 pixpllcn = pixpllc->n - 1;
844 pixpllcp = pixpllc->p - 1;
845 pixpllcs = pixpllc->s;
847 xpixpllcm = pixpllcm;
848 xpixpllcn = pixpllcn;
849 xpixpllcp = (pixpllcs << 3) | pixpllcp;
851 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
853 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
854 tmp = RREG8(DAC_DATA);
855 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
856 WREG8(DAC_DATA, tmp);
858 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
859 tmp = RREG8(DAC_DATA);
860 tmp |= MGA1064_REMHEADCTL_CLKDIS;
861 WREG8(DAC_DATA, tmp);
863 tmp = RREG8(MGAREG_MEM_MISC_READ);
864 tmp |= (0x3<<2) | 0xc0;
865 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
867 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
868 tmp = RREG8(DAC_DATA);
869 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
870 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
871 WREG8(DAC_DATA, tmp);
875 WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
876 WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
877 WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
882 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
883 .compute = mgag200_pixpll_compute_g200er,
884 .update = mgag200_pixpll_update_g200er,
891 static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
892 struct mgag200_pll_values *pixpllc)
894 static const unsigned int vcomax = 800000;
895 static const unsigned int vcomin = 400000;
896 static const unsigned int pllreffreq = 25000;
898 unsigned int delta, tmpdelta;
899 unsigned int testp, testm, testn, testp2;
900 unsigned int p, m, n, s;
901 unsigned int computed;
906 for (testp = 1; testp < 8; testp++) {
907 for (testp2 = 1; testp2 < 8; testp2++) {
910 if ((clock * testp * testp2) > vcomax)
912 if ((clock * testp * testp2) < vcomin)
914 for (testm = 1; testm < 26; testm++) {
915 for (testn = 32; testn < 2048 ; testn++) {
916 computed = (pllreffreq * testn) / (testm * testp * testp2);
917 if (computed > clock)
918 tmpdelta = computed - clock;
920 tmpdelta = clock - computed;
921 if (tmpdelta < delta) {
941 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
942 .compute = mgag200_pixpll_compute_g200ew3,
943 .update = mgag200_pixpll_update_g200wb, // same as G200WB
950 int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
952 struct drm_device *dev = &mdev->base;
956 switch (mdev->type) {
959 pixpll->funcs = &mgag200_pixpll_funcs_g200;
963 if (mdev->model.g200se.unique_rev_id >= 0x04)
964 pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
966 pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
969 pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
972 pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
975 pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
978 pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
981 pixpll->funcs = &mgag200_pixpll_funcs_g200er;
984 pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
987 drm_err(dev, "unknown device type %d\n", mdev->type);