drm/i915: Set crtc/clone mask in different output devices
authorMa Ling <ling.ma@intel.com>
Mon, 24 Aug 2009 05:50:24 +0000 (13:50 +0800)
committerEric Anholt <eric@anholt.net>
Tue, 25 Aug 2009 00:01:33 +0000 (17:01 -0700)
Based on Bspec each encoder has different sharing pipe property,
i.e. Integrated or SDVO TV both will occupy one pipe exclusively,
and sdvo-non-tv and crt are allowed to share one. The patch moves
sharing judgment into differnet output functions, and sets the right
clone bit.

This fixes both HDMI outputs choosing the same pipe.

https://bugs.freedesktop.org/show_bug.cgi?id=22247

Signed-off-by: Ma Ling <ling.ma@intel.com>
Reviewed-by : Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
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 4cf8e2e88a40eb56aae2052fedab7af3c03b45c4..d1294978a38c96ef2ced3ea29070f5722063aa3e 100644 (file)
@@ -537,6 +537,10 @@ void intel_crt_init(struct drm_device *dev)
        }
 
        intel_output->type = INTEL_OUTPUT_ANALOG;
+       intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                  (1 << INTEL_ANALOG_CLONE_BIT) |
+                                  (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
 
index 4fad113a1b290253e496a23fea21b35934f0e574..3fadb5358858dbe40b0563285845fb7647c9ff6b 100644 (file)
@@ -3170,7 +3170,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
 
         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct intel_output *intel_output = to_intel_output(connector);
-               if (type_mask & (1 << intel_output->type))
+               if (type_mask & intel_output->clone_mask)
                        index_mask |= (1 << entry);
                entry++;
        }
@@ -3253,51 +3253,10 @@ static void intel_setup_outputs(struct drm_device *dev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct intel_output *intel_output = to_intel_output(connector);
                struct drm_encoder *encoder = &intel_output->enc;
-               int crtc_mask = 0, clone_mask = 0;
 
-               /* valid crtcs */
-               switch(intel_output->type) {
-               case INTEL_OUTPUT_HDMI:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_HDMI));
-                       break;
-               case INTEL_OUTPUT_DVO:
-               case INTEL_OUTPUT_SDVO:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-                                     (1 << INTEL_OUTPUT_DVO) |
-                                     (1 << INTEL_OUTPUT_SDVO));
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-                                     (1 << INTEL_OUTPUT_DVO) |
-                                     (1 << INTEL_OUTPUT_SDVO));
-                       break;
-               case INTEL_OUTPUT_LVDS:
-                       crtc_mask = (1 << 1);
-                       clone_mask = (1 << INTEL_OUTPUT_LVDS);
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       crtc_mask = ((1 << 0) |
-                                    (1 << 1));
-                       clone_mask = (1 << INTEL_OUTPUT_TVOUT);
-                       break;
-               case INTEL_OUTPUT_DISPLAYPORT:
-                       crtc_mask = ((1 << 0) |
-                                    (1 << 1));
-                       clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
-                       break;
-               case INTEL_OUTPUT_EDP:
-                       crtc_mask = (1 << 1);
-                       clone_mask = (1 << INTEL_OUTPUT_EDP);
-                       break;
-               }
-               encoder->possible_crtcs = crtc_mask;
-               encoder->possible_clones = intel_connector_clones(dev, clone_mask);
+               encoder->possible_crtcs = intel_output->crtc_mask;
+               encoder->possible_clones = intel_connector_clones(dev,
+                                               intel_output->clone_mask);
        }
 }
 
index a6ff15ac548aa9074eec2647ce377a2290dc58c0..f2afc4af4bc95499f9512aa7b9e7db6160f7e1bd 100644 (file)
@@ -1254,6 +1254,18 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        else
                intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
 
+       if (output_reg == DP_B)
+               intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
+       else if (output_reg == DP_C)
+               intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
+       else if (output_reg == DP_D)
+               intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+
+       if (IS_eDP(intel_output)) {
+               intel_output->crtc_mask = (1 << 1);
+               intel_output->clone_mask = (1 << INTEL_OUTPUT_EDP);
+       } else
+               intel_output->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
 
index d6f92ea1b5538fc0928119b600f4eaa241f66ada..25aa6facc12d30655c8de7b2ad66fd76cff99319 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_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
 #define INTEL_DVO_CHIP_TMDS 2
@@ -86,6 +104,8 @@ struct intel_output {
        bool needs_tv_clock;
        void *dev_priv;
        void (*hot_plug)(struct intel_output *);
+       int crtc_mask;
+       int clone_mask;
 };
 
 struct intel_crtc {
index 13bff20930e89f9a5bd2d83b3a4dace630252cf5..a4d2606de778c3d419713c3d8552290d828826c0 100644 (file)
@@ -435,14 +435,20 @@ void intel_dvo_init(struct drm_device *dev)
                        continue;
 
                intel_output->type = INTEL_OUTPUT_DVO;
+               intel_output->crtc_mask = (1 << 0) | (1 << 1);
                switch (dvo->type) {
                case INTEL_DVO_CHIP_TMDS:
+                       intel_output->clone_mask =
+                               (1 << INTEL_DVO_TMDS_CLONE_BIT) |
+                               (1 << INTEL_ANALOG_CLONE_BIT);
                        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_output->clone_mask =
+                               (1 << INTEL_DVO_LVDS_CLONE_BIT);
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_LVDS);
index 1842290cded3f074883a155269ceed3ae2e0b749..fa304e136010b0cef680590adbfc606b1776dcfa 100644 (file)
@@ -230,22 +230,28 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
 
        /* Set up the DDC bus. */
-       if (sdvox_reg == SDVOB)
+       if (sdvox_reg == SDVOB) {
+               intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
-       else if (sdvox_reg == SDVOC)
+       } else if (sdvox_reg == SDVOC) {
+               intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
-       else if (sdvox_reg == HDMIB)
+       } else if (sdvox_reg == HDMIB) {
+               intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
                                                                "HDMIB");
-       else if (sdvox_reg == HDMIC)
+       } else if (sdvox_reg == HDMIC) {
+               intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
                                                                "HDMIC");
-       else if (sdvox_reg == HDMID)
+       } else if (sdvox_reg == HDMID) {
+               intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
                                                                "HDMID");
-
+       }
        if (!intel_output->ddc_bus)
                goto err_connector;
 
index 3f445a80c552908b251cfa9d0d688c653a2f10ab..8df02ef892617ed7a47b8ab9d88665b675cbb046 100644 (file)
@@ -916,6 +916,8 @@ void intel_lvds_init(struct drm_device *dev)
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        intel_output->type = INTEL_OUTPUT_LVDS;
 
+       intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+       intel_output->crtc_mask = (1 << 1);
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
        drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
index 95ca0acc49455e22e0d8357f45697c7f7a55d1ef..d3b74ba62b4a07bb1702eca5e62f28dcea017ade 100644 (file)
@@ -1967,6 +1967,9 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                        intel_sdvo_set_colorimetry(intel_output,
                                                   SDVO_COLORIMETRY_RGB256);
                        connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
+                       intel_output->clone_mask =
+                                       (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                       (1 << INTEL_ANALOG_CLONE_BIT);
                }
        } else if (flags & SDVO_OUTPUT_SVID0) {
 
@@ -1975,11 +1978,14 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
                sdvo_priv->is_tv = true;
                intel_output->needs_tv_clock = true;
+               intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
        } else if (flags & SDVO_OUTPUT_RGB0) {
 
                sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
                encoder->encoder_type = DRM_MODE_ENCODER_DAC;
                connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+               intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                       (1 << INTEL_ANALOG_CLONE_BIT);
        } else if (flags & SDVO_OUTPUT_RGB1) {
 
                sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
@@ -1991,12 +1997,16 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
                connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
                sdvo_priv->is_lvds = true;
+               intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+                                       (1 << INTEL_SDVO_LVDS_CLONE_BIT);
        } else if (flags & SDVO_OUTPUT_LVDS1) {
 
                sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
                encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
                connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
                sdvo_priv->is_lvds = true;
+               intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+                                       (1 << INTEL_SDVO_LVDS_CLONE_BIT);
        } else {
 
                unsigned char bytes[2];
@@ -2009,6 +2019,7 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                                  bytes[0], bytes[1]);
                ret = false;
        }
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
 
        if (ret && registered)
                ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
index da4ab4dc16306b6fc4b7727da0954f7736a290cb..2fbe13a0de8113a4cf9486cd38595ef8fa1ee99c 100644 (file)
@@ -1718,6 +1718,7 @@ intel_tv_init(struct drm_device *dev)
        if (!intel_output) {
                return;
        }
+
        connector = &intel_output->base;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@@ -1729,6 +1730,7 @@ intel_tv_init(struct drm_device *dev)
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        tv_priv = (struct intel_tv_priv *)(intel_output + 1);
        intel_output->type = INTEL_OUTPUT_TVOUT;
+       intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT);
        intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
        intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
        intel_output->dev_priv = tv_priv;