mgag200_pll.c (23117B)
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <linux/delay.h> 4 5#include "mgag200_drv.h" 6 7/* 8 * G200 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 * G200SE 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 /* Permited delta is 0.5% as VESA Specification */ 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 * G200WB 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 /* 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); 380 381 WREG8(DAC_INDEX, MGA1064_REMHEADCTL); 382 tmp = RREG8(DAC_DATA); 383 tmp |= MGA1064_REMHEADCTL_CLKDIS; 384 WREG8(DAC_DATA, tmp); 385 386 /* select PLL Set C */ 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 /* reset the PLL */ 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 /* program pixel pll register */ 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 /* turn pll on */ 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 /* 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); 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 /* reset dotclock rate bit */ 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 * G200EV 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 * G200EH 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 * G200EH3 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, // same as G200EH 773}; 774 775/* 776 * G200ER 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 * G200EW3 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, // same as G200WB 945}; 946 947/* 948 * PLL initialization 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}