diff mbox

[2/6] drm/i915: Added a return type for the restore crtc mode function

Message ID 1408008267-11443-3-git-send-email-akash.goel@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

akash.goel@intel.com Aug. 14, 2014, 9:24 a.m. UTC
From: Akash Goel <akash.goel@intel.com>

This patch changes the return type of 'crtc_restore_mode'
function from 'void', so that an error could be returned back to
User space, from the set property ioctl call, if the configuation
is not valid.

Signed-off-by: Akash Goel <akash.goel@intel.com>
Signed-off-by: Pallavi G<pallavi.g@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |  5 ++--
 drivers/gpu/drm/i915/intel_dp.c      | 30 +++++++++++++++----
 drivers/gpu/drm/i915/intel_drv.h     |  2 +-
 drivers/gpu/drm/i915/intel_hdmi.c    | 28 +++++++++++++++---
 drivers/gpu/drm/i915/intel_lvds.c    |  7 ++++-
 drivers/gpu/drm/i915/intel_sdvo.c    | 57 +++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_tv.c      | 26 ++++++++++++++--
 7 files changed, 136 insertions(+), 19 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5871efa..47a5424 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10964,9 +10964,10 @@  static int intel_set_mode(struct drm_crtc *crtc,
 	return ret;
 }
 
-void intel_crtc_restore_mode(struct drm_crtc *crtc)
+int intel_crtc_restore_mode(struct drm_crtc *crtc)
 {
-	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
+	return intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
+						crtc->primary->fb);
 }
 
 #undef for_each_intel_crtc_masked
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3273b77..4457a06 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3889,6 +3889,9 @@  intel_dp_set_property(struct drm_connector *connector,
 	struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	int ret;
+	bool old_has_audio = 0, old_auto = 0;
+	uint32_t old_range = 0;
+	int old_force_audio = 0, old_fitting_mode = 0;
 
 	ret = drm_object_property_set_value(&connector->base, property, val);
 	if (ret)
@@ -3901,6 +3904,9 @@  intel_dp_set_property(struct drm_connector *connector,
 		if (i == intel_dp->force_audio)
 			return 0;
 
+		old_force_audio = intel_dp->force_audio;
+		old_has_audio = intel_dp->has_audio;
+
 		intel_dp->force_audio = i;
 
 		if (i == HDMI_AUDIO_AUTO)
@@ -3916,8 +3922,8 @@  intel_dp_set_property(struct drm_connector *connector,
 	}
 
 	if (property == dev_priv->broadcast_rgb_property) {
-		bool old_auto = intel_dp->color_range_auto;
-		uint32_t old_range = intel_dp->color_range;
+		old_auto = intel_dp->color_range_auto;
+		old_range = intel_dp->color_range;
 
 		switch (val) {
 		case INTEL_BROADCAST_RGB_AUTO:
@@ -3953,6 +3959,7 @@  intel_dp_set_property(struct drm_connector *connector,
 			/* the eDP scaling property is not changed */
 			return 0;
 		}
+		old_fitting_mode = intel_connector->panel.fitting_mode;
 		intel_connector->panel.fitting_mode = val;
 
 		goto done;
@@ -3961,9 +3968,22 @@  intel_dp_set_property(struct drm_connector *connector,
 	return -EINVAL;
 
 done:
-	if (intel_encoder->base.crtc)
-		intel_crtc_restore_mode(intel_encoder->base.crtc);
-
+	if (intel_encoder->base.crtc) {
+		ret = intel_crtc_restore_mode(intel_encoder->base.crtc);
+		if (ret) {
+			if (property == dev_priv->force_audio_property) {
+				intel_dp->force_audio = old_force_audio;
+				intel_dp->has_audio = old_has_audio;
+			}
+			else if (property == dev_priv->broadcast_rgb_property) {
+				intel_dp->color_range_auto = old_auto;
+				intel_dp->color_range = old_range;
+			}
+			else if (property == connector->dev->mode_config.scaling_mode_property)
+				intel_connector->panel.fitting_mode = old_fitting_mode;
+		}
+		return ret;
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d1b5ded..a30abd9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -802,7 +802,7 @@  void intel_frontbuffer_flip(struct drm_device *dev,
 
 void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
 void intel_mark_idle(struct drm_device *dev);
-void intel_crtc_restore_mode(struct drm_crtc *crtc);
+int intel_crtc_restore_mode(struct drm_crtc *crtc);
 void intel_crtc_control(struct drm_crtc *crtc, bool enable);
 void intel_crtc_update_dpms(struct drm_crtc *crtc);
 void intel_encoder_destroy(struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 9169786..a711000 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1074,6 +1074,9 @@  intel_hdmi_set_property(struct drm_connector *connector,
 		hdmi_to_dig_port(intel_hdmi);
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
+	enum hdmi_force_audio old_force_audio = 0;
+	bool old_has_audio = 0, old_has_hdmi_sink = 0, old_auto = 0;
+	uint32_t old_range = 0;
 
 	ret = drm_object_property_set_value(&connector->base, property, val);
 	if (ret)
@@ -1086,6 +1089,10 @@  intel_hdmi_set_property(struct drm_connector *connector,
 		if (i == intel_hdmi->force_audio)
 			return 0;
 
+		old_force_audio = intel_hdmi->force_audio;
+		old_has_hdmi_sink = intel_hdmi->has_hdmi_sink;
+		old_has_audio = intel_hdmi->has_audio;
+
 		intel_hdmi->force_audio = i;
 
 		if (i == HDMI_AUDIO_AUTO)
@@ -1101,8 +1108,8 @@  intel_hdmi_set_property(struct drm_connector *connector,
 	}
 
 	if (property == dev_priv->broadcast_rgb_property) {
-		bool old_auto = intel_hdmi->color_range_auto;
-		uint32_t old_range = intel_hdmi->color_range;
+		old_auto = intel_hdmi->color_range_auto;
+		old_range = intel_hdmi->color_range;
 
 		switch (val) {
 		case INTEL_BROADCAST_RGB_AUTO:
@@ -1147,8 +1154,21 @@  intel_hdmi_set_property(struct drm_connector *connector,
 	return -EINVAL;
 
 done:
-	if (intel_dig_port->base.base.crtc)
-		intel_crtc_restore_mode(intel_dig_port->base.base.crtc);
+	if (intel_dig_port->base.base.crtc) {
+		ret = intel_crtc_restore_mode(intel_dig_port->base.base.crtc);
+		if (ret) {
+			if (property == dev_priv->force_audio_property) {
+				intel_hdmi->force_audio = old_force_audio;
+				intel_hdmi->has_hdmi_sink = old_has_hdmi_sink;
+				intel_hdmi->has_audio = old_has_audio;
+			}
+			else if (property == dev_priv->broadcast_rgb_property) {
+				intel_hdmi->color_range_auto = old_auto;
+				intel_hdmi->color_range = old_range;
+			}
+		}
+		return ret;
+	}
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 2a53768..8fd9299 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -493,6 +493,7 @@  static int intel_lvds_set_property(struct drm_connector *connector,
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_device *dev = connector->dev;
+	int old_fitting_mode = 0;
 
 	if (property == dev->mode_config.scaling_mode_property) {
 		struct drm_crtc *crtc;
@@ -506,6 +507,7 @@  static int intel_lvds_set_property(struct drm_connector *connector,
 			/* the LVDS scaling property is not changed */
 			return 0;
 		}
+		old_fitting_mode = intel_connector->panel.fitting_mode;
 		intel_connector->panel.fitting_mode = value;
 
 		crtc = intel_attached_encoder(connector)->base.crtc;
@@ -514,7 +516,10 @@  static int intel_lvds_set_property(struct drm_connector *connector,
 			 * If the CRTC is enabled, the display will be changed
 			 * according to the new panel fitting mode.
 			 */
-			intel_crtc_restore_mode(crtc);
+			int ret = intel_crtc_restore_mode(crtc);
+			if (ret)
+				intel_connector->panel.fitting_mode = old_fitting_mode;
+			return ret;
 		}
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 9350edd..fe9b447 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2074,6 +2074,9 @@  intel_sdvo_set_property(struct drm_connector *connector,
 	uint16_t temp_value;
 	uint8_t cmd;
 	int ret;
+	bool old_has_hdmi_audio = 0, old_auto = 0;
+	uint32_t old_range = 0, old_value = 0;
+	int old_force_audio = 0, old_tv_format_index = 0;
 
 	ret = drm_object_property_set_value(&connector->base, property, val);
 	if (ret)
@@ -2086,6 +2089,9 @@  intel_sdvo_set_property(struct drm_connector *connector,
 		if (i == intel_sdvo_connector->force_audio)
 			return 0;
 
+		old_force_audio = intel_sdvo_connector->force_audio;
+		old_has_hdmi_audio = intel_sdvo->has_hdmi_audio;
+
 		intel_sdvo_connector->force_audio = i;
 
 		if (i == HDMI_AUDIO_AUTO)
@@ -2101,8 +2107,8 @@  intel_sdvo_set_property(struct drm_connector *connector,
 	}
 
 	if (property == dev_priv->broadcast_rgb_property) {
-		bool old_auto = intel_sdvo->color_range_auto;
-		uint32_t old_range = intel_sdvo->color_range;
+		old_auto = intel_sdvo->color_range_auto;
+		old_range = intel_sdvo->color_range;
 
 		switch (val) {
 		case INTEL_BROADCAST_RGB_AUTO:
@@ -2133,6 +2139,7 @@  intel_sdvo_set_property(struct drm_connector *connector,
 	if (intel_sdvo_connector->name == property) { \
 		if (intel_sdvo_connector->cur_##name == temp_value) return 0; \
 		if (intel_sdvo_connector->max_##name < temp_value) return -EINVAL; \
+		old_value = intel_sdvo_connector->cur_##name; \
 		cmd = SDVO_CMD_SET_##NAME; \
 		intel_sdvo_connector->cur_##name = temp_value; \
 		goto set_value; \
@@ -2146,6 +2153,7 @@  intel_sdvo_set_property(struct drm_connector *connector,
 		    intel_sdvo_connector->tv_format_supported[val])
 			return 0;
 
+		old_tv_format_index = intel_sdvo->tv_format_index;
 		intel_sdvo->tv_format_index = intel_sdvo_connector->tv_format_supported[val];
 		goto done;
 	} else if (IS_TV_OR_LVDS(intel_sdvo_connector)) {
@@ -2156,6 +2164,7 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			if (intel_sdvo_connector->left_margin == temp_value)
 				return 0;
 
+			old_value = temp_value;
 			intel_sdvo_connector->left_margin = temp_value;
 			intel_sdvo_connector->right_margin = temp_value;
 			temp_value = intel_sdvo_connector->max_hscan -
@@ -2168,6 +2177,7 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			if (intel_sdvo_connector->right_margin == temp_value)
 				return 0;
 
+			old_value = temp_value;
 			intel_sdvo_connector->left_margin = temp_value;
 			intel_sdvo_connector->right_margin = temp_value;
 			temp_value = intel_sdvo_connector->max_hscan -
@@ -2180,6 +2190,7 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			if (intel_sdvo_connector->top_margin == temp_value)
 				return 0;
 
+			old_value = temp_value;
 			intel_sdvo_connector->top_margin = temp_value;
 			intel_sdvo_connector->bottom_margin = temp_value;
 			temp_value = intel_sdvo_connector->max_vscan -
@@ -2192,6 +2203,7 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			if (intel_sdvo_connector->bottom_margin == temp_value)
 				return 0;
 
+			old_value = temp_value;
 			intel_sdvo_connector->top_margin = temp_value;
 			intel_sdvo_connector->bottom_margin = temp_value;
 			temp_value = intel_sdvo_connector->max_vscan -
@@ -2222,11 +2234,48 @@  set_value:
 
 
 done:
-	if (intel_sdvo->base.base.crtc)
-		intel_crtc_restore_mode(intel_sdvo->base.base.crtc);
+	if (intel_sdvo->base.base.crtc) {
+		int ret = intel_crtc_restore_mode(intel_sdvo->base.base.crtc);
+
+#define UNDO_PROPERTY(name) \
+		else if (intel_sdvo_connector->name == property) \
+			intel_sdvo_connector->cur_##name = old_value;
+
+		if (property == dev_priv->force_audio_property) {
+			intel_sdvo_connector->force_audio = old_force_audio;
+			intel_sdvo->has_hdmi_audio = old_has_hdmi_audio;
+		} else if (property == dev_priv->broadcast_rgb_property) {
+			intel_sdvo->color_range_auto = old_auto;
+			intel_sdvo->color_range = old_range;
+		} else if ((intel_sdvo_connector->left == property) ||
+				   (intel_sdvo_connector->right == property)) {
+			intel_sdvo_connector->left_margin = old_value;
+			intel_sdvo_connector->right_margin = old_value;
+		} else if ((intel_sdvo_connector->top == property) ||
+				   (intel_sdvo_connector->bottom == property)) {
+			intel_sdvo_connector->top_margin = old_value;
+			intel_sdvo_connector->bottom_margin = old_value;
+		} else if (property == intel_sdvo_connector->tv_format)
+			intel_sdvo->tv_format_index = old_tv_format_index;
+		UNDO_PROPERTY(hpos)
+		UNDO_PROPERTY(vpos)
+		UNDO_PROPERTY(saturation)
+		UNDO_PROPERTY(contrast)
+		UNDO_PROPERTY(hue)
+		UNDO_PROPERTY(brightness)
+		UNDO_PROPERTY(sharpness)
+		UNDO_PROPERTY(flicker_filter)
+		UNDO_PROPERTY(flicker_filter_2d)
+		UNDO_PROPERTY(flicker_filter_adaptive)
+		UNDO_PROPERTY(tv_chroma_filter)
+		UNDO_PROPERTY(tv_luma_filter)
+		UNDO_PROPERTY(dot_crawl)
+		return ret;
+	}
 
 	return 0;
 #undef CHECK_PROPERTY
+#undef UNDO_PROPERTY
 }
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 32186a6..83059a8 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1458,6 +1458,8 @@  intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 	struct drm_crtc *crtc = intel_tv->base.base.crtc;
 	int ret = 0;
 	bool changed = false;
+	int old_margin = 0;
+	const char *old_format = NULL;
 
 	ret = drm_object_property_set_value(&connector->base, property, val);
 	if (ret < 0)
@@ -1465,18 +1467,22 @@  intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 
 	if (property == dev->mode_config.tv_left_margin_property &&
 		intel_tv->margin[TV_MARGIN_LEFT] != val) {
+		old_margin = intel_tv->margin[TV_MARGIN_LEFT];
 		intel_tv->margin[TV_MARGIN_LEFT] = val;
 		changed = true;
 	} else if (property == dev->mode_config.tv_right_margin_property &&
 		intel_tv->margin[TV_MARGIN_RIGHT] != val) {
+		old_margin = intel_tv->margin[TV_MARGIN_RIGHT];
 		intel_tv->margin[TV_MARGIN_RIGHT] = val;
 		changed = true;
 	} else if (property == dev->mode_config.tv_top_margin_property &&
 		intel_tv->margin[TV_MARGIN_TOP] != val) {
+		old_margin = intel_tv->margin[TV_MARGIN_TOP];
 		intel_tv->margin[TV_MARGIN_TOP] = val;
 		changed = true;
 	} else if (property == dev->mode_config.tv_bottom_margin_property &&
 		intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
+		old_margin = intel_tv->margin[TV_MARGIN_BOTTOM];
 		intel_tv->margin[TV_MARGIN_BOTTOM] = val;
 		changed = true;
 	} else if (property == dev->mode_config.tv_mode_property) {
@@ -1487,6 +1493,7 @@  intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 		if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
 			goto out;
 
+		old_format = intel_tv->tv_format;
 		intel_tv->tv_format = tv_modes[val].name;
 		changed = true;
 	} else {
@@ -1494,8 +1501,23 @@  intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 		goto out;
 	}
 
-	if (changed && crtc)
-		intel_crtc_restore_mode(crtc);
+	if (changed && crtc) {
+		ret =  intel_crtc_restore_mode(crtc);
+		if (ret) {
+			if (property == dev->mode_config.tv_left_margin_property)
+				intel_tv->margin[TV_MARGIN_LEFT] = old_margin;
+			else if (property == dev->mode_config.tv_right_margin_property)
+				intel_tv->margin[TV_MARGIN_RIGHT] = old_margin;
+			else if (property == dev->mode_config.tv_top_margin_property)
+				intel_tv->margin[TV_MARGIN_TOP] = old_margin;
+			else if (property == dev->mode_config.tv_bottom_margin_property)
+				intel_tv->margin[TV_MARGIN_BOTTOM] = old_margin;
+			else if (property == dev->mode_config.tv_mode_property) {
+				intel_tv->tv_format = old_format;
+			}
+		}
+		return ret;
+	}
 out:
 	return ret;
 }