[PATCH v2 5/9] drm/panel: novatek-nt36672a: Combine two init callbacks into one

From: Alexey Minnekhanov

Date: Thu Sep 17 2026 - 13:56:11 EST


The split between .send_init_cmds_1 and _cmds_2 is completely artificial
and unnecessary. Two command sets are split in between by the sequence:
- exit_sleep_mode
- delay
- set_display_on

But not every panel driver follows this "split" in their init sequence.
Some may have different delay timer, or put exit_sleep_mode/display_on
commands into other places in the sequence.

In order to make this driver more extensible, combine two init functions
into one by puting exit_sleep_mode/delay/display_on in the middle,
followed by commands from cmds_2. As part of this step, also move the
tianma-beryllium specific deinit sequence with its delays from
nt36672a_panel_unprepare() to tianma_fhd_video_send_deinit_cmds(), so
that each panel model can have its deinit sequence with its own delays.

No functional change - full init sequence with all the delays for the
tianma_fhd_video panel is kept the same in the end.

Signed-off-by: Alexey Minnekhanov <alexeymin@xxxxxxxxxx>

---
v2: move tianma_fhd deinit commands into its own deinit function
(set_display_off, msleep, enter_sleep_mode, msleep)
---
drivers/gpu/drm/panel/panel-novatek-nt36672a.c | 61 ++++++++++----------------
1 file changed, 23 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
index 73bec4f47ec60..a445c8067aa5f 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
@@ -51,8 +51,7 @@ struct nt36672a_panel_desc {
enum mipi_dsi_pixel_format format;
unsigned int lanes;

- void (*send_init_cmds_1)(struct mipi_dsi_multi_context *dsi_ctx);
- void (*send_init_cmds_2)(struct mipi_dsi_multi_context *dsi_ctx);
+ void (*send_init_cmds)(struct mipi_dsi_multi_context *dsi_ctx);
void (*send_deinit_cmds)(struct mipi_dsi_multi_context *dsi_ctx);
};

@@ -92,20 +91,6 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel)
if (pinfo->desc->send_deinit_cmds)
pinfo->desc->send_deinit_cmds(&dsi_ctx);

- /* Reset error to continue with display off even if send_cmds failed */
- dsi_ctx.accum_err = 0;
- mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
- /* Reset error to continue power-down even if display off failed */
- dsi_ctx.accum_err = 0;
-
- /* 120ms delay required here as per DCS spec */
- msleep(120);
-
- mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
-
- /* 0x3C = 60ms delay */
- msleep(60);
-
nt36672a_panel_power_off(panel);

return 0;
@@ -140,22 +125,9 @@ static int nt36672a_panel_prepare(struct drm_panel *panel)

dsi_ctx.accum_err = nt36672a_panel_power_on(pinfo);

- /* send first part of init cmds */
- if (pinfo->desc->send_init_cmds_1)
- pinfo->desc->send_init_cmds_1(&dsi_ctx);
-
- mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
-
- /* 0x46 = 70 ms delay */
- mipi_dsi_msleep(&dsi_ctx, 70);
-
- mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
-
- /* Send rest of the init cmds */
- if (pinfo->desc->send_init_cmds_2)
- pinfo->desc->send_init_cmds_2(&dsi_ctx);
-
- mipi_dsi_msleep(&dsi_ctx, 120);
+ /* send init cmds */
+ if (pinfo->desc->send_init_cmds)
+ pinfo->desc->send_init_cmds(&dsi_ctx);

if (dsi_ctx.accum_err < 0)
gpiod_set_value(pinfo->reset_gpio, 0);
@@ -192,7 +164,7 @@ static const struct drm_panel_funcs panel_funcs = {
.get_modes = nt36672a_panel_get_modes,
};

-static void tianma_fhd_video_send_init_cmds_1(struct mipi_dsi_multi_context *dsi_ctx)
+static void tianma_fhd_video_send_init_cmds(struct mipi_dsi_multi_context *dsi_ctx)
{
u8 reg;

@@ -352,15 +324,19 @@ static void tianma_fhd_video_send_init_cmds_1(struct mipi_dsi_multi_context *dsi
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x51, 0xff);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x53, 0x24);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0x55, 0x00);
-}

-static void tianma_fhd_video_send_init_cmds_2(struct mipi_dsi_multi_context *dsi_ctx)
-{
+ mipi_dsi_dcs_exit_sleep_mode_multi(dsi_ctx);
+ /* 0x46 = 70 ms delay */
+ mipi_dsi_msleep(dsi_ctx, 70);
+ mipi_dsi_dcs_set_display_on_multi(dsi_ctx);
+
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xff, 0x24);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfb, 0x01);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc3, 0x01);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc4, 0x54);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xff, 0x10);
+
+ mipi_dsi_msleep(dsi_ctx, 120);
}

static void tianma_fhd_video_send_deinit_cmds(struct mipi_dsi_multi_context *dsi_ctx)
@@ -369,6 +345,16 @@ static void tianma_fhd_video_send_deinit_cmds(struct mipi_dsi_multi_context *dsi
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xfb, 0x01);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xc3, 0x01);
mipi_dsi_dcs_write_seq_multi(dsi_ctx, 0xff, 0x10);
+
+ /* Reset error to continue with display off even if send_cmds failed */
+ dsi_ctx->accum_err = 0;
+ mipi_dsi_dcs_set_display_off_multi(dsi_ctx);
+ /* Reset error to continue power-down even if display off failed */
+ dsi_ctx->accum_err = 0;
+ /* 120ms delay required here as per DCS spec */
+ msleep(120);
+ mipi_dsi_dcs_enter_sleep_mode_multi(dsi_ctx);
+ msleep(60); /* 0x3C = 60ms delay */
}

static const struct drm_display_mode tianma_fhd_video_panel_default_mode = {
@@ -399,8 +385,7 @@ static const struct nt36672a_panel_desc tianma_fhd_video_panel_desc = {
| MIPI_DSI_MODE_VIDEO_BURST,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
- .send_init_cmds_1 = tianma_fhd_video_send_init_cmds_1,
- .send_init_cmds_2 = tianma_fhd_video_send_init_cmds_2,
+ .send_init_cmds = tianma_fhd_video_send_init_cmds,
.send_deinit_cmds = tianma_fhd_video_send_deinit_cmds,
};


--
2.55.0