231 lines
6.2 KiB
Diff
231 lines
6.2 KiB
Diff
|
From c40a06a43fd147cb3ca61e617f26a2343219d190 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
|
||
|
Date: Sun, 17 Oct 2021 18:03:05 +0200
|
||
|
Subject: [PATCH 301/391] 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 <megi@xff.cz>
|
||
|
---
|
||
|
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 2ce121a6a..1f23190a3 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 void hx8394_remove(struct mipi_dsi_device *dsi)
|
||
|
--
|
||
|
2.35.3
|
||
|
|