Add driver to setup P097PFZ behing SSD2858 (4 to 8 lanes bridge).

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

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);
-- 
2.21.0

Reply via email to