diff options
author | PixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com> | 2022-12-19 01:16:03 -0800 |
---|---|---|
committer | SecurityBot <android-nexus-securitybot@system.gserviceaccount.com> | 2022-12-19 01:16:04 -0800 |
commit | dc04241ce93fe1de3fa764f2a8b7f02af9385cbe (patch) | |
tree | 50e55e6b9e9f960b016f033d3525bdff82cd2d98 | |
parent | 880bb6f9e7a2082fac1c01389dde915f282bcca8 (diff) | |
parent | 190bd94c1f25067b73ead73b017b22c3e4161dad (diff) | |
download | display-android-gs-raviole-5.10-u-preview-1.tar.gz |
Merge android13-gs-pixel-5.10-tm-qpr3 into android13-gs-pixel-5.10-udcandroid-u-preview-1_r0.4android-u-preview-1_r0.2android-gs-raviole-5.10-u-preview-1android-gs-pantah-5.10-u-preview-1
SBMerger: 478053055
Change-Id: I9f306796e67a55227d55ca5b9c227734221d425a
Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
-rw-r--r-- | include/trace/panel_trace.h | 76 | ||||
-rw-r--r-- | samsung/cal_9845/dsim_reg.c | 9 | ||||
-rw-r--r-- | samsung/exynos_drm_decon.c | 7 | ||||
-rw-r--r-- | samsung/exynos_drm_dsim.c | 28 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-drv.c | 73 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-drv.h | 3 |
6 files changed, 184 insertions, 12 deletions
diff --git a/include/trace/panel_trace.h b/include/trace/panel_trace.h new file mode 100644 index 0000000..adeb44d --- /dev/null +++ b/include/trace/panel_trace.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Panel command trace support + * + * Copyright (C) 2022 Google, Inc. + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM panel + +#if !defined(_PANEL_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _PANEL_TRACE_H_ + +#include <linux/tracepoint.h> + +TRACE_EVENT_CONDITION(dsi_tx, + TP_PROTO(u8 type, const u8 *tx_buf, size_t length, bool last), + TP_ARGS(type, tx_buf, length, last), + TP_CONDITION(length > 0), + TP_STRUCT__entry( + __field( u8, type ) + __dynamic_array(u8, tx_buf, length ) + __field( bool, last ) + ), + TP_fast_assign( + __entry->type = type; + memcpy(__get_dynamic_array(tx_buf), tx_buf, length); + __entry->last = last; + ), + TP_printk("type=0x%02x length=%u last=%d tx=[%s]", __entry->type, + __get_dynamic_array_len(tx_buf), __entry->last, + __print_hex(__get_dynamic_array(tx_buf), + __get_dynamic_array_len(tx_buf))) +); + +TRACE_EVENT_CONDITION(dsi_rx, + TP_PROTO(u8 cmd, const u8 *rx_buf, size_t length), + TP_ARGS(cmd, rx_buf, length), + TP_CONDITION(length > 0), + TP_STRUCT__entry( + __field( u8, cmd ) + __dynamic_array(u8, rx_buf, length ) + ), + TP_fast_assign( + __entry->cmd = cmd; + memcpy(__get_dynamic_array(rx_buf), rx_buf, length); + ), + TP_printk("cmd=0x%02x length=%u rx=[%s]", __entry->cmd, + __get_dynamic_array_len(rx_buf), + __print_hex(__get_dynamic_array(rx_buf), + __get_dynamic_array_len(rx_buf))) +); + +TRACE_EVENT(dsi_cmd_fifo_status, + TP_PROTO(u8 header, u16 payload), + TP_ARGS(header, payload), + TP_STRUCT__entry( + __field(u8, header ) + __field(u16, payload) + ), + TP_fast_assign( + __entry->header = header; + __entry->payload = payload; + ), + TP_printk("header=%d payload=%d", __entry->header, __entry->payload) +); + +#endif /* _PANEL_TRACE_H_ */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH trace/. + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE panel_trace + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/samsung/cal_9845/dsim_reg.c b/samsung/cal_9845/dsim_reg.c index 8645e0b..d67b6cc 100644 --- a/samsung/cal_9845/dsim_reg.c +++ b/samsung/cal_9845/dsim_reg.c @@ -90,10 +90,6 @@ static struct cal_regs_desc regs_desc[REGS_DSIM_TYPE_MAX][MAX_DSI_CNT]; #define PLL_LOCK_CNT_MARGIN (PLL_LOCK_CNT_MUL * \ PLL_LOCK_CNT_MARGIN_RATIO / 100) -#if !defined(CONFIG_BOARD_EMULATOR) -static DEFINE_MUTEX(dphy_lock); -#endif - static const u32 DSIM_PHY_BIAS_CON_VAL[] = { 0x00000010, 0x00000110, @@ -2088,13 +2084,14 @@ void dsim_reg_init(u32 id, struct dsim_reg_config *config, dsim_reg_enable_word_clock(id, 1); #if !defined(CONFIG_BOARD_EMULATOR) - mutex_lock(&dphy_lock); /* Enable DPHY reset : DPHY reset start */ dpu_sysreg_dphy_reset(id, 0); +#endif + +#if !defined(CONFIG_BOARD_EMULATOR) dsim_reg_set_clocks(id, config, clks, 1); dsim_reg_set_lanes_dphy(id, lanes, true); dpu_sysreg_dphy_reset(id, 1); /* Release DPHY reset */ - mutex_unlock(&dphy_lock); #endif dsim_reg_set_link_clock(id, 1); /* Selection to word clock */ diff --git a/samsung/exynos_drm_decon.c b/samsung/exynos_drm_decon.c index 348de03..f2782fa 100644 --- a/samsung/exynos_drm_decon.c +++ b/samsung/exynos_drm_decon.c @@ -103,14 +103,17 @@ void decon_dump(const struct decon_device *decon) continue; if (d->state != DECON_STATE_ON) { - drm_printf(&p, "%s[%u]: DECON disabled(%d)\n", - decon->dev->driver->name, decon->id, decon->state); + drm_printf(&p, "%s[%u]: DECON state is not On(%d)\n", + d->dev->driver->name, d->id, d->state); continue; } __decon_dump(&p, d->id, &d->regs, d->config.dsc.enabled, d->dqe != NULL); } + if (decon->state != DECON_STATE_ON) + return; + for (i = 0; i < decon->dpp_cnt; ++i) dpp_dump(&p, decon->dpp[i]); diff --git a/samsung/exynos_drm_dsim.c b/samsung/exynos_drm_dsim.c index 91b9f03..9ff30f3 100644 --- a/samsung/exynos_drm_dsim.c +++ b/samsung/exynos_drm_dsim.c @@ -56,6 +56,8 @@ #include <regs-dsim.h> #include <trace/dpu_trace.h> +#define CREATE_TRACE_POINTS +#include <trace/panel_trace.h> #include "exynos_drm_connector.h" #include "exynos_drm_crtc.h" @@ -64,6 +66,12 @@ struct dsim_device *dsim_drvdata[MAX_DSI_CNT]; +/* + * This global mutex lock protects to initialize or de-initialize DSIM and DPHY + * hardware when multi display is in operation + */ +DEFINE_MUTEX(g_dsim_lock); + #define PANEL_DRV_LEN 64 #define RETRY_READ_FIFO_MAX 10 @@ -238,8 +246,10 @@ static void _dsim_exit_ulps_locked(struct dsim_device *dsim) dsim_phy_power_on(dsim); + mutex_lock(&g_dsim_lock); dsim_reg_init(dsim->id, &dsim->config, &dsim->clk_param, false); dsim_reg_exit_ulps_and_start(dsim->id, 0, 0x1F); + mutex_unlock(&g_dsim_lock); dsim->state = DSIM_STATE_HSCLKEN; enable_irq(dsim->irq); @@ -291,10 +301,12 @@ static void _dsim_enable(struct dsim_device *dsim) dsim_info(dsim, "dsim handover. skip_init=%d\n", skip_init); } + mutex_lock(&g_dsim_lock); if (!skip_init) dsim_reg_init(dsim->id, &dsim->config, &dsim->clk_param, true); dsim_reg_start(dsim->id); + mutex_unlock(&g_dsim_lock); /* TODO: dsi start: enable irq, sfr configuration */ dsim->state = DSIM_STATE_HSCLKEN; @@ -377,7 +389,9 @@ static void _dsim_enter_ulps_locked(struct dsim_device *dsim) mutex_unlock(&dsim->cmd_lock); disable_irq(dsim->irq); + mutex_lock(&g_dsim_lock); dsim_reg_stop_and_enter_ulps(dsim->id, 0, 0x1F); + mutex_unlock(&g_dsim_lock); dsim_phy_power_off(dsim); @@ -415,8 +429,10 @@ static void _dsim_disable(struct dsim_device *dsim) /* Wait for current read & write CMDs. */ mutex_lock(&dsim->cmd_lock); + mutex_lock(&g_dsim_lock); /* TODO: 0x1F will be changed */ dsim_reg_stop(dsim->id, 0x1F); + mutex_unlock(&g_dsim_lock); disable_irq(dsim->irq); dsim->state = DSIM_STATE_SUSPEND; @@ -805,11 +821,15 @@ getnode_fail: static void dsim_restart(struct dsim_device *dsim) { mutex_lock(&dsim->cmd_lock); + mutex_lock(&g_dsim_lock); dsim_reg_stop(dsim->id, 0x1F); + mutex_unlock(&g_dsim_lock); disable_irq(dsim->irq); + mutex_lock(&g_dsim_lock); dsim_reg_init(dsim->id, &dsim->config, &dsim->clk_param, true); dsim_reg_start(dsim->id); + mutex_unlock(&g_dsim_lock); enable_irq(dsim->irq); mutex_unlock(&dsim->cmd_lock); } @@ -2033,6 +2053,7 @@ dsim_write_data(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) is_last = true; } + trace_dsi_tx(msg->type, msg->tx_buf, msg->tx_len, is_last); dsim_debug(dsim, "%s last command\n", is_last ? "" : "Not"); if (is_last) { @@ -2073,6 +2094,7 @@ dsim_write_data(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) } err: + trace_dsi_cmd_fifo_status(dsim->total_pend_ph, dsim->total_pend_pl); DPU_ATRACE_END(__func__); return ret; } @@ -2081,16 +2103,18 @@ static int dsim_req_read_command(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) { struct mipi_dsi_packet packet; + const u8 rx_len = msg->rx_len & 0xff; dsim_reg_clear_int(dsim->id, DSIM_INTSRC_SFR_PH_FIFO_EMPTY); reinit_completion(&dsim->ph_wr_comp); - + trace_dsi_tx(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, &rx_len, 1, true); /* set the maximum packet size returned */ dsim_reg_wr_tx_header(dsim->id, MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, msg->rx_len, 0, false); /* read request */ mipi_dsi_create_packet(&packet, msg); + trace_dsi_tx(msg->type, msg->tx_buf, msg->tx_len, true); dsim_reg_wr_tx_header(dsim->id, packet.header[0], packet.header[1], packet.header[2], true); @@ -2103,6 +2127,7 @@ dsim_read_data(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) u32 rx_fifo, rx_size = 0; int i = 0, ret = 0; u8 *rx_buf = msg->rx_buf; + const u8 *tx_buf = msg->tx_buf; if (msg->rx_len > MAX_RX_FIFO) { dsim_err(dsim, "invalid rx len(%lu) max(%d)\n", msg->rx_len, @@ -2187,6 +2212,7 @@ dsim_read_data(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) } while (!dsim_reg_rx_fifo_is_empty(dsim->id) && --retry_cnt); } + trace_dsi_rx(tx_buf[0], rx_buf, rx_size); return rx_size; } diff --git a/samsung/panel/panel-samsung-drv.c b/samsung/panel/panel-samsung-drv.c index 7bf0767..80eb6f2 100644 --- a/samsung/panel/panel-samsung-drv.c +++ b/samsung/panel/panel-samsung-drv.c @@ -3360,6 +3360,59 @@ static u64 exynos_panel_vsync_start_time_us(u32 te_us, u32 te_period_us) return te_period_us * 55 / 100; } +/* avoid accumulate te varaince cause predicted value is not accurate enough */ +#define ACCEPTABLE_TE_PERIOD_DETLA_NS (3 * NSEC_PER_SEC) +static ktime_t exynos_panel_te_ts_prediction(struct exynos_panel *ctx, ktime_t last_te, + s64 since_last_te_us, u32 te_period_us) +{ + const struct exynos_panel_desc *desc = ctx->desc; + s64 rr_switch_delta_us; + u32 te_period_before_rr_switch_us; + u32 rr_switch_applied_duration; + s64 te_period_delta_ns; + + if (!desc || last_te == 0) + return 0; + + rr_switch_delta_us = ktime_us_delta(last_te, ctx->last_rr_switch_ts); + te_period_before_rr_switch_us = ctx->last_rr != 0 ? USEC_PER_SEC / ctx->last_rr : 0; + + if (ctx->last_rr_switch_ts == ctx->last_lp_exit_ts) { + /* new refresh rate should take effect at first vsync after exiting AOD mode */ + rr_switch_applied_duration = 0; + } else { + /* If vrr_switch_duration is not set that mean we don't know the new refresh rate + * take effect timing. It may take effect at first or second vsync after sending + * rr switch commands. + */ + rr_switch_applied_duration = desc->vrr_switch_duration != 0 ? + (desc->vrr_switch_duration - 1) : 1; + } + + if (rr_switch_delta_us < 0 && te_period_before_rr_switch_us != 0) { + ktime_t first_te_after_rr_switch; + + te_period_delta_ns = ((-rr_switch_delta_us / te_period_before_rr_switch_us) + 1) * + te_period_before_rr_switch_us * NSEC_PER_USEC; + + if (te_period_delta_ns < ACCEPTABLE_TE_PERIOD_DETLA_NS) { + first_te_after_rr_switch = last_te + te_period_delta_ns; + rr_switch_delta_us = + ktime_us_delta(first_te_after_rr_switch, ctx->last_rr_switch_ts); + } + } + + if (rr_switch_delta_us > (rr_switch_applied_duration * te_period_before_rr_switch_us)) { + te_period_delta_ns = + (since_last_te_us / te_period_us) * te_period_us * NSEC_PER_USEC; + + if (te_period_delta_ns < ACCEPTABLE_TE_PERIOD_DETLA_NS) + return (last_te + te_period_delta_ns); + } + + return 0; +} + static void exynos_panel_check_mipi_sync_timing(struct drm_crtc *crtc, const struct exynos_panel_mode *current_mode, struct exynos_panel *ctx) @@ -3368,6 +3421,7 @@ static void exynos_panel_check_mipi_sync_timing(struct drm_crtc *crtc, int retry; u64 left, right; bool vblank_taken = false; + bool rr_applied = false; if (WARN_ON(!current_mode)) return; @@ -3402,7 +3456,7 @@ static void exynos_panel_check_mipi_sync_timing(struct drm_crtc *crtc, retry = te_period_us / USEC_PER_MSEC + 1; do { - ktime_t last_te = 0, now; + ktime_t last_te = 0, now, predicted_te; s64 since_last_te_us; s64 rr_switch_delta_us; s64 te_period_before_rr_switch_us; @@ -3411,7 +3465,15 @@ static void exynos_panel_check_mipi_sync_timing(struct drm_crtc *crtc, now = ktime_get(); since_last_te_us = ktime_us_delta(now, last_te); /* Need a vblank as a reference point */ - if (since_last_te_us > te_period_us) { + predicted_te = + exynos_panel_te_ts_prediction(ctx, last_te, since_last_te_us, te_period_us); + if (predicted_te) { + DPU_ATRACE_BEGIN("predicted_te"); + last_te = predicted_te; + since_last_te_us = ktime_us_delta(now, last_te); + rr_applied = true; + DPU_ATRACE_END("predicted_te"); + } else if (since_last_te_us > te_period_us) { DPU_ATRACE_BEGIN("time_window_wait_crtc"); if (vblank_taken || !drm_crtc_vblank_get(crtc)) { drm_crtc_wait_one_vblank(crtc); @@ -3430,7 +3492,8 @@ static void exynos_panel_check_mipi_sync_timing(struct drm_crtc *crtc, */ rr_switch_delta_us = ktime_us_delta(last_te, ctx->last_rr_switch_ts); te_period_before_rr_switch_us = ctx->last_rr != 0 ? USEC_PER_SEC / ctx->last_rr : 0; - if (rr_switch_delta_us > 0 && rr_switch_delta_us < te_period_before_rr_switch_us) { + if (rr_switch_delta_us > 0 && rr_switch_delta_us < te_period_before_rr_switch_us && + !rr_applied) { DPU_ATRACE_BEGIN("time_window_wait_crtc2"); if (vblank_taken || !drm_crtc_vblank_get(crtc)) { drm_crtc_wait_one_vblank(crtc); @@ -3549,6 +3612,7 @@ static void exynos_panel_bridge_mode_set(struct drm_bridge *bridge, const struct exynos_panel_funcs *funcs = ctx->desc->exynos_panel_func; const struct exynos_panel_mode *old_mode; bool need_update_backlight = false; + bool come_out_lp_mode = false; if (WARN_ON(!pmode)) return; @@ -3599,6 +3663,7 @@ static void exynos_panel_bridge_mode_set(struct drm_bridge *bridge, ctx->panel_state = PANEL_STATE_NORMAL; need_update_backlight = true; state_changed = true; + come_out_lp_mode = true; } ctx->current_binned_lp = NULL; } else if (funcs->mode_set) { @@ -3641,6 +3706,8 @@ static void exynos_panel_bridge_mode_set(struct drm_bridge *bridge, if (old_mode && drm_mode_vrefresh(&pmode->mode) != drm_mode_vrefresh(&old_mode->mode)) { ctx->last_rr_switch_ts = ktime_get(); ctx->last_rr = drm_mode_vrefresh(&old_mode->mode); + if (come_out_lp_mode) + ctx->last_lp_exit_ts = ctx->last_rr_switch_ts; } mutex_unlock(&ctx->mode_lock); diff --git a/samsung/panel/panel-samsung-drv.h b/samsung/panel/panel-samsung-drv.h index 1f23297..f42d586 100644 --- a/samsung/panel/panel-samsung-drv.h +++ b/samsung/panel/panel-samsung-drv.h @@ -484,6 +484,7 @@ struct exynos_panel_desc { bool is_partial; bool is_panel_idle_supported; bool no_lhbm_rr_constraints; + bool mipi_sync_te_prediction; const u32 lhbm_effective_delay_frames; const unsigned int delay_dsc_reg_init_us; const struct brightness_capability *brt_capability; @@ -625,6 +626,8 @@ struct exynos_panel { * mean rr switch so it differs from last_mode_set_ts */ ktime_t last_rr_switch_ts; + /* Record the last come out lp mode timestamp */ + ktime_t last_lp_exit_ts; u32 last_rr; struct { |