diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index fbe000a73a..10e5d5d014 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -5075,9 +5075,9 @@ static int dsi_display_ext_get_info(struct drm_connector *connector, info->is_connected = connector->status != connector_status_disconnected; if (!strcmp(display->display_type, "primary")) - info->is_primary = true; - else - info->is_primary = false; + info->display_type = SDE_CONNECTOR_PRIMARY; + else if (!strcmp(display->display_type, "secondary")) + info->display_type = SDE_CONNECTOR_SECONDARY; info->capabilities |= (MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG); @@ -5431,10 +5431,11 @@ int dsi_display_get_info(struct drm_connector *connector, info->h_tile_instance[i] = display->ctrl[i].ctrl->cell_index; info->is_connected = true; - info->is_primary = false; if (!strcmp(display->display_type, "primary")) - info->is_primary = true; + info->display_type = SDE_CONNECTOR_PRIMARY; + else if (!strcmp(display->display_type, "secondary")) + info->display_type = SDE_CONNECTOR_SECONDARY; info->width_mm = phy_props.panel_width_mm; info->height_mm = phy_props.panel_height_mm; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 3f03d9e1bf..920353a183 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -486,7 +486,7 @@ struct msm_mode_info { * @max_height: Max height of display. In case of hot pluggable display * this is max height supported by controller * @clk_rate: DSI bit clock per lane in HZ. - * @is_primary: Set to true if display is primary display + * @display_type: Enum for type of display * @is_te_using_watchdog_timer: Boolean to indicate watchdog TE is * used instead of panel TE in cmd mode panels * @roi_caps: Region of interest capability info @@ -509,7 +509,7 @@ struct msm_display_info { uint32_t max_height; uint64_t clk_rate; - bool is_primary; + uint32_t display_type; bool is_te_using_watchdog_timer; struct msm_roi_caps roi_caps; diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index ba2efe1cdd..7d368011b3 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -1533,8 +1533,8 @@ int sde_connector_helper_reset_custom_properties( return 0; } -static int _sde_connector_primary_preference(struct sde_connector *sde_conn, - struct sde_kms *sde_kms) +static int _sde_connector_lm_preference(struct sde_connector *sde_conn, + struct sde_kms *sde_kms, uint32_t disp_type) { int ret = 0; u32 num_lm = 0; @@ -1544,6 +1544,11 @@ static int _sde_connector_primary_preference(struct sde_connector *sde_conn, return -EINVAL; } + if (!disp_type || disp_type >= SDE_CONNECTOR_MAX) { + SDE_DEBUG("invalid display_type"); + return -EINVAL; + } + ret = sde_conn->ops.get_default_lms(sde_conn->display, &num_lm); if (ret || !num_lm) { SDE_DEBUG("failed to get default lm count"); @@ -1557,7 +1562,7 @@ static int _sde_connector_primary_preference(struct sde_connector *sde_conn, return -EINVAL; } - sde_hw_mixer_set_preference(sde_kms->catalog, num_lm); + sde_hw_mixer_set_preference(sde_kms->catalog, num_lm, disp_type); return ret; } @@ -2453,8 +2458,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, goto error_destroy_property; } - if (display_info.is_primary) - _sde_connector_primary_preference(c_conn, sde_kms); + _sde_connector_lm_preference(c_conn, sde_kms, + display_info.display_type); SDE_DEBUG("connector %d attach encoder %d\n", c_conn->base.base.id, encoder->base.id); diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index f83cc1248a..8ba3f9fa23 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -314,6 +314,16 @@ struct sde_connector_ops { int (*get_default_lms)(void *display, u32 *num_lm); }; +/** + * enum sde_connector_display_type - list of display types + */ +enum sde_connector_display { + SDE_CONNECTOR_UNDEFINED, + SDE_CONNECTOR_PRIMARY, + SDE_CONNECTOR_SECONDARY, + SDE_CONNECTOR_MAX +}; + /** * enum sde_connector_events - list of recognized connector events */ diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 4b8c13828b..5175171573 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -408,7 +408,9 @@ bool sde_encoder_is_primary_display(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - return sde_enc && sde_enc->disp_info.is_primary; + return sde_enc && + (sde_enc->disp_info.display_type == + SDE_CONNECTOR_PRIMARY); } int sde_encoder_in_cont_splash(struct drm_encoder *drm_enc) @@ -659,7 +661,7 @@ void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc, sde_connector_get_mode_info(conn_state, &sde_enc->mode_info); hw_res->topology = sde_enc->mode_info.topology; - hw_res->is_primary = sde_enc->disp_info.is_primary; + hw_res->display_type = sde_enc->disp_info.display_type; } void sde_encoder_destroy(struct drm_encoder *drm_enc) @@ -1900,8 +1902,9 @@ static int _sde_encoder_update_rsc_client( qsync_mode = sde_connector_get_qsync_mode( sde_enc->cur_master->connector); - if (sde_encoder_in_clone_mode(drm_enc) || !disp_info->is_primary || - (disp_info->is_primary && qsync_mode)) + if (sde_encoder_in_clone_mode(drm_enc) || + (disp_info->display_type != SDE_CONNECTOR_PRIMARY) || + (disp_info->display_type && qsync_mode)) rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE; else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) rsc_state = enable ? SDE_RSC_CMD_STATE : SDE_RSC_IDLE_STATE; @@ -1927,7 +1930,7 @@ static int _sde_encoder_update_rsc_client( } if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_init - && disp_info->is_primary) { + && (disp_info->display_type == SDE_CONNECTOR_PRIMARY)) { /* update it only once */ sde_enc->rsc_state_init = true; @@ -2043,7 +2046,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, struct sde_kms *sde_kms; struct sde_encoder_virt *sde_enc; int rc; - bool is_cmd_mode = false, is_primary; + bool is_cmd_mode = false; sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; @@ -2052,8 +2055,6 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; - is_primary = sde_enc->disp_info.is_primary; - SDE_DEBUG_ENC(sde_enc, "enable:%d\n", enable); SDE_EVT32(DRMID(drm_enc), enable); @@ -3258,7 +3259,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) * they have been fully disabled, so delay the pre-stop operations * until after the physical disable calls have returned. */ - if (sde_enc->disp_info.is_primary && + if (sde_enc->disp_info.display_type == SDE_CONNECTOR_PRIMARY && (intf_mode == INTF_MODE_CMD || intf_mode == INTF_MODE_VIDEO)) { sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_STOP); @@ -4640,7 +4641,6 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_ATRACE_BEGIN("sde_encoder_prepare_for_kickoff"); for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; - params->is_primary = sde_enc->disp_info.is_primary; params->frame_trigger_mode = sde_enc->frame_trigger_mode; params->recovery_events_enabled = sde_enc->recovery_events_enabled; @@ -5476,7 +5476,8 @@ struct drm_encoder *sde_encoder_init( } snprintf(name, SDE_NAME_SIZE, "rsc_enc%u", drm_enc->base.id); sde_enc->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX, name, - disp_info->is_primary ? SDE_RSC_PRIMARY_DISP_CLIENT : + (disp_info->display_type == SDE_CONNECTOR_PRIMARY) ? + SDE_RSC_PRIMARY_DISP_CLIENT : SDE_RSC_EXTERNAL_DISP_CLIENT, intf_index + 1); if (IS_ERR_OR_NULL(sde_enc->rsc_client)) { SDE_DEBUG("sde rsc client create failed :%ld\n", diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 973f075e11..96922e3758 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -43,7 +43,7 @@ * @needs_cdm: Encoder requests a CDM based on pixel format conversion needs * @display_num_of_h_tiles: Number of horizontal tiles in case of split * interface - * @is_primary: set to true if the display is primary display + * @display_type: Type of the display * @topology: Topology of the display */ struct sde_encoder_hw_resources { @@ -51,20 +51,18 @@ struct sde_encoder_hw_resources { enum sde_intf_mode wbs[WB_MAX]; bool needs_cdm; u32 display_num_of_h_tiles; - bool is_primary; + bool display_type; struct msm_display_topology topology; }; /** * sde_encoder_kickoff_params - info encoder requires at kickoff - * @is_primary: set to true if the display is primary display * @affected_displays: bitmask, bit set means the ROI of the commit lies within * the bounds of the physical display at the bit index * @recovery_events_enabled: indicates status of client for recoovery events * @frame_trigger_mode: indicates frame trigger mode */ struct sde_encoder_kickoff_params { - u32 is_primary; unsigned long affected_displays; bool recovery_events_enabled; enum frame_trigger_mode_type frame_trigger_mode; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index c1892ea255..27490166d3 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -15,6 +15,7 @@ #include "sde_hw_catalog_format.h" #include "sde_kms.h" #include "sde_hw_uidle.h" +#include "sde_connector.h" /************************************************************* * MACRO DEFINITION @@ -1613,16 +1614,50 @@ end: return rc; } -void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm) +void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, + uint32_t disp_type) { - u32 i; + u32 i, cnt = 0, sec_cnt = 0; - for (i = 0; i < sde_cfg->mixer_count; i++) { - clear_bit(SDE_DISP_PRIMARY_PREF, - &sde_cfg->mixer[i].features); - if (i < num_lm) - set_bit(SDE_DISP_PRIMARY_PREF, + if (disp_type == SDE_CONNECTOR_PRIMARY) { + for (i = 0; i < sde_cfg->mixer_count; i++) { + /* Check if lm was previously set for secondary */ + /* Clear pref, primary has higher priority */ + if (sde_cfg->mixer[i].features & + BIT(SDE_DISP_SECONDARY_PREF)) { + clear_bit(SDE_DISP_SECONDARY_PREF, + &sde_cfg->mixer[i].features); + sec_cnt++; + } + clear_bit(SDE_DISP_PRIMARY_PREF, &sde_cfg->mixer[i].features); + + /* Set lm for primary pref */ + if (cnt < num_lm) { + set_bit(SDE_DISP_PRIMARY_PREF, + &sde_cfg->mixer[i].features); + cnt++; + } + + /* After primary pref is set, now re apply secondary */ + if (cnt >= num_lm && cnt < (num_lm + sec_cnt)) { + set_bit(SDE_DISP_SECONDARY_PREF, + &sde_cfg->mixer[i].features); + cnt++; + } + } + } else if (disp_type == SDE_CONNECTOR_SECONDARY) { + for (i = 0; i < sde_cfg->mixer_count; i++) { + clear_bit(SDE_DISP_SECONDARY_PREF, + &sde_cfg->mixer[i].features); + + if (cnt < num_lm && !(sde_cfg->mixer[i].features & + BIT(SDE_DISP_PRIMARY_PREF))) { + set_bit(SDE_DISP_SECONDARY_PREF, + &sde_cfg->mixer[i].features); + cnt++; + } + } } } diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 0f03612f75..5e7739854d 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -268,6 +268,7 @@ enum { * @SDE_DIM_LAYER Layer mixer supports dim layer * @SDE_DISP_CWB_PREF Layer mixer preferred for CWB * @SDE_DISP_PRIMARY_PREF Layer mixer preferred for primary display + * @SDE_DISP_SECONDARY_PREF Layer mixer preferred for secondary display * @SDE_MIXER_MAX maximum value */ enum { @@ -276,6 +277,7 @@ enum { SDE_MIXER_GC, SDE_DIM_LAYER, SDE_DISP_PRIMARY_PREF, + SDE_DISP_SECONDARY_PREF, SDE_DISP_CWB_PREF, SDE_MIXER_MAX }; @@ -1381,8 +1383,10 @@ struct sde_mdss_hw_cfg_handler { * overwrite if exists * @sde_cfg: pointer to sspp cfg * @num_lm: num lms to set preference + * @disp_type: is the given display primary/secondary */ -void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm); +void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, + uint32_t disp_type); /** * sde_hw_catalog_init - sde hardware catalog init API parses dtsi property diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 019308404d..5436654119 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -2347,9 +2347,9 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms) encoder = NULL; continue; } - SDE_DEBUG("info.is_connected = %s, info.is_primary = %s\n", + SDE_DEBUG("info.is_connected = %s, info.display_type = %d\n", ((info.is_connected) ? "true" : "false"), - ((info.is_primary) ? "true" : "false")); + info.display_type); if (!encoder) { SDE_ERROR("encoder not initialized\n"); diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index 3dc38648a5..236fe3fdb1 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -796,7 +796,8 @@ static bool _sde_rm_check_lm_and_get_connected_blks( *dspp = NULL; *ds = NULL; *pp = NULL; - display_pref = lm_cfg->features & BIT(SDE_DISP_PRIMARY_PREF); + display_pref = lm_cfg->features & BIT(SDE_DISP_PRIMARY_PREF) || + lm_cfg->features & BIT(SDE_DISP_SECONDARY_PREF); cwb_pref = lm_cfg->features & BIT(SDE_DISP_CWB_PREF); SDE_DEBUG("check lm %d: dspp %d ds %d pp %d disp_pref: %d cwb_pref%d\n", @@ -831,10 +832,10 @@ static bool _sde_rm_check_lm_and_get_connected_blks( SDE_DEBUG("fail: cwb supported lm not allocated\n"); return false; } - } else if (!(reqs->hw_res.is_primary && display_pref)) { + } else if (!(reqs->hw_res.display_type && display_pref)) { SDE_DEBUG( - "display preference is not met. is_primary: %d display_pref: %d\n", - (int)reqs->hw_res.is_primary, (int)display_pref); + "display preference is not met. display_type: %d display_pref: %d\n", + (int)reqs->hw_res.display_type, (int)display_pref); return false; } @@ -1022,11 +1023,11 @@ static int _sde_rm_reserve_ctls( if (top->top_name == SDE_RM_TOPOLOGY_PPSPLIT && !has_ppsplit) continue; - } else if (!(reqs->hw_res.is_primary && primary_pref) && - !_ctl_ids) { + } else if (!(reqs->hw_res.display_type == + SDE_CONNECTOR_PRIMARY && primary_pref) && !_ctl_ids) { SDE_DEBUG( - "display pref not met. is_primary: %d primary_pref: %d\n", - reqs->hw_res.is_primary, primary_pref); + "display pref not met. display_type: %d primary_pref: %d\n", + reqs->hw_res.display_type, primary_pref); continue; }