aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-12-09 17:44:25 -0500
committerDave Airlie <airlied@redhat.com>2009-12-10 00:09:05 -0500
commitb27b63750d912e80d61d2120c4a1664062d0f808 (patch)
treed419533d2b4c7fec1cf4ad89485da755347a33fb /drivers/gpu/drm
parent69b3b5e59bc763c30d0098ae4bbe1225c0e82a04 (diff)
drm/radeon/kms/avivo: add support for new pll selection algo
Supported on all AVIVO-based asics. Can be disabled via the new_pll module parameter: new_pll=0 - disable new_pll=1 - enable enabled by default [airlied: fixed to use do_div] Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c92
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h9
6 files changed, 120 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 6d82417fb903..260fcf59f00c 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -499,8 +499,18 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
499 else 499 else
500 pll = &rdev->clock.p2pll; 500 pll = &rdev->clock.p2pll;
501 501
502 radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, 502 if (ASIC_IS_AVIVO(rdev)) {
503 &ref_div, &post_div, pll_flags); 503 if (radeon_new_pll)
504 radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
505 &fb_div, &frac_fb_div,
506 &ref_div, &post_div, pll_flags);
507 else
508 radeon_compute_pll(pll, adjusted_clock, &pll_clock,
509 &fb_div, &frac_fb_div,
510 &ref_div, &post_div, pll_flags);
511 } else
512 radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
513 &ref_div, &post_div, pll_flags);
504 514
505 index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); 515 index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
506 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, 516 atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5941e7d2d7ff..c938bb54123c 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -88,6 +88,7 @@ extern int radeon_benchmarking;
88extern int radeon_testing; 88extern int radeon_testing;
89extern int radeon_connector_table; 89extern int radeon_connector_table;
90extern int radeon_tv; 90extern int radeon_tv;
91extern int radeon_new_pll;
91 92
92/* 93/*
93 * Copy from radeon_drv.h so we don't have to include both and have conflicting 94 * Copy from radeon_drv.h so we don't have to include both and have conflicting
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 8737adf6d386..12a0c760e7ff 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -871,7 +871,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
871 * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per 871 * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per
872 * family. 872 * family.
873 */ 873 */
874 p1pll->pll_out_min = 64800; 874 if (!radeon_new_pll)
875 p1pll->pll_out_min = 64800;
875 } 876 }
876 877
877 p1pll->pll_in_min = 878 p1pll->pll_in_min =
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index f099ce2d4cc3..a133b833e45d 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -560,6 +560,98 @@ void radeon_compute_pll(struct radeon_pll *pll,
560 *post_div_p = best_post_div; 560 *post_div_p = best_post_div;
561} 561}
562 562
563void radeon_compute_pll_avivo(struct radeon_pll *pll,
564 uint64_t freq,
565 uint32_t *dot_clock_p,
566 uint32_t *fb_div_p,
567 uint32_t *frac_fb_div_p,
568 uint32_t *ref_div_p,
569 uint32_t *post_div_p,
570 int flags)
571{
572 fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq;
573 fixed20_12 pll_out_max, pll_out_min;
574 fixed20_12 pll_in_max, pll_in_min;
575 fixed20_12 reference_freq;
576 fixed20_12 error, ffreq, a, b;
577
578 pll_out_max.full = rfixed_const(pll->pll_out_max);
579 pll_out_min.full = rfixed_const(pll->pll_out_min);
580 pll_in_max.full = rfixed_const(pll->pll_in_max);
581 pll_in_min.full = rfixed_const(pll->pll_in_min);
582 reference_freq.full = rfixed_const(pll->reference_freq);
583 do_div(freq, 10);
584 ffreq.full = rfixed_const(freq);
585 error.full = rfixed_const(100 * 100);
586
587 /* max p */
588 p.full = rfixed_div(pll_out_max, ffreq);
589 p.full = rfixed_floor(p);
590
591 /* min m */
592 m.full = rfixed_div(reference_freq, pll_in_max);
593 m.full = rfixed_ceil(m);
594
595 while (1) {
596 n.full = rfixed_div(ffreq, reference_freq);
597 n.full = rfixed_mul(n, m);
598 n.full = rfixed_mul(n, p);
599
600 f_vco.full = rfixed_div(n, m);
601 f_vco.full = rfixed_mul(f_vco, reference_freq);
602
603 f_pclk.full = rfixed_div(f_vco, p);
604
605 if (f_pclk.full > ffreq.full)
606 error.full = f_pclk.full - ffreq.full;
607 else
608 error.full = ffreq.full - f_pclk.full;
609 error.full = rfixed_div(error, f_pclk);
610 a.full = rfixed_const(100 * 100);
611 error.full = rfixed_mul(error, a);
612
613 a.full = rfixed_mul(m, p);
614 a.full = rfixed_div(n, a);
615 best_freq.full = rfixed_mul(reference_freq, a);
616
617 if (rfixed_trunc(error) < 25)
618 break;
619
620 a.full = rfixed_const(1);
621 m.full = m.full + a.full;
622 a.full = rfixed_div(reference_freq, m);
623 if (a.full >= pll_in_min.full)
624 continue;
625
626 m.full = rfixed_div(reference_freq, pll_in_max);
627 m.full = rfixed_ceil(m);
628 a.full= rfixed_const(1);
629 p.full = p.full - a.full;
630 a.full = rfixed_mul(p, ffreq);
631 if (a.full >= pll_out_min.full)
632 continue;
633 else {
634 DRM_ERROR("Unable to find pll dividers\n");
635 break;
636 }
637 }
638
639 a.full = rfixed_const(10);
640 b.full = rfixed_mul(n, a);
641
642 frac_n.full = rfixed_floor(n);
643 frac_n.full = rfixed_mul(frac_n, a);
644 frac_n.full = b.full - frac_n.full;
645
646 *dot_clock_p = rfixed_trunc(best_freq);
647 *fb_div_p = rfixed_trunc(n);
648 *frac_fb_div_p = rfixed_trunc(frac_n);
649 *ref_div_p = rfixed_trunc(m);
650 *post_div_p = rfixed_trunc(p);
651
652 DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
653}
654
563static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) 655static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
564{ 656{
565 struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); 657 struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 7f50fb864af8..28077247f4f3 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -86,6 +86,7 @@ int radeon_benchmarking = 0;
86int radeon_testing = 0; 86int radeon_testing = 0;
87int radeon_connector_table = 0; 87int radeon_connector_table = 0;
88int radeon_tv = 1; 88int radeon_tv = 1;
89int radeon_new_pll = 1;
89 90
90MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); 91MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
91module_param_named(no_wb, radeon_no_wb, int, 0444); 92module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -120,6 +121,9 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);
120MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); 121MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
121module_param_named(tv, radeon_tv, int, 0444); 122module_param_named(tv, radeon_tv, int, 0444);
122 123
124MODULE_PARM_DESC(r4xx_atom, "Select new PLL code for AVIVO chips");
125module_param_named(new_pll, radeon_new_pll, int, 0444);
126
123static int radeon_suspend(struct drm_device *dev, pm_message_t state) 127static int radeon_suspend(struct drm_device *dev, pm_message_t state)
124{ 128{
125 drm_radeon_private_t *dev_priv = dev->dev_private; 129 drm_radeon_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 15ec7ca18a95..44d4b652ea12 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -437,6 +437,15 @@ extern void radeon_compute_pll(struct radeon_pll *pll,
437 uint32_t *post_div_p, 437 uint32_t *post_div_p,
438 int flags); 438 int flags);
439 439
440extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
441 uint64_t freq,
442 uint32_t *dot_clock_p,
443 uint32_t *fb_div_p,
444 uint32_t *frac_fb_div_p,
445 uint32_t *ref_div_p,
446 uint32_t *post_div_p,
447 int flags);
448
440extern void radeon_setup_encoder_clones(struct drm_device *dev); 449extern void radeon_setup_encoder_clones(struct drm_device *dev);
441 450
442struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); 451struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);