linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/4] Innolux P097PFG panel
@ 2018-07-02 10:27 Heiko Stuebner
  2018-07-02 10:27 ` [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels Heiko Stuebner
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Heiko Stuebner @ 2018-07-02 10:27 UTC (permalink / raw)
  To: thierry.reding
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov, Heiko Stuebner

The Innolux p097pfg is one of two possible panels used in the
gru-scarlet ChromeOS devices.

This v5 mainly addresses the very valuable comments from Emil
regarding power-supply and delay handling as well as documenting
the (unsatisfying) source of the init commands.

Individual changelogs inside the specific patches.

Tested with the recently resurrected Rockchip dual-dsi patches
on a gru-scarlet.


Lin Huang (2):
  drm/panel: p079zca: add variable unprepare_delay properties
  drm/panel: p079zca: support Innolux P097PFG panel

huang lin (2):
  drm/panel: p079zca: refactor panel driver to support multiple panels
  dt-bindings: Add Innolux P097PFG panel bindings

 .../display/panel/innolux,p097pfg.txt         |  24 ++
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 353 +++++++++++++++---
 2 files changed, 328 insertions(+), 49 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt

-- 
2.17.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels
  2018-07-02 10:27 [PATCH v5 0/4] Innolux P097PFG panel Heiko Stuebner
@ 2018-07-02 10:27 ` Heiko Stuebner
  2018-07-10 10:57   ` Thierry Reding
  2018-07-02 10:27 ` [PATCH v5 2/4] drm/panel: p079zca: add variable unprepare_delay properties Heiko Stuebner
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Heiko Stuebner @ 2018-07-02 10:27 UTC (permalink / raw)
  To: thierry.reding
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov, Heiko Stuebner

From: huang lin <hl@rock-chips.com>

Refactor Innolux P079ZCA panel driver, let it support
multi panels from Innolux that share similar power sequences.

Panels may require different power supplies so use regulator bulk
interfaces and define per panel supply-names.

Changes in v2:
- Change regulator property name to meet the panel datasheet
Changes in v3:
- this patch only refactor P079ZCA panel to support multi panel,
  support P097PFG panel in another patch
Changes in v4:
- Modify the patch which suggest by Thierry
Changes in v5:
- use regulator_bulk to handle different supply number

Signed-off-by: Lin Huang <hl@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 143 ++++++++++++------
 1 file changed, 100 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index bb53e0850764..840ad4a6a6a6 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,29 @@
 
 #include <video/mipi_display.h>
 
+struct panel_desc {
+	const struct drm_display_mode *modes;
+	unsigned int bpc;
+	struct {
+		unsigned int width;
+		unsigned int height;
+	} size;
+
+	unsigned long flags;
+	enum mipi_dsi_pixel_format format;
+	unsigned int lanes;
+	const char * const *supply_names;
+	unsigned int num_supplies;
+};
+
 struct innolux_panel {
 	struct drm_panel base;
 	struct mipi_dsi_device *link;
+	const struct panel_desc *desc;
 
 	struct backlight_device *backlight;
-	struct regulator *supply;
+	struct regulator_bulk_data *supplies;
+	unsigned int num_supplies;
 	struct gpio_desc *enable_gpio;
 
 	bool prepared;
@@ -77,9 +94,7 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
 	/* T8: 80ms - 1000ms */
 	msleep(80);
 
-	err = regulator_disable(innolux->supply);
-	if (err < 0)
-		return err;
+	regulator_bulk_disable(innolux->desc->num_supplies, innolux->supplies);
 
 	innolux->prepared = false;
 
@@ -89,14 +104,15 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
 static int innolux_panel_prepare(struct drm_panel *panel)
 {
 	struct innolux_panel *innolux = to_innolux_panel(panel);
-	int err, regulator_err;
+	int err;
 
 	if (innolux->prepared)
 		return 0;
 
 	gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-	err = regulator_enable(innolux->supply);
+	err = regulator_bulk_enable(innolux->desc->num_supplies,
+				    innolux->supplies);
 	if (err < 0)
 		return err;
 
@@ -133,12 +149,9 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 	return 0;
 
 poweroff:
-	regulator_err = regulator_disable(innolux->supply);
-	if (regulator_err)
-		DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
-			      regulator_err);
-
 	gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+	regulator_bulk_disable(innolux->desc->num_supplies, innolux->supplies);
+
 	return err;
 }
 
@@ -162,7 +175,11 @@ static int innolux_panel_enable(struct drm_panel *panel)
 	return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const char * const innolux_p079zca_supply_names[] = {
+	"power",
+};
+
+static const struct drm_display_mode innolux_p079zca_mode = {
 	.clock = 56900,
 	.hdisplay = 768,
 	.hsync_start = 768 + 40,
@@ -175,15 +192,31 @@ static const struct drm_display_mode default_mode = {
 	.vrefresh = 60,
 };
 
+static const struct panel_desc innolux_p079zca_panel_desc = {
+	.modes = &innolux_p079zca_mode,
+	.bpc = 8,
+	.size = {
+		.width = 120,
+		.height = 160,
+	},
+	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+		 MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+	.lanes = 4,
+	.supply_names = innolux_p079zca_supply_names,
+	.num_supplies = ARRAY_SIZE(innolux_p079zca_supply_names),
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
 	struct drm_display_mode *mode;
+	struct innolux_panel *innolux = to_innolux_panel(panel);
+	const struct drm_display_mode *m = innolux->desc->modes;
 
-	mode = drm_mode_duplicate(panel->drm, &default_mode);
+	mode = drm_mode_duplicate(panel->drm, m);
 	if (!mode) {
 		DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
-			      default_mode.hdisplay, default_mode.vdisplay,
-			      default_mode.vrefresh);
+			      m->hdisplay, m->vdisplay, m->vrefresh);
 		return -ENOMEM;
 	}
 
@@ -191,9 +224,11 @@ static int innolux_panel_get_modes(struct drm_panel *panel)
 
 	drm_mode_probed_add(panel->connector, mode);
 
-	panel->connector->display_info.width_mm = 120;
-	panel->connector->display_info.height_mm = 160;
-	panel->connector->display_info.bpc = 8;
+	panel->connector->display_info.width_mm =
+			innolux->desc->size.width;
+	panel->connector->display_info.height_mm =
+			innolux->desc->size.height;
+	panel->connector->display_info.bpc = innolux->desc->bpc;
 
 	return 1;
 }
@@ -207,19 +242,38 @@ static const struct drm_panel_funcs innolux_panel_funcs = {
 };
 
 static const struct of_device_id innolux_of_match[] = {
-	{ .compatible = "innolux,p079zca", },
+	{ .compatible = "innolux,p079zca",
+	  .data = &innolux_p079zca_panel_desc
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, innolux_of_match);
 
-static int innolux_panel_add(struct innolux_panel *innolux)
+static int innolux_panel_add(struct mipi_dsi_device *dsi,
+			     const struct panel_desc *desc)
 {
-	struct device *dev = &innolux->link->dev;
-	int err;
+	struct innolux_panel *innolux;
+	struct device *dev = &dsi->dev;
+	int err, i;
 
-	innolux->supply = devm_regulator_get(dev, "power");
-	if (IS_ERR(innolux->supply))
-		return PTR_ERR(innolux->supply);
+	innolux = devm_kzalloc(dev, sizeof(*innolux), GFP_KERNEL);
+	if (!innolux)
+		return -ENOMEM;
+
+	innolux->desc = desc;
+
+	innolux->supplies = devm_kcalloc(dev, desc->num_supplies,
+				     sizeof(*innolux->supplies), GFP_KERNEL);
+	if (!innolux->supplies)
+		return -ENOMEM;
+
+	for (i = 0; i < desc->num_supplies; i++)
+		innolux->supplies[i].supply = desc->supply_names[i];
+
+	err = devm_regulator_bulk_get(dev, desc->num_supplies,
+					   innolux->supplies);
+	if (err < 0)
+		return err;
 
 	innolux->enable_gpio = devm_gpiod_get_optional(dev, "enable",
 						       GPIOD_OUT_HIGH);
@@ -230,15 +284,21 @@ static int innolux_panel_add(struct innolux_panel *innolux)
 	}
 
 	innolux->backlight = devm_of_find_backlight(dev);
-
 	if (IS_ERR(innolux->backlight))
 		return PTR_ERR(innolux->backlight);
 
 	drm_panel_init(&innolux->base);
 	innolux->base.funcs = &innolux_panel_funcs;
-	innolux->base.dev = &innolux->link->dev;
+	innolux->base.dev = dev;
+
+	err = drm_panel_add(&innolux->base);
+	if (err < 0)
+		return err;
+
+	mipi_dsi_set_drvdata(dsi, innolux);
+	innolux->link = dsi;
 
-	return drm_panel_add(&innolux->base);
+	return 0;
 }
 
 static void innolux_panel_del(struct innolux_panel *innolux)
@@ -249,28 +309,24 @@ static void innolux_panel_del(struct innolux_panel *innolux)
 
 static int innolux_panel_probe(struct mipi_dsi_device *dsi)
 {
-	struct innolux_panel *innolux;
+	const struct panel_desc *desc;
+	const struct of_device_id *id;
 	int err;
 
-	dsi->lanes = 4;
-	dsi->format = MIPI_DSI_FMT_RGB888;
-	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
-			  MIPI_DSI_MODE_LPM;
-
-	innolux = devm_kzalloc(&dsi->dev, sizeof(*innolux), GFP_KERNEL);
-	if (!innolux)
-		return -ENOMEM;
-
-	mipi_dsi_set_drvdata(dsi, innolux);
+	id = of_match_node(innolux_of_match, dsi->dev.of_node);
+	if (!id)
+		return -ENODEV;
 
-	innolux->link = dsi;
+	desc = id->data;
+	dsi->mode_flags = desc->flags;
+	dsi->format = desc->format;
+	dsi->lanes = desc->lanes;
 
-	err = innolux_panel_add(innolux);
+	err = innolux_panel_add(dsi, desc);
 	if (err < 0)
 		return err;
 
-	err = mipi_dsi_attach(dsi);
-	return err;
+	return mipi_dsi_attach(dsi);
 }
 
 static int innolux_panel_remove(struct mipi_dsi_device *dsi)
@@ -317,5 +373,6 @@ static struct mipi_dsi_driver innolux_panel_driver = {
 module_mipi_dsi_driver(innolux_panel_driver);
 
 MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
 MODULE_DESCRIPTION("Innolux P079ZCA panel driver");
 MODULE_LICENSE("GPL v2");
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 2/4] drm/panel: p079zca: add variable unprepare_delay properties
  2018-07-02 10:27 [PATCH v5 0/4] Innolux P097PFG panel Heiko Stuebner
  2018-07-02 10:27 ` [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels Heiko Stuebner
@ 2018-07-02 10:27 ` Heiko Stuebner
  2018-07-10 10:57   ` Thierry Reding
  2018-07-02 10:27 ` [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings Heiko Stuebner
  2018-07-02 10:27 ` [PATCH v5 4/4] drm/panel: p079zca: support Innolux P097PFG panel Heiko Stuebner
  3 siblings, 1 reply; 10+ messages in thread
From: Heiko Stuebner @ 2018-07-02 10:27 UTC (permalink / raw)
  To: thierry.reding
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov, Heiko Stuebner

From: Lin Huang <hl@rock-chips.com>

When panel power down, p079zca need delay between reset and disable
power supply, but p097pfg does not need it. Similarly p097zca needs
a delay after entering panel sleep mode. So add two delay properties,
so we can meet these two panel power down sequence.

Signed-off-by: Lin Huang <hl@rock-chips.com>
[add sleep-mode delay]
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 840ad4a6a6a6..630b0c2549ef 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -33,6 +33,8 @@ struct panel_desc {
 	unsigned int lanes;
 	const char * const *supply_names;
 	unsigned int num_supplies;
+	unsigned int sleep_mode_delay;
+	unsigned int power_down_delay;
 };
 
 struct innolux_panel {
@@ -89,10 +91,13 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
 		return err;
 	}
 
+	if (innolux->desc->sleep_mode_delay)
+		msleep(innolux->desc->sleep_mode_delay);
+
 	gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-	/* T8: 80ms - 1000ms */
-	msleep(80);
+	if (innolux->desc->power_down_delay)
+		msleep(innolux->desc->power_down_delay);
 
 	regulator_bulk_disable(innolux->desc->num_supplies, innolux->supplies);
 
@@ -205,6 +210,7 @@ static const struct panel_desc innolux_p079zca_panel_desc = {
 	.lanes = 4,
 	.supply_names = innolux_p079zca_supply_names,
 	.num_supplies = ARRAY_SIZE(innolux_p079zca_supply_names),
+	.power_down_delay = 80, /* T8: 80ms - 1000ms */
 };
 
 static int innolux_panel_get_modes(struct drm_panel *panel)
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings
  2018-07-02 10:27 [PATCH v5 0/4] Innolux P097PFG panel Heiko Stuebner
  2018-07-02 10:27 ` [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels Heiko Stuebner
  2018-07-02 10:27 ` [PATCH v5 2/4] drm/panel: p079zca: add variable unprepare_delay properties Heiko Stuebner
@ 2018-07-02 10:27 ` Heiko Stuebner
  2018-07-03 17:20   ` Rob Herring
  2018-07-10 10:58   ` Thierry Reding
  2018-07-02 10:27 ` [PATCH v5 4/4] drm/panel: p079zca: support Innolux P097PFG panel Heiko Stuebner
  3 siblings, 2 replies; 10+ messages in thread
From: Heiko Stuebner @ 2018-07-02 10:27 UTC (permalink / raw)
  To: thierry.reding
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov, Heiko Stuebner

From: huang lin <hl@rock-chips.com>

The Innolux P097PFG panel is 9.7" panel with 1536X2048
resolution, it reuse P079ZCA panel driver, so improve
p079ZCA dt-binding to support P097PFG.

Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- use separate file for binding
- keep power supplies as required

Signed-off-by: Lin Huang <hl@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 .../display/panel/innolux,p097pfg.txt         | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt

diff --git a/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt b/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt
new file mode 100644
index 000000000000..595d9dfeffd3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt
@@ -0,0 +1,24 @@
+Innolux P097PFG 9.7" 1536x2048 TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,p097pfg"
+- reg: DSI virtual channel of the peripheral
+- avdd-supply: phandle of the regulator that provides positive voltage
+- avee-supply: phandle of the regulator that provides negative voltage
+- enable-gpios: panel enable gpio
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+	&mipi_dsi {
+		panel {
+			compatible = "innolux,p079zca";
+			reg = <0>;
+			avdd-supply = <...>;
+			avee-supply = <...>;
+			backlight = <&backlight>;
+			enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		};
+	};
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 4/4] drm/panel: p079zca: support Innolux P097PFG panel
  2018-07-02 10:27 [PATCH v5 0/4] Innolux P097PFG panel Heiko Stuebner
                   ` (2 preceding siblings ...)
  2018-07-02 10:27 ` [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings Heiko Stuebner
@ 2018-07-02 10:27 ` Heiko Stuebner
  2018-07-10 10:59   ` Thierry Reding
  3 siblings, 1 reply; 10+ messages in thread
From: Heiko Stuebner @ 2018-07-02 10:27 UTC (permalink / raw)
  To: thierry.reding
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov, Heiko Stuebner

From: Lin Huang <hl@rock-chips.com>

Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel, it reuse
the Innolux P079ZCA panel driver.

Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- Document source of init-commands
- 4 lanes per DSI interface

Signed-off-by: Lin Huang <hl@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 200 +++++++++++++++++-
 1 file changed, 196 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 630b0c2549ef..8d25b87bfbd6 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,6 +20,15 @@
 
 #include <video/mipi_display.h>
 
+struct panel_init_cmd {
+	int len;
+	const char *data;
+};
+
+#define _INIT_CMD(...) { \
+	.len = sizeof((char[]){__VA_ARGS__}), \
+	.data = (char[]){__VA_ARGS__} }
+
 struct panel_desc {
 	const struct drm_display_mode *modes;
 	unsigned int bpc;
@@ -30,6 +39,7 @@ struct panel_desc {
 
 	unsigned long flags;
 	enum mipi_dsi_pixel_format format;
+	const struct panel_init_cmd *init_cmds;
 	unsigned int lanes;
 	const char * const *supply_names;
 	unsigned int num_supplies;
@@ -121,13 +131,43 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 	if (err < 0)
 		return err;
 
-	/* T2: 15ms - 1000ms */
-	usleep_range(15000, 16000);
+	/* p079zca: t2 (20ms), p097pfg: t4 (15ms) */
+	usleep_range(20000, 21000);
 
 	gpiod_set_value_cansleep(innolux->enable_gpio, 1);
 
-	/* T4: 15ms - 1000ms */
-	usleep_range(15000, 16000);
+	/* p079zca: t4, p097pfg: t5 */
+	usleep_range(20000, 21000);
+
+	if (innolux->desc->init_cmds) {
+		const struct panel_init_cmd *cmds =
+					innolux->desc->init_cmds;
+		int i;
+
+		for (i = 0; cmds[i].len != 0; i++) {
+			const struct panel_init_cmd *cmd = &cmds[i];
+
+			err = mipi_dsi_generic_write(innolux->link, cmd->data,
+						     cmd->len);
+			if (err < 0) {
+				dev_err(panel->dev,
+					"failed to write command %d\n", i);
+				goto poweroff;
+			}
+
+			/*
+			 * Included by random guessing, because without this
+			 * (or at least, some delay), the panel sometimes
+			 * didn't appear to pick up the command sequence.
+			 */
+			err = mipi_dsi_dcs_nop(innolux->link);
+			if (err < 0) {
+				dev_err(panel->dev,
+					"failed to send DCS nop: %d\n", err);
+				goto poweroff;
+			}
+		}
+	}
 
 	err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
 	if (err < 0) {
@@ -213,6 +253,155 @@ static const struct panel_desc innolux_p079zca_panel_desc = {
 	.power_down_delay = 80, /* T8: 80ms - 1000ms */
 };
 
+static const char * const innolux_p097pfg_supply_names[] = {
+	"avdd",
+	"avee",
+};
+
+static const struct drm_display_mode innolux_p097pfg_mode = {
+	.clock = 229000,
+	.hdisplay = 1536,
+	.hsync_start = 1536 + 100,
+	.hsync_end = 1536 + 100 + 24,
+	.htotal = 1536 + 100 + 24 + 100,
+	.vdisplay = 2048,
+	.vsync_start = 2048 + 100,
+	.vsync_end = 2048 + 100 + 2,
+	.vtotal = 2048 + 100 + 2 + 18,
+	.vrefresh = 60,
+};
+
+/*
+ * Display manufacturer failed to provide init sequencing according to
+ * https://chromium-review.googlesource.com/c/chromiumos/third_party/coreboot/+/892065/
+ * so the init sequence stems from a register dump of a working panel.
+ */
+static const struct panel_init_cmd innolux_p097pfg_init_cmds[] = {
+	/* page 0 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00),
+	_INIT_CMD(0xB1, 0xE8, 0x11),
+	_INIT_CMD(0xB2, 0x25, 0x02),
+	_INIT_CMD(0xB5, 0x08, 0x00),
+	_INIT_CMD(0xBC, 0x0F, 0x00),
+	_INIT_CMD(0xB8, 0x03, 0x06, 0x00, 0x00),
+	_INIT_CMD(0xBD, 0x01, 0x90, 0x14, 0x14),
+	_INIT_CMD(0x6F, 0x01),
+	_INIT_CMD(0xC0, 0x03),
+	_INIT_CMD(0x6F, 0x02),
+	_INIT_CMD(0xC1, 0x0D),
+	_INIT_CMD(0xD9, 0x01, 0x09, 0x70),
+	_INIT_CMD(0xC5, 0x12, 0x21, 0x00),
+	_INIT_CMD(0xBB, 0x93, 0x93),
+
+	/* page 1 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01),
+	_INIT_CMD(0xB3, 0x3C, 0x3C),
+	_INIT_CMD(0xB4, 0x0F, 0x0F),
+	_INIT_CMD(0xB9, 0x45, 0x45),
+	_INIT_CMD(0xBA, 0x14, 0x14),
+	_INIT_CMD(0xCA, 0x02),
+	_INIT_CMD(0xCE, 0x04),
+	_INIT_CMD(0xC3, 0x9B, 0x9B),
+	_INIT_CMD(0xD8, 0xC0, 0x03),
+	_INIT_CMD(0xBC, 0x82, 0x01),
+	_INIT_CMD(0xBD, 0x9E, 0x01),
+
+	/* page 2 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x02),
+	_INIT_CMD(0xB0, 0x82),
+	_INIT_CMD(0xD1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x82, 0x00, 0xA5,
+		  0x00, 0xC1, 0x00, 0xEA, 0x01, 0x0D, 0x01, 0x40),
+	_INIT_CMD(0xD2, 0x01, 0x6A, 0x01, 0xA8, 0x01, 0xDC, 0x02, 0x29,
+		  0x02, 0x67, 0x02, 0x68, 0x02, 0xA8, 0x02, 0xF0),
+	_INIT_CMD(0xD3, 0x03, 0x19, 0x03, 0x49, 0x03, 0x67, 0x03, 0x8C,
+		  0x03, 0xA6, 0x03, 0xC7, 0x03, 0xDE, 0x03, 0xEC),
+	_INIT_CMD(0xD4, 0x03, 0xFF, 0x03, 0xFF),
+	_INIT_CMD(0xE0, 0x00, 0x00, 0x00, 0x86, 0x00, 0xC5, 0x00, 0xE5,
+		  0x00, 0xFF, 0x01, 0x26, 0x01, 0x45, 0x01, 0x75),
+	_INIT_CMD(0xE1, 0x01, 0x9C, 0x01, 0xD5, 0x02, 0x05, 0x02, 0x4D,
+		  0x02, 0x86, 0x02, 0x87, 0x02, 0xC3, 0x03, 0x03),
+	_INIT_CMD(0xE2, 0x03, 0x2A, 0x03, 0x56, 0x03, 0x72, 0x03, 0x94,
+		  0x03, 0xAC, 0x03, 0xCB, 0x03, 0xE0, 0x03, 0xED),
+	_INIT_CMD(0xE3, 0x03, 0xFF, 0x03, 0xFF),
+
+	/* page 3 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x03),
+	_INIT_CMD(0xB0, 0x00, 0x00, 0x00, 0x00),
+	_INIT_CMD(0xB1, 0x00, 0x00, 0x00, 0x00),
+	_INIT_CMD(0xB2, 0x00, 0x00, 0x06, 0x04, 0x01, 0x40, 0x85),
+	_INIT_CMD(0xB3, 0x10, 0x07, 0xFC, 0x04, 0x01, 0x40, 0x80),
+	_INIT_CMD(0xB6, 0xF0, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
+		  0x40, 0x80),
+	_INIT_CMD(0xBA, 0xC5, 0x07, 0x00, 0x04, 0x11, 0x25, 0x8C),
+	_INIT_CMD(0xBB, 0xC5, 0x07, 0x00, 0x03, 0x11, 0x25, 0x8C),
+	_INIT_CMD(0xC0, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80),
+	_INIT_CMD(0xC1, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x80, 0x80),
+	_INIT_CMD(0xC4, 0x00, 0x00),
+	_INIT_CMD(0xEF, 0x41),
+
+	/* page 4 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x04),
+	_INIT_CMD(0xEC, 0x4C),
+
+	/* page 5 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x05),
+	_INIT_CMD(0xB0, 0x13, 0x03, 0x03, 0x01),
+	_INIT_CMD(0xB1, 0x30, 0x00),
+	_INIT_CMD(0xB2, 0x02, 0x02, 0x00),
+	_INIT_CMD(0xB3, 0x82, 0x23, 0x82, 0x9D),
+	_INIT_CMD(0xB4, 0xC5, 0x75, 0x24, 0x57),
+	_INIT_CMD(0xB5, 0x00, 0xD4, 0x72, 0x11, 0x11, 0xAB, 0x0A),
+	_INIT_CMD(0xB6, 0x00, 0x00, 0xD5, 0x72, 0x24, 0x56),
+	_INIT_CMD(0xB7, 0x5C, 0xDC, 0x5C, 0x5C),
+	_INIT_CMD(0xB9, 0x0C, 0x00, 0x00, 0x01, 0x00),
+	_INIT_CMD(0xC0, 0x75, 0x11, 0x11, 0x54, 0x05),
+	_INIT_CMD(0xC6, 0x00, 0x00, 0x00, 0x00),
+	_INIT_CMD(0xD0, 0x00, 0x48, 0x08, 0x00, 0x00),
+	_INIT_CMD(0xD1, 0x00, 0x48, 0x09, 0x00, 0x00),
+
+	/* page 6 */
+	_INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x06),
+	_INIT_CMD(0xB0, 0x02, 0x32, 0x32, 0x08, 0x2F),
+	_INIT_CMD(0xB1, 0x2E, 0x15, 0x14, 0x13, 0x12),
+	_INIT_CMD(0xB2, 0x11, 0x10, 0x00, 0x3D, 0x3D),
+	_INIT_CMD(0xB3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
+	_INIT_CMD(0xB4, 0x3D, 0x32),
+	_INIT_CMD(0xB5, 0x03, 0x32, 0x32, 0x09, 0x2F),
+	_INIT_CMD(0xB6, 0x2E, 0x1B, 0x1A, 0x19, 0x18),
+	_INIT_CMD(0xB7, 0x17, 0x16, 0x01, 0x3D, 0x3D),
+	_INIT_CMD(0xB8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
+	_INIT_CMD(0xB9, 0x3D, 0x32),
+	_INIT_CMD(0xC0, 0x01, 0x32, 0x32, 0x09, 0x2F),
+	_INIT_CMD(0xC1, 0x2E, 0x1A, 0x1B, 0x16, 0x17),
+	_INIT_CMD(0xC2, 0x18, 0x19, 0x03, 0x3D, 0x3D),
+	_INIT_CMD(0xC3, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
+	_INIT_CMD(0xC4, 0x3D, 0x32),
+	_INIT_CMD(0xC5, 0x00, 0x32, 0x32, 0x08, 0x2F),
+	_INIT_CMD(0xC6, 0x2E, 0x14, 0x15, 0x10, 0x11),
+	_INIT_CMD(0xC7, 0x12, 0x13, 0x02, 0x3D, 0x3D),
+	_INIT_CMD(0xC8, 0x3D, 0x3D, 0x3D, 0x3D, 0x3D),
+	_INIT_CMD(0xC9, 0x3D, 0x32),
+
+	{},
+};
+
+static const struct panel_desc innolux_p097pfg_panel_desc = {
+	.modes = &innolux_p097pfg_mode,
+	.bpc = 8,
+	.size = {
+		.width = 147,
+		.height = 196,
+	},
+	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+		 MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+	.init_cmds = innolux_p097pfg_init_cmds,
+	.lanes = 4,
+	.supply_names = innolux_p097pfg_supply_names,
+	.num_supplies = ARRAY_SIZE(innolux_p097pfg_supply_names),
+	.sleep_mode_delay = 100, /* T15 */
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
 	struct drm_display_mode *mode;
@@ -251,6 +440,9 @@ static const struct of_device_id innolux_of_match[] = {
 	{ .compatible = "innolux,p079zca",
 	  .data = &innolux_p079zca_panel_desc
 	},
+	{ .compatible = "innolux,p097pfg",
+	  .data = &innolux_p097pfg_panel_desc
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, innolux_of_match);
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings
  2018-07-02 10:27 ` [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings Heiko Stuebner
@ 2018-07-03 17:20   ` Rob Herring
  2018-07-10 10:58   ` Thierry Reding
  1 sibling, 0 replies; 10+ messages in thread
From: Rob Herring @ 2018-07-03 17:20 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: thierry.reding, mark.rutland, devicetree, hl, briannorris,
	emil.l.velikov, linux-kernel, dri-devel

On Mon, Jul 02, 2018 at 12:27:20PM +0200, Heiko Stuebner wrote:
> From: huang lin <hl@rock-chips.com>
> 
> The Innolux P097PFG panel is 9.7" panel with 1536X2048
> resolution, it reuse P079ZCA panel driver, so improve
> p079ZCA dt-binding to support P097PFG.
> 
> Changes in v2:
> - None
> Changes in v3:
> - None
> Changes in v4:
> - None
> Changes in v5:
> - use separate file for binding
> - keep power supplies as required
> 
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  .../display/panel/innolux,p097pfg.txt         | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt

Reviewed-by: Rob Herring <robh@kernel.org>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels
  2018-07-02 10:27 ` [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels Heiko Stuebner
@ 2018-07-10 10:57   ` Thierry Reding
  0 siblings, 0 replies; 10+ messages in thread
From: Thierry Reding @ 2018-07-10 10:57 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov

[-- Attachment #1: Type: text/plain, Size: 2423 bytes --]

On Mon, Jul 02, 2018 at 12:27:18PM +0200, Heiko Stuebner wrote:
> From: huang lin <hl@rock-chips.com>
> 
> Refactor Innolux P079ZCA panel driver, let it support
> multi panels from Innolux that share similar power sequences.
> 
> Panels may require different power supplies so use regulator bulk
> interfaces and define per panel supply-names.
> 
> Changes in v2:
> - Change regulator property name to meet the panel datasheet
> Changes in v3:
> - this patch only refactor P079ZCA panel to support multi panel,
>   support P097PFG panel in another patch
> Changes in v4:
> - Modify the patch which suggest by Thierry
> Changes in v5:
> - use regulator_bulk to handle different supply number
> 
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/gpu/drm/panel/panel-innolux-p079zca.c | 143 ++++++++++++------
>  1 file changed, 100 insertions(+), 43 deletions(-)

Applied with minor changes, see below.

> diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
> index bb53e0850764..840ad4a6a6a6 100644
> --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
> +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
> @@ -20,12 +20,29 @@
>  
>  #include <video/mipi_display.h>
>  
> +struct panel_desc {
> +	const struct drm_display_mode *modes;

I renamed this to "mode" because there is always only one.

> +	unsigned int bpc;
> +	struct {
> +		unsigned int width;
> +		unsigned int height;
> +	} size;
> +
> +	unsigned long flags;
> +	enum mipi_dsi_pixel_format format;
> +	unsigned int lanes;
> +	const char * const *supply_names;
> +	unsigned int num_supplies;
> +};
> +
>  struct innolux_panel {
>  	struct drm_panel base;
>  	struct mipi_dsi_device *link;
> +	const struct panel_desc *desc;
>  
>  	struct backlight_device *backlight;
> -	struct regulator *supply;
> +	struct regulator_bulk_data *supplies;
> +	unsigned int num_supplies;
>  	struct gpio_desc *enable_gpio;
>  
>  	bool prepared;
> @@ -77,9 +94,7 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
>  	/* T8: 80ms - 1000ms */
>  	msleep(80);
>  
> -	err = regulator_disable(innolux->supply);
> -	if (err < 0)
> -		return err;
> +	regulator_bulk_disable(innolux->desc->num_supplies, innolux->supplies);

I kept the error check and return here.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 2/4] drm/panel: p079zca: add variable unprepare_delay properties
  2018-07-02 10:27 ` [PATCH v5 2/4] drm/panel: p079zca: add variable unprepare_delay properties Heiko Stuebner
@ 2018-07-10 10:57   ` Thierry Reding
  0 siblings, 0 replies; 10+ messages in thread
From: Thierry Reding @ 2018-07-10 10:57 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov

[-- Attachment #1: Type: text/plain, Size: 663 bytes --]

On Mon, Jul 02, 2018 at 12:27:19PM +0200, Heiko Stuebner wrote:
> From: Lin Huang <hl@rock-chips.com>
> 
> When panel power down, p079zca need delay between reset and disable
> power supply, but p097pfg does not need it. Similarly p097zca needs
> a delay after entering panel sleep mode. So add two delay properties,
> so we can meet these two panel power down sequence.
> 
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> [add sleep-mode delay]
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/gpu/drm/panel/panel-innolux-p079zca.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)

Applied, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings
  2018-07-02 10:27 ` [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings Heiko Stuebner
  2018-07-03 17:20   ` Rob Herring
@ 2018-07-10 10:58   ` Thierry Reding
  1 sibling, 0 replies; 10+ messages in thread
From: Thierry Reding @ 2018-07-10 10:58 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov

[-- Attachment #1: Type: text/plain, Size: 787 bytes --]

On Mon, Jul 02, 2018 at 12:27:20PM +0200, Heiko Stuebner wrote:
> From: huang lin <hl@rock-chips.com>
> 
> The Innolux P097PFG panel is 9.7" panel with 1536X2048
> resolution, it reuse P079ZCA panel driver, so improve
> p079ZCA dt-binding to support P097PFG.
> 
> Changes in v2:
> - None
> Changes in v3:
> - None
> Changes in v4:
> - None
> Changes in v5:
> - use separate file for binding
> - keep power supplies as required
> 
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  .../display/panel/innolux,p097pfg.txt         | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,p097pfg.txt

Applied, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 4/4] drm/panel: p079zca: support Innolux P097PFG panel
  2018-07-02 10:27 ` [PATCH v5 4/4] drm/panel: p079zca: support Innolux P097PFG panel Heiko Stuebner
@ 2018-07-10 10:59   ` Thierry Reding
  0 siblings, 0 replies; 10+ messages in thread
From: Thierry Reding @ 2018-07-10 10:59 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: robh+dt, mark.rutland, dri-devel, devicetree, linux-kernel,
	seanpaul, briannorris, hl, emil.l.velikov

[-- Attachment #1: Type: text/plain, Size: 2232 bytes --]

On Mon, Jul 02, 2018 at 12:27:21PM +0200, Heiko Stuebner wrote:
> From: Lin Huang <hl@rock-chips.com>
> 
> Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel, it reuse
> the Innolux P079ZCA panel driver.
> 
> Changes in v2:
> - None
> Changes in v3:
> - None
> Changes in v4:
> - None
> Changes in v5:
> - Document source of init-commands
> - 4 lanes per DSI interface
> 
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/gpu/drm/panel/panel-innolux-p079zca.c | 200 +++++++++++++++++-
>  1 file changed, 196 insertions(+), 4 deletions(-)

Applied with two small changes, see below.

> diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
> index 630b0c2549ef..8d25b87bfbd6 100644
> --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
> +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
> @@ -20,6 +20,15 @@
>  
>  #include <video/mipi_display.h>
>  
> +struct panel_init_cmd {
> +	int len;

I changed the type here to size_t for consistency.

> +	const char *data;
> +};
> +
> +#define _INIT_CMD(...) { \
> +	.len = sizeof((char[]){__VA_ARGS__}), \
> +	.data = (char[]){__VA_ARGS__} }
> +
>  struct panel_desc {
>  	const struct drm_display_mode *modes;
>  	unsigned int bpc;
> @@ -30,6 +39,7 @@ struct panel_desc {
>  
>  	unsigned long flags;
>  	enum mipi_dsi_pixel_format format;
> +	const struct panel_init_cmd *init_cmds;
>  	unsigned int lanes;
>  	const char * const *supply_names;
>  	unsigned int num_supplies;
> @@ -121,13 +131,43 @@ static int innolux_panel_prepare(struct drm_panel *panel)
>  	if (err < 0)
>  		return err;
>  
> -	/* T2: 15ms - 1000ms */
> -	usleep_range(15000, 16000);
> +	/* p079zca: t2 (20ms), p097pfg: t4 (15ms) */
> +	usleep_range(20000, 21000);
>  
>  	gpiod_set_value_cansleep(innolux->enable_gpio, 1);
>  
> -	/* T4: 15ms - 1000ms */
> -	usleep_range(15000, 16000);
> +	/* p079zca: t4, p097pfg: t5 */
> +	usleep_range(20000, 21000);
> +
> +	if (innolux->desc->init_cmds) {
> +		const struct panel_init_cmd *cmds =
> +					innolux->desc->init_cmds;
> +		int i;

I made this unsigned.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-07-10 10:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-02 10:27 [PATCH v5 0/4] Innolux P097PFG panel Heiko Stuebner
2018-07-02 10:27 ` [PATCH v5 1/4] drm/panel: p079zca: refactor panel driver to support multiple panels Heiko Stuebner
2018-07-10 10:57   ` Thierry Reding
2018-07-02 10:27 ` [PATCH v5 2/4] drm/panel: p079zca: add variable unprepare_delay properties Heiko Stuebner
2018-07-10 10:57   ` Thierry Reding
2018-07-02 10:27 ` [PATCH v5 3/4] dt-bindings: Add Innolux P097PFG panel bindings Heiko Stuebner
2018-07-03 17:20   ` Rob Herring
2018-07-10 10:58   ` Thierry Reding
2018-07-02 10:27 ` [PATCH v5 4/4] drm/panel: p079zca: support Innolux P097PFG panel Heiko Stuebner
2018-07-10 10:59   ` Thierry Reding

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).