From 6701a6127e17af4db303653910e70e20febdeb89 Mon Sep 17 00:00:00 2001 From: Jayaprakash Madisetty Date: Thu, 1 Apr 2021 18:04:32 +0530 Subject: [PATCH] disp: msm: sde: correct num_datapath during PM resume with CWB In PM resume with CWB concurrency usecase, crtc pointer in conn->state is NULL since drm_mode_config_reset operation is performed on pm_resume. This change relies on conn_mask in new_crtc_state for primary connector retrieval and also adds get_num_lm_from_mode callback to DSI for LM count retrieval from dsi panel topology. Existing get_mode_info api cannot retrieve the topology info because mode->priv_info is NULL. This occurs as WB encoder is added in the drm encoder_list before primary encoder, introduced as part of commit d28ebf05f4aa ("disp: msm: sde: populate WB display encoder list before dsi"). Change-Id: I55358fd88ab778bd81475cf3628be13335de1cb5 Signed-off-by: Jayaprakash Madisetty --- msm/dsi/dsi_display.h | 8 ++++++++ msm/dsi/dsi_drm.c | 23 +++++++++++++++++++++++ msm/sde/sde_connector.c | 14 ++++++++++++++ msm/sde/sde_connector.h | 19 ++++++++++++++++++- msm/sde/sde_crtc.c | 39 ++++++++++++++++++++++++++++----------- msm/sde/sde_crtc.h | 3 ++- msm/sde/sde_kms.c | 1 + msm/sde/sde_rm.c | 2 +- 8 files changed, 95 insertions(+), 14 deletions(-) diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 3db835574ea1..7ac0c8ba8feb 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -426,6 +426,14 @@ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm); */ int dsi_display_get_qsync_min_fps(void *dsi_display, u32 mode_fps); +/** + * dsi_conn_get_lm_from_mode() - retrieves LM count from dsi mode priv info + * @display: Handle to display. + * @mode: Pointer to DRM mode structure + * + * Return: LM count from dsi panel topology + */ +int dsi_conn_get_lm_from_mode(void *dsi_display, const struct drm_display_mode *mode); /** * dsi_display_find_mode() - retrieve cached DSI mode given relevant params diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index d93d3867eee6..64549d570428 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -511,6 +511,29 @@ u64 dsi_drm_find_bit_clk_rate(void *display, return bit_clk_rate; } +int dsi_conn_get_lm_from_mode(void *display, const struct drm_display_mode *drm_mode) +{ + struct dsi_display *dsi_display = display; + struct dsi_display_mode dsi_mode, *panel_dsi_mode; + int rc = -EINVAL; + + if (!dsi_display || !drm_mode) { + DSI_ERR("Invalid params %d %d\n", !display, !drm_mode); + return rc; + } + + convert_to_dsi_mode(drm_mode, &dsi_mode); + + rc = dsi_display_find_mode(dsi_display, &dsi_mode, &panel_dsi_mode); + if (rc) { + DSI_ERR("mode not found %d\n", rc); + drm_mode_debug_printmodeline(drm_mode); + return rc; + } + + return panel_dsi_mode->priv_info->topology.num_lm; +} + int dsi_conn_get_mode_info(struct drm_connector *connector, const struct drm_display_mode *drm_mode, struct msm_mode_info *mode_info, diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index b2baee1bf4ab..eeda022f1da7 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -421,6 +421,20 @@ static void sde_connector_get_avail_res_info(struct drm_connector *conn, avail_res->max_mixer_width = sde_kms->catalog->max_mixer_width; } +int sde_connector_get_lm_cnt_from_topology(struct drm_connector *conn, + const struct drm_display_mode *drm_mode) +{ + struct sde_connector *c_conn; + + c_conn = to_sde_connector(conn); + + if (!c_conn || c_conn->connector_type != DRM_MODE_CONNECTOR_DSI || + !c_conn->ops.get_num_lm_from_mode) + return -EINVAL; + + return c_conn->ops.get_num_lm_from_mode(c_conn->display, drm_mode); +} + int sde_connector_get_mode_info(struct drm_connector *conn, const struct drm_display_mode *drm_mode, struct msm_mode_info *mode_info) diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index aad04d29f2f4..94f868ccff29 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_CONNECTOR_H_ @@ -382,6 +382,14 @@ struct sde_connector_ops { * Returns: Qsync min fps value on success */ int (*get_qsync_min_fps)(void *display, u32 mode_fps); + + /** + * get_num_lm_from_mode - Get LM count from topology for this drm mode + * @display: Pointer to private display structure + * @mode: Pointer to drm mode info structure + */ + int (*get_num_lm_from_mode)(void *display, const struct drm_display_mode *mode); + }; /** @@ -981,6 +989,15 @@ int sde_connector_helper_reset_custom_properties( int sde_connector_state_get_mode_info(struct drm_connector_state *conn_state, struct msm_mode_info *mode_info); +/** + * sde_connector_get_lm_cnt_from_topology - retrieves the topology info + * from the panel mode and returns the lm count. + * conn: Pointer to DRM connector object + * drm_mode: Pointer to the drm mode structure + */ +int sde_connector_get_lm_cnt_from_topology(struct drm_connector *conn, + const struct drm_display_mode *drm_mode); + /** * sde_connector_state_get_topology - get topology from given connector state * conn_state: Pointer to the DRM connector state object diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index a54e222a81b8..ac24500587bc 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -5075,40 +5075,57 @@ end: } /** - * sde_crtc_get_num_datapath - get the number of datapath active - * of primary connector + * sde_crtc_get_num_datapath - get the number of layermixers active + * on primary connector * @crtc: Pointer to DRM crtc object - * @connector: Pointer to DRM connector object of WB in CWB case + * @virtual_conn: Pointer to DRM connector object of WB in CWB case + * @crtc_state: Pointer to DRM crtc state */ int sde_crtc_get_num_datapath(struct drm_crtc *crtc, - struct drm_connector *connector) + struct drm_connector *virtual_conn, struct drm_crtc_state *crtc_state) { struct sde_crtc *sde_crtc = to_sde_crtc(crtc); + struct drm_connector *conn, *primary_conn = NULL; struct sde_connector_state *sde_conn_state = NULL; - struct drm_connector *conn; struct drm_connector_list_iter conn_iter; + int num_lm = 0; - if (!sde_crtc || !connector) { + if (!sde_crtc || !virtual_conn || !crtc_state) { SDE_DEBUG("Invalid argument\n"); return 0; } + /* return num_mixers used for primary when available in sde_crtc */ if (sde_crtc->num_mixers) return sde_crtc->num_mixers; drm_connector_list_iter_begin(crtc->dev, &conn_iter); drm_for_each_connector_iter(conn, &conn_iter) { - if (conn->state && conn->state->crtc == crtc && - conn != connector) + if ((drm_connector_mask(conn) & crtc_state->connector_mask) + && conn != virtual_conn) { sde_conn_state = to_sde_connector_state(conn->state); + primary_conn = conn; + break; + } } - drm_connector_list_iter_end(&conn_iter); + /* if primary sde_conn_state has mode info available, return num_lm from here */ if (sde_conn_state) - return sde_conn_state->mode_info.topology.num_lm; + num_lm = sde_conn_state->mode_info.topology.num_lm; - return 0; + /* if PM resume occurs with CWB enabled, retrieve num_lm from primary dsi panel mode */ + if (primary_conn && !num_lm) { + num_lm = sde_connector_get_lm_cnt_from_topology(primary_conn, + &crtc_state->adjusted_mode); + if (num_lm < 0) { + SDE_DEBUG("lm cnt fail for conn:%d num_lm:%d\n", + primary_conn->base.id, num_lm); + num_lm = 0; + } + } + + return num_lm; } int sde_crtc_vblank(struct drm_crtc *crtc, bool en) diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index c325097eeba8..292e2a4cb49f 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -927,9 +927,10 @@ void sde_crtc_static_cache_read_kickoff(struct drm_crtc *crtc); * of primary connector * @crtc: Pointer to DRM crtc object * @connector: Pointer to DRM connector object of WB in CWB case + * @crtc_state: Pointer to DRM crtc state */ int sde_crtc_get_num_datapath(struct drm_crtc *crtc, - struct drm_connector *connector); + struct drm_connector *connector, struct drm_crtc_state *crtc_state); /** * sde_crtc_reset_sw_state - reset dirty proerties on crtc and diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index df3e6a41b341..1af0d328443b 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1748,6 +1748,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .set_allowed_mode_switch = dsi_conn_set_allowed_mode_switch, .get_qsync_min_fps = dsi_display_get_qsync_min_fps, .prepare_commit = dsi_conn_prepare_commit, + .get_num_lm_from_mode = dsi_conn_get_lm_from_mode, }; static const struct sde_connector_ops wb_ops = { .post_init = sde_wb_connector_post_init, diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index cb3d589bd072..ed35add22d82 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -2054,7 +2054,7 @@ static int _sde_rm_populate_requirements( &rm->topology_tbl[SDE_RM_TOPOLOGY_DUALPIPE_3DMERGE]; num_lm = sde_crtc_get_num_datapath(crtc_state->crtc, - conn_state->connector); + conn_state->connector, crtc_state); if (num_lm == 1) reqs->topology =