diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-03-26 19:44:50 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-03-27 19:50:04 -0400 |
commit | b8cecdf5a8cb847b8234fa3f5b61e89aea53032f (patch) | |
tree | 23392113cad8923a3d238464c126ac6521a19a5c /drivers | |
parent | 7c23396b40ed1e1d4751b0cadb8d1c8183a4e020 (diff) |
drm/i915: introduce struct intel_crtc_config
Currently only containing the requested and the adjusted mode. And
only crtc callbacks are converted somewhat to it, encoders will be
done on a as-needed basis (simply too much churn in one patch
otherwise).
Future patches will add tons more useful stuff to this struct,
starting with the very simple.
v2: Store the pipe_config in the intel_crtc, so that the ->mode-set,
->enable and also ->disable have easy access to it.
v3: Store the pipe config in the right crtc ...
v4: Rebased.
v5: Fixup an OOPS when trying to kfree an ERR_PTR.
v6: Used drm_moode_copy and some other small cleanups as suggested
by Ville Syrjälä.
v7: drm_mode_copy preserves the mode id of the destination, so no need
to clear it again (Ville).
v8: Break a long line spotted by Paulo.
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 82 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 7 |
3 files changed, 57 insertions, 36 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f69538508d8c..2962a9ab44d5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -284,6 +284,8 @@ struct drm_i915_error_state { | |||
284 | struct intel_display_error_state *display; | 284 | struct intel_display_error_state *display; |
285 | }; | 285 | }; |
286 | 286 | ||
287 | struct intel_crtc_config; | ||
288 | |||
287 | struct drm_i915_display_funcs { | 289 | struct drm_i915_display_funcs { |
288 | bool (*fbc_enabled)(struct drm_device *dev); | 290 | bool (*fbc_enabled)(struct drm_device *dev); |
289 | void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval); | 291 | void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval); |
@@ -297,8 +299,6 @@ struct drm_i915_display_funcs { | |||
297 | struct drm_display_mode *mode); | 299 | struct drm_display_mode *mode); |
298 | void (*modeset_global_resources)(struct drm_device *dev); | 300 | void (*modeset_global_resources)(struct drm_device *dev); |
299 | int (*crtc_mode_set)(struct drm_crtc *crtc, | 301 | int (*crtc_mode_set)(struct drm_crtc *crtc, |
300 | struct drm_display_mode *mode, | ||
301 | struct drm_display_mode *adjusted_mode, | ||
302 | int x, int y, | 302 | int x, int y, |
303 | struct drm_framebuffer *old_fb); | 303 | struct drm_framebuffer *old_fb); |
304 | void (*crtc_enable)(struct drm_crtc *crtc); | 304 | void (*crtc_enable)(struct drm_crtc *crtc); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2db50e234c2c..e22be581ed9b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3971,15 +3971,16 @@ bool intel_connector_get_hw_state(struct intel_connector *connector) | |||
3971 | return encoder->get_hw_state(encoder, &pipe); | 3971 | return encoder->get_hw_state(encoder, &pipe); |
3972 | } | 3972 | } |
3973 | 3973 | ||
3974 | static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, | 3974 | static bool intel_crtc_compute_config(struct drm_crtc *crtc, |
3975 | const struct drm_display_mode *mode, | 3975 | struct intel_crtc_config *pipe_config) |
3976 | struct drm_display_mode *adjusted_mode) | ||
3977 | { | 3976 | { |
3978 | struct drm_device *dev = crtc->dev; | 3977 | struct drm_device *dev = crtc->dev; |
3978 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; | ||
3979 | 3979 | ||
3980 | if (HAS_PCH_SPLIT(dev)) { | 3980 | if (HAS_PCH_SPLIT(dev)) { |
3981 | /* FDI link clock is fixed at 2.7G */ | 3981 | /* FDI link clock is fixed at 2.7G */ |
3982 | if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4) | 3982 | if (pipe_config->requested_mode.clock * 3 |
3983 | > IRONLAKE_FDI_FREQ * 4) | ||
3983 | return false; | 3984 | return false; |
3984 | } | 3985 | } |
3985 | 3986 | ||
@@ -4665,14 +4666,15 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc, | |||
4665 | } | 4666 | } |
4666 | 4667 | ||
4667 | static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | 4668 | static int i9xx_crtc_mode_set(struct drm_crtc *crtc, |
4668 | struct drm_display_mode *mode, | ||
4669 | struct drm_display_mode *adjusted_mode, | ||
4670 | int x, int y, | 4669 | int x, int y, |
4671 | struct drm_framebuffer *fb) | 4670 | struct drm_framebuffer *fb) |
4672 | { | 4671 | { |
4673 | struct drm_device *dev = crtc->dev; | 4672 | struct drm_device *dev = crtc->dev; |
4674 | struct drm_i915_private *dev_priv = dev->dev_private; | 4673 | struct drm_i915_private *dev_priv = dev->dev_private; |
4675 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4674 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4675 | struct drm_display_mode *adjusted_mode = | ||
4676 | &intel_crtc->config.adjusted_mode; | ||
4677 | struct drm_display_mode *mode = &intel_crtc->config.requested_mode; | ||
4676 | int pipe = intel_crtc->pipe; | 4678 | int pipe = intel_crtc->pipe; |
4677 | int plane = intel_crtc->plane; | 4679 | int plane = intel_crtc->plane; |
4678 | int refclk, num_connectors = 0; | 4680 | int refclk, num_connectors = 0; |
@@ -5637,14 +5639,15 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, | |||
5637 | } | 5639 | } |
5638 | 5640 | ||
5639 | static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | 5641 | static int ironlake_crtc_mode_set(struct drm_crtc *crtc, |
5640 | struct drm_display_mode *mode, | ||
5641 | struct drm_display_mode *adjusted_mode, | ||
5642 | int x, int y, | 5642 | int x, int y, |
5643 | struct drm_framebuffer *fb) | 5643 | struct drm_framebuffer *fb) |
5644 | { | 5644 | { |
5645 | struct drm_device *dev = crtc->dev; | 5645 | struct drm_device *dev = crtc->dev; |
5646 | struct drm_i915_private *dev_priv = dev->dev_private; | 5646 | struct drm_i915_private *dev_priv = dev->dev_private; |
5647 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5647 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
5648 | struct drm_display_mode *adjusted_mode = | ||
5649 | &intel_crtc->config.adjusted_mode; | ||
5650 | struct drm_display_mode *mode = &intel_crtc->config.requested_mode; | ||
5648 | int pipe = intel_crtc->pipe; | 5651 | int pipe = intel_crtc->pipe; |
5649 | int plane = intel_crtc->plane; | 5652 | int plane = intel_crtc->plane; |
5650 | int num_connectors = 0; | 5653 | int num_connectors = 0; |
@@ -5803,14 +5806,15 @@ static void haswell_modeset_global_resources(struct drm_device *dev) | |||
5803 | } | 5806 | } |
5804 | 5807 | ||
5805 | static int haswell_crtc_mode_set(struct drm_crtc *crtc, | 5808 | static int haswell_crtc_mode_set(struct drm_crtc *crtc, |
5806 | struct drm_display_mode *mode, | ||
5807 | struct drm_display_mode *adjusted_mode, | ||
5808 | int x, int y, | 5809 | int x, int y, |
5809 | struct drm_framebuffer *fb) | 5810 | struct drm_framebuffer *fb) |
5810 | { | 5811 | { |
5811 | struct drm_device *dev = crtc->dev; | 5812 | struct drm_device *dev = crtc->dev; |
5812 | struct drm_i915_private *dev_priv = dev->dev_private; | 5813 | struct drm_i915_private *dev_priv = dev->dev_private; |
5813 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5814 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
5815 | struct drm_display_mode *adjusted_mode = | ||
5816 | &intel_crtc->config.adjusted_mode; | ||
5817 | struct drm_display_mode *mode = &intel_crtc->config.requested_mode; | ||
5814 | int pipe = intel_crtc->pipe; | 5818 | int pipe = intel_crtc->pipe; |
5815 | int plane = intel_crtc->plane; | 5819 | int plane = intel_crtc->plane; |
5816 | int num_connectors = 0; | 5820 | int num_connectors = 0; |
@@ -5887,8 +5891,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, | |||
5887 | } | 5891 | } |
5888 | 5892 | ||
5889 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 5893 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |
5890 | struct drm_display_mode *mode, | ||
5891 | struct drm_display_mode *adjusted_mode, | ||
5892 | int x, int y, | 5894 | int x, int y, |
5893 | struct drm_framebuffer *fb) | 5895 | struct drm_framebuffer *fb) |
5894 | { | 5896 | { |
@@ -5897,6 +5899,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
5897 | struct drm_encoder_helper_funcs *encoder_funcs; | 5899 | struct drm_encoder_helper_funcs *encoder_funcs; |
5898 | struct intel_encoder *encoder; | 5900 | struct intel_encoder *encoder; |
5899 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5901 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
5902 | struct drm_display_mode *adjusted_mode = | ||
5903 | &intel_crtc->config.adjusted_mode; | ||
5904 | struct drm_display_mode *mode = &intel_crtc->config.requested_mode; | ||
5900 | int pipe = intel_crtc->pipe; | 5905 | int pipe = intel_crtc->pipe; |
5901 | int ret; | 5906 | int ret; |
5902 | 5907 | ||
@@ -5907,8 +5912,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
5907 | 5912 | ||
5908 | drm_vblank_pre_modeset(dev, pipe); | 5913 | drm_vblank_pre_modeset(dev, pipe); |
5909 | 5914 | ||
5910 | ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, | 5915 | ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb); |
5911 | x, y, fb); | 5916 | |
5912 | drm_vblank_post_modeset(dev, pipe); | 5917 | drm_vblank_post_modeset(dev, pipe); |
5913 | 5918 | ||
5914 | if (ret != 0) | 5919 | if (ret != 0) |
@@ -7530,19 +7535,22 @@ static void intel_modeset_commit_output_state(struct drm_device *dev) | |||
7530 | } | 7535 | } |
7531 | } | 7536 | } |
7532 | 7537 | ||
7533 | static struct drm_display_mode * | 7538 | static struct intel_crtc_config * |
7534 | intel_modeset_adjusted_mode(struct drm_crtc *crtc, | 7539 | intel_modeset_pipe_config(struct drm_crtc *crtc, |
7535 | struct drm_display_mode *mode) | 7540 | struct drm_display_mode *mode) |
7536 | { | 7541 | { |
7537 | struct drm_device *dev = crtc->dev; | 7542 | struct drm_device *dev = crtc->dev; |
7538 | struct drm_display_mode *adjusted_mode; | ||
7539 | struct drm_encoder_helper_funcs *encoder_funcs; | 7543 | struct drm_encoder_helper_funcs *encoder_funcs; |
7540 | struct intel_encoder *encoder; | 7544 | struct intel_encoder *encoder; |
7545 | struct intel_crtc_config *pipe_config; | ||
7541 | 7546 | ||
7542 | adjusted_mode = drm_mode_duplicate(dev, mode); | 7547 | pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); |
7543 | if (!adjusted_mode) | 7548 | if (!pipe_config) |
7544 | return ERR_PTR(-ENOMEM); | 7549 | return ERR_PTR(-ENOMEM); |
7545 | 7550 | ||
7551 | drm_mode_copy(&pipe_config->adjusted_mode, mode); | ||
7552 | drm_mode_copy(&pipe_config->requested_mode, mode); | ||
7553 | |||
7546 | /* Pass our mode to the connectors and the CRTC to give them a chance to | 7554 | /* Pass our mode to the connectors and the CRTC to give them a chance to |
7547 | * adjust it according to limitations or connector properties, and also | 7555 | * adjust it according to limitations or connector properties, and also |
7548 | * a chance to reject the mode entirely. | 7556 | * a chance to reject the mode entirely. |
@@ -7553,22 +7561,23 @@ intel_modeset_adjusted_mode(struct drm_crtc *crtc, | |||
7553 | if (&encoder->new_crtc->base != crtc) | 7561 | if (&encoder->new_crtc->base != crtc) |
7554 | continue; | 7562 | continue; |
7555 | encoder_funcs = encoder->base.helper_private; | 7563 | encoder_funcs = encoder->base.helper_private; |
7556 | if (!(encoder_funcs->mode_fixup(&encoder->base, mode, | 7564 | if (!(encoder_funcs->mode_fixup(&encoder->base, |
7557 | adjusted_mode))) { | 7565 | &pipe_config->requested_mode, |
7566 | &pipe_config->adjusted_mode))) { | ||
7558 | DRM_DEBUG_KMS("Encoder fixup failed\n"); | 7567 | DRM_DEBUG_KMS("Encoder fixup failed\n"); |
7559 | goto fail; | 7568 | goto fail; |
7560 | } | 7569 | } |
7561 | } | 7570 | } |
7562 | 7571 | ||
7563 | if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) { | 7572 | if (!(intel_crtc_compute_config(crtc, pipe_config))) { |
7564 | DRM_DEBUG_KMS("CRTC fixup failed\n"); | 7573 | DRM_DEBUG_KMS("CRTC fixup failed\n"); |
7565 | goto fail; | 7574 | goto fail; |
7566 | } | 7575 | } |
7567 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); | 7576 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
7568 | 7577 | ||
7569 | return adjusted_mode; | 7578 | return pipe_config; |
7570 | fail: | 7579 | fail: |
7571 | drm_mode_destroy(dev, adjusted_mode); | 7580 | kfree(pipe_config); |
7572 | return ERR_PTR(-EINVAL); | 7581 | return ERR_PTR(-EINVAL); |
7573 | } | 7582 | } |
7574 | 7583 | ||
@@ -7834,7 +7843,8 @@ int intel_set_mode(struct drm_crtc *crtc, | |||
7834 | { | 7843 | { |
7835 | struct drm_device *dev = crtc->dev; | 7844 | struct drm_device *dev = crtc->dev; |
7836 | drm_i915_private_t *dev_priv = dev->dev_private; | 7845 | drm_i915_private_t *dev_priv = dev->dev_private; |
7837 | struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode; | 7846 | struct drm_display_mode *saved_mode, *saved_hwmode; |
7847 | struct intel_crtc_config *pipe_config = NULL; | ||
7838 | struct intel_crtc *intel_crtc; | 7848 | struct intel_crtc *intel_crtc; |
7839 | unsigned disable_pipes, prepare_pipes, modeset_pipes; | 7849 | unsigned disable_pipes, prepare_pipes, modeset_pipes; |
7840 | int ret = 0; | 7850 | int ret = 0; |
@@ -7861,11 +7871,12 @@ int intel_set_mode(struct drm_crtc *crtc, | |||
7861 | * Hence simply check whether any bit is set in modeset_pipes in all the | 7871 | * Hence simply check whether any bit is set in modeset_pipes in all the |
7862 | * pieces of code that are not yet converted to deal with mutliple crtcs | 7872 | * pieces of code that are not yet converted to deal with mutliple crtcs |
7863 | * changing their mode at the same time. */ | 7873 | * changing their mode at the same time. */ |
7864 | adjusted_mode = NULL; | ||
7865 | if (modeset_pipes) { | 7874 | if (modeset_pipes) { |
7866 | adjusted_mode = intel_modeset_adjusted_mode(crtc, mode); | 7875 | pipe_config = intel_modeset_pipe_config(crtc, mode); |
7867 | if (IS_ERR(adjusted_mode)) { | 7876 | if (IS_ERR(pipe_config)) { |
7868 | ret = PTR_ERR(adjusted_mode); | 7877 | ret = PTR_ERR(pipe_config); |
7878 | pipe_config = NULL; | ||
7879 | |||
7869 | goto out; | 7880 | goto out; |
7870 | } | 7881 | } |
7871 | } | 7882 | } |
@@ -7878,8 +7889,12 @@ int intel_set_mode(struct drm_crtc *crtc, | |||
7878 | /* crtc->mode is already used by the ->mode_set callbacks, hence we need | 7889 | /* crtc->mode is already used by the ->mode_set callbacks, hence we need |
7879 | * to set it here already despite that we pass it down the callchain. | 7890 | * to set it here already despite that we pass it down the callchain. |
7880 | */ | 7891 | */ |
7881 | if (modeset_pipes) | 7892 | if (modeset_pipes) { |
7882 | crtc->mode = *mode; | 7893 | crtc->mode = *mode; |
7894 | /* mode_set/enable/disable functions rely on a correct pipe | ||
7895 | * config. */ | ||
7896 | to_intel_crtc(crtc)->config = *pipe_config; | ||
7897 | } | ||
7883 | 7898 | ||
7884 | /* Only after disabling all output pipelines that will be changed can we | 7899 | /* Only after disabling all output pipelines that will be changed can we |
7885 | * update the the output configuration. */ | 7900 | * update the the output configuration. */ |
@@ -7893,7 +7908,6 @@ int intel_set_mode(struct drm_crtc *crtc, | |||
7893 | */ | 7908 | */ |
7894 | for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { | 7909 | for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { |
7895 | ret = intel_crtc_mode_set(&intel_crtc->base, | 7910 | ret = intel_crtc_mode_set(&intel_crtc->base, |
7896 | mode, adjusted_mode, | ||
7897 | x, y, fb); | 7911 | x, y, fb); |
7898 | if (ret) | 7912 | if (ret) |
7899 | goto done; | 7913 | goto done; |
@@ -7905,7 +7919,7 @@ int intel_set_mode(struct drm_crtc *crtc, | |||
7905 | 7919 | ||
7906 | if (modeset_pipes) { | 7920 | if (modeset_pipes) { |
7907 | /* Store real post-adjustment hardware mode. */ | 7921 | /* Store real post-adjustment hardware mode. */ |
7908 | crtc->hwmode = *adjusted_mode; | 7922 | crtc->hwmode = pipe_config->adjusted_mode; |
7909 | 7923 | ||
7910 | /* Calculate and store various constants which | 7924 | /* Calculate and store various constants which |
7911 | * are later needed by vblank and swap-completion | 7925 | * are later needed by vblank and swap-completion |
@@ -7916,7 +7930,6 @@ int intel_set_mode(struct drm_crtc *crtc, | |||
7916 | 7930 | ||
7917 | /* FIXME: add subpixel order */ | 7931 | /* FIXME: add subpixel order */ |
7918 | done: | 7932 | done: |
7919 | drm_mode_destroy(dev, adjusted_mode); | ||
7920 | if (ret && crtc->enabled) { | 7933 | if (ret && crtc->enabled) { |
7921 | crtc->hwmode = *saved_hwmode; | 7934 | crtc->hwmode = *saved_hwmode; |
7922 | crtc->mode = *saved_mode; | 7935 | crtc->mode = *saved_mode; |
@@ -7925,6 +7938,7 @@ done: | |||
7925 | } | 7938 | } |
7926 | 7939 | ||
7927 | out: | 7940 | out: |
7941 | kfree(pipe_config); | ||
7928 | kfree(saved_mode); | 7942 | kfree(saved_mode); |
7929 | return ret; | 7943 | return ret; |
7930 | } | 7944 | } |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 54bc2ea61fa9..4cc66251fd34 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -200,6 +200,11 @@ struct intel_connector { | |||
200 | struct edid *edid; | 200 | struct edid *edid; |
201 | }; | 201 | }; |
202 | 202 | ||
203 | struct intel_crtc_config { | ||
204 | struct drm_display_mode requested_mode; | ||
205 | struct drm_display_mode adjusted_mode; | ||
206 | }; | ||
207 | |||
203 | struct intel_crtc { | 208 | struct intel_crtc { |
204 | struct drm_crtc base; | 209 | struct drm_crtc base; |
205 | enum pipe pipe; | 210 | enum pipe pipe; |
@@ -233,6 +238,8 @@ struct intel_crtc { | |||
233 | bool cursor_visible; | 238 | bool cursor_visible; |
234 | unsigned int bpp; | 239 | unsigned int bpp; |
235 | 240 | ||
241 | struct intel_crtc_config config; | ||
242 | |||
236 | /* We can share PLLs across outputs if the timings match */ | 243 | /* We can share PLLs across outputs if the timings match */ |
237 | struct intel_pch_pll *pch_pll; | 244 | struct intel_pch_pll *pch_pll; |
238 | uint32_t ddi_pll_sel; | 245 | uint32_t ddi_pll_sel; |