diff options
author | Paulo Zanoni <paulo.r.zanoni@intel.com> | 2012-09-20 17:36:04 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-09-25 04:37:34 -0400 |
commit | f48d8f235a9e3d2331b25743807340fc65b86587 (patch) | |
tree | 28f8773b581511c8944cb0c12ae186c370f9ff4b /drivers/gpu/drm/i915/intel_display.c | |
parent | cc769b6257884e26476e1643d7203b4e875b2387 (diff) |
drm/i915: extract set_m_n from ironlake_crtc_mode_set
The set_m_n code was spread all over the mode_set function.
Version 2:
Don't set the DP M/N registers on ironlake_set_m_n. Daniel Vetter has
plans to add some encoder-specific callbacks. Also, on this version we
don't change the order we're writing the registers, making the code
change safer.
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 131 |
1 files changed, 79 insertions, 52 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1458563913f3..e92c6d329137 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4707,6 +4707,82 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, | |||
4707 | return true; | 4707 | return true; |
4708 | } | 4708 | } |
4709 | 4709 | ||
4710 | static void ironlake_set_m_n(struct drm_crtc *crtc, | ||
4711 | struct drm_display_mode *mode, | ||
4712 | struct drm_display_mode *adjusted_mode) | ||
4713 | { | ||
4714 | struct drm_device *dev = crtc->dev; | ||
4715 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4716 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
4717 | enum pipe pipe = intel_crtc->pipe; | ||
4718 | struct intel_encoder *intel_encoder, *edp_encoder = NULL; | ||
4719 | struct fdi_m_n m_n = {0}; | ||
4720 | int target_clock, pixel_multiplier, lane, link_bw; | ||
4721 | bool is_dp = false, is_cpu_edp = false; | ||
4722 | |||
4723 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { | ||
4724 | switch (intel_encoder->type) { | ||
4725 | case INTEL_OUTPUT_DISPLAYPORT: | ||
4726 | is_dp = true; | ||
4727 | break; | ||
4728 | case INTEL_OUTPUT_EDP: | ||
4729 | is_dp = true; | ||
4730 | if (!intel_encoder_is_pch_edp(&intel_encoder->base)) | ||
4731 | is_cpu_edp = true; | ||
4732 | edp_encoder = intel_encoder; | ||
4733 | break; | ||
4734 | } | ||
4735 | } | ||
4736 | |||
4737 | /* FDI link */ | ||
4738 | pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
4739 | lane = 0; | ||
4740 | /* CPU eDP doesn't require FDI link, so just set DP M/N | ||
4741 | according to current link config */ | ||
4742 | if (is_cpu_edp) { | ||
4743 | intel_edp_link_config(edp_encoder, &lane, &link_bw); | ||
4744 | } else { | ||
4745 | /* FDI is a binary signal running at ~2.7GHz, encoding | ||
4746 | * each output octet as 10 bits. The actual frequency | ||
4747 | * is stored as a divider into a 100MHz clock, and the | ||
4748 | * mode pixel clock is stored in units of 1KHz. | ||
4749 | * Hence the bw of each lane in terms of the mode signal | ||
4750 | * is: | ||
4751 | */ | ||
4752 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; | ||
4753 | } | ||
4754 | |||
4755 | /* [e]DP over FDI requires target mode clock instead of link clock. */ | ||
4756 | if (edp_encoder) | ||
4757 | target_clock = intel_edp_target_clock(edp_encoder, mode); | ||
4758 | else if (is_dp) | ||
4759 | target_clock = mode->clock; | ||
4760 | else | ||
4761 | target_clock = adjusted_mode->clock; | ||
4762 | |||
4763 | if (!lane) { | ||
4764 | /* | ||
4765 | * Account for spread spectrum to avoid | ||
4766 | * oversubscribing the link. Max center spread | ||
4767 | * is 2.5%; use 5% for safety's sake. | ||
4768 | */ | ||
4769 | u32 bps = target_clock * intel_crtc->bpp * 21 / 20; | ||
4770 | lane = bps / (link_bw * 8) + 1; | ||
4771 | } | ||
4772 | |||
4773 | intel_crtc->fdi_lanes = lane; | ||
4774 | |||
4775 | if (pixel_multiplier > 1) | ||
4776 | link_bw *= pixel_multiplier; | ||
4777 | ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, | ||
4778 | &m_n); | ||
4779 | |||
4780 | I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); | ||
4781 | I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); | ||
4782 | I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); | ||
4783 | I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); | ||
4784 | } | ||
4785 | |||
4710 | static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | 4786 | static int ironlake_crtc_mode_set(struct drm_crtc *crtc, |
4711 | struct drm_display_mode *mode, | 4787 | struct drm_display_mode *mode, |
4712 | struct drm_display_mode *adjusted_mode, | 4788 | struct drm_display_mode *adjusted_mode, |
@@ -4723,11 +4799,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
4723 | u32 dpll, fp = 0, fp2 = 0; | 4799 | u32 dpll, fp = 0, fp2 = 0; |
4724 | bool ok, has_reduced_clock = false, is_sdvo = false; | 4800 | bool ok, has_reduced_clock = false, is_sdvo = false; |
4725 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; | 4801 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
4726 | struct intel_encoder *encoder, *edp_encoder = NULL; | 4802 | struct intel_encoder *encoder; |
4727 | int ret; | ||
4728 | struct fdi_m_n m_n = {0}; | ||
4729 | u32 temp; | 4803 | u32 temp; |
4730 | int target_clock, pixel_multiplier, lane, link_bw, factor; | 4804 | int ret, factor; |
4731 | bool dither; | 4805 | bool dither; |
4732 | bool is_cpu_edp = false, is_pch_edp = false; | 4806 | bool is_cpu_edp = false, is_pch_edp = false; |
4733 | 4807 | ||
@@ -4757,7 +4831,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
4757 | is_pch_edp = true; | 4831 | is_pch_edp = true; |
4758 | else | 4832 | else |
4759 | is_cpu_edp = true; | 4833 | is_cpu_edp = true; |
4760 | edp_encoder = encoder; | ||
4761 | break; | 4834 | break; |
4762 | } | 4835 | } |
4763 | 4836 | ||
@@ -4774,54 +4847,11 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
4774 | /* Ensure that the cursor is valid for the new mode before changing... */ | 4847 | /* Ensure that the cursor is valid for the new mode before changing... */ |
4775 | intel_crtc_update_cursor(crtc, true); | 4848 | intel_crtc_update_cursor(crtc, true); |
4776 | 4849 | ||
4777 | /* FDI link */ | ||
4778 | pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
4779 | lane = 0; | ||
4780 | /* CPU eDP doesn't require FDI link, so just set DP M/N | ||
4781 | according to current link config */ | ||
4782 | if (is_cpu_edp) { | ||
4783 | intel_edp_link_config(edp_encoder, &lane, &link_bw); | ||
4784 | } else { | ||
4785 | /* FDI is a binary signal running at ~2.7GHz, encoding | ||
4786 | * each output octet as 10 bits. The actual frequency | ||
4787 | * is stored as a divider into a 100MHz clock, and the | ||
4788 | * mode pixel clock is stored in units of 1KHz. | ||
4789 | * Hence the bw of each lane in terms of the mode signal | ||
4790 | * is: | ||
4791 | */ | ||
4792 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; | ||
4793 | } | ||
4794 | |||
4795 | /* [e]DP over FDI requires target mode clock instead of link clock. */ | ||
4796 | if (edp_encoder) | ||
4797 | target_clock = intel_edp_target_clock(edp_encoder, mode); | ||
4798 | else if (is_dp) | ||
4799 | target_clock = mode->clock; | ||
4800 | else | ||
4801 | target_clock = adjusted_mode->clock; | ||
4802 | |||
4803 | /* determine panel color depth */ | 4850 | /* determine panel color depth */ |
4804 | dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp, mode); | 4851 | dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp, mode); |
4805 | if (is_lvds && dev_priv->lvds_dither) | 4852 | if (is_lvds && dev_priv->lvds_dither) |
4806 | dither = true; | 4853 | dither = true; |
4807 | 4854 | ||
4808 | if (!lane) { | ||
4809 | /* | ||
4810 | * Account for spread spectrum to avoid | ||
4811 | * oversubscribing the link. Max center spread | ||
4812 | * is 2.5%; use 5% for safety's sake. | ||
4813 | */ | ||
4814 | u32 bps = target_clock * intel_crtc->bpp * 21 / 20; | ||
4815 | lane = bps / (link_bw * 8) + 1; | ||
4816 | } | ||
4817 | |||
4818 | intel_crtc->fdi_lanes = lane; | ||
4819 | |||
4820 | if (pixel_multiplier > 1) | ||
4821 | link_bw *= pixel_multiplier; | ||
4822 | ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, | ||
4823 | &m_n); | ||
4824 | |||
4825 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | 4855 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; |
4826 | if (has_reduced_clock) | 4856 | if (has_reduced_clock) |
4827 | fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | | 4857 | fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | |
@@ -5018,10 +5048,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
5018 | I915_WRITE(PIPESRC(pipe), | 5048 | I915_WRITE(PIPESRC(pipe), |
5019 | ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | 5049 | ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); |
5020 | 5050 | ||
5021 | I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); | 5051 | ironlake_set_m_n(crtc, mode, adjusted_mode); |
5022 | I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); | ||
5023 | I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); | ||
5024 | I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); | ||
5025 | 5052 | ||
5026 | if (is_cpu_edp) | 5053 | if (is_cpu_edp) |
5027 | ironlake_set_pll_edp(crtc, adjusted_mode->clock); | 5054 | ironlake_set_pll_edp(crtc, adjusted_mode->clock); |