drm/i915: add pipe_config->timings_set
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 26 Mar 2013 23:44:52 +0000 (00:44 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 27 Mar 2013 23:50:05 +0000 (00:50 +0100)
Only used by the lvds encoder. Note that we shouldn't do the same
simple conversion with the FORCE_6BPC flag, since that's much better
handled by moving all the pipe_bpc computation around.

This requires that we pass the pipe config around to encoders, so
that they can set special attributes and set constraints. To do so
introduce a new ->compute_config encoder callback, which is called in
stead of the drm crtc helper's ->mode_fixup.

To avoid massive churn all over the codebase we don't want to convert
all existing ->mode_fixup functions. Instead I've opted to convert
them on an as-needed basis (mostly to cut down on rebase conflicts and
to have more freedom to experiment around while developing the
patches).

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_lvds.c

index 1e3090978882e28fc8d9fb3366f0517d5f8e9023..673d91a3e1f28e9bde3ecc7ca7bf628ad7452efe 100644 (file)
@@ -3987,7 +3987,7 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc,
        /* All interlaced capable intel hw wants timings in frames. Note though
         * that intel_lvds_mode_fixup does some funny tricks with the crtc
         * timings, so we need to be careful not to clobber these.*/
-       if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET))
+       if (!pipe_config->timings_set)
                drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        /* WaPruneModeWithIncorrectHsyncOffset: Cantiga+ cannot handle modes
@@ -7560,6 +7560,16 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 
                if (&encoder->new_crtc->base != crtc)
                        continue;
+
+               if (encoder->compute_config) {
+                       if (!(encoder->compute_config(encoder, pipe_config))) {
+                               DRM_DEBUG_KMS("Encoder config failure\n");
+                               goto fail;
+                       }
+
+                       continue;
+               }
+
                encoder_funcs = encoder->base.helper_private;
                if (!(encoder_funcs->mode_fixup(&encoder->base,
                                                &pipe_config->requested_mode,
index 4cc66251fd34f624edbd635ed7357035748b7797..054032ae2856d3aeb32fad17cf914a1e73cf7f2f 100644 (file)
 #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
 #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
 #define INTEL_MODE_DP_FORCE_6BPC (0x10)
-/* This flag must be set by the encoder's mode_fixup if it changes the crtc
- * timings in the mode to prevent the crtc fixup from overwriting them.
- * Currently only lvds needs that. */
-#define INTEL_MODE_CRTC_TIMINGS_SET (0x20)
 /*
  * Set when limited 16-235 (as opposed to full 0-255) RGB color range is
  * to be used.
@@ -158,6 +154,8 @@ struct intel_encoder {
        bool cloneable;
        bool connectors_active;
        void (*hot_plug)(struct intel_encoder *);
+       bool (*compute_config)(struct intel_encoder *,
+                              struct intel_crtc_config *);
        void (*pre_pll_enable)(struct intel_encoder *);
        void (*pre_enable)(struct intel_encoder *);
        void (*enable)(struct intel_encoder *);
@@ -203,6 +201,10 @@ struct intel_connector {
 struct intel_crtc_config {
        struct drm_display_mode requested_mode;
        struct drm_display_mode adjusted_mode;
+       /* This flag must be set by the encoder's compute_config callback if it
+        * changes the crtc timings in the mode to prevent the crtc fixup from
+        * overwriting them.  Currently only lvds needs that. */
+       bool timings_set;
 };
 
 struct intel_crtc {
index 6ff145f97e90fa39444526dc5f35e3b27c43c7f5..a2c516c116cb4c254dff840ee5ad78ef5666c9e2 100644 (file)
@@ -261,8 +261,6 @@ centre_horizontally(struct drm_display_mode *mode,
 
        mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
        mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
-
-       mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static void
@@ -284,8 +282,6 @@ centre_vertically(struct drm_display_mode *mode,
 
        mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
        mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
-
-       mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static inline u32 panel_fitter_scaling(u32 source, u32 target)
@@ -301,15 +297,17 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target)
        return (FACTOR * ratio + FACTOR/2) / FACTOR;
 }
 
-static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
-                                 const struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode)
+static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
+                                     struct intel_crtc_config *pipe_config)
 {
-       struct drm_device *dev = encoder->dev;
+       struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
+       struct intel_lvds_encoder *lvds_encoder =
+               to_lvds_encoder(&intel_encoder->base);
        struct intel_connector *intel_connector =
                &lvds_encoder->attached_connector->base;
+       struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+       struct drm_display_mode *mode = &pipe_config->requested_mode;
        struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
        u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
        int pipe;
@@ -359,6 +357,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                I915_WRITE(BCLRPAT(pipe), 0);
 
        drm_mode_set_crtcinfo(adjusted_mode, 0);
+       pipe_config->timings_set = true;
 
        switch (intel_connector->panel.fitting_mode) {
        case DRM_MODE_SCALE_CENTER:
@@ -661,7 +660,6 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 }
 
 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
-       .mode_fixup = intel_lvds_mode_fixup,
        .mode_set = intel_lvds_mode_set,
 };
 
@@ -1105,6 +1103,7 @@ bool intel_lvds_init(struct drm_device *dev)
        intel_encoder->enable = intel_enable_lvds;
        intel_encoder->pre_enable = intel_pre_enable_lvds;
        intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;
+       intel_encoder->compute_config = intel_lvds_compute_config;
        intel_encoder->disable = intel_disable_lvds;
        intel_encoder->get_hw_state = intel_lvds_get_hw_state;
        intel_connector->get_hw_state = intel_connector_get_hw_state;