diff mbox series

[3/3] drm/panel: panel-innolux: Add support for P097PFZ behind SSD2858

Message ID 20190912090404.89822-4-jitao.shi@mediatek.com (mailing list archive)
State New, archived
Headers show
Series add panel driver for innolux,p097pfg with ssd2825 bridge | expand

Commit Message

Jitao Shi Sept. 12, 2019, 9:04 a.m. UTC
Add driver to setup P097PFZ behing SSD2858 (4 to 8 lanes bridge).

Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
---
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 103 +++++++++++++++++-
 1 file changed, 102 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 8db404fb5eeb..a658ccba30a0 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -138,7 +138,7 @@  static int innolux_panel_prepare(struct drm_panel *panel)
 		if (!innolux->enable_gpio[i])
 			break;
 
-		/* p079zca: t2 (20ms), p097pfg: t4 (15ms) */
+		/* p079zca: t2 (20ms), p097pfg: t4 (15ms); ssd2858: 20ms */
 		usleep_range(20000, 21000);
 		gpiod_set_value_cansleep(innolux->enable_gpio[i], 1);
 	}
@@ -162,6 +162,18 @@  static int innolux_panel_prepare(struct drm_panel *panel)
 				goto poweroff;
 			}
 
+			/*
+			 * If the command list contains exit sleep mode or set
+			 * display on, wait the appropriate time (needed for
+			 * displays behind a bridge).
+			 */
+			/* T6: 120ms - 1000ms*/
+			if (cmd->data[0] == MIPI_DCS_EXIT_SLEEP_MODE)
+				msleep(120);
+			 /* T7: 5ms */
+			if (cmd->data[0] == MIPI_DCS_SET_DISPLAY_ON)
+				usleep_range(5000, 6000);
+
 			/*
 			 * Included by random guessing, because without this
 			 * (or at least, some delay), the panel sometimes
@@ -410,6 +422,92 @@  static const struct panel_desc innolux_p097pfg_panel_desc = {
 	.sleep_mode_delay = 100, /* T15 */
 };
 
+static const char * const innolux_p097pfg_ssd2858_supply_names[] = {
+	"avdd",
+	"avee",
+	"pp1800",
+	"pp3300",
+	"pp1200-bridge",
+	"vddio-bridge",
+};
+
+static const struct drm_display_mode innolux_p097pfg_ssd2858_mode = {
+	.clock = 211660,
+	.hdisplay = 1536,
+	.hsync_start = 1536 + 140,
+	.hsync_end = 1536 + 140 + 10,
+	.htotal = 1536 + 140 + 10 + 10,
+	.vdisplay = 2048,
+	.vsync_start = 2048 + 20,
+	.vsync_end = 2048 + 20 + 2,
+	.vtotal = 2048 + 20 + 2 + 10,
+	.vrefresh = 60,
+};
+
+static const struct panel_init_cmd innolux_p097pfg_ssd2858_init_cmds[] = {
+	/* SSD2858 config */
+	_INIT_CMD(0xff, 0x00),
+	/* LOCKCNT=0x1f4, MRX=0, POSTDIV=1 (/2), MULT=0x49
+	 * 27 Mhz => 985.5 Mhz
+	 */
+	_INIT_CMD(0x00, 0x08, 0x01, 0xf4, 0x01, 0x49),
+	/* MTXDIV=1, SYSDIV=3 (=> 4) */
+	_INIT_CMD(0x00, 0x0c, 0x00, 0x00, 0x00, 0x03),
+	/* MTXVPF=24bpp, MRXLS=4 lanes, MRXVB=bypass, MRXECC=1, MRXEOT=1
+	 * MRXEE=1
+	 */
+	_INIT_CMD(0x00, 0x14, 0x0c, 0x3d, 0x80, 0x0f),
+	_INIT_CMD(0x00, 0x20, 0x15, 0x92, 0x56, 0x7d),
+	_INIT_CMD(0x00, 0x24, 0x00, 0x00, 0x30, 0x00),
+
+	_INIT_CMD(0x10, 0x08, 0x01, 0x20, 0x08, 0x45),
+	_INIT_CMD(0x10, 0x1c, 0x00, 0x00, 0x00, 0x00),
+	_INIT_CMD(0x20, 0x0c, 0x00, 0x00, 0x00, 0x04),
+	/* Pixel clock 985.5 Mhz * 0x49/0x4b = 959 Mhz */
+	_INIT_CMD(0x20, 0x10, 0x00, 0x4b, 0x00, 0x49),
+	_INIT_CMD(0x20, 0xa0, 0x00, 0x00, 0x00, 0x00),
+	/* EOT=1, LPE = 0, LSOUT=4 lanes, LPD=25 */
+	_INIT_CMD(0x60, 0x08, 0x00, 0xd9, 0x00, 0x08),
+	_INIT_CMD(0x60, 0x14, 0x01, 0x00, 0x01, 0x06),
+	/* DSI0 enable (default: probably not needed) */
+	_INIT_CMD(0x60, 0x80, 0x00, 0x00, 0x00, 0x0f),
+	/* DSI1 enable */
+	_INIT_CMD(0x60, 0xa0, 0x00, 0x00, 0x00, 0x0f),
+
+	/* HSA=0x18, VSA=0x02, HBP=0x50, VBP=0x0c */
+	_INIT_CMD(0x60, 0x0c, 0x0c, 0x50, 0x02, 0x18),
+	/* VACT= 0x800 (2048), VFP= 0x14, HFP=0x50 */
+	_INIT_CMD(0x60, 0x10, 0x08, 0x00, 0x14, 0x50),
+	/* HACT=0x300 (768) */
+	_INIT_CMD(0x60, 0x84, 0x00, 0x00, 0x03, 0x00),
+	_INIT_CMD(0x60, 0xa4, 0x00, 0x00, 0x03, 0x00),
+
+	/* Take panel out of sleep. */
+	_INIT_CMD(0xff, 0x01),
+	_INIT_CMD(0x11),
+	_INIT_CMD(0x29),
+	_INIT_CMD(0xff, 0x00),
+
+	{},
+};
+
+static const struct panel_desc innolux_p097pfg_ssd2858_panel_desc = {
+	.mode = &innolux_p097pfg_ssd2858_mode,
+	.bpc = 8,
+	.size = {
+		.width = 147,
+		.height = 196,
+	},
+	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+		 MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+	.init_cmds = innolux_p097pfg_ssd2858_init_cmds,
+	.lanes = 4,
+	.supply_names = innolux_p097pfg_ssd2858_supply_names,
+	.num_supplies = ARRAY_SIZE(innolux_p097pfg_ssd2858_supply_names),
+	.sleep_mode_delay = 100, /* T15 */
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
 	struct innolux_panel *innolux = to_innolux_panel(panel);
@@ -451,6 +549,9 @@  static const struct of_device_id innolux_of_match[] = {
 	{ .compatible = "innolux,p097pfg",
 	  .data = &innolux_p097pfg_panel_desc
 	},
+	{ .compatible = "innolux,p097pfg_ssd2858",
+	  .data = &innolux_p097pfg_ssd2858_panel_desc
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, innolux_of_match);