diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index e6ec6b0a2b..9bedcbd6e9 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -377,6 +377,7 @@ end: int dp_connector_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) { diff --git a/msm/dp/dp_drm.h b/msm/dp/dp_drm.h index 18d09d4227..2890467131 100644 --- a/msm/dp/dp_drm.h +++ b/msm/dp/dp_drm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _DP_DRM_H_ @@ -103,12 +103,14 @@ enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector, * @connector: Pointer to drm connector structure * @drm_mode: Display mode set for the display * @mode_info: Out parameter. Information of the mode + * @sub_mode: Additional mode info to drm display mode * @display: Pointer to private display structure * @avail_res: Pointer with curr available resources * Returns: zero on success */ int dp_connector_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res); @@ -216,6 +218,7 @@ static inline enum drm_mode_status dp_connector_mode_valid( static inline int dp_connector_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) { diff --git a/msm/dp/dp_mst_drm.c b/msm/dp/dp_mst_drm.c index a2efd2797c..abb71b8fb8 100644 --- a/msm/dp/dp_mst_drm.c +++ b/msm/dp/dp_mst_drm.c @@ -1116,6 +1116,7 @@ int dp_mst_connector_get_info(struct drm_connector *connector, int dp_mst_connector_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) @@ -1125,7 +1126,7 @@ int dp_mst_connector_get_mode_info(struct drm_connector *connector, DP_MST_DEBUG("enter:\n"); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY, connector->base.id); - rc = dp_connector_get_mode_info(connector, drm_mode, mode_info, + rc = dp_connector_get_mode_info(connector, drm_mode, NULL, mode_info, display, avail_res); DP_MST_DEBUG("mst connector:%d get mode info. rc:%d\n", diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index e4c87522ed..722689c48f 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -36,10 +36,6 @@ #define SEC_PANEL_NAME_MAX_LEN 256 -#define DSI_MODE_MATCH_ACTIVE_TIMINGS (1 << 0) -#define DSI_MODE_MATCH_PORCH_TIMINGS (1 << 1) -#define DSI_MODE_MATCH_FULL_TIMINGS (DSI_MODE_MATCH_ACTIVE_TIMINGS | DSI_MODE_MATCH_PORCH_TIMINGS) - u8 dbgfs_tx_cmd_buf[SZ_4K]; static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN]; static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN]; @@ -6235,7 +6231,7 @@ static int dsi_display_ext_get_info(struct drm_connector *connector, } static int dsi_display_ext_get_mode_info(struct drm_connector *connector, - const struct drm_display_mode *drm_mode, + const struct drm_display_mode *drm_mode, struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) { @@ -7167,11 +7163,16 @@ static bool dsi_display_mode_match(const struct dsi_display_mode *mode1, !dsi_display_match_timings(mode1, mode2, match_flags)) return false; + if ((match_flags & DSI_MODE_MATCH_DSC_CONFIG) && + mode1->priv_info->dsc_enabled != mode2->priv_info->dsc_enabled) + return false; + return true; } int dsi_display_find_mode(struct dsi_display *display, - const struct dsi_display_mode *cmp, + struct dsi_display_mode *cmp, + struct msm_sub_mode *sub_mode, struct dsi_display_mode **out_mode) { u32 count, i; @@ -7179,6 +7180,7 @@ int dsi_display_find_mode(struct dsi_display *display, struct dsi_display_mode *m; struct dsi_dyn_clk_caps *dyn_clk_caps; unsigned int match_flags = DSI_MODE_MATCH_FULL_TIMINGS; + struct dsi_display_mode_priv_info priv_info; if (!display || !out_mode) return -EINVAL; @@ -7209,6 +7211,15 @@ int dsi_display_find_mode(struct dsi_display *display, if (dyn_clk_caps->maintain_const_fps) match_flags = DSI_MODE_MATCH_ACTIVE_TIMINGS; + if (sub_mode && sub_mode->dsc_mode) { + match_flags |= DSI_MODE_MATCH_DSC_CONFIG; + cmp->priv_info = &priv_info; + memset(cmp->priv_info, 0, + sizeof(struct dsi_display_mode_priv_info)); + cmp->priv_info->dsc_enabled = (sub_mode->dsc_mode == + MSM_DISPLAY_DSC_MODE_ENABLED) ? true : false; + } + if (dsi_display_mode_match(cmp, m, match_flags)) { *out_mode = m; rc = 0; @@ -7286,11 +7297,20 @@ int dsi_display_validate_mode_change(struct dsi_display *display, if (sde_conn->expected_panel_mode == MSM_DISPLAY_VIDEO_MODE && display->config.panel_mode == DSI_OP_CMD_MODE) { adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS_TO_VID; + SDE_EVT32(SDE_EVTLOG_FUNC_CASE1, sde_conn->expected_panel_mode, + display->config.panel_mode); DSI_DEBUG("Panel operating mode change to video detected\n"); } else if (sde_conn->expected_panel_mode == MSM_DISPLAY_CMD_MODE && display->config.panel_mode == DSI_OP_VIDEO_MODE) { adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_POMS_TO_CMD; + SDE_EVT32(SDE_EVTLOG_FUNC_CASE2, sde_conn->expected_panel_mode, + display->config.panel_mode); DSI_DEBUG("Panel operating mode change to command detected\n"); + } else if (cur_mode->timing.dsc_enabled != adj_mode->timing.dsc_enabled) { + adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS; + SDE_EVT32(SDE_EVTLOG_FUNC_CASE3, cur_mode->timing.dsc_enabled, + adj_mode->timing.dsc_enabled); + DSI_DEBUG("DSC mode change detected\n"); } else { dyn_clk_caps = &(display->panel->dyn_clk_caps); /* dfps and dynamic clock with const fps use case */ @@ -7300,7 +7320,7 @@ int dsi_display_validate_mode_change(struct dsi_display *display, dyn_clk_caps->maintain_const_fps) { DSI_DEBUG("Mode switch is seamless variable refresh\n"); adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR; - SDE_EVT32(SDE_EVTLOG_FUNC_CASE1, + SDE_EVT32(SDE_EVTLOG_FUNC_CASE4, cur_mode->timing.refresh_rate, adj_mode->timing.refresh_rate, cur_mode->timing.h_front_porch, @@ -7333,7 +7353,7 @@ int dsi_display_validate_mode_change(struct dsi_display *display, adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_DYN_CLK; - SDE_EVT32(SDE_EVTLOG_FUNC_CASE2, + SDE_EVT32(SDE_EVTLOG_FUNC_CASE5, cur_mode->pixel_clk_khz, adj_mode->pixel_clk_khz); } diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index e5322f1074..27f7f9bd92 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -24,6 +24,12 @@ #define DSI_CLIENT_NAME_SIZE 20 #define MAX_CMDLINE_PARAM_LEN 512 #define MAX_CMD_PAYLOAD_SIZE 256 + +#define DSI_MODE_MATCH_ACTIVE_TIMINGS (1 << 0) +#define DSI_MODE_MATCH_PORCH_TIMINGS (1 << 1) +#define DSI_MODE_MATCH_FULL_TIMINGS (DSI_MODE_MATCH_ACTIVE_TIMINGS | DSI_MODE_MATCH_PORCH_TIMINGS) +#define DSI_MODE_MATCH_DSC_CONFIG (1 << 2) + /* * DSI Validate Mode modifiers * @DSI_VALIDATE_FLAG_ALLOW_ADJUST: Allow mode validation to also do fixup @@ -436,12 +442,14 @@ int dsi_display_get_avr_step_req_fps(void *dsi_display, u32 mode_fps); * dsi_display_find_mode() - retrieve cached DSI mode given relevant params * @display: Handle to display. * @cmp: Mode to use as comparison to find original + * @sub_mode: Additional mode info to drm display mode * @out_mode: Output parameter, pointer to retrieved mode * * Return: error code. */ int dsi_display_find_mode(struct dsi_display *display, - const struct dsi_display_mode *cmp, + struct dsi_display_mode *cmp, + struct msm_sub_mode *sub_mode, struct dsi_display_mode **out_mode); /** * dsi_display_validate_mode() - validates if mode is supported by display diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 0ef393a41b..095017e909 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -398,7 +398,8 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge, struct dsi_display_mode dsi_mode, cur_dsi_mode, *panel_dsi_mode; struct drm_crtc_state *crtc_state; struct drm_connector_state *drm_conn_state; - struct sde_connector_state *conn_state; + struct sde_connector_state *conn_state, *old_conn_state; + struct msm_sub_mode new_sub_mode; crtc_state = container_of(mode, struct drm_crtc_state, mode); @@ -435,12 +436,15 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge, convert_to_dsi_mode(mode, &dsi_mode); msm_parse_mode_priv_info(&conn_state->msm_mode, &dsi_mode); + new_sub_mode.dsc_mode = sde_connector_get_property(drm_conn_state, + CONNECTOR_PROP_DSC_MODE); /* * retrieve dsi mode from dsi driver's cache since not safe to take * the drm mode config mutex in all paths */ - rc = dsi_display_find_mode(display, &dsi_mode, &panel_dsi_mode); + rc = dsi_display_find_mode(display, &dsi_mode, &new_sub_mode, + &panel_dsi_mode); if (rc) return rc; @@ -474,10 +478,11 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge, crtc_state->crtc) { const struct drm_display_mode *cur_mode = &crtc_state->crtc->state->mode; + old_conn_state = to_sde_connector_state(display->drm_conn->state); + convert_to_dsi_mode(cur_mode, &cur_dsi_mode); - cur_dsi_mode.timing.dsc_enabled = - dsi_mode.priv_info->dsc_enabled; - cur_dsi_mode.timing.dsc = &dsi_mode.priv_info->dsc; + msm_parse_mode_priv_info(&old_conn_state->msm_mode, &cur_dsi_mode); + rc = dsi_display_validate_mode_change(c_bridge->display, &cur_dsi_mode, &dsi_mode); if (rc) { @@ -546,6 +551,7 @@ u32 dsi_drm_get_dfps_maxfps(void *display) int dsi_conn_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) { @@ -557,7 +563,7 @@ int dsi_conn_get_mode_info(struct drm_connector *connector, return -EINVAL; convert_to_dsi_mode(drm_mode, &partial_dsi_mode); - rc = dsi_display_find_mode(display, &partial_dsi_mode, &dsi_mode); + rc = dsi_display_find_mode(display, &partial_dsi_mode, sub_mode, &dsi_mode); if (rc || !dsi_mode->priv_info) return -EINVAL; @@ -831,25 +837,21 @@ enum drm_connector_status dsi_conn_detect(struct drm_connector *conn, void dsi_connector_put_modes(struct drm_connector *connector, void *display) { - struct drm_display_mode *drm_mode; - struct dsi_display_mode dsi_mode, *full_dsi_mode = NULL; struct dsi_display *dsi_display; - int rc = 0; + int count, i; if (!connector || !display) return; - list_for_each_entry(drm_mode, &connector->modes, head) { - convert_to_dsi_mode(drm_mode, &dsi_mode); - rc = dsi_display_find_mode(display, &dsi_mode, &full_dsi_mode); - if (rc) - continue; + dsi_display = display; + count = dsi_display->panel->num_display_modes; + for (i = 0; i < count; i++) { + struct dsi_display_mode *dsi_mode = &dsi_display->modes[i]; - dsi_display_put_mode(display, full_dsi_mode); + dsi_display_put_mode(dsi_display, dsi_mode); } /* free the display structure modes also */ - dsi_display = display; kfree(dsi_display->modes); dsi_display->modes = NULL; } @@ -1050,7 +1052,7 @@ enum drm_mode_status dsi_conn_mode_valid(struct drm_connector *connector, if (conn_state) msm_parse_mode_priv_info(&conn_state->msm_mode, &dsi_mode); - rc = dsi_display_find_mode(display, &dsi_mode, &full_dsi_mode); + rc = dsi_display_find_mode(display, &dsi_mode, NULL, &full_dsi_mode); if (rc) { DSI_ERR("could not find mode %s\n", mode->name); return MODE_ERROR; @@ -1273,7 +1275,7 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector, convert_to_dsi_mode(drm_mode, &dsi_mode); - rc = dsi_display_find_mode(display, &dsi_mode, &panel_dsi_mode); + rc = dsi_display_find_mode(display, &dsi_mode, NULL, &panel_dsi_mode); if (rc) return; @@ -1290,7 +1292,7 @@ void dsi_conn_set_allowed_mode_switch(struct drm_connector *connector, convert_to_dsi_mode(cmp_drm_mode, &dsi_mode); rc = dsi_display_find_mode(display, &dsi_mode, - &cmp_panel_dsi_mode); + NULL, &cmp_panel_dsi_mode); if (rc) return; diff --git a/msm/dsi/dsi_drm.h b/msm/dsi/dsi_drm.h index e198412d9b..c91cd3bf3f 100644 --- a/msm/dsi/dsi_drm.h +++ b/msm/dsi/dsi_drm.h @@ -68,6 +68,7 @@ void dsi_connector_put_modes(struct drm_connector *connector, /** * dsi_conn_get_mode_info - retrieve information on the mode selected * @drm_mode: Display mode set for the display + * @sub_mode: Additional mode info to drm display mode * @mode_info: Out parameter. information of the mode. * @display: Pointer to private display structure * @avail_res: Pointer with curr available resources @@ -75,6 +76,7 @@ void dsi_connector_put_modes(struct drm_connector *connector, */ int dsi_conn_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res); diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 58fca3dea4..c8d33bfc6f 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -226,6 +226,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE, CONNECTOR_PROP_SET_PANEL_MODE, CONNECTOR_PROP_AVR_STEP, + CONNECTOR_PROP_DSC_MODE, /* total # of properties */ CONNECTOR_PROP_COUNT @@ -307,6 +308,18 @@ enum panel_op_mode { MSM_DISPLAY_MODE_MAX = BIT(2) }; +/** + * enum msm_display_dsc_mode - panel dsc mode + * @MSM_DISPLAY_DSC_MODE_NONE: No operation + * @MSM_DISPLAY_DSC_MODE_ENABLED: DSC is enabled + * @MSM_DISPLAY_DSC_MODE_DISABLED: DSC is disabled + */ +enum msm_display_dsc_mode { + MSM_DISPLAY_DSC_MODE_NONE, + MSM_DISPLAY_DSC_MODE_ENABLED, + MSM_DISPLAY_DSC_MODE_DISABLED, +}; + /** * struct msm_display_mode - wrapper for drm_display_mode * @base: drm_display_mode attached to this msm_mode @@ -319,6 +332,14 @@ struct msm_display_mode { u32 *private; }; +/** + * struct msm_sub_mode - msm display sub mode + * @dsc_enabled: boolean used to indicate if dsc should be enabled + */ +struct msm_sub_mode { + enum msm_display_dsc_mode dsc_mode; +}; + /** * struct msm_ratio - integer ratio * @numer: numerator diff --git a/msm/msm_kms.h b/msm/msm_kms.h index 8f245b5d16..062a911107 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -295,6 +295,9 @@ static inline bool msm_is_private_mode_changed( if (msm_is_mode_seamless_dyn_clk(msm_mode)) return true; + if (msm_is_mode_seamless_dms(msm_mode)) + return true; + return false; } diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 2b4154b6b6..5d0d6130fb 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -66,6 +66,11 @@ static const struct drm_prop_enum_list e_qsync_mode[] = { {SDE_RM_QSYNC_CONTINUOUS_MODE, "continuous"}, {SDE_RM_QSYNC_ONE_SHOT_MODE, "one_shot"}, }; +static const struct drm_prop_enum_list e_dsc_mode[] = { + {MSM_DISPLAY_DSC_MODE_NONE, "none"}, + {MSM_DISPLAY_DSC_MODE_ENABLED, "dsc_enabled"}, + {MSM_DISPLAY_DSC_MODE_DISABLED, "dsc_disabled"}, +}; static const struct drm_prop_enum_list e_frame_trigger_mode[] = { {FRAME_DONE_WAIT_DEFAULT, "default"}, {FRAME_DONE_WAIT_SERIALIZE, "serialize_frame_trigger"}, @@ -441,6 +446,7 @@ int sde_connector_set_msm_mode(struct drm_connector_state *conn_state, int sde_connector_get_mode_info(struct drm_connector *conn, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info) { struct sde_connector *sde_conn; @@ -455,7 +461,7 @@ int sde_connector_get_mode_info(struct drm_connector *conn, sde_connector_get_avail_res_info(conn, &avail_res); - return sde_conn->ops.get_mode_info(conn, drm_mode, + return sde_conn->ops.get_mode_info(conn, drm_mode, sub_mode, mode_info, sde_conn->display, &avail_res); } @@ -2631,7 +2637,7 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, memset(&mode_info, 0, sizeof(mode_info)); - rc = sde_connector_get_mode_info(&c_conn->base, mode, + rc = sde_connector_get_mode_info(&c_conn->base, mode, NULL, &mode_info); if (rc) { SDE_ERROR_CONN(c_conn, @@ -2892,6 +2898,9 @@ static int _sde_connector_install_properties(struct drm_device *dev, CONNECTOR_PROP_AVR_STEP); } + msm_property_install_enum(&c_conn->property_info, "dsc_mode", 0, + 0, e_dsc_mode, ARRAY_SIZE(e_dsc_mode), 0, CONNECTOR_PROP_DSC_MODE); + if (display_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) msm_property_install_enum(&c_conn->property_info, "frame_trigger_mode", 0, 0, diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 3557cc1cf2..50f1781f55 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -138,6 +138,7 @@ struct sde_connector_ops { * get_mode_info - retrieve mode information * @connector: Pointer to drm connector structure * @drm_mode: Display mode set for the display + * @sub_mode: Additional mode info to drm display mode * @mode_info: Out parameter. information of the display mode * @display: Pointer to private display structure * @avail_res: Pointer with curr available resources @@ -145,6 +146,7 @@ struct sde_connector_ops { */ int (*get_mode_info)(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res); @@ -1080,11 +1082,13 @@ int sde_connector_set_msm_mode(struct drm_connector_state *conn_state, * sde_connector_get_mode_info - retrieve mode info for given mode * @connector: Pointer to drm connector structure * @drm_mode: Display mode set for the display +* @sub_mode: Additional mode info to drm display mode * @mode_info: Out parameter. information of the display mode * Returns: Zero on success */ int sde_connector_get_mode_info(struct drm_connector *conn, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info); /** diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 674f1d5e00..fd08a1b942 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -933,12 +933,15 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc, { int ret = 0; struct drm_display_mode *adj_mode = &crtc_state->adjusted_mode; + struct msm_sub_mode sub_mode; if (sde_conn && msm_atomic_needs_modeset(crtc_state, conn_state)) { struct msm_display_topology *topology = NULL; + sub_mode.dsc_mode = sde_connector_get_property(conn_state, + CONNECTOR_PROP_DSC_MODE); ret = sde_connector_get_mode_info(&sde_conn->base, - adj_mode, &sde_conn_state->mode_info); + adj_mode, &sub_mode, &sde_conn_state->mode_info); if (ret) { SDE_ERROR_ENC(sde_enc, "failed to get mode info, rc = %d\n", ret); @@ -5432,6 +5435,7 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder, struct sde_encoder_phys *phys_enc; struct drm_bridge *bridge; int ret = 0, i; + struct msm_sub_mode sub_mode; if (!encoder) { SDE_ERROR("invalid drm enc\n"); @@ -5497,9 +5501,11 @@ int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder, return -EINVAL; } + sub_mode.dsc_mode = splash_display->dsc_cnt ? MSM_DISPLAY_DSC_MODE_ENABLED : + MSM_DISPLAY_DSC_MODE_DISABLED; drm_mode = &encoder->crtc->state->adjusted_mode; ret = sde_connector_get_mode_info(&sde_conn->base, - drm_mode, &sde_conn_state->mode_info); + drm_mode, &sub_mode, &sde_conn_state->mode_info); if (ret) { SDE_ERROR_ENC(sde_enc, "conn: ->get_mode_info failed. ret=%d\n", ret); @@ -5647,3 +5653,24 @@ void sde_encoder_enable_recovery_event(struct drm_encoder *encoder) sde_enc = to_sde_encoder_virt(encoder); sde_enc->recovery_events_enabled = true; } + +bool sde_encoder_needs_dsc_disable(struct drm_encoder *drm_enc) +{ + struct sde_kms *sde_kms; + struct drm_connector *conn; + struct sde_connector_state *conn_state; + + if (!drm_enc) + return false; + + sde_kms = sde_encoder_get_kms(drm_enc); + if (!sde_kms) + return false; + + conn = sde_encoder_get_connector(sde_kms->dev, drm_enc); + if (!conn || !conn->state) + return false; + + conn_state = to_sde_connector_state(conn->state); + return TOPOLOGY_DSC_MODE(conn_state->old_topology_name); +} diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 8ace4f3210..afc68f632e 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -559,6 +559,12 @@ void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable); struct drm_connector *sde_encoder_get_connector(struct drm_device *dev, struct drm_encoder *drm_enc); +/**sde_encoder_needs_dsc_disable - indicates if dsc should be disabled + * based on previous topology + * @drm_enc: Pointer to drm encoder structure + */ +bool sde_encoder_needs_dsc_disable(struct drm_encoder *drm_enc); + /** * sde_encoder_get_transfer_time - get the mdp transfer time in usecs * @drm_enc: Pointer to drm encoder structure diff --git a/msm/sde/sde_encoder_dce.c b/msm/sde/sde_encoder_dce.c index b5d2a7c4b2..09aced4981 100644 --- a/msm/sde/sde_encoder_dce.c +++ b/msm/sde/sde_encoder_dce.c @@ -936,7 +936,8 @@ void sde_encoder_dce_disable(struct sde_encoder_virt *sde_enc) comp_type = sde_enc->mode_info.comp_info.comp_type; - if (comp_type == MSM_DISPLAY_COMPRESSION_DSC) + if (comp_type == MSM_DISPLAY_COMPRESSION_DSC || + sde_encoder_needs_dsc_disable(&sde_enc->base)) _dce_dsc_disable(sde_enc); else if (comp_type == MSM_DISPLAY_COMPRESSION_VDC) _dce_vdc_disable(sde_enc); diff --git a/msm/sde/sde_rm.h b/msm/sde/sde_rm.h index ba6b7ee5fb..4963fa1350 100644 --- a/msm/sde/sde_rm.h +++ b/msm/sde/sde_rm.h @@ -33,6 +33,14 @@ x == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE ||\ x == SDE_RM_TOPOLOGY_QUADPIPE_DSC4HSMERGE) +#define TOPOLOGY_DSC_MODE(x) \ + (x == SDE_RM_TOPOLOGY_SINGLEPIPE_DSC ||\ + x == SDE_RM_TOPOLOGY_DUALPIPE_DSC ||\ + x == SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE_DSC ||\ + x == SDE_RM_TOPOLOGY_DUALPIPE_DSCMERGE ||\ + x == SDE_RM_TOPOLOGY_QUADPIPE_3DMERGE_DSC ||\ + x == SDE_RM_TOPOLOGY_QUADPIPE_DSCMERGE ||\ + x == SDE_RM_TOPOLOGY_QUADPIPE_DSC4HSMERGE) /** * enum sde_rm_topology_name - HW resource use case in use by connector * @SDE_RM_TOPOLOGY_NONE: No topology in use currently diff --git a/msm/sde/sde_wb.c b/msm/sde/sde_wb.c index e859eed6a6..4a0aa957df 100644 --- a/msm/sde/sde_wb.c +++ b/msm/sde/sde_wb.c @@ -373,6 +373,7 @@ int sde_wb_get_info(struct drm_connector *connector, int sde_wb_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) { diff --git a/msm/sde/sde_wb.h b/msm/sde/sde_wb.h index 6ee9e59ab4..708ed5f013 100644 --- a/msm/sde/sde_wb.h +++ b/msm/sde/sde_wb.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef __SDE_WB_H__ @@ -196,6 +196,7 @@ int sde_wb_get_info(struct drm_connector *connector, * sde_wb_get_mode_info - retrieve information of the mode selected * @connector: Pointer to drm connector structure * @drm_mode: Display mode set for the display + * @sub_mode: Additional mode info to drm display mode * @mode_info: Out parameter. information of the mode. * @display: Pointer to private display structure * @avail_res: Pointer with curr available resources @@ -203,6 +204,7 @@ int sde_wb_get_info(struct drm_connector *connector, */ int sde_wb_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res); @@ -352,6 +354,7 @@ int sde_wb_connector_set_info_blob(struct drm_connector *connector, static inline int sde_wb_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, + struct msm_sub_mode *sub_mode, struct msm_mode_info *mode_info, void *display, const struct msm_resource_caps_info *avail_res) {