diff mbox

[19/81] drm/i915: simplify possible_clones computation

Message ID 1342016944-23395-20-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter July 11, 2012, 2:28 p.m. UTC
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).

Also explain why sdvo LVDS outputs cannot be cloned: Native LVDS (and
also eDP) can't be cloned, because the panel fitter is before the
ouput MUX (and for cpu eDP cloning isn't possible, anyway).

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     |    4 +---
 drivers/gpu/drm/i915/intel_display.c |   18 +++++++++++++-----
 drivers/gpu/drm/i915/intel_dp.c      |   14 +++-----------
 drivers/gpu/drm/i915/intel_drv.h     |   25 +++++--------------------
 drivers/gpu/drm/i915/intel_dvo.c     |    7 ++-----
 drivers/gpu/drm/i915/intel_hdmi.c    |   10 ++--------
 drivers/gpu/drm/i915/intel_lvds.c    |    2 +-
 drivers/gpu/drm/i915/intel_sdvo.c    |   14 +++++++-------
 drivers/gpu/drm/i915/intel_tv.c      |    2 +-
 9 files changed, 35 insertions(+), 61 deletions(-)

Comments

Paulo Zanoni July 12, 2012, 6:10 p.m. UTC | #1
Hi

I like your idea.

2012/7/11 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Intel hw only has one MUX for encoders, so outputs are either not
> cloneable or all in the same group of cloneable outputs.

I don't agree with this sentence... Our documentation contains
sections called "Simultaneous Display Capabilities on a Single Display
Pipe/Transcoder" describing the details and what/how/who/when cloning
is possible.

So in our code, before your patch, these were valid:
- CRT could be cloned with CRT, SDVO-non-tv, SDVO-lvds
- DVO-tmds could be cloned with CRT, DVO-tmds  (notice that even
though DVO-tmds can be cloned with CRT, CRT can't be cloned with
DVO-tmds! bug!)
- SDVO-non-tv could be cloned with CRT and SDVO-non-tv
- SDVO-lvds could be cloned with CRT, SDVO-lvds

After your patch, all these can be cloned with each other:
- CRT, DVO-tmds, SDVO-non-tv, SDVO-lvds

Things that were previously not possible and now are possible:

- SDVO-non-tv with SDVO-lvds
- DVO-tmds with SDVO-non-tv (does hardware with both DVO and SDVO exist?)
- DVO-tmds with SDVO-lvds (same question)

Maybe we should find a way to move all this code to inside
intel_encoder_clones directly? Or keep your patch just like it is, but
add a check inside intel_encoder_clones preventing SDVO-non-tv with
SDVO-lvds?


> 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).
>
> Also explain why sdvo LVDS outputs cannot be cloned: Native LVDS (and

I think you mean "sdvo LVDS can be cloned".



> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3190e9d..95b1022 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2481,18 +2481,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);


You removed the "if" statement... Is this correct? Even if it is
correct, move to a separate patch?


> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index d630db8..5fe044c 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -2129,8 +2129,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;


Please add a white space between "cloneable" and "=".


Cheers,
Paulo
Daniel Vetter July 12, 2012, 6:47 p.m. UTC | #2
On Thu, Jul 12, 2012 at 03:10:21PM -0300, Paulo Zanoni wrote:
> Hi
> 
> I like your idea.
> 
> 2012/7/11 Daniel Vetter <daniel.vetter@ffwll.ch>:
> > Intel hw only has one MUX for encoders, so outputs are either not
> > cloneable or all in the same group of cloneable outputs.
> 
> I don't agree with this sentence... Our documentation contains
> sections called "Simultaneous Display Capabilities on a Single Display
> Pipe/Transcoder" describing the details and what/how/who/when cloning
> is possible.
> 
> So in our code, before your patch, these were valid:
> - CRT could be cloned with CRT, SDVO-non-tv, SDVO-lvds
> - DVO-tmds could be cloned with CRT, DVO-tmds  (notice that even
> though DVO-tmds can be cloned with CRT, CRT can't be cloned with
> DVO-tmds! bug!)
> - SDVO-non-tv could be cloned with CRT and SDVO-non-tv
> - SDVO-lvds could be cloned with CRT, SDVO-lvds
> 
> After your patch, all these can be cloned with each other:
> - CRT, DVO-tmds, SDVO-non-tv, SDVO-lvds
> 
> Things that were previously not possible and now are possible:
> 
> - SDVO-non-tv with SDVO-lvds
> - DVO-tmds with SDVO-non-tv (does hardware with both DVO and SDVO exist?)
> - DVO-tmds with SDVO-lvds (same question)

dvo is gen2 only, sdvo is gen3+. For the SDVO-non-tv cloned with SDVO-lvds
I couldn't come up with any reason why cloning SDVO-lvds with SDVO-non-tv
wouldn't work ... After checking the docs the only case I've found as
justification why that would not work is that you can't use the panel
fitter together with anything else. Which explains why lvds can't be
cloned, but not why sdvo-lvds can't be cloned because we simply don't use
the panel fitter there (we use the lvds encoder to do the upscaling ...).

Imo this is a case where the spec is just guidance for implementers and in
the specific case of sdvo-lvds doesn't make much sense - I suspect that
the windows code also uses the panel fitter in some cases for sdvo-lvds
... or they're talking about enabling multiple outputs on the same sdvo
encoder, which again we don't support.

I think we can ignore this special case until someone whith sdvo-tmds +
sdvo-lvds files a bug report about broken clonig ...

All extend the commit message with this discussion.

> Maybe we should find a way to move all this code to inside
> intel_encoder_clones directly? Or keep your patch just like it is, but
> add a check inside intel_encoder_clones preventing SDVO-non-tv with
> SDVO-lvds?
> 
> 
> > 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).
> >
> > Also explain why sdvo LVDS outputs cannot be cloned: Native LVDS (and
> 
> I think you mean "sdvo LVDS can be cloned".

Yeah, will fix.
> 
> 
> 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 3190e9d..95b1022 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -2481,18 +2481,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);
> 
> 
> You removed the "if" statement... Is this correct? Even if it is
> correct, move to a separate patch?

I've figured 81 patches are enough already, and generally initializing
work items unconditionally is a good thing - we've recently broken resume
due to such an initialization bug.

> > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> > index d630db8..5fe044c 100644
> > --- a/drivers/gpu/drm/i915/intel_sdvo.c
> > +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> > @@ -2129,8 +2129,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;
> 
> 
> Please add a white space between "cloneable" and "=".

Will fix.

Thanks, Daniel
> 
> 
> Cheers,
> Paulo
> 
> -- 
> Paulo Zanoni
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9525822..c3f6680 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -690,9 +690,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
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1a201b2..38891ff 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6716,15 +6716,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++;
 	}
 
@@ -6883,7 +6891,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 */
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3190e9d..95b1022 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2481,18 +2481,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);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 16680e5..f8c1f04 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -89,25 +89,6 @@ 
 #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,11 +134,15 @@  struct intel_encoder {
 	int type;
 	bool needs_tv_clock;
 	bool connectors_active;
+	/*
+	 * 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 *);
 	void (*enable)(struct intel_encoder *);
 	void (*disable)(struct intel_encoder *);
 	int crtc_mask;
-	int clone_mask;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 756e977..86a3d2b 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -424,17 +424,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);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 188399f..b01900d 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -959,42 +959,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;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f1d0a05..1e879bf 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -943,7 +943,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))
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d630db8..5fe044c 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2129,8 +2129,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)
@@ -2161,7 +2160,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);
 
@@ -2204,8 +2203,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);
@@ -2237,8 +2235,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))
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index a0ec1eb..ef9e7a5 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1624,7 +1624,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;