From: Ondrej Jirman <megous@megous.com>
Date: Sun, 17 Oct 2021 18:03:05 +0200
Subject: [PATCH 06/36] drm: panel: hx8394: Improve the panel driver (make it
 work with DSI fixes)

Powerup/down should be done in prepare/unprepare. Enable/disable is just
for initialization. Fix timings and reset order according to datasheet.

Reset panel on probe.

Signed-off-by: Ondrej Jirman <megous@megous.com>
---
 drivers/gpu/drm/panel/panel-himax-hx8394.c | 84 ++++++++++++++++++------------
 1 file changed, 52 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index 14659cb..2f69b94 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -89,11 +89,6 @@ static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
 	dsi_dcs_write_seq(dsi, 0xbd, 0x00);
 	dsi_dcs_write_seq(dsi, 0xc6, 0xed);
 
-	// msleep(0xfa);
-	// dsi_dcs_write_seq(dsi, 0x11);
-	// msleep(0x32);
-	// dsi_dcs_write_seq(dsi, 0x29);
-
 	return 0;
 }
 
@@ -141,30 +136,38 @@ static int hx8394_enable(struct drm_panel *panel)
 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 	int ret;
 
+	dev_info(ctx->dev, "enable\n");
+
 	ret = ctx->desc->init_sequence(ctx);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
 		return ret;
 	}
 
-	msleep(20);
-
 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
 		return ret;
 	}
 
 	/* Panel is operational 120 msec after reset */
-	msleep(60);
+	msleep(120);
 
 	ret = mipi_dsi_dcs_set_display_on(dsi);
-	if (ret)
-		return ret;
-
-	dev_dbg(ctx->dev, "Panel init sequence done\n");
+	if (ret) {
+		dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret);
+		goto sleep_in;
+	}
 
 	return 0;
+
+sleep_in:
+	/* This will probably fail, but let's try orderly power off anyway. */
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (!ret)
+		msleep(50);
+
+        return ret;
 }
 
 static int hx8394_disable(struct drm_panel *panel)
@@ -173,13 +176,15 @@ static int hx8394_disable(struct drm_panel *panel)
 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 	int ret;
 
-	ret = mipi_dsi_dcs_set_display_off(dsi);
-	if (ret < 0)
-		dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
+	dev_info(ctx->dev, "disable\n");
 
 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
-	if (ret < 0)
+	if (ret) {
 		dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+
+	msleep(50); /* about 3 frames */
 
 	return 0;
 }
@@ -187,13 +192,19 @@ static int hx8394_disable(struct drm_panel *panel)
 static int hx8394_unprepare(struct drm_panel *panel)
 {
 	struct hx8394 *ctx = panel_to_hx8394(panel);
+	//struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+	//int ret;
 
 	if (!ctx->prepared)
 		return 0;
 
+	dev_info(ctx->dev, "unprepare\n");
+
 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
 	regulator_disable(ctx->iovcc);
 	regulator_disable(ctx->vcc);
+
 	ctx->prepared = false;
 
 	return 0;
@@ -202,33 +213,38 @@ static int hx8394_unprepare(struct drm_panel *panel)
 static int hx8394_prepare(struct drm_panel *panel)
 {
 	struct hx8394 *ctx = panel_to_hx8394(panel);
+	//struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 	int ret;
 
 	if (ctx->prepared)
 		return 0;
 
-	dev_dbg(ctx->dev, "Resetting the panel\n");
+	dev_info(ctx->dev, "prepare\n");
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
 	ret = regulator_enable(ctx->vcc);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
 		return ret;
 	}
+
 	ret = regulator_enable(ctx->iovcc);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
 		goto disable_vcc;
 	}
 
-	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
-	mdelay(0x32);
 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
-	msleep(0x64);
+
+	msleep(180);
 
 	ctx->prepared = true;
 
 	return 0;
 
 disable_vcc:
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
 	regulator_disable(ctx->vcc);
 	return ret;
 }
@@ -273,9 +289,11 @@ static int allpixelson_set(void *data, u64 val)
 	dev_dbg(ctx->dev, "Setting all pixels on\n");
 	dsi_generic_write_seq(dsi, 0x23);
 	msleep(val * 1000);
+
 	/* Reset the panel to get video back */
 	drm_panel_disable(&ctx->panel);
 	drm_panel_unprepare(&ctx->panel);
+
 	drm_panel_prepare(&ctx->panel);
 	drm_panel_enable(&ctx->panel);
 
@@ -309,9 +327,10 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
 	if (!ctx)
 		return -ENOMEM;
 
-	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(ctx->reset_gpio))
-		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset gpio\n");
 
 	mipi_dsi_set_drvdata(dsi, ctx);
 
@@ -324,7 +343,8 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
 
 	ctx->vcc = devm_regulator_get(dev, "vcc");
 	if (IS_ERR(ctx->vcc))
-		return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
+		return dev_err_probe(dev, PTR_ERR(ctx->vcc),
+				     "Failed to request vcc regulator\n");
 
 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
 	if (IS_ERR(ctx->iovcc))
@@ -342,7 +362,7 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
 
 	ret = mipi_dsi_attach(dsi);
 	if (ret < 0) {
-		dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
+		dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
 		drm_panel_remove(&ctx->panel);
 		return ret;
 	}
@@ -361,13 +381,13 @@ static void hx8394_shutdown(struct mipi_dsi_device *dsi)
 	struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
 	int ret;
 
-	ret = drm_panel_unprepare(&ctx->panel);
-	if (ret < 0)
-		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
 	ret = drm_panel_disable(&ctx->panel);
 	if (ret < 0)
 		dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
+
+	ret = drm_panel_unprepare(&ctx->panel);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
 }
 
 static int hx8394_remove(struct mipi_dsi_device *dsi)