[PATCH 06/10] drm/panel: otm8009a: Properly sequence [un]prepare with backlight

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I noticed while removing the enabled flag that backlight update checks
prepared in such a way that could race with hardware turning on/off.
This patch adds a mutex to ensure these races don't happen.

In addition to the lock, this patch also renames prepared to initialized
to better reflect what it means when used in the backlight hook.

Signed-off-by: Sean Paul <seanpaul@xxxxxxxxxxxx>
---
 drivers/gpu/drm/panel/panel-orisetech-otm8009a.c | 43 ++++++++++++++++--------
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
index 0a5898fd4502..d099af3c91df 100644
--- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
+++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
@@ -11,6 +11,7 @@
 #include <drm/drm_panel.h>
 #include <linux/backlight.h>
 #include <linux/gpio/consumer.h>
+#include <linux/mutex.h>
 #include <video/mipi_display.h>
 
 #define DRV_NAME "orisetech_otm8009a"
@@ -62,7 +63,9 @@ struct otm8009a {
 	struct drm_panel panel;
 	struct backlight_device *bl_dev;
 	struct gpio_desc *reset_gpio;
-	bool prepared;
+
+	struct mutex lock;
+	bool initialized;
 };
 
 static const struct drm_display_mode default_mode = {
@@ -265,26 +268,30 @@ static int otm8009a_unprepare(struct drm_panel *panel)
 {
 	struct otm8009a *ctx = panel_to_otm8009a(panel);
 
-	if (!ctx->prepared)
-		return 0;
+	mutex_lock(&ctx->lock);
+	if (!ctx->initialized)
+		goto out;
 
 	if (ctx->reset_gpio) {
 		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
 		msleep(20);
 	}
 
-	ctx->prepared = false;
+	ctx->initialized = false;
 
+out:
+	mutex_unlock(&ctx->lock);
 	return 0;
 }
 
 static int otm8009a_prepare(struct drm_panel *panel)
 {
 	struct otm8009a *ctx = panel_to_otm8009a(panel);
-	int ret;
+	int ret = 0;
 
-	if (ctx->prepared)
-		return 0;
+	mutex_lock(&ctx->lock);
+	if (ctx->initialized)
+		goto out;
 
 	if (ctx->reset_gpio) {
 		gpiod_set_value_cansleep(ctx->reset_gpio, 0);
@@ -296,18 +303,20 @@ static int otm8009a_prepare(struct drm_panel *panel)
 
 	ret = otm8009a_init_sequence(ctx);
 	if (ret)
-		return ret;
+		goto out;
 
-	ctx->prepared = true;
+	ctx->initialized = true;
 
 	/*
 	 * Power on the backlight. Note: end-user still controls brightness
-	 * Note: ctx->prepared must be true before updating the backlight.
+	 * Note: ctx->initialized must be true before updating the backlight.
 	 */
 	ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
 	backlight_update_status(ctx->bl_dev);
 
-	return 0;
+out:
+	mutex_unlock(&ctx->lock);
+	return ret;
 }
 
 static int otm8009a_get_modes(struct drm_panel *panel)
@@ -348,10 +357,13 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd)
 {
 	struct otm8009a *ctx = bl_get_data(bd);
 	u8 data[2];
+	int ret = 0;
 
-	if (!ctx->prepared) {
+	mutex_lock(&ctx->lock);
+	if (!ctx->initialized) {
 		DRM_DEBUG("lcd not ready yet for setting its backlight!\n");
-		return -ENXIO;
+		ret = -ENXIO;
+		goto out;
 	}
 
 	if (bd->props.power <= FB_BLANK_NORMAL) {
@@ -375,7 +387,9 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd)
 	data[0] = MIPI_DCS_WRITE_CONTROL_DISPLAY;
 	otm8009a_dcs_write_buf(ctx, data, ARRAY_SIZE(data));
 
-	return 0;
+out:
+	mutex_unlock(&ctx->lock);
+	return ret;
 }
 
 static const struct backlight_ops otm8009a_backlight_ops = {
@@ -401,6 +415,7 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
 	mipi_dsi_set_drvdata(dsi, ctx);
 
 	ctx->dev = dev;
+	mutex_init(&ctx->lock);
 
 	dsi->lanes = 2;
 	dsi->format = MIPI_DSI_FMT_RGB888;
-- 
2.14.1.821.g8fa685d3b7-goog

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux