diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index b2007450ea..4dc51b6773 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2987,7 +2987,10 @@ static int dsi_display_clocks_init(struct dsi_display *display) goto error; } - if (dyn_clk_caps->dyn_clk_support) { + if (dyn_clk_caps->dyn_clk_support && + (display->panel->panel_mode == + DSI_OP_VIDEO_MODE)) { + if (dsi_display_check_prefix(src_byte, clk_name)) src->byte_clk = NULL; @@ -4016,7 +4019,7 @@ exit: return rc; } -static int dsi_display_dynamic_clk_switch(struct dsi_display *display, +static int dsi_display_dynamic_clk_switch_vid(struct dsi_display *display, struct dsi_display_mode *mode) { int rc = 0, mask, i; @@ -4085,6 +4088,39 @@ exit: return rc; } +static int dsi_display_dynamic_clk_configure_cmd(struct dsi_display *display, + int clk_rate) +{ + int rc = 0; + + if (clk_rate <= 0) { + pr_err("%s: bitrate should be greater than 0\n", __func__); + return -EINVAL; + } + + if (clk_rate == display->cached_clk_rate) { + pr_info("%s: ignore duplicated DSI clk setting\n", __func__); + return rc; + } + + display->cached_clk_rate = clk_rate; + + rc = dsi_display_update_dsi_bitrate(display, clk_rate); + if (!rc) { + pr_info("%s: bit clk is ready to be configured to '%d'\n", + __func__, clk_rate); + atomic_set(&display->clkrate_change_pending, 1); + } else { + pr_err("%s: Failed to prepare to configure '%d'. rc = %d\n", + __func__, clk_rate, rc); + /* Caching clock failed, so don't go on doing so. */ + atomic_set(&display->clkrate_change_pending, 0); + display->cached_clk_rate = 0; + } + + return rc; +} + static int dsi_display_dfps_update(struct dsi_display *display, struct dsi_display_mode *dsi_mode) { @@ -4318,7 +4354,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, struct dsi_display_mode *mode, u32 flags) { - int rc = 0; + int rc = 0, clk_rate = 0; int i; struct dsi_display_ctrl *ctrl; struct dsi_display_mode_priv_info *priv_info; @@ -4355,15 +4391,25 @@ static int dsi_display_set_mode_sub(struct dsi_display *display, goto error; } } else if (mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK) { - rc = dsi_display_dynamic_clk_switch(display, mode); - if (rc) - pr_err("dynamic clk change failed %d\n", rc); - /* - * skip rest of the opearations since - * dsi_display_dynamic_clk_switch() already takes - * care of them. - */ - return rc; + if (display->panel->panel_mode == DSI_OP_VIDEO_MODE) { + rc = dsi_display_dynamic_clk_switch_vid(display, mode); + if (rc) + pr_err("dynamic clk change failed %d\n", rc); + /* + * skip rest of the opearations since + * dsi_display_dynamic_clk_switch_vid() already takes + * care of them. + */ + return rc; + } else if (display->panel->panel_mode == DSI_OP_CMD_MODE) { + clk_rate = mode->timing.clk_rate_hz; + rc = dsi_display_dynamic_clk_configure_cmd(display, + clk_rate); + if (rc) { + pr_err("Failed to configure dynamic clk\n"); + return rc; + } + } } display_for_each_ctrl(i, display) { diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index decf9aa658..3dafde7603 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -231,7 +231,8 @@ static void dsi_bridge_enable(struct drm_bridge *bridge) } if (c_bridge->dsi_mode.dsi_mode_flags & - (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR)) { + (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR | + DSI_MODE_FLAG_DYN_CLK)) { pr_debug("[%d] seamless enable\n", c_bridge->id); return; } diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 77ede1015d..7051b5932d 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -3093,12 +3093,9 @@ struct dsi_panel *dsi_panel_get(struct device *parent, pr_err("failed to parse qsync features, rc=%d\n", rc); } - if (panel->panel_mode == DSI_OP_VIDEO_MODE) { - rc = dsi_panel_parse_dyn_clk_caps(panel); - if (rc) - pr_err("failed to parse dynamic clk config, rc=%d\n", - rc); - } + rc = dsi_panel_parse_dyn_clk_caps(panel); + if (rc) + pr_err("failed to parse dynamic clk config, rc=%d\n", rc); rc = dsi_panel_parse_phy_props(panel); if (rc) { @@ -3522,6 +3519,7 @@ int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel, struct dsi_host_config *config) { int rc = 0; + struct dsi_dyn_clk_caps *dyn_clk_caps = &panel->dyn_clk_caps; if (!panel || !mode || !config) { pr_err("invalid params\n"); @@ -3549,7 +3547,11 @@ int dsi_panel_get_host_cfg_for_mode(struct dsi_panel *panel, config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled; config->video_timing.dsc = &mode->priv_info->dsc; - config->bit_clk_rate_hz_override = mode->priv_info->clk_rate_hz; + if (dyn_clk_caps->dyn_clk_support) + config->bit_clk_rate_hz_override = mode->timing.clk_rate_hz; + else + config->bit_clk_rate_hz_override = mode->priv_info->clk_rate_hz; + config->esc_clk_rate_hz = 19200000; mutex_unlock(&panel->panel_lock); return rc; diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index aacf11293a..0a93c5aa9e 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -4057,7 +4057,9 @@ static void sde_crtc_enable(struct drm_crtc *crtc, /* return early if crtc is already enabled, do this after UIDLE check */ if (sde_crtc->enabled) { - if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode)) + if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode) || + msm_is_mode_seamless_dyn_clk(&crtc->state->adjusted_mode)) + SDE_DEBUG("%s extra crtc enable expected during DMS\n", sde_crtc->name); else diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index ec85900706..2db4a6ddd1 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2792,7 +2792,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, sde_encoder_virt_mode_switch(intf_mode, sde_enc, adj_mode); /* release resources before seamless mode change */ - if (msm_is_mode_seamless_dms(adj_mode)) { + if (msm_is_mode_seamless_dms(adj_mode) || + msm_is_mode_seamless_dyn_clk(adj_mode)) { /* restore resource state before releasing them */ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); @@ -2866,7 +2867,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } /* update resources after seamless mode change */ - if (msm_is_mode_seamless_dms(adj_mode)) + if (msm_is_mode_seamless_dms(adj_mode) || + msm_is_mode_seamless_dyn_clk(adj_mode)) sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_POST_MODESET); } @@ -3147,7 +3149,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) } /* register input handler if not already registered */ - if (sde_enc->input_handler && !msm_is_mode_seamless_dms(cur_mode)) { + if (sde_enc->input_handler && !msm_is_mode_seamless_dms(cur_mode) && + !msm_is_mode_seamless_dyn_clk(cur_mode)) { ret = _sde_encoder_input_handler_register( sde_enc->input_handler); if (ret) @@ -3193,7 +3196,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) * already. Invoke restore to reconfigure the * new mode. */ - if (msm_is_mode_seamless_dms(cur_mode) && + if ((msm_is_mode_seamless_dms(cur_mode) || + msm_is_mode_seamless_dyn_clk(cur_mode)) && phys->ops.restore) phys->ops.restore(phys); else if (phys->ops.enable) @@ -3206,7 +3210,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) sde_enc->misr_frame_count); } - if (msm_is_mode_seamless_dms(cur_mode) && + if ((msm_is_mode_seamless_dms(cur_mode) || + msm_is_mode_seamless_dyn_clk(cur_mode)) && sde_enc->cur_master->ops.restore) sde_enc->cur_master->ops.restore(sde_enc->cur_master); else if (sde_enc->cur_master->ops.enable)