summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lu <luchris@google.com>2023-03-06 23:06:39 +0800
committerTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2023-06-19 03:08:31 +0000
commit9d0fabdf24f1feed77de63dd8c9f996d1cf117fe (patch)
tree46f3ff7a0675571d4f8f02b5c6381dd2d9513f08
parent8eb5be234f1cd2536d16d236675d97405728f16d (diff)
downloadshusky-9d0fabdf24f1feed77de63dd8c9f996d1cf117fe.tar.gz
display: hk3: update panel settings
- Update panel voltages settings - Modify IRC commands - Send pixel off command instead of DBV=0 in normal mode - Remove the code of increasing source amplifier power in AOD - Use one TE width setting for both HS and NS modes - Set default TE pulse width after entering AOD mode Bug: 270294713 Bug: 277198298 Test: suspend/resume, enter/exit AOD Change-Id: Idf5542d9d7fe8bd60dd1822661e3924710bce07d Signed-off-by: Chris Lu <luchris@google.com>
-rw-r--r--display/panel-google-hk3.c255
1 files changed, 180 insertions, 75 deletions
diff --git a/display/panel-google-hk3.c b/display/panel-google-hk3.c
index b6c7e9f..2cc4e1c 100644
--- a/display/panel-google-hk3.c
+++ b/display/panel-google-hk3.c
@@ -149,6 +149,11 @@ struct hk3_panel {
* handled in the commit_done function.
*/
bool pending_temp_update;
+ /**
+ * @is_pixel_off: pixel-off command is sent to panel. Only sending normal-on or resetting
+ * panel can recover to normal mode after entering pixel-off state.
+ */
+ bool is_pixel_off;
};
#define to_spanel(ctx) container_of(ctx, struct hk3_panel, base)
@@ -293,7 +298,7 @@ static const struct drm_dsc_config fhd_pps_config = {
#define HK3_TE2_FALLING_EDGE_OFFSET_NS 0x25
#define HK3_TE_USEC_60HZ_HS 8500
-#define HK3_TE_USEC_60HZ_NS 346
+#define HK3_TE_USEC_60HZ_NS 546
#define PROJECT "HK3"
@@ -302,6 +307,9 @@ static const u8 lock_cmd_f0[] = { 0xF0, 0xA5, 0xA5 };
static const u8 freq_update[] = { 0xF7, 0x0F };
static const u8 lhbm_brightness_index[] = { 0xB0, 0x03, 0x21, 0x95 };
static const u8 lhbm_brightness_reg = 0x95;
+static const u8 pixel_off[] = { 0x22 };
+static const u8 sync_begin[] = { 0xE4, 0x00, 0x2C, 0x2C, 0xA2, 0x00, 0x00 };
+static const u8 sync_end[] = { 0xE4, 0x00, 0x2C, 0x2C, 0x82, 0x00, 0x00 };
static const u8 aod_on[] = { MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24 };
static const u8 aod_off[] = { MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20 };
static const u8 min_dbv[] = { MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0x00, 0x04 };
@@ -319,7 +327,7 @@ static const struct exynos_dsi_cmd hk3_lp_high_cmds[] = {
EXYNOS_DSI_CMD0(unlock_cmd_f0),
/* AOD High Mode, 50nit */
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x52, 0x94),
- EXYNOS_DSI_CMD_SEQ(0x94, 0x00),
+ EXYNOS_DSI_CMD_SEQ(0x94, 0x00, 0x07, 0x6A, 0x02),
EXYNOS_DSI_CMD0(lock_cmd_f0),
EXYNOS_DSI_CMD0(min_dbv),
};
@@ -543,20 +551,6 @@ static void hk3_update_panel_feat(struct exynos_panel *ctx,
EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
- /* TE width setting */
- if (test_bit(FEAT_OP_NS, changed_feat)) {
- EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x04, 0xB9);
- if (test_bit(FEAT_OP_NS, spanel->feat))
- /* Changeable TE setting */
- EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xC9, 0x0B, 0xE8,
- /* Fixed TE setting */
- 0x0B, 0xC9, 0x0B, 0xE8, 0x0B, 0xC9, 0x0B, 0xE8);
- else
- /* Changeable TE setting */
- EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xBB, 0x00, 0x2F,
- /* Fixed TE setting */
- 0x0B, 0xBB, 0x00, 0x2F, 0x0B, 0xBB, 0x00, 0x2F);
- }
/* TE setting */
if (test_bit(FEAT_EARLY_EXIT, changed_feat) ||
test_bit(FEAT_OP_NS, changed_feat)) {
@@ -587,22 +581,22 @@ static void hk3_update_panel_feat(struct exynos_panel *ctx,
if (test_bit(FEAT_IRC_Z_MODE, changed_feat)) {
EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x02, 0x00, 0x92);
if (test_bit(FEAT_IRC_Z_MODE, spanel->feat)) {
- if (spanel->material == MATERIAL_E6)
+ if (spanel->material == MATERIAL_E6) {
EXYNOS_DCS_BUF_ADD(ctx, 0x92, 0xBE, 0x98);
- else
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x02, 0xF3, 0x68);
+ EXYNOS_DCS_BUF_ADD(ctx, 0x68, 0x97, 0x87, 0x87, 0xFB, 0xFD, 0xF1);
+ } else {
EXYNOS_DCS_BUF_ADD(ctx, 0x92, 0xF1, 0xC1);
- EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x02, 0xF3, 0x68);
- if (ctx->panel_rev >= PANEL_REV_DVT1)
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x02, 0xF3, 0x68);
EXYNOS_DCS_BUF_ADD(ctx, 0x68, 0x82, 0x70, 0x23, 0x91, 0x88, 0x3C);
- else
- EXYNOS_DCS_BUF_ADD(ctx, 0x68, 0x97, 0x87, 0x87, 0xFB, 0xFD, 0xF1);
+ }
} else {
EXYNOS_DCS_BUF_ADD(ctx, 0x92, 0x00, 0x00);
EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x02, 0xF3, 0x68);
- if (ctx->panel_rev >= PANEL_REV_DVT1)
- EXYNOS_DCS_BUF_ADD(ctx, 0x68, 0x77, 0x81, 0x23, 0x8C, 0x99, 0x3C);
- else
+ if (spanel->material == MATERIAL_E6)
EXYNOS_DCS_BUF_ADD(ctx, 0x68, 0x71, 0x81, 0x59, 0x90, 0xA2, 0x80);
+ else
+ EXYNOS_DCS_BUF_ADD(ctx, 0x68, 0x77, 0x81, 0x23, 0x8C, 0x99, 0x3C);
}
}
} else {
@@ -1206,12 +1200,30 @@ static int hk3_set_brightness(struct exynos_panel *ctx, u16 br)
if (ctx->current_mode->exynos_mode.is_lp_mode) {
const struct exynos_panel_funcs *funcs;
+ /* don't stay at pixel-off state in AOD, or black screen is possibly seen */
+ if (spanel->is_pixel_off) {
+ EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_ENTER_NORMAL_MODE);
+ spanel->is_pixel_off = false;
+ }
funcs = ctx->desc->exynos_panel_func;
if (funcs && funcs->set_binned_lp)
funcs->set_binned_lp(ctx, br);
return 0;
}
+ /* Use pixel off command instead of setting DBV 0 */
+ if (!br) {
+ if (!spanel->is_pixel_off) {
+ EXYNOS_DCS_WRITE_TABLE(ctx, pixel_off);
+ spanel->is_pixel_off = true;
+ dev_dbg(ctx->dev, "%s: pixel off instead of dbv 0\n", __func__);
+ }
+ return 0;
+ } else if (br && spanel->is_pixel_off) {
+ EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_ENTER_NORMAL_MODE);
+ spanel->is_pixel_off = false;
+ }
+
brightness = (br & 0xff) << 8 | br >> 8;
ret = exynos_dcs_set_brightness(ctx, brightness);
if (!ret) {
@@ -1222,33 +1234,67 @@ static int hk3_set_brightness(struct exynos_panel *ctx, u16 br)
return ret;
}
+static const struct exynos_dsi_cmd hk3_display_on_cmds[] = {
+ EXYNOS_DSI_CMD0(unlock_cmd_f0),
+ EXYNOS_DSI_CMD0(sync_begin),
+ /* AMP type change (return) */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x4F, 0xF4),
+ EXYNOS_DSI_CMD_SEQ(0xF4, 0x70),
+ /* Vreg = 7.1V (return) */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x31, 0xF4),
+ EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_GE(PANEL_REV_DVT1), 0xF4, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A),
+ EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_LT(PANEL_REV_DVT1), 0xF4, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B),
+ EXYNOS_DSI_CMD0(sync_end),
+ EXYNOS_DSI_CMD0(lock_cmd_f0),
+
+ EXYNOS_DSI_CMD_SEQ(MIPI_DCS_SET_DISPLAY_ON),
+};
+static DEFINE_EXYNOS_CMD_SET(hk3_display_on);
+
+static const struct exynos_dsi_cmd hk3_display_off_cmds[] = {
+ EXYNOS_DSI_CMD_SEQ(MIPI_DCS_SET_DISPLAY_OFF),
+
+ EXYNOS_DSI_CMD0(unlock_cmd_f0),
+ EXYNOS_DSI_CMD0(sync_begin),
+ /* AMP type change */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x4F, 0xF4),
+ EXYNOS_DSI_CMD_SEQ(0xF4, 0x50),
+ /* Vreg = 4.5 */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x31, 0xF4),
+ EXYNOS_DSI_CMD_SEQ(0xF4, 0x00, 0x00, 0x00, 0x00, 0x00),
+ EXYNOS_DSI_CMD0(sync_end),
+ EXYNOS_DSI_CMD0(lock_cmd_f0),
+};
+static DEFINE_EXYNOS_CMD_SET(hk3_display_off);
+
static unsigned int hk3_get_te_usec(struct exynos_panel *ctx,
const struct exynos_panel_mode *pmode)
{
- const int vrefresh = drm_mode_vrefresh(&pmode->mode);
+ struct hk3_panel *spanel = to_spanel(ctx);
- if (vrefresh != 60) {
+ if (spanel->hw_vrefresh != 60)
return pmode->exynos_mode.te_usec;
- } else {
- struct hk3_panel *spanel = to_spanel(ctx);
-
+ else
return (test_bit(FEAT_OP_NS, spanel->feat) ? HK3_TE_USEC_60HZ_NS :
HK3_TE_USEC_60HZ_HS);
- }
}
-static void hk3_wait_for_vsync_done(struct exynos_panel *ctx,
- const struct exynos_panel_mode *pmode)
+static void hk3_wait_for_vsync_done(struct exynos_panel *ctx)
{
struct hk3_panel *spanel = to_spanel(ctx);
+ const struct exynos_panel_mode *pmode = ctx->current_mode;
+
+ dev_dbg(ctx->dev, "%s: %dhz\n", __func__, spanel->hw_vrefresh);
DPU_ATRACE_BEGIN(__func__);
exynos_panel_wait_for_vsync_done(ctx, hk3_get_te_usec(ctx, pmode),
EXYNOS_VREFRESH_TO_PERIOD_USEC(spanel->hw_vrefresh));
+ /* add 1ms tolerance */
+ exynos_panel_msleep(1);
DPU_ATRACE_END(__func__);
}
-static void hk3_disable_idle(struct exynos_panel *ctx, bool is_aod)
+static void hk3_disable_idle_for_normal_mode(struct exynos_panel *ctx)
{
struct hk3_panel *spanel = to_spanel(ctx);
@@ -1259,16 +1305,42 @@ static void hk3_disable_idle(struct exynos_panel *ctx, bool is_aod)
EXYNOS_DCS_BUF_ADD(ctx, 0xBD, 0x21);
/* Changeable TE is a must to ensure command sync */
EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x04);
- if (is_aod) {
- /* 30 Hz */
- EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x01, 0x60);
+ /* Changeable TE width setting */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x04, 0xB9);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xBB, 0x00, 0x2F);
+ /* HS 120Hz */
+ EXYNOS_DCS_BUF_ADD(ctx, 0x60, 0x00);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, freq_update);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
+
+ spanel->hw_idle_vrefresh = 0;
+}
+
+static void hk3_disable_idle_for_aod_mode(struct exynos_panel *ctx, bool is_aod_in)
+{
+ struct hk3_panel *spanel = to_spanel(ctx);
+
+ dev_dbg(ctx->dev, "%s\n", __func__);
+
+ EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
+ /* manual mode */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xBD, 0x21);
+ /* Changeable TE is a must to ensure command sync */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x04);
+ /* Changeable TE width setting and frequency */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x04, 0xB9);
+ if (is_aod_in) {
+ /* width 273us in normal mode */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xBB, 0x00, 0x2F);
+ /* HS 120Hz */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xF2, 0x01);
EXYNOS_DCS_BUF_ADD(ctx, 0x60, 0x00);
} else {
- /* only set 60 or 120 Hz */
- if (test_bit(FEAT_OP_NS, spanel->feat))
- EXYNOS_DCS_BUF_ADD(ctx, 0x60, 0x18);
- else
- EXYNOS_DCS_BUF_ADD(ctx, 0x60, spanel->hw_vrefresh == 60 ? 0x01 : 0x00);
+ /* width 693us in AOD mode */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xE0, 0x00, 0x2F);
+ /* AOD 30Hz */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x01, 0x60);
+ EXYNOS_DCS_BUF_ADD(ctx, 0x60, 0x00);
}
EXYNOS_DCS_BUF_ADD_SET(ctx, freq_update);
EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
@@ -1279,20 +1351,32 @@ static void hk3_disable_idle(struct exynos_panel *ctx, bool is_aod)
static void hk3_set_lp_mode(struct exynos_panel *ctx, const struct exynos_panel_mode *pmode)
{
struct hk3_panel *spanel = to_spanel(ctx);
+ const u16 brightness = exynos_panel_get_brightness(ctx);
dev_dbg(ctx->dev, "%s\n", __func__);
DPU_ATRACE_BEGIN(__func__);
- EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_SET_DISPLAY_OFF);
- hk3_wait_for_vsync_done(ctx, pmode);
- EXYNOS_DCS_BUF_ADD_SET(ctx, aod_on);
+ /* disabling idle is a must before entering AOD */
+ hk3_disable_idle_for_aod_mode(ctx, true);
+ hk3_wait_for_vsync_done(ctx);
+ /* HS 120Hz should be effective here */
+ spanel->hw_vrefresh = 120;
+ exynos_panel_send_cmd_set(ctx, &hk3_display_off_cmd_set);
+
+ hk3_wait_for_vsync_done(ctx);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, aod_on);
+
+ exynos_panel_set_binned_lp(ctx, brightness);
EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
- /* AOD Low Mode, 10nit */
- EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x52, 0x94);
- EXYNOS_DCS_BUF_ADD(ctx, 0x94, 0x01, 0x07, 0x6A, 0x02);
/* Fixed TE: sync on */
EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x51);
+ /* Default TE pulse width 693us */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x08, 0xB9);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xE0, 0x00, 0x2F, 0x0B, 0xE0, 0x00, 0x2F);
+ /* Frequency set for AOD */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x02, 0xB9);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x00);
/* Auto frame insertion: 1Hz */
EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x18, 0xBD);
EXYNOS_DCS_BUF_ADD(ctx, 0xBD, 0x04, 0x00, 0x74);
@@ -1310,7 +1394,7 @@ static void hk3_set_lp_mode(struct exynos_panel *ctx, const struct exynos_panel_
EXYNOS_DCS_BUF_ADD(ctx, 0xBD, 0x22, 0x22, 0x22, 0x22);
EXYNOS_DCS_BUF_ADD_SET(ctx, freq_update);
EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
- EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_SET_DISPLAY_ON);
+ exynos_panel_send_cmd_set(ctx, &hk3_display_on_cmd_set);
spanel->hw_vrefresh = 30;
@@ -1327,23 +1411,26 @@ static void hk3_set_nolp_mode(struct exynos_panel *ctx,
DPU_ATRACE_BEGIN(__func__);
/* disabling idle is a must before exiting AOD */
- hk3_disable_idle(ctx, true);
- hk3_wait_for_vsync_done(ctx, pmode);
- EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_SET_DISPLAY_OFF);
+ hk3_disable_idle_for_aod_mode(ctx, false);
+ hk3_wait_for_vsync_done(ctx);
+ exynos_panel_send_cmd_set(ctx, &hk3_display_off_cmd_set);
+ hk3_wait_for_vsync_done(ctx);
EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
+ /* TE width setting */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x04, 0xB9);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB9, 0x0B, 0xBB, 0x00, 0x2F, /* changeable TE */
+ 0x0B, 0xBB, 0x00, 0x2F, 0x0B, 0xBB, 0x00, 0x2F); /* fixed TE */
/* disabling AOD low Mode is a must before aod-off */
EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x52, 0x94);
EXYNOS_DCS_BUF_ADD(ctx, 0x94, 0x00);
EXYNOS_DCS_BUF_ADD_SET(ctx, lock_cmd_f0);
EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, aod_off);
-
- hk3_wait_for_vsync_done(ctx, pmode);
hk3_update_panel_feat(ctx, pmode, true);
/* backlight control and dimming */
hk3_write_display_mode(ctx, &pmode->mode);
hk3_change_frequency(ctx, pmode);
- EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_SET_DISPLAY_ON);
+ exynos_panel_send_cmd_set(ctx, &hk3_display_on_cmd_set);
DPU_ATRACE_END(__func__);
@@ -1351,6 +1438,16 @@ static void hk3_set_nolp_mode(struct exynos_panel *ctx,
}
static const struct exynos_dsi_cmd hk3_init_cmds[] = {
+ EXYNOS_DSI_CMD_SEQ_DELAY(10, MIPI_DCS_EXIT_SLEEP_MODE),
+
+ EXYNOS_DSI_CMD0(unlock_cmd_f0),
+ /* AMP type change */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x4F, 0xF4),
+ EXYNOS_DSI_CMD_SEQ(0xF4, 0x50),
+ /* VREG 4.5V */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x31, 0xF4),
+ EXYNOS_DSI_CMD_SEQ(0xF4, 0x00, 0x00, 0x00, 0x00, 0x00),
+ EXYNOS_DSI_CMD(lock_cmd_f0, 110),
/* Enable TE*/
EXYNOS_DSI_CMD_SEQ(MIPI_DCS_SET_TEAR_ON),
@@ -1358,9 +1455,6 @@ static const struct exynos_dsi_cmd hk3_init_cmds[] = {
/* AOD Transition Set */
EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_LT(PANEL_REV_DVT1), 0xB0, 0x00, 0x03, 0xBB),
EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_LT(PANEL_REV_DVT1), 0xBB, 0x41),
- /* AOD SAP settings */
- EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x04, 0xF6),
- EXYNOS_DSI_CMD_SEQ(0xF6, 0x5A),
/* TSP SYNC Enable (Auto Set) */
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x3C, 0xB9),
@@ -1374,6 +1468,11 @@ static const struct exynos_dsi_cmd hk3_init_cmds[] = {
0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
0x40, 0x00, 0x40, 0x00),
+ /* TE width setting */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x04, 0xB9),
+ EXYNOS_DSI_CMD_SEQ(0xB9, 0x0B, 0xBB, 0x00, 0x2F, /* changeable TE */
+ 0x0B, 0xBB, 0x00, 0x2F, 0x0B, 0xBB, 0x00, 0x2F), /* fixed TE */
+
/* enable OPEC (auto still IMG detect off) */
EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_LT(PANEL_REV_MP), 0xB0, 0x00, 0x1D, 0x63),
EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_LT(PANEL_REV_MP), 0x63, 0x02, 0x18),
@@ -1464,10 +1563,11 @@ static int hk3_enable(struct drm_panel *panel)
EXYNOS_PPS_WRITE_BUF(ctx, &pps_payload);
if (needs_reset) {
- EXYNOS_DCS_WRITE_SEQ_DELAY(ctx, 120, MIPI_DCS_EXIT_SLEEP_MODE);
exynos_panel_send_cmd_set(ctx, &hk3_init_cmd_set);
if (ctx->panel_rev == PANEL_REV_PROTO1)
hk3_lhbm_luminance_opr_setting(ctx);
+
+ spanel->is_pixel_off = false;
}
EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
@@ -1484,10 +1584,12 @@ static int hk3_enable(struct drm_panel *panel)
if (needs_reset && spanel->material == MATERIAL_E7_DOE)
exynos_panel_send_cmd_set(ctx, &hk3_ns_gamma_fix_cmd_set);
- if (pmode->exynos_mode.is_lp_mode)
+ if (pmode->exynos_mode.is_lp_mode) {
hk3_set_lp_mode(ctx, pmode);
- else if (needs_reset || (ctx->panel_state == PANEL_STATE_BLANK))
- EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_SET_DISPLAY_ON);
+ } else if (needs_reset || (ctx->panel_state == PANEL_STATE_BLANK)) {
+ hk3_wait_for_vsync_done(ctx);
+ exynos_panel_send_cmd_set(ctx, &hk3_display_on_cmd_set);
+ }
spanel->lhbm_ctl.hist_roi_configured = false;
@@ -1500,7 +1602,9 @@ static int hk3_disable(struct drm_panel *panel)
{
struct exynos_panel *ctx = container_of(panel, struct exynos_panel, panel);
struct hk3_panel *spanel = to_spanel(ctx);
- int ret;
+ int ret, delay_us;
+
+ dev_info(ctx->dev, "%s\n", __func__);
/* skip disable sequence if going through modeset */
if (ctx->panel_state == PANEL_STATE_MODESET) {
@@ -1513,6 +1617,14 @@ static int hk3_disable(struct drm_panel *panel)
if (ret)
return ret;
+ hk3_disable_idle_for_normal_mode(ctx);
+ delay_us = EXYNOS_VREFRESH_TO_PERIOD_USEC(spanel->hw_vrefresh) + 1000;
+ exynos_panel_msleep(delay_us / 1000);
+ exynos_panel_send_cmd_set(ctx, &hk3_display_off_cmd_set);
+ exynos_panel_msleep(20);
+ if (ctx->panel_state == PANEL_STATE_OFF)
+ EXYNOS_DCS_WRITE_SEQ_DELAY(ctx, 100, MIPI_DCS_ENTER_SLEEP_MODE);
+
/* panel register state gets reset after disabling hardware */
bitmap_clear(spanel->hw_feat, 0, FEAT_MAX);
spanel->hw_vrefresh = 60;
@@ -1521,11 +1633,6 @@ static int hk3_disable(struct drm_panel *panel)
spanel->hw_za_enabled = false;
spanel->hw_dbv = 0;
- EXYNOS_DCS_WRITE_SEQ_DELAY(ctx, 20, MIPI_DCS_SET_DISPLAY_OFF);
-
- if (ctx->panel_state == PANEL_STATE_OFF)
- EXYNOS_DCS_WRITE_SEQ_DELAY(ctx, 100, MIPI_DCS_ENTER_SLEEP_MODE);
-
return 0;
}
@@ -2035,7 +2142,7 @@ static const struct exynos_panel_mode hk3_modes[] = {
.exynos_mode = {
.mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS,
.vblank_usec = 120,
- .te_usec = 276,
+ .te_usec = 273,
.bpc = 8,
.dsc = HK3_WQHD_DSC,
.underrun_param = &underrun_param,
@@ -2095,7 +2202,7 @@ static const struct exynos_panel_mode hk3_modes[] = {
.exynos_mode = {
.mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS,
.vblank_usec = 120,
- .te_usec = 276,
+ .te_usec = 273,
.bpc = 8,
.dsc = HK3_FHD_DSC,
.underrun_param = &underrun_param,
@@ -2285,16 +2392,13 @@ static void hk3_panel_init(struct exynos_panel *ctx)
#endif
hk3_lhbm_brightness_init(ctx);
- EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
if (ctx->panel_rev < PANEL_REV_DVT1) {
/* AOD Transition Set */
+ EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x03, 0xBB);
EXYNOS_DCS_BUF_ADD(ctx, 0xBB, 0x41);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
}
- /* AOD SAP settings */
- EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x04, 0xF6);
- EXYNOS_DCS_BUF_ADD(ctx, 0xF6, 0x5A);
- EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
spanel->tz = thermal_zone_get_zone_by_name("disp_therm");
if (IS_ERR_OR_NULL(spanel->tz))
@@ -2318,6 +2422,7 @@ static int hk3_panel_probe(struct mipi_dsi_device *dsi)
/* ddic default temp */
spanel->hw_temp = 25;
spanel->pending_temp_update = false;
+ spanel->is_pixel_off = false;
return exynos_panel_common_init(dsi, &spanel->base);
}