drm/i915: introduce struct intel_crtc_config
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 26 Mar 2013 23:44:50 +0000 (00:44 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 27 Mar 2013 23:50:04 +0000 (00:50 +0100)
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>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h

index f695385..2962a9a 100644 (file)
@@ -284,6 +284,8 @@ struct drm_i915_error_state {
        struct intel_display_error_state *display;
 };
 
+struct intel_crtc_config;
+
 struct drm_i915_display_funcs {
        bool (*fbc_enabled)(struct drm_device *dev);
        void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
@@ -297,8 +299,6 @@ struct drm_i915_display_funcs {
                                 struct drm_display_mode *mode);
        void (*modeset_global_resources)(struct drm_device *dev);
        int (*crtc_mode_set)(struct drm_crtc *crtc,
-                            struct drm_display_mode *mode,
-                            struct drm_display_mode *adjusted_mode,
                             int x, int y,
                             struct drm_framebuffer *old_fb);
        void (*crtc_enable)(struct drm_crtc *crtc);
index 2db50e2..e22be58 100644 (file)
@@ -3971,15 +3971,16 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
        return encoder->get_hw_state(encoder, &pipe);
 }
 
-static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
-                                 const struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
+static bool intel_crtc_compute_config(struct drm_crtc *crtc,
+                                     struct intel_crtc_config *pipe_config)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 
        if (HAS_PCH_SPLIT(dev)) {
                /* FDI link clock is fixed at 2.7G */
-               if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4)
+               if (pipe_config->requested_mode.clock * 3
+                   > IRONLAKE_FDI_FREQ * 4)
                        return false;
        }
 
@@ -4665,14 +4666,15 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 }
 
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode,
                              int x, int y,
                              struct drm_framebuffer *fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_display_mode *adjusted_mode =
+               &intel_crtc->config.adjusted_mode;
+       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int refclk, num_connectors = 0;
@@ -5637,14 +5639,15 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 }
 
 static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode,
                                  int x, int y,
                                  struct drm_framebuffer *fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_display_mode *adjusted_mode =
+               &intel_crtc->config.adjusted_mode;
+       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int num_connectors = 0;
@@ -5803,14 +5806,15 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
 }
 
 static int haswell_crtc_mode_set(struct drm_crtc *crtc,
-                                struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode,
                                 int x, int y,
                                 struct drm_framebuffer *fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_display_mode *adjusted_mode =
+               &intel_crtc->config.adjusted_mode;
+       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int num_connectors = 0;
@@ -5887,8 +5891,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 }
 
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
                               int x, int y,
                               struct drm_framebuffer *fb)
 {
@@ -5897,6 +5899,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        struct drm_encoder_helper_funcs *encoder_funcs;
        struct intel_encoder *encoder;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_display_mode *adjusted_mode =
+               &intel_crtc->config.adjusted_mode;
+       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int ret;
 
@@ -5907,8 +5912,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        drm_vblank_pre_modeset(dev, pipe);
 
-       ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-                                             x, y, fb);
+       ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb);
+
        drm_vblank_post_modeset(dev, pipe);
 
        if (ret != 0)
@@ -7530,19 +7535,22 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
        }
 }
 
-static struct drm_display_mode *
-intel_modeset_adjusted_mode(struct drm_crtc *crtc,
-                           struct drm_display_mode *mode)
+static struct intel_crtc_config *
+intel_modeset_pipe_config(struct drm_crtc *crtc,
+                         struct drm_display_mode *mode)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_display_mode *adjusted_mode;
        struct drm_encoder_helper_funcs *encoder_funcs;
        struct intel_encoder *encoder;
+       struct intel_crtc_config *pipe_config;
 
-       adjusted_mode = drm_mode_duplicate(dev, mode);
-       if (!adjusted_mode)
+       pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
+       if (!pipe_config)
                return ERR_PTR(-ENOMEM);
 
+       drm_mode_copy(&pipe_config->adjusted_mode, mode);
+       drm_mode_copy(&pipe_config->requested_mode, mode);
+
        /* Pass our mode to the connectors and the CRTC to give them a chance to
         * adjust it according to limitations or connector properties, and also
         * a chance to reject the mode entirely.
@@ -7553,22 +7561,23 @@ intel_modeset_adjusted_mode(struct drm_crtc *crtc,
                if (&encoder->new_crtc->base != crtc)
                        continue;
                encoder_funcs = encoder->base.helper_private;
-               if (!(encoder_funcs->mode_fixup(&encoder->base, mode,
-                                               adjusted_mode))) {
+               if (!(encoder_funcs->mode_fixup(&encoder->base,
+                                               &pipe_config->requested_mode,
+                                               &pipe_config->adjusted_mode))) {
                        DRM_DEBUG_KMS("Encoder fixup failed\n");
                        goto fail;
                }
        }
 
-       if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
+       if (!(intel_crtc_compute_config(crtc, pipe_config))) {
                DRM_DEBUG_KMS("CRTC fixup failed\n");
                goto fail;
        }
        DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
-       return adjusted_mode;
+       return pipe_config;
 fail:
-       drm_mode_destroy(dev, adjusted_mode);
+       kfree(pipe_config);
        return ERR_PTR(-EINVAL);
 }
 
@@ -7834,7 +7843,8 @@ int intel_set_mode(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode;
+       struct drm_display_mode *saved_mode, *saved_hwmode;
+       struct intel_crtc_config *pipe_config = NULL;
        struct intel_crtc *intel_crtc;
        unsigned disable_pipes, prepare_pipes, modeset_pipes;
        int ret = 0;
@@ -7861,11 +7871,12 @@ int intel_set_mode(struct drm_crtc *crtc,
         * Hence simply check whether any bit is set in modeset_pipes in all the
         * pieces of code that are not yet converted to deal with mutliple crtcs
         * changing their mode at the same time. */
-       adjusted_mode = NULL;
        if (modeset_pipes) {
-               adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
-               if (IS_ERR(adjusted_mode)) {
-                       ret = PTR_ERR(adjusted_mode);
+               pipe_config = intel_modeset_pipe_config(crtc, mode);
+               if (IS_ERR(pipe_config)) {
+                       ret = PTR_ERR(pipe_config);
+                       pipe_config = NULL;
+
                        goto out;
                }
        }
@@ -7878,8 +7889,12 @@ int intel_set_mode(struct drm_crtc *crtc,
        /* crtc->mode is already used by the ->mode_set callbacks, hence we need
         * to set it here already despite that we pass it down the callchain.
         */
-       if (modeset_pipes)
+       if (modeset_pipes) {
                crtc->mode = *mode;
+               /* mode_set/enable/disable functions rely on a correct pipe
+                * config. */
+               to_intel_crtc(crtc)->config = *pipe_config;
+       }
 
        /* Only after disabling all output pipelines that will be changed can we
         * update the the output configuration. */
@@ -7893,7 +7908,6 @@ int intel_set_mode(struct drm_crtc *crtc,
         */
        for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
                ret = intel_crtc_mode_set(&intel_crtc->base,
-                                         mode, adjusted_mode,
                                          x, y, fb);
                if (ret)
                        goto done;
@@ -7905,7 +7919,7 @@ int intel_set_mode(struct drm_crtc *crtc,
 
        if (modeset_pipes) {
                /* Store real post-adjustment hardware mode. */
-               crtc->hwmode = *adjusted_mode;
+               crtc->hwmode = pipe_config->adjusted_mode;
 
                /* Calculate and store various constants which
                 * are later needed by vblank and swap-completion
@@ -7916,7 +7930,6 @@ int intel_set_mode(struct drm_crtc *crtc,
 
        /* FIXME: add subpixel order */
 done:
-       drm_mode_destroy(dev, adjusted_mode);
        if (ret && crtc->enabled) {
                crtc->hwmode = *saved_hwmode;
                crtc->mode = *saved_mode;
@@ -7925,6 +7938,7 @@ done:
        }
 
 out:
+       kfree(pipe_config);
        kfree(saved_mode);
        return ret;
 }
index 54bc2ea..4cc6625 100644 (file)
@@ -200,6 +200,11 @@ struct intel_connector {
        struct edid *edid;
 };
 
+struct intel_crtc_config {
+       struct drm_display_mode requested_mode;
+       struct drm_display_mode adjusted_mode;
+};
+
 struct intel_crtc {
        struct drm_crtc base;
        enum pipe pipe;
@@ -233,6 +238,8 @@ struct intel_crtc {
        bool cursor_visible;
        unsigned int bpp;
 
+       struct intel_crtc_config config;
+
        /* We can share PLLs across outputs if the timings match */
        struct intel_pch_pll *pch_pll;
        uint32_t ddi_pll_sel;