diff options
author | Chris Lu <luchris@google.com> | 2023-08-10 09:22:51 +0000 |
---|---|---|
committer | Chris Lu <luchris@google.com> | 2023-08-22 03:55:38 +0000 |
commit | 9ebbddea53ead943b7af22b75744c50b33a70fe5 (patch) | |
tree | 526679f4cc2626bb4fa61aac69bd06bf68efbd39 | |
parent | 4ce8f8cf9f099450d808ec3c9bfefaea90613701 (diff) | |
download | shusky-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.c | 64 | ||||
-rw-r--r-- | display/panel-google-hk3.c | 68 | ||||
-rw-r--r-- | display/panel-google-shoreline.c | 79 |
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}, |