diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 39 | 
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 0e03985b0fe..c275bf0fa36 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2251,7 +2251,6 @@ 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.cloneable = true;  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);  	if (intel_sdvo->is_hdmi) @@ -2282,7 +2281,6 @@ 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.cloneable = false;  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); @@ -2325,8 +2323,6 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)  		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;  	} -	intel_sdvo->base.cloneable = true; -  	intel_sdvo_connector_init(intel_sdvo_connector,  				  intel_sdvo);  	return true; @@ -2357,9 +2353,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)  		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;  	} -	/* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */ -	intel_sdvo->base.cloneable = false; -  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);  	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))  		goto err; @@ -2432,6 +2425,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)  	return true;  } +static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) +{ +	struct drm_device *dev = intel_sdvo->base.base.dev; +	struct drm_connector *connector, *tmp; + +	list_for_each_entry_safe(connector, tmp, +				 &dev->mode_config.connector_list, head) { +		if (intel_attached_encoder(connector) == &intel_sdvo->base) +			intel_sdvo_destroy(connector); +	} +} +  static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,  					  struct intel_sdvo_connector *intel_sdvo_connector,  					  int type) @@ -2753,9 +2758,20 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  				    intel_sdvo->caps.output_flags) != true) {  		DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",  			      SDVO_NAME(intel_sdvo)); -		goto err; +		/* Output_setup can leave behind connectors! */ +		goto err_output;  	} +	/* +	 * Cloning SDVO with anything is often impossible, since the SDVO +	 * encoder can request a special input timing mode. And even if that's +	 * not the case we have evidence that cloning a plain unscaled mode with +	 * VGA doesn't really work. Furthermore the cloning flags are way too +	 * simplistic anyway to express such constraints, so just give up on +	 * cloning for SDVO encoders. +	 */ +	intel_sdvo->base.cloneable = false; +  	/* Only enable the hotplug irq if we need it, to work around noisy  	 * hotplug lines.  	 */ @@ -2766,12 +2782,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  	/* Set the input timing to the screen. Assume always input 0. */  	if (!intel_sdvo_set_target_input(intel_sdvo)) -		goto err; +		goto err_output;  	if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,  						    &intel_sdvo->pixel_clock_min,  						    &intel_sdvo->pixel_clock_max)) -		goto err; +		goto err_output;  	DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "  			"clock range %dMHz - %dMHz, " @@ -2791,6 +2807,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  			(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');  	return true; +err_output: +	intel_sdvo_output_cleanup(intel_sdvo); +  err:  	drm_encoder_cleanup(&intel_encoder->base);  	i2c_del_adapter(&intel_sdvo->ddc);  |