aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_display.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-01 00:41:26 -0500
committerDave Airlie <airlied@redhat.com>2010-03-01 00:41:26 -0500
commitcf7934a2a0ec55759fcf6861a868baadfd522300 (patch)
tree97fb4aac01d1b4e112126b2bd3852e3646d4b408 /drivers/gpu/drm/radeon/radeon_display.c
parentaa71fa3cd5b7b4f669cd74c5a16de57d2938cd85 (diff)
parent6070a4a928f8c92b9fae7d6717ebbb05f425d6b2 (diff)
Merge remote branch 'anholt/drm-intel-next' into drm-next-stage
* anholt/drm-intel-next: (103 commits) drm/i915: Use a dmi quirk to skip a broken SDVO TV output. drm/i915: enable/disable LVDS port at DPMS time drm/i915: check for multiple write domains in pin_and_relocate drm/i915: clean-up i915_gem_flush_gpu_write_domain drm/i915: reuse i915_gpu_idle helper drm/i915: ensure lru ordering of fence_list drm/i915: extract fence stealing code drm/i915: fixup active list locking in object_unbind drm/i915: reuse i915_gem_object_put_fence_reg for fence stealing code drm/i915: Add dependency on the intel agp module drm/i915: More s/IS_IRONLAKE/HAS_PCH_SPLIT for Sandybridge. drm/i915: Correct the Sandybridge chipset info structs. drm/i915: Disable the hangcheck reset on Sandybridge until we add support. drm/i915: Add a new mobile Sandybridge PCI ID. agp/intel: Add a new Sandybridge HB/IG PCI ID combo. drm/i915, agp/intel: Fix stolen memory size on Sandybridge drm/i915: Correct locking in the modesetting failure path, fixing a BUG_ON. drm/i915: Disable the surface tile swizzling on Sandybridge. agp/intel: Use a non-reserved value for the cache field of the PTEs. drm/i915: Fix sandybridge status page setup. ...
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c325
1 files changed, 235 insertions, 90 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 3db825505626..ba8d806dcf39 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -68,6 +68,36 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc)
68 WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id); 68 WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
69} 69}
70 70
71static void evergreen_crtc_load_lut(struct drm_crtc *crtc)
72{
73 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
74 struct drm_device *dev = crtc->dev;
75 struct radeon_device *rdev = dev->dev_private;
76 int i;
77
78 DRM_DEBUG("%d\n", radeon_crtc->crtc_id);
79 WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0);
80
81 WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
82 WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
83 WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
84
85 WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
86 WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
87 WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
88
89 WREG32(EVERGREEN_DC_LUT_RW_MODE, radeon_crtc->crtc_id);
90 WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK, 0x00000007);
91
92 WREG32(EVERGREEN_DC_LUT_RW_INDEX, 0);
93 for (i = 0; i < 256; i++) {
94 WREG32(EVERGREEN_DC_LUT_30_COLOR,
95 (radeon_crtc->lut_r[i] << 20) |
96 (radeon_crtc->lut_g[i] << 10) |
97 (radeon_crtc->lut_b[i] << 0));
98 }
99}
100
71static void legacy_crtc_load_lut(struct drm_crtc *crtc) 101static void legacy_crtc_load_lut(struct drm_crtc *crtc)
72{ 102{
73 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 103 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -100,7 +130,9 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc)
100 if (!crtc->enabled) 130 if (!crtc->enabled)
101 return; 131 return;
102 132
103 if (ASIC_IS_AVIVO(rdev)) 133 if (ASIC_IS_DCE4(rdev))
134 evergreen_crtc_load_lut(crtc);
135 else if (ASIC_IS_AVIVO(rdev))
104 avivo_crtc_load_lut(crtc); 136 avivo_crtc_load_lut(crtc);
105 else 137 else
106 legacy_crtc_load_lut(crtc); 138 legacy_crtc_load_lut(crtc);
@@ -361,6 +393,8 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
361 393
362int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) 394int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
363{ 395{
396 struct drm_device *dev = radeon_connector->base.dev;
397 struct radeon_device *rdev = dev->dev_private;
364 int ret = 0; 398 int ret = 0;
365 399
366 if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || 400 if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
@@ -373,11 +407,11 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
373 if (!radeon_connector->ddc_bus) 407 if (!radeon_connector->ddc_bus)
374 return -1; 408 return -1;
375 if (!radeon_connector->edid) { 409 if (!radeon_connector->edid) {
376 radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
377 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); 410 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
378 radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
379 } 411 }
380 412 /* some servers provide a hardcoded edid in rom for KVMs */
413 if (!radeon_connector->edid)
414 radeon_connector->edid = radeon_combios_get_hardcoded_edid(rdev);
381 if (radeon_connector->edid) { 415 if (radeon_connector->edid) {
382 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); 416 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
383 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); 417 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
@@ -395,9 +429,7 @@ static int radeon_ddc_dump(struct drm_connector *connector)
395 429
396 if (!radeon_connector->ddc_bus) 430 if (!radeon_connector->ddc_bus)
397 return -1; 431 return -1;
398 radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
399 edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); 432 edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
400 radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
401 if (edid) { 433 if (edid) {
402 kfree(edid); 434 kfree(edid);
403 } 435 }
@@ -414,13 +446,13 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d)
414 return n; 446 return n;
415} 447}
416 448
417void radeon_compute_pll(struct radeon_pll *pll, 449static void radeon_compute_pll_legacy(struct radeon_pll *pll,
418 uint64_t freq, 450 uint64_t freq,
419 uint32_t *dot_clock_p, 451 uint32_t *dot_clock_p,
420 uint32_t *fb_div_p, 452 uint32_t *fb_div_p,
421 uint32_t *frac_fb_div_p, 453 uint32_t *frac_fb_div_p,
422 uint32_t *ref_div_p, 454 uint32_t *ref_div_p,
423 uint32_t *post_div_p) 455 uint32_t *post_div_p)
424{ 456{
425 uint32_t min_ref_div = pll->min_ref_div; 457 uint32_t min_ref_div = pll->min_ref_div;
426 uint32_t max_ref_div = pll->max_ref_div; 458 uint32_t max_ref_div = pll->max_ref_div;
@@ -580,95 +612,194 @@ void radeon_compute_pll(struct radeon_pll *pll,
580 *post_div_p = best_post_div; 612 *post_div_p = best_post_div;
581} 613}
582 614
583void radeon_compute_pll_avivo(struct radeon_pll *pll, 615static bool
584 uint64_t freq, 616calc_fb_div(struct radeon_pll *pll,
585 uint32_t *dot_clock_p, 617 uint32_t freq,
586 uint32_t *fb_div_p, 618 uint32_t post_div,
587 uint32_t *frac_fb_div_p, 619 uint32_t ref_div,
588 uint32_t *ref_div_p, 620 uint32_t *fb_div,
589 uint32_t *post_div_p) 621 uint32_t *fb_div_frac)
590{ 622{
591 fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; 623 fixed20_12 feedback_divider, a, b;
592 fixed20_12 pll_out_max, pll_out_min; 624 u32 vco_freq;
593 fixed20_12 pll_in_max, pll_in_min; 625
594 fixed20_12 reference_freq; 626 vco_freq = freq * post_div;
595 fixed20_12 error, ffreq, a, b; 627 /* feedback_divider = vco_freq * ref_div / pll->reference_freq; */
596 628 a.full = rfixed_const(pll->reference_freq);
597 pll_out_max.full = rfixed_const(pll->pll_out_max); 629 feedback_divider.full = rfixed_const(vco_freq);
598 pll_out_min.full = rfixed_const(pll->pll_out_min); 630 feedback_divider.full = rfixed_div(feedback_divider, a);
599 pll_in_max.full = rfixed_const(pll->pll_in_max); 631 a.full = rfixed_const(ref_div);
600 pll_in_min.full = rfixed_const(pll->pll_in_min); 632 feedback_divider.full = rfixed_mul(feedback_divider, a);
601 reference_freq.full = rfixed_const(pll->reference_freq); 633
602 do_div(freq, 10); 634 if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
635 /* feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1; */
636 a.full = rfixed_const(10);
637 feedback_divider.full = rfixed_mul(feedback_divider, a);
638 feedback_divider.full += rfixed_const_half(0);
639 feedback_divider.full = rfixed_floor(feedback_divider);
640 feedback_divider.full = rfixed_div(feedback_divider, a);
641
642 /* *fb_div = floor(feedback_divider); */
643 a.full = rfixed_floor(feedback_divider);
644 *fb_div = rfixed_trunc(a);
645 /* *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0; */
646 a.full = rfixed_const(10);
647 b.full = rfixed_mul(feedback_divider, a);
648
649 feedback_divider.full = rfixed_floor(feedback_divider);
650 feedback_divider.full = rfixed_mul(feedback_divider, a);
651 feedback_divider.full = b.full - feedback_divider.full;
652 *fb_div_frac = rfixed_trunc(feedback_divider);
653 } else {
654 /* *fb_div = floor(feedback_divider + 0.5); */
655 feedback_divider.full += rfixed_const_half(0);
656 feedback_divider.full = rfixed_floor(feedback_divider);
657
658 *fb_div = rfixed_trunc(feedback_divider);
659 *fb_div_frac = 0;
660 }
661
662 if (((*fb_div) < pll->min_feedback_div) || ((*fb_div) > pll->max_feedback_div))
663 return false;
664 else
665 return true;
666}
667
668static bool
669calc_fb_ref_div(struct radeon_pll *pll,
670 uint32_t freq,
671 uint32_t post_div,
672 uint32_t *fb_div,
673 uint32_t *fb_div_frac,
674 uint32_t *ref_div)
675{
676 fixed20_12 ffreq, max_error, error, pll_out, a;
677 u32 vco;
678
603 ffreq.full = rfixed_const(freq); 679 ffreq.full = rfixed_const(freq);
604 error.full = rfixed_const(100 * 100); 680 /* max_error = ffreq * 0.0025; */
681 a.full = rfixed_const(400);
682 max_error.full = rfixed_div(ffreq, a);
605 683
606 /* max p */ 684 for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
607 p.full = rfixed_div(pll_out_max, ffreq); 685 if (calc_fb_div(pll, freq, post_div, (*ref_div), fb_div, fb_div_frac)) {
608 p.full = rfixed_floor(p); 686 vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac));
687 vco = vco / ((*ref_div) * 10);
609 688
610 /* min m */ 689 if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
611 m.full = rfixed_div(reference_freq, pll_in_max); 690 continue;
612 m.full = rfixed_ceil(m);
613 691
614 while (1) { 692 /* pll_out = vco / post_div; */
615 n.full = rfixed_div(ffreq, reference_freq); 693 a.full = rfixed_const(post_div);
616 n.full = rfixed_mul(n, m); 694 pll_out.full = rfixed_const(vco);
617 n.full = rfixed_mul(n, p); 695 pll_out.full = rfixed_div(pll_out, a);
618 696
619 f_vco.full = rfixed_div(n, m); 697 if (pll_out.full >= ffreq.full) {
620 f_vco.full = rfixed_mul(f_vco, reference_freq); 698 error.full = pll_out.full - ffreq.full;
699 if (error.full <= max_error.full)
700 return true;
701 }
702 }
703 }
704 return false;
705}
621 706
622 f_pclk.full = rfixed_div(f_vco, p); 707static void radeon_compute_pll_new(struct radeon_pll *pll,
708 uint64_t freq,
709 uint32_t *dot_clock_p,
710 uint32_t *fb_div_p,
711 uint32_t *frac_fb_div_p,
712 uint32_t *ref_div_p,
713 uint32_t *post_div_p)
714{
715 u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
716 u32 best_freq = 0, vco_frequency;
623 717
624 if (f_pclk.full > ffreq.full) 718 /* freq = freq / 10; */
625 error.full = f_pclk.full - ffreq.full; 719 do_div(freq, 10);
626 else
627 error.full = ffreq.full - f_pclk.full;
628 error.full = rfixed_div(error, f_pclk);
629 a.full = rfixed_const(100 * 100);
630 error.full = rfixed_mul(error, a);
631
632 a.full = rfixed_mul(m, p);
633 a.full = rfixed_div(n, a);
634 best_freq.full = rfixed_mul(reference_freq, a);
635
636 if (rfixed_trunc(error) < 25)
637 break;
638
639 a.full = rfixed_const(1);
640 m.full = m.full + a.full;
641 a.full = rfixed_div(reference_freq, m);
642 if (a.full >= pll_in_min.full)
643 continue;
644 720
645 m.full = rfixed_div(reference_freq, pll_in_max); 721 if (pll->flags & RADEON_PLL_USE_POST_DIV) {
646 m.full = rfixed_ceil(m); 722 post_div = pll->post_div;
647 a.full= rfixed_const(1); 723 if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
648 p.full = p.full - a.full; 724 goto done;
649 a.full = rfixed_mul(p, ffreq); 725
650 if (a.full >= pll_out_min.full) 726 vco_frequency = freq * post_div;
651 continue; 727 if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
652 else { 728 goto done;
653 DRM_ERROR("Unable to find pll dividers\n"); 729
654 break; 730 if (pll->flags & RADEON_PLL_USE_REF_DIV) {
731 ref_div = pll->reference_div;
732 if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
733 goto done;
734 if (!calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
735 goto done;
736 }
737 } else {
738 for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
739 if (pll->flags & RADEON_PLL_LEGACY) {
740 if ((post_div == 5) ||
741 (post_div == 7) ||
742 (post_div == 9) ||
743 (post_div == 10) ||
744 (post_div == 11))
745 continue;
746 }
747
748 if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
749 continue;
750
751 vco_frequency = freq * post_div;
752 if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
753 continue;
754 if (pll->flags & RADEON_PLL_USE_REF_DIV) {
755 ref_div = pll->reference_div;
756 if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
757 goto done;
758 if (calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
759 break;
760 } else {
761 if (calc_fb_ref_div(pll, freq, post_div, &fb_div, &fb_div_frac, &ref_div))
762 break;
763 }
655 } 764 }
656 } 765 }
657 766
658 a.full = rfixed_const(10); 767 best_freq = pll->reference_freq * 10 * fb_div;
659 b.full = rfixed_mul(n, a); 768 best_freq += pll->reference_freq * fb_div_frac;
769 best_freq = best_freq / (ref_div * post_div);
660 770
661 frac_n.full = rfixed_floor(n); 771done:
662 frac_n.full = rfixed_mul(frac_n, a); 772 if (best_freq == 0)
663 frac_n.full = b.full - frac_n.full; 773 DRM_ERROR("Couldn't find valid PLL dividers\n");
664 774
665 *dot_clock_p = rfixed_trunc(best_freq); 775 *dot_clock_p = best_freq / 10;
666 *fb_div_p = rfixed_trunc(n); 776 *fb_div_p = fb_div;
667 *frac_fb_div_p = rfixed_trunc(frac_n); 777 *frac_fb_div_p = fb_div_frac;
668 *ref_div_p = rfixed_trunc(m); 778 *ref_div_p = ref_div;
669 *post_div_p = rfixed_trunc(p); 779 *post_div_p = post_div;
670 780
671 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); 781 DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
782}
783
784void radeon_compute_pll(struct radeon_pll *pll,
785 uint64_t freq,
786 uint32_t *dot_clock_p,
787 uint32_t *fb_div_p,
788 uint32_t *frac_fb_div_p,
789 uint32_t *ref_div_p,
790 uint32_t *post_div_p)
791{
792 switch (pll->algo) {
793 case PLL_ALGO_NEW:
794 radeon_compute_pll_new(pll, freq, dot_clock_p, fb_div_p,
795 frac_fb_div_p, ref_div_p, post_div_p);
796 break;
797 case PLL_ALGO_LEGACY:
798 default:
799 radeon_compute_pll_legacy(pll, freq, dot_clock_p, fb_div_p,
800 frac_fb_div_p, ref_div_p, post_div_p);
801 break;
802 }
672} 803}
673 804
674static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) 805static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -816,7 +947,7 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
816 947
817int radeon_modeset_init(struct radeon_device *rdev) 948int radeon_modeset_init(struct radeon_device *rdev)
818{ 949{
819 int num_crtc = 2, i; 950 int i;
820 int ret; 951 int ret;
821 952
822 drm_mode_config_init(rdev->ddev); 953 drm_mode_config_init(rdev->ddev);
@@ -839,11 +970,23 @@ int radeon_modeset_init(struct radeon_device *rdev)
839 return ret; 970 return ret;
840 } 971 }
841 972
973 /* check combios for a valid hardcoded EDID - Sun servers */
974 if (!rdev->is_atom_bios) {
975 /* check for hardcoded EDID in BIOS */
976 radeon_combios_check_hardcoded_edid(rdev);
977 }
978
842 if (rdev->flags & RADEON_SINGLE_CRTC) 979 if (rdev->flags & RADEON_SINGLE_CRTC)
843 num_crtc = 1; 980 rdev->num_crtc = 1;
981 else {
982 if (ASIC_IS_DCE4(rdev))
983 rdev->num_crtc = 6;
984 else
985 rdev->num_crtc = 2;
986 }
844 987
845 /* allocate crtcs */ 988 /* allocate crtcs */
846 for (i = 0; i < num_crtc; i++) { 989 for (i = 0; i < rdev->num_crtc; i++) {
847 radeon_crtc_init(rdev->ddev, i); 990 radeon_crtc_init(rdev->ddev, i);
848 } 991 }
849 992
@@ -860,6 +1003,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
860 1003
861void radeon_modeset_fini(struct radeon_device *rdev) 1004void radeon_modeset_fini(struct radeon_device *rdev)
862{ 1005{
1006 kfree(rdev->mode_info.bios_hardcoded_edid);
1007
863 if (rdev->mode_info.mode_config_initialized) { 1008 if (rdev->mode_info.mode_config_initialized) {
864 radeon_hpd_fini(rdev); 1009 radeon_hpd_fini(rdev);
865 drm_mode_config_cleanup(rdev->ddev); 1010 drm_mode_config_cleanup(rdev->ddev);