summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lu <luchris@google.com>2023-08-10 09:22:51 +0000
committerChris Lu <luchris@google.com>2023-08-22 03:55:38 +0000
commit9ebbddea53ead943b7af22b75744c50b33a70fe5 (patch)
tree526679f4cc2626bb4fa61aac69bd06bf68efbd39
parent4ce8f8cf9f099450d808ec3c9bfefaea90613701 (diff)
downloadshusky-9ebbddea53ead943b7af22b75744c50b33a70fe5.tar.gz
panel: hk3 and sb3: support dynamic FFC
Add the functions to send FFC related commands while the DSI clock is changed. Bug: 294337457 Test: capture log and trace for timing suspend and resume, AOD in/out HW measurement Change-Id: Ic8ef80cedab06a2256caa852f8e0d87afa9379f5 Signed-off-by: Chris Lu <luchris@google.com>
-rw-r--r--display/panel-google-bigsurf.c64
-rw-r--r--display/panel-google-hk3.c68
-rw-r--r--display/panel-google-shoreline.c79
3 files changed, 201 insertions, 10 deletions
diff --git a/display/panel-google-bigsurf.c b/display/panel-google-bigsurf.c
index 37a0130..b421dd9 100644
--- a/display/panel-google-bigsurf.c
+++ b/display/panel-google-bigsurf.c
@@ -20,6 +20,9 @@
#define BIGSURF_DDIC_ID_LEN 8
#define BIGSURF_DIMMING_FRAME 32
+#define MIPI_DSI_FREQ_DEFAULT 756
+#define MIPI_DSI_FREQ_ALTERNATIVE 776
+
#define WIDTH_MM 64
#define HEIGHT_MM 143
@@ -174,8 +177,8 @@ static const struct exynos_dsi_cmd bigsurf_init_cmds[] = {
EXYNOS_DSI_CMD_SEQ(0xD8, 0x38),
/* FFC Off */
EXYNOS_DSI_CMD_SEQ(0xC3, 0x00),
- /* FFC setting (MIPI: 756Mbps) and FFC On */
- EXYNOS_DSI_CMD_SEQ(0xC3, 0xDD, 0x06, 0x20, 0x0C, 0xFF, 0x00, 0x06, 0x20,
+ /* FFC setting (MIPI: 756Mbps) */
+ EXYNOS_DSI_CMD_SEQ(0xC3, 0x00, 0x06, 0x20, 0x0C, 0xFF, 0x00, 0x06, 0x20,
0x0C, 0xFF, 0x00, 0x04, 0x63, 0x0C, 0x05, 0xD9,
0x10, 0x04, 0x63, 0x0C, 0x05, 0xD9, 0x10, 0x04,
0x63, 0x0C, 0x05, 0xD9, 0x10, 0x04, 0x63, 0x0C,
@@ -540,6 +543,7 @@ static int bigsurf_enable(struct drm_panel *panel)
EXYNOS_DCS_WRITE_SEQ(ctx, MIPI_DCS_SET_DISPLAY_ON);
spanel->lhbm_ctl.hist_roi_configured = false;
+ ctx->dsi_hs_clk = MIPI_DSI_FREQ_DEFAULT;
return 0;
}
@@ -620,6 +624,59 @@ static int bigsurf_atomic_check(struct exynos_panel *ctx, struct drm_atomic_stat
return 0;
}
+static void bigsurf_pre_update_ffc(struct exynos_panel *ctx)
+{
+ dev_dbg(ctx->dev, "%s\n", __func__);
+
+ DPU_ATRACE_BEGIN(__func__);
+
+ /* FFC off */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01);
+ EXYNOS_DCS_BUF_ADD_AND_FLUSH(ctx, 0xC3, 0x00);
+
+ DPU_ATRACE_END(__func__);
+}
+
+static void bigsurf_update_ffc(struct exynos_panel *ctx, unsigned int hs_clk)
+{
+ dev_dbg(ctx->dev, "%s: hs_clk: current=%d, target=%d\n",
+ __func__, ctx->dsi_hs_clk, hs_clk);
+
+ DPU_ATRACE_BEGIN(__func__);
+
+ if (hs_clk != MIPI_DSI_FREQ_DEFAULT && hs_clk != MIPI_DSI_FREQ_ALTERNATIVE) {
+ dev_warn(ctx->dev, "invalid hs_clk=%d for FFC\n", hs_clk);
+ } else if (ctx->dsi_hs_clk != hs_clk) {
+ dev_info(ctx->dev, "%s: updating for hs_clk=%d\n", __func__, hs_clk);
+ ctx->dsi_hs_clk = hs_clk;
+
+ /* Update FFC */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01);
+ if (hs_clk == MIPI_DSI_FREQ_DEFAULT)
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC3, 0x00, 0x06, 0x20, 0x0C, 0xFF,
+ 0x00, 0x06, 0x20, 0x0C, 0xFF, 0x00,
+ 0x04, 0x63, 0x0C, 0x05, 0xD9, 0x10,
+ 0x04, 0x63, 0x0C, 0x05, 0xD9, 0x10,
+ 0x04, 0x63, 0x0C, 0x05, 0xD9, 0x10,
+ 0x04, 0x63, 0x0C, 0x05, 0xD9, 0x10,
+ 0x04, 0x63, 0x0C, 0x05, 0xD9, 0x10);
+ else /* MIPI_DSI_FREQ_ALTERNATIVE */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC3, 0x00, 0x06, 0x20, 0x0C, 0xFF,
+ 0x00, 0x06, 0x20, 0x0C, 0xFF, 0x00,
+ 0x04, 0x46, 0x0C, 0x06, 0x0D, 0x11,
+ 0x04, 0x46, 0x0C, 0x06, 0x0D, 0x11,
+ 0x04, 0x46, 0x0C, 0x06, 0x0D, 0x11,
+ 0x04, 0x46, 0x0C, 0x06, 0x0D, 0x11,
+ 0x04, 0x46, 0x0C, 0x06, 0x0D, 0x11);
+ }
+
+ /* FFC on */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01);
+ EXYNOS_DCS_BUF_ADD_AND_FLUSH(ctx, 0xC3, 0xDD);
+
+ DPU_ATRACE_END(__func__);
+}
+
static void bigsurf_set_local_hbm_background_brightness(struct exynos_panel *ctx, u16 br)
{
u16 level;
@@ -1069,6 +1126,8 @@ static const struct exynos_panel_funcs bigsurf_exynos_funcs = {
.update_te2 = bigsurf_update_te2,
.read_id = bigsurf_read_id,
.atomic_check = bigsurf_atomic_check,
+ .pre_update_ffc = bigsurf_pre_update_ffc,
+ .update_ffc = bigsurf_update_ffc,
};
static const struct exynos_brightness_configuration bigsurf_btr_configs[] = {
@@ -1195,6 +1254,7 @@ struct exynos_panel_desc google_bigsurf = {
.lhbm_effective_delay_frames = 2,
.lhbm_post_cmd_delay_frames = 3,
.lhbm_on_delay_frames = 2,
+ .default_dsi_hs_clk = MIPI_DSI_FREQ_DEFAULT,
.reset_timing_ms = {1, 1, 20},
.reg_ctrl_enable = {
{PANEL_REG_ID_VDDI, 0},
diff --git a/display/panel-google-hk3.c b/display/panel-google-hk3.c
index 810cca9..0b626cf 100644
--- a/display/panel-google-hk3.c
+++ b/display/panel-google-hk3.c
@@ -132,7 +132,7 @@ struct hk3_panel {
bool force_changeable_te2;
/** @hw_acl_setting: automatic current limiting setting */
u8 hw_acl_setting;
- /** @hw_dbv: indecate the current dbv */
+ /** @hw_dbv: indicate the current dbv */
u16 hw_dbv;
/** @hw_za_enabled: whether zonal attenuation is enabled */
bool hw_za_enabled;
@@ -304,6 +304,9 @@ static const struct drm_dsc_config fhd_pps_config = {
#define HK3_TE_USEC_60HZ_NS 546
#define HK3_TE_PERIOD_DELTA_TOLERANCE_USEC 2000
+#define MIPI_DSI_FREQ_DEFAULT 1368
+#define MIPI_DSI_FREQ_ALTERNATIVE 1346
+
#define PROJECT "HK3"
static const u8 unlock_cmd_f0[] = { 0xF0, 0x5A, 0x5A };
@@ -1529,9 +1532,9 @@ static const struct exynos_dsi_cmd hk3_init_cmds[] = {
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x3C, 0xB9),
EXYNOS_DSI_CMD_SEQ(0xB9, 0x19, 0x09),
- /* FFC: 165MHz, MIPI Speed 1368 Mbps */
+ /* FFC: off, 165MHz, MIPI Speed 1368 Mbps */
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x36, 0xC5),
- EXYNOS_DSI_CMD_SEQ(0xC5, 0x11, 0x10, 0x50, 0x05, 0x4D, 0x31, 0x40, 0x00,
+ EXYNOS_DSI_CMD_SEQ(0xC5, 0x10, 0x10, 0x50, 0x05, 0x4D, 0x31, 0x40, 0x00,
0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
@@ -1657,6 +1660,7 @@ static int hk3_enable(struct drm_panel *panel)
hk3_negative_field_setting(ctx);
spanel->is_pixel_off = false;
+ ctx->dsi_hs_clk = MIPI_DSI_FREQ_DEFAULT;
}
PANEL_SEQ_LABEL_END("init");
@@ -2046,6 +2050,61 @@ static void hk3_normal_mode_work(struct exynos_panel *ctx)
}
}
+static void hk3_pre_update_ffc(struct exynos_panel *ctx)
+{
+ dev_dbg(ctx->dev, "%s\n", __func__);
+
+ DPU_ATRACE_BEGIN(__func__);
+
+ EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
+ /* FFC off */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x36, 0xC5);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x10);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
+
+ DPU_ATRACE_END(__func__);
+}
+
+static void hk3_update_ffc(struct exynos_panel *ctx, unsigned int hs_clk)
+{
+ dev_dbg(ctx->dev, "%s: hs_clk: current=%d, target=%d\n",
+ __func__, ctx->dsi_hs_clk, hs_clk);
+
+ DPU_ATRACE_BEGIN(__func__);
+
+ if (hs_clk != MIPI_DSI_FREQ_DEFAULT && hs_clk != MIPI_DSI_FREQ_ALTERNATIVE) {
+ dev_warn(ctx->dev, "%s: invalid hs_clk=%d for FFC\n", __func__, hs_clk);
+ } else if (ctx->dsi_hs_clk != hs_clk) {
+ dev_info(ctx->dev, "%s: updating for hs_clk=%d\n", __func__, hs_clk);
+ ctx->dsi_hs_clk = hs_clk;
+
+ /* Update FFC */
+ EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x37, 0xC5);
+ if (hs_clk == MIPI_DSI_FREQ_DEFAULT)
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x10, 0x50, 0x05, 0x4D, 0x31, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x4D, 0x31, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00);
+ else /* MIPI_DSI_FREQ_ALTERNATIVE */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x10, 0x50, 0x05, 0x4E, 0x74, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x4E, 0x74, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x4E, 0x74, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x4E, 0x74, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, lock_cmd_f0);
+ }
+
+ /* FFC on */
+ EXYNOS_DCS_BUF_ADD_SET(ctx, unlock_cmd_f0);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x36, 0xC5);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x11);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, lock_cmd_f0);
+
+ DPU_ATRACE_END(__func__);
+}
+
static const struct exynos_display_underrun_param underrun_param = {
.te_idle_us = 350,
.te_var = 1,
@@ -2567,6 +2626,8 @@ static const struct exynos_panel_funcs hk3_exynos_funcs = {
.get_te_usec = hk3_get_te_usec,
.set_acl_mode = hk3_set_acl_mode,
.run_normal_mode_work = hk3_normal_mode_work,
+ .pre_update_ffc = hk3_pre_update_ffc,
+ .update_ffc = hk3_update_ffc,
};
const struct brightness_capability hk3_brightness_capability = {
@@ -2632,6 +2693,7 @@ const struct exynos_panel_desc google_hk3 = {
.lhbm_effective_delay_frames = 1,
.lhbm_post_cmd_delay_frames = 1,
.normal_mode_work_delay_ms = 30000,
+ .default_dsi_hs_clk = MIPI_DSI_FREQ_DEFAULT,
.reset_timing_ms = {1, 1, 5},
.reg_ctrl_enable = {
{PANEL_REG_ID_VDDI, 1},
diff --git a/display/panel-google-shoreline.c b/display/panel-google-shoreline.c
index f5cf754..a93cb55 100644
--- a/display/panel-google-shoreline.c
+++ b/display/panel-google-shoreline.c
@@ -85,6 +85,9 @@ static const struct drm_dsc_config pps_config = {
#define SHORELINE_TE2_RISING_EDGE_120HZ_AOD 0x960
#define SHORELINE_TE2_FALLING_EDGE_120HZ_AOD 0x30
+#define MIPI_DSI_FREQ_DEFAULT 756
+#define MIPI_DSI_FREQ_ALTERNATIVE 776
+
#define WIDTH_MM 64
#define HEIGHT_MM 143
@@ -92,6 +95,8 @@ static const struct drm_dsc_config pps_config = {
static const u8 test_key_on_f0[] = { 0xF0, 0x5A, 0x5A };
static const u8 test_key_off_f0[] = { 0xF0, 0xA5, 0xA5 };
+static const u8 test_key_on_fc[] = { 0xFC, 0x5A, 0x5A };
+static const u8 test_key_off_fc[] = { 0xFC, 0xA5, 0xA5 };
static const u8 sync_begin[] = { 0x72, 0x2C, 0x2C, 0xA1, 0x00, 0x00 };
static const u8 sync_end[] = { 0x72, 0x2C, 0x2C, 0x81, 0x00, 0x00 };
static const u8 freq_update[] = { 0xF7, 0x0F };
@@ -167,15 +172,15 @@ static const struct exynos_dsi_cmd shoreline_init_cmds[] = {
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x09, 0x6D), /* global para */
EXYNOS_DSI_CMD_SEQ(0x6D, 0xC6, 0xE3, 0x65), /* Size and Location */
- /* FFC Settings (OSC: 180 MHz, MIPI: 756 Mbps) */
- EXYNOS_DSI_CMD_SEQ(0xFC, 0x5A, 0x5A), /* Test Key Enable */
+ /* FFC Settings (off, OSC: 180 MHz, MIPI: 756 Mbps) */
+ EXYNOS_DSI_CMD0(test_key_on_fc), /* Test Key Enable */
+ EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x36, 0xC5), /* Global Para */
+ EXYNOS_DSI_CMD_SEQ(0xC5, 0x10), /* FFC OFF */
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x3E, 0xC5), /* Global Para 120HS */
EXYNOS_DSI_CMD_SEQ(0xC5, 0x98, 0x62), /* OSC frequency Setting */
EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x46, 0xC5), /* Global Para 60HS */
EXYNOS_DSI_CMD_SEQ(0xC5, 0x98, 0x62), /* OSC frequency Setting */
- EXYNOS_DSI_CMD_SEQ(0xB0, 0x00, 0x36, 0xC5), /* Global Para */
- EXYNOS_DSI_CMD_SEQ(0xC5, 0x11, 0x10, 0x50, 0x05), /* FFC ON */
- EXYNOS_DSI_CMD_SEQ(0xFC, 0xA5, 0xA5), /* Test Key Disable */
+ EXYNOS_DSI_CMD0(test_key_off_fc), /* Test Key Disable */
/* DBV Voltage Workaround */
EXYNOS_DSI_CMD_SEQ_REV(PANEL_REV_EVT1, 0x60, 0x00, 0x00), /* 120Hz HS */
@@ -491,6 +496,66 @@ static int shoreline_atomic_check(struct exynos_panel *ctx, struct drm_atomic_st
return 0;
}
+static void shoreline_pre_update_ffc(struct exynos_panel *ctx)
+{
+ dev_dbg(ctx->dev, "%s\n", __func__);
+
+ DPU_ATRACE_BEGIN(__func__);
+
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_on_f0);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_on_fc);
+ /* FFC off */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x36, 0xC5);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x10);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_off_fc);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, test_key_off_f0);
+
+ DPU_ATRACE_END(__func__);
+}
+
+static void shoreline_update_ffc(struct exynos_panel *ctx, unsigned int hs_clk)
+{
+ dev_dbg(ctx->dev, "%s: hs_clk: current=%d, target=%d\n",
+ __func__, ctx->dsi_hs_clk, hs_clk);
+
+ DPU_ATRACE_BEGIN(__func__);
+
+ if (hs_clk != MIPI_DSI_FREQ_DEFAULT && hs_clk != MIPI_DSI_FREQ_ALTERNATIVE) {
+ dev_warn(ctx->dev, "%s: invalid hs_clk=%d for FFC\n", __func__, hs_clk);
+ } else if (ctx->dsi_hs_clk != hs_clk) {
+ dev_info(ctx->dev, "%s: updating for hs_clk=%d\n", __func__, hs_clk);
+ ctx->dsi_hs_clk = hs_clk;
+
+ /* Update FFC */
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_on_f0);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_on_fc);
+ /* 120HS */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x3E, 0xC5);
+ if (hs_clk == MIPI_DSI_FREQ_DEFAULT)
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x98, 0x62);
+ else /* MIPI_DSI_FREQ_ALTERNATIVE */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x94, 0x74);
+ /* 60HS */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x46, 0xC5);
+ if (hs_clk == MIPI_DSI_FREQ_DEFAULT)
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x98, 0x62);
+ else /* MIPI_DSI_FREQ_ALTERNATIVE */
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x94, 0x74);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_off_fc);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_off_f0);
+ }
+
+ /* FFC on */
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_on_f0);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_on_fc);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xB0, 0x00, 0x36, 0xC5);
+ EXYNOS_DCS_BUF_ADD(ctx, 0xC5, 0x11, 0x10, 0x50, 0x05);
+ EXYNOS_DCS_BUF_ADD_SET(ctx, test_key_off_fc);
+ EXYNOS_DCS_BUF_ADD_SET_AND_FLUSH(ctx, test_key_off_f0);
+
+ DPU_ATRACE_END(__func__);
+}
+
static void shoreline_update_wrctrld(struct exynos_panel *ctx)
{
u8 val = SHORELINE_WRCTRLD_BCTRL_BIT;
@@ -589,6 +654,7 @@ static int shoreline_enable(struct drm_panel *panel)
shoreline_display_on(ctx);
spanel->lhbm_ctl.hist_roi_configured = false;
+ ctx->dsi_hs_clk = MIPI_DSI_FREQ_DEFAULT;
return 0;
}
@@ -1054,6 +1120,8 @@ static const struct exynos_panel_funcs shoreline_exynos_funcs = {
.update_te2 = shoreline_update_te2,
.read_id = shoreline_read_id,
.atomic_check = shoreline_atomic_check,
+ .pre_update_ffc = shoreline_pre_update_ffc,
+ .update_ffc = shoreline_update_ffc,
};
static const struct exynos_brightness_configuration shoreline_btr_configs[] = {
@@ -1179,6 +1247,7 @@ static struct exynos_panel_desc google_shoreline = {
.exynos_panel_func = &shoreline_exynos_funcs,
.lhbm_effective_delay_frames = 1,
.lhbm_post_cmd_delay_frames = 1,
+ .default_dsi_hs_clk = MIPI_DSI_FREQ_DEFAULT,
.reset_timing_ms = {1, 1, 20},
.reg_ctrl_enable = {
{PANEL_REG_ID_VDDI, 0},