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;
128 permitteddelta = clock * 5 / 1000;
130 for (testp = 8; testp > 0; testp /= 2) {
131 if (clock * testp > vcomax)
133 if (clock * testp < vcomin)
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;
142 tmpdelta = clock - computed;
143 if (tmpdelta < delta) {
153 if (delta > permitteddelta) {
154 pr_warn("PLL delta too large\n");
166 static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
167 const struct mgag200_pll_values *pixpllc)
169 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
170 u8 xpixpllcm, xpixpllcn, xpixpllcp;
171 struct mga_device *mdev = pixpll->mdev;
173 pixpllcm = pixpllc->m - 1;
174 pixpllcn = pixpllc->n - 1;
175 pixpllcp = pixpllc->p - 1;
176 pixpllcs = pixpllc->s;
178 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
179 xpixpllcn = pixpllcn;
180 xpixpllcp = (pixpllcs << 3) | pixpllcp;
182 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
184 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
185 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
186 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
189 static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
190 struct mgag200_pll_values *pixpllc)
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};
197 unsigned int delta, tmpdelta, permitteddelta;
198 unsigned int testp, testm, testn;
199 unsigned int p, m, n, s;
200 unsigned int computed;
211 /* Permited delta is 0.5% as VESA Specification */
212 permitteddelta = clock * 5 / 1000;
214 for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
215 testp = pvalues_e4[i];
217 if ((clock * testp) > vcomax)
219 if ((clock * testp) < vcomin)
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;
228 tmpdelta = clock - computed;
230 if (tmpdelta < delta) {
240 fvv = pllreffreq * n / m;
241 fvv = (fvv - 800000) / 50000;
246 if (delta > permitteddelta) {
247 pr_warn("PLL delta too large\n");
259 static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
260 const struct mgag200_pll_values *pixpllc)
262 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
263 u8 xpixpllcm, xpixpllcn, xpixpllcp;
264 struct mga_device *mdev = pixpll->mdev;
266 pixpllcm = pixpllc->m - 1;
267 pixpllcn = pixpllc->n - 1;
268 pixpllcp = pixpllc->p - 1;
269 pixpllcs = pixpllc->s;
271 xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
272 xpixpllcn = pixpllcn;
273 xpixpllcp = (pixpllcs << 3) | pixpllcp;
275 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
277 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
278 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
279 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
281 WREG_DAC(0x1a, 0x09);
283 WREG_DAC(0x1a, 0x01);
286 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
287 .compute = mgag200_pixpll_compute_g200se_00,
288 .update = mgag200_pixpll_update_g200se_00,
291 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
292 .compute = mgag200_pixpll_compute_g200se_04,
293 .update = mgag200_pixpll_update_g200se_04,
300 static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
301 struct mgag200_pll_values *pixpllc)
303 static const unsigned int vcomax = 550000;
304 static const unsigned int vcomin = 150000;
305 static const unsigned int pllreffreq = 48000;
307 unsigned int delta, tmpdelta;
308 unsigned int testp, testm, testn;
309 unsigned int p, m, n, s;
310 unsigned int computed;
315 for (testp = 1; testp < 9; testp++) {
316 if (clock * testp > vcomax)
318 if (clock * testp < vcomin)
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;
327 tmpdelta = clock - computed;
328 if (tmpdelta < delta) {
348 mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
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;
356 pixpllcm = pixpllc->m - 1;
357 pixpllcn = pixpllc->n - 1;
358 pixpllcp = pixpllc->p - 1;
359 pixpllcs = pixpllc->s;
361 xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
362 xpixpllcn = pixpllcn;
363 xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
365 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
367 for (i = 0; i <= 32 && pll_locked == false; i++) {
369 WREG8(MGAREG_CRTC_INDEX, 0x1e);
370 tmp = RREG8(MGAREG_CRTC_DATA);
372 WREG8(MGAREG_CRTC_DATA, tmp+1);
375 /* set pixclkdis to 1 */
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);
381 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
382 tmp = RREG8(DAC_DATA);
383 tmp |= MGA1064_REMHEADCTL_CLKDIS;
384 WREG8(DAC_DATA, tmp);
386 /* select PLL Set C */
387 tmp = RREG8(MGAREG_MEM_MISC_READ);
389 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
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);
399 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
400 tmp = RREG8(DAC_DATA);
402 WREG8(DAC_DATA, tmp);
406 /* program pixel pll register */
407 WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
408 WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
409 WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
414 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
415 tmp = RREG8(DAC_DATA);
417 WREG_DAC(MGA1064_VREF_CTL, tmp);
421 /* select the pixel pll */
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);
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);
434 /* reset dotclock rate bit */
435 WREG8(MGAREG_SEQ_INDEX, 1);
436 tmp = RREG8(MGAREG_SEQ_DATA);
438 WREG8(MGAREG_SEQ_DATA, tmp);
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);
445 vcount = RREG8(MGAREG_VCOUNT);
447 for (j = 0; j < 30 && pll_locked == false; j++) {
448 tmpcount = RREG8(MGAREG_VCOUNT);
449 if (tmpcount < vcount)
451 if ((tmpcount - vcount) > 2)
458 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
459 tmp = RREG8(DAC_DATA);
460 tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
461 WREG_DAC(MGA1064_REMHEADCTL, tmp);
464 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
465 .compute = mgag200_pixpll_compute_g200wb,
466 .update = mgag200_pixpll_update_g200wb,
473 static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
474 struct mgag200_pll_values *pixpllc)
476 static const unsigned int vcomax = 550000;
477 static const unsigned int vcomin = 150000;
478 static const unsigned int pllreffreq = 50000;
480 unsigned int delta, tmpdelta;
481 unsigned int testp, testm, testn;
482 unsigned int p, m, n, s;
483 unsigned int computed;
488 for (testp = 16; testp > 0; testp--) {
489 if (clock * testp > vcomax)
491 if (clock * testp < vcomin)
494 for (testn = 1; testn < 257; testn++) {
495 for (testm = 1; testm < 17; testm++) {
496 computed = (pllreffreq * testn) /
498 if (computed > clock)
499 tmpdelta = computed - clock;
501 tmpdelta = clock - computed;
502 if (tmpdelta < delta) {
521 mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
523 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
524 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
525 struct mga_device *mdev = pixpll->mdev;
527 pixpllcm = pixpllc->m - 1;
528 pixpllcn = pixpllc->n - 1;
529 pixpllcp = pixpllc->p - 1;
530 pixpllcs = pixpllc->s;
532 xpixpllcm = pixpllcm;
533 xpixpllcn = pixpllcn;
534 xpixpllcp = (pixpllcs << 3) | pixpllcp;
536 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
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);
543 tmp = RREG8(MGAREG_MEM_MISC_READ);
545 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
547 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
548 tmp = RREG8(DAC_DATA);
549 WREG8(DAC_DATA, tmp & ~0x40);
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);
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);
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);
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);
575 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
576 tmp = RREG8(DAC_DATA);
577 WREG8(DAC_DATA, tmp | 0x40);
579 tmp = RREG8(MGAREG_MEM_MISC_READ);
581 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
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);
589 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
590 .compute = mgag200_pixpll_compute_g200ev,
591 .update = mgag200_pixpll_update_g200ev,
598 static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
599 struct mgag200_pll_values *pixpllc)
601 static const unsigned int vcomax = 800000;
602 static const unsigned int vcomin = 400000;
603 static const unsigned int pllreffreq = 33333;
605 unsigned int delta, tmpdelta;
606 unsigned int testp, testm, testn;
607 unsigned int p, m, n, s;
608 unsigned int computed;
613 for (testp = 16; testp > 0; testp >>= 1) {
614 if (clock * testp > vcomax)
616 if (clock * testp < vcomin)
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;
625 tmpdelta = clock - computed;
626 if (tmpdelta < delta) {
645 mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
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;
653 pixpllcm = pixpllc->m - 1;
654 pixpllcn = pixpllc->n - 1;
655 pixpllcp = pixpllc->p - 1;
656 pixpllcs = pixpllc->s;
658 xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
659 xpixpllcn = pixpllcn;
660 xpixpllcp = (pixpllcs << 3) | pixpllcp;
662 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
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);
670 tmp = RREG8(MGAREG_MEM_MISC_READ);
672 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
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);
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);
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);
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);
699 vcount = RREG8(MGAREG_VCOUNT);
701 for (j = 0; j < 30 && pll_locked == false; j++) {
702 tmpcount = RREG8(MGAREG_VCOUNT);
703 if (tmpcount < vcount)
705 if ((tmpcount - vcount) > 2)
713 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
714 .compute = mgag200_pixpll_compute_g200eh,
715 .update = mgag200_pixpll_update_g200eh,
722 static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
723 struct mgag200_pll_values *pixpllc)
725 static const unsigned int vcomax = 3000000;
726 static const unsigned int vcomin = 1500000;
727 static const unsigned int pllreffreq = 25000;
729 unsigned int delta, tmpdelta;
730 unsigned int testp, testm, testn;
731 unsigned int p, m, n, s;
732 unsigned int computed;
738 for (testm = 150; testm >= 6; testm--) {
739 if (clock * testm > vcomax)
741 if (clock * testm < vcomin)
743 for (testn = 120; testn >= 60; testn--) {
744 computed = (pllreffreq * testn) / testm;
745 if (computed > clock)
746 tmpdelta = computed - clock;
748 tmpdelta = clock - computed;
749 if (tmpdelta < delta) {
770 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
771 .compute = mgag200_pixpll_compute_g200eh3,
772 .update = mgag200_pixpll_update_g200eh, // same as G200EH
779 static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
780 struct mgag200_pll_values *pixpllc)
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 };
787 unsigned int delta, tmpdelta;
788 int testr, testn, testm, testo;
789 unsigned int p, m, n, s;
790 unsigned int computed, vco;
795 for (testr = 0; testr < 4; testr++) {
798 for (testn = 5; testn < 129; testn++) {
801 for (testm = 3; testm >= 0; testm--) {
804 for (testo = 5; testo < 33; testo++) {
805 vco = pllreffreq * (testn + 1) /
811 computed = vco / (m_div_val[testm] * (testo + 1));
812 if (computed > clock)
813 tmpdelta = computed - clock;
815 tmpdelta = clock - computed;
816 if (tmpdelta < delta) {
818 m = (testm | (testo << 3)) + 1;
837 mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
839 unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
840 u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
841 struct mga_device *mdev = pixpll->mdev;
843 pixpllcm = pixpllc->m - 1;
844 pixpllcn = pixpllc->n - 1;
845 pixpllcp = pixpllc->p - 1;
846 pixpllcs = pixpllc->s;
848 xpixpllcm = pixpllcm;
849 xpixpllcn = pixpllcn;
850 xpixpllcp = (pixpllcs << 3) | pixpllcp;
852 WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
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);
859 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
860 tmp = RREG8(DAC_DATA);
861 tmp |= MGA1064_REMHEADCTL_CLKDIS;
862 WREG8(DAC_DATA, tmp);
864 tmp = RREG8(MGAREG_MEM_MISC_READ);
865 tmp |= (0x3<<2) | 0xc0;
866 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
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);
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);
883 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
884 .compute = mgag200_pixpll_compute_g200er,
885 .update = mgag200_pixpll_update_g200er,
892 static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
893 struct mgag200_pll_values *pixpllc)
895 static const unsigned int vcomax = 800000;
896 static const unsigned int vcomin = 400000;
897 static const unsigned int pllreffreq = 25000;
899 unsigned int delta, tmpdelta;
900 unsigned int testp, testm, testn, testp2;
901 unsigned int p, m, n, s;
902 unsigned int computed;
907 for (testp = 1; testp < 8; testp++) {
908 for (testp2 = 1; testp2 < 8; testp2++) {
911 if ((clock * testp * testp2) > vcomax)
913 if ((clock * testp * testp2) < vcomin)
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;
921 tmpdelta = clock - computed;
922 if (tmpdelta < delta) {
942 static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
943 .compute = mgag200_pixpll_compute_g200ew3,
944 .update = mgag200_pixpll_update_g200wb, // same as G200WB
951 int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
953 struct drm_device *dev = &mdev->base;
957 switch (mdev->type) {
960 pixpll->funcs = &mgag200_pixpll_funcs_g200;
964 if (mdev->model.g200se.unique_rev_id >= 0x04)
965 pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
967 pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
970 pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
973 pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
976 pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
979 pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
982 pixpll->funcs = &mgag200_pixpll_funcs_g200er;
985 pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
988 drm_err(dev, "unknown device type %d\n", mdev->type);