diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-01 00:41:26 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-01 00:41:26 -0500 |
commit | cf7934a2a0ec55759fcf6861a868baadfd522300 (patch) | |
tree | 97fb4aac01d1b4e112126b2bd3852e3646d4b408 /drivers/gpu/drm/radeon/radeon_display.c | |
parent | aa71fa3cd5b7b4f669cd74c5a16de57d2938cd85 (diff) | |
parent | 6070a4a928f8c92b9fae7d6717ebbb05f425d6b2 (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.c | 325 |
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 | ||
71 | static 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 | |||
71 | static void legacy_crtc_load_lut(struct drm_crtc *crtc) | 101 | static 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 | ||
362 | int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | 394 | int 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 | ||
417 | void radeon_compute_pll(struct radeon_pll *pll, | 449 | static 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 | ||
583 | void radeon_compute_pll_avivo(struct radeon_pll *pll, | 615 | static bool |
584 | uint64_t freq, | 616 | calc_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 | |||
668 | static bool | ||
669 | calc_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); | 707 | static 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); | 771 | done: |
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 | |||
784 | void 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 | ||
674 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | 805 | static 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 | ||
817 | int radeon_modeset_init(struct radeon_device *rdev) | 948 | int 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 | ||
861 | void radeon_modeset_fini(struct radeon_device *rdev) | 1004 | void 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); |