drm/i915: simplify possible_clones computation
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 12 Jul 2012 18:08:18 +0000 (20:08 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 25 Jul 2012 16:23:46 +0000 (18:23 +0200)
Intel hw only has one MUX for encoders, so outputs are either not
cloneable or all in the same group of cloneable outputs. This neatly
simplifies the code and allows us to ditch some ugly if cascades in
the dp and hdmi init code (well, we need these if cascades for other
stuff still, but that can be taken care of in follow-up patches).

Note that this changes two things:
- dvo can now be cloned with sdvo, but dvo is gen2 whereas sdvo is
  gen3+, so no problem. Note that the old code had a bug and didn't
  allow cloning crt with dvo (but only the other way round).
- sdvo-lvds can now be cloned with sdvo-non-tv. Spec says this won't
  work, but the only reason I've found is that you can't use the
  panel-fitter (used for lvds upscaling) with anything else. But we
  don't use the panel fitter for sdvo-lvds. Imo this part of Bspec is
  a) rather confusing b) mostly as a guideline to implementors (i.e.
  explicitly stating what is already implicit from the spec, without
  always going into the details of why). So I think we can ignore this
  - worst case we'll get a bug report from a user with with sdvo-lvds
  and sdvo-tmds and have to add that special case back in.

Because sdvo lvds is a bit special explain in comments why sdvo LVDS
outputs can be cloned, but native LVDS and eDP can't be cloned - we
use the panel fitter for the later, but not for sdvo.

Note that this also uncoditionally initializes the panel_vdd work used
by eDP. Trying to be clever doesn't buy us anything (but strange bugs)
and this way we can kill the is_edp check.

v2: Incorporate review from Paulo
- Add in a missing space.
- Pimp comment message to address his concerns.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c

index 7ed4a41c396590f77b477d36f4400fb687e86990..e1d02be368a5860e3eb081ae790991e17f3e09b3 100644 (file)
@@ -658,9 +658,7 @@ void intel_crt_init(struct drm_device *dev)
        intel_connector_attach_encoder(intel_connector, &crt->base);
 
        crt->base.type = INTEL_OUTPUT_ANALOG;
-       crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
-                               1 << INTEL_ANALOG_CLONE_BIT |
-                               1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       crt->base.cloneable = true;
        if (IS_HASWELL(dev))
                crt->base.crtc_mask = (1 << 0);
        else
index e9e476eca89f4b60e88b8ec8e3643b8cc0cb8817..5c0a72606225ecd2aaf98b9ba78a1f573eb49678 100644 (file)
@@ -6707,15 +6707,23 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
        return 0;
 }
 
-static int intel_encoder_clones(struct drm_device *dev, int type_mask)
+static int intel_encoder_clones(struct intel_encoder *encoder)
 {
-       struct intel_encoder *encoder;
+       struct drm_device *dev = encoder->base.dev;
+       struct intel_encoder *source_encoder;
        int index_mask = 0;
        int entry = 0;
 
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-               if (type_mask & encoder->clone_mask)
+       list_for_each_entry(source_encoder,
+                           &dev->mode_config.encoder_list, base.head) {
+
+               if (encoder == source_encoder)
                        index_mask |= (1 << entry);
+
+               /* Intel hw has only one MUX where enocoders could be cloned. */
+               if (encoder->cloneable && source_encoder->cloneable)
+                       index_mask |= (1 << entry);
+
                entry++;
        }
 
@@ -6874,7 +6882,7 @@ static void intel_setup_outputs(struct drm_device *dev)
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
                encoder->base.possible_crtcs = encoder->crtc_mask;
                encoder->base.possible_clones =
-                       intel_encoder_clones(dev, encoder->clone_mask);
+                       intel_encoder_clones(encoder);
        }
 
        /* disable all the possible outputs/crtcs before entering KMS mode */
index 9f415643c8e2b04ceb3f2e3dbf202c34b55b989d..d1489ab56fc9d1cd5dceb2bd15d943f4821add88 100644 (file)
@@ -2451,18 +2451,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
        connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-       if (output_reg == DP_B || output_reg == PCH_DP_B)
-               intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
-       else if (output_reg == DP_C || output_reg == PCH_DP_C)
-               intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
-       else if (output_reg == DP_D || output_reg == PCH_DP_D)
-               intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+       intel_encoder->cloneable = false;
 
-       if (is_edp(intel_dp)) {
-               intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-               INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-                                 ironlake_panel_vdd_work);
-       }
+       INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+                         ironlake_panel_vdd_work);
 
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
index 35488aae5d092e2104bc044c5a1db058f9bf940f..76ba554f65921d6cf3755b58693d1633c0c20682 100644 (file)
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
 
-/* Intel Pipe Clone Bit */
-#define INTEL_HDMIB_CLONE_BIT 1
-#define INTEL_HDMIC_CLONE_BIT 2
-#define INTEL_HDMID_CLONE_BIT 3
-#define INTEL_HDMIE_CLONE_BIT 4
-#define INTEL_HDMIF_CLONE_BIT 5
-#define INTEL_SDVO_NON_TV_CLONE_BIT 6
-#define INTEL_SDVO_TV_CLONE_BIT 7
-#define INTEL_SDVO_LVDS_CLONE_BIT 8
-#define INTEL_ANALOG_CLONE_BIT 9
-#define INTEL_TV_CLONE_BIT 10
-#define INTEL_DP_B_CLONE_BIT 11
-#define INTEL_DP_C_CLONE_BIT 12
-#define INTEL_DP_D_CLONE_BIT 13
-#define INTEL_LVDS_CLONE_BIT 14
-#define INTEL_DVO_TMDS_CLONE_BIT 15
-#define INTEL_DVO_LVDS_CLONE_BIT 16
-#define INTEL_EDP_CLONE_BIT 17
-
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
 #define INTEL_DVO_CHIP_TMDS 2
@@ -153,9 +134,13 @@ struct intel_encoder {
        struct drm_encoder base;
        int type;
        bool needs_tv_clock;
+       /*
+        * Intel hw has only one MUX where encoders could be clone, hence a
+        * simple flag is enough to compute the possible_clones mask.
+        */
+       bool cloneable;
        void (*hot_plug)(struct intel_encoder *);
        int crtc_mask;
-       int clone_mask;
 };
 
 struct intel_connector {
index 36c542e5036b915e40eb2444608835ade5458027..556cf6bf2a55e30f52b20512bdc240b000c1ea35 100644 (file)
@@ -396,17 +396,14 @@ void intel_dvo_init(struct drm_device *dev)
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
                switch (dvo->type) {
                case INTEL_DVO_CHIP_TMDS:
-                       intel_encoder->clone_mask =
-                               (1 << INTEL_DVO_TMDS_CLONE_BIT) |
-                               (1 << INTEL_ANALOG_CLONE_BIT);
+                       intel_encoder->cloneable = true;
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_DVII);
                        encoder_type = DRM_MODE_ENCODER_TMDS;
                        break;
                case INTEL_DVO_CHIP_LVDS:
-                       intel_encoder->clone_mask =
-                               (1 << INTEL_DVO_LVDS_CLONE_BIT);
+                       intel_encoder->cloneable = false;
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_LVDS);
index 98f602427eb8cb8fe9a8cc975ff1b4128ce68ae6..593b8fe2e00ac669c5e1e0368a14f85d0e4f463d 100644 (file)
@@ -923,42 +923,36 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        connector->doublescan_allowed = 0;
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
+       intel_encoder->cloneable = false;
+
        /* Set up the DDC bus. */
        if (sdvox_reg == SDVOB) {
-               intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
                dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == SDVOC) {
-               intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
                dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMIB) {
-               intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
                dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMIC) {
-               intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
                dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == HDMID) {
-               intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
                dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
                DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
-               intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
                intel_hdmi->ddi_port = PORT_B;
                dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
                DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
-               intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
                intel_hdmi->ddi_port = PORT_C;
                dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
        } else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
                DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
-               intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
                intel_hdmi->ddi_port = PORT_D;
                dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
index e05c0d3e3440f1398f85806f00203998bbfc24ce..d789fdad5d3761585ecdcbb7d257365addd2a6dc 100644 (file)
@@ -967,7 +967,7 @@ bool intel_lvds_init(struct drm_device *dev)
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        intel_encoder->type = INTEL_OUTPUT_LVDS;
 
-       intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+       intel_encoder->cloneable = false;
        if (HAS_PCH_SPLIT(dev))
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
        else if (IS_GEN4(dev))
index 26a6a4d0d0788b536de65f3b4ca6261768115179..d881602a9155387fee0f82b400752c89e39c4d65 100644 (file)
@@ -2078,8 +2078,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
                connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
                intel_sdvo->is_hdmi = true;
        }
-       intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-                                      (1 << INTEL_ANALOG_CLONE_BIT));
+       intel_sdvo->base.cloneable = true;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (intel_sdvo->is_hdmi)
@@ -2110,7 +2109,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
        intel_sdvo->is_tv = true;
        intel_sdvo->base.needs_tv_clock = true;
-       intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+       intel_sdvo->base.cloneable = false;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 
@@ -2153,8 +2152,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
        }
 
-       intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-                                      (1 << INTEL_ANALOG_CLONE_BIT));
+       intel_sdvo->base.cloneable = true;
 
        intel_sdvo_connector_init(intel_sdvo_connector,
                                  intel_sdvo);
@@ -2186,8 +2184,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
 
-       intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) |
-                                      (1 << INTEL_SDVO_LVDS_CLONE_BIT));
+       /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
+        * as opposed to native LVDS, where we upscale with the panel-fitter
+        * (and hence only the native LVDS resolution could be cloned). */
+       intel_sdvo->base.cloneable = true;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
index befce6c4970496a821e2a84b8b4e6bda29c04f9d..1a0bab07699e9d0e0d7cd87f095d57cbe3913285 100644 (file)
@@ -1622,7 +1622,7 @@ intel_tv_init(struct drm_device *dev)
        intel_connector_attach_encoder(intel_connector, intel_encoder);
        intel_encoder->type = INTEL_OUTPUT_TVOUT;
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
-       intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
+       intel_encoder->cloneable = false;
        intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
        intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
        intel_tv->type = DRM_MODE_CONNECTOR_Unknown;