Loading drivers/gpu/drm/msm/msm_atomic.c +3 −2 Original line number Diff line number Diff line /* * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (C) 2014 Red Hat * Author: Rob Clark <robdclark@gmail.com> * Loading Loading @@ -87,7 +87,8 @@ static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state, int conn_cnt = 0; if (msm_is_mode_seamless(&crtc_state->mode) || msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode)) msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode) || msm_is_mode_seamless_poms(&crtc_state->adjusted_mode)) return true; if (msm_is_mode_seamless_dms(&crtc_state->adjusted_mode) && !enable) Loading drivers/gpu/drm/msm/msm_drv.h +13 −1 Original line number Diff line number Diff line Loading @@ -248,6 +248,18 @@ enum msm_display_caps { MSM_DISPLAY_CAP_MST_MODE = BIT(5), }; /** * enum panel_mode - panel operation mode * @MSM_DISPLAY_VIDEO_MODE: video mode panel * @MSM_DISPLAY_CMD_MODE: Command mode panel * @MODE_MAX: */ enum panel_op_mode { MSM_DISPLAY_VIDEO_MODE = 0, MSM_DISPLAY_CMD_MODE, MSM_DISPLAY_MODE_MAX, }; /** * enum msm_event_wait - type of HW events to wait for * @MSM_ENC_COMMIT_DONE - wait for the driver to flush the registers to HW Loading Loading @@ -484,7 +496,7 @@ struct msm_mode_info { struct msm_display_info { int intf_type; uint32_t capabilities; enum panel_op_mode curr_panel_mode; uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; Loading drivers/gpu/drm/msm/msm_kms.h +9 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ #define MSM_MODE_FLAG_SEAMLESS_DMS (1<<2) /* Request to switch the fps */ #define MSM_MODE_FLAG_SEAMLESS_VRR (1<<3) /* Request to switch the panel mode */ #define MSM_MODE_FLAG_SEAMLESS_POMS (1<<4) /* As there are different display controller blocks depending on the * snapdragon version, the kms support is split out and the appropriate Loading Loading @@ -212,6 +214,13 @@ static inline bool msm_is_mode_seamless_vrr(const struct drm_display_mode *mode) : false; } static inline bool msm_is_mode_seamless_poms( const struct drm_display_mode *mode) { return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_POMS) : false; } static inline bool msm_needs_vblank_pre_modeset( const struct drm_display_mode *mode) { Loading drivers/gpu/drm/msm/sde/sde_crtc.c +12 −10 Original line number Diff line number Diff line Loading @@ -1824,8 +1824,8 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc, */ drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { post_commit |= sde_encoder_check_mode(encoder, MSM_DISPLAY_CAP_VID_MODE); post_commit |= sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE); } SDE_DEBUG("crtc%d: secure_level %d old_valid_fb %d post_commit %d\n", Loading Loading @@ -3164,8 +3164,8 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, _sde_crtc_dest_scaler_setup(crtc); /* cancel the idle notify delayed work */ if (sde_encoder_check_mode(sde_crtc->mixers[0].encoder, MSM_DISPLAY_CAP_VID_MODE) && if (sde_encoder_check_curr_mode(sde_crtc->mixers[0].encoder, MSM_DISPLAY_VIDEO_MODE) && kthread_cancel_delayed_work_sync(&sde_crtc->idle_notify_work)) SDE_DEBUG("idle notify work cancelled\n"); Loading Loading @@ -3281,8 +3281,9 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc, _sde_crtc_wait_for_fences(crtc); /* schedule the idle notify delayed work */ if (idle_time && sde_encoder_check_mode(sde_crtc->mixers[0].encoder, MSM_DISPLAY_CAP_VID_MODE)) { if (idle_time && sde_encoder_check_curr_mode( sde_crtc->mixers[0].encoder, MSM_DISPLAY_VIDEO_MODE)) { kthread_queue_delayed_work(&event_thread->worker, &sde_crtc->idle_notify_work, msecs_to_jiffies(idle_time)); Loading Loading @@ -4373,8 +4374,8 @@ static int _sde_crtc_check_secure_state_smmu_translation(struct drm_crtc *crtc, drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { is_video_mode |= sde_encoder_check_mode(encoder, MSM_DISPLAY_CAP_VID_MODE); is_video_mode |= sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE); } /* Loading Loading @@ -5059,8 +5060,9 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, cstate = to_sde_crtc_state(state); drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) { is_vid |= sde_encoder_check_mode(encoder, MSM_DISPLAY_CAP_VID_MODE); if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE)) is_vid = true; if (is_vid) break; } Loading drivers/gpu/drm/msm/sde/sde_encoder.c +95 −34 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ enum sde_enc_rc_states { * @te_source: vsync source pin information * @num_phys_encs: Actual number of physical encoders contained. * @phys_encs: Container of physical encoders managed. * @phys_vid_encs: Video physical encoders for panel mode switch. * @phys_cmd_encs: Command physical encoders for panel mode switch. * @cur_master: Pointer to the current master in this mode. Optimization * Only valid after enable. Cleared as disable. * @hw_pp Handle to the pingpong blocks used for the display. No. Loading Loading @@ -235,6 +237,8 @@ struct sde_encoder_virt { unsigned int num_phys_encs; struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct sde_encoder_phys *phys_vid_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct sde_encoder_phys *phys_cmd_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct sde_encoder_phys *cur_master; struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; Loading Loading @@ -767,8 +771,16 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc) sde_rsc_client_destroy(sde_enc->rsc_client); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; struct sde_encoder_phys *phys; phys = sde_enc->phys_vid_encs[i]; if (phys && phys->ops.destroy) { phys->ops.destroy(phys); --sde_enc->num_phys_encs; sde_enc->phys_encs[i] = NULL; } phys = sde_enc->phys_cmd_encs[i]; if (phys && phys->ops.destroy) { phys->ops.destroy(phys); --sde_enc->num_phys_encs; Loading Loading @@ -1789,7 +1801,7 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc, return; } if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_CMD_MODE)) { if (is_dummy) vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0 - sde_enc->te_source; Loading Loading @@ -1999,9 +2011,9 @@ static int _sde_encoder_update_rsc_client( if (sde_encoder_in_clone_mode(drm_enc) || !disp_info->is_primary || (disp_info->is_primary && qsync_mode)) rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE; else if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) rsc_state = enable ? SDE_RSC_CMD_STATE : SDE_RSC_IDLE_STATE; else if (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE) else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE)) rsc_state = enable ? SDE_RSC_VID_STATE : SDE_RSC_IDLE_STATE; SDE_EVT32(rsc_state, qsync_mode); Loading Loading @@ -2139,14 +2151,15 @@ 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, is_primary; bool is_cmd_mode = false, is_primary; sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; sde_kms = to_sde_kms(priv->kms); is_cmd_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE; 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); Loading Loading @@ -2722,9 +2735,8 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, } sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; is_vid_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_VID_MODE; if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE)) is_vid_mode = true; /* * when idle_pc is not supported, process only KICKOFF, STOP and MODESET * events and return early for other events (ie wb display). Loading Loading @@ -2783,6 +2795,32 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, return ret; } static void sde_encoder_virt_mode_switch(enum sde_intf_mode intf_mode, struct sde_encoder_virt *sde_enc, struct drm_display_mode *adj_mode) { int i = 0; if (intf_mode == INTF_MODE_CMD) { for (i = 0; i < sde_enc->num_phys_encs; i++) sde_enc->phys_encs[i] = sde_enc->phys_vid_encs[i]; sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_VIDEO_MODE; SDE_DEBUG_ENC(sde_enc, "switch to video physical encoder\n"); SDE_EVT32(DRMID(&sde_enc->base), intf_mode, msm_is_mode_seamless_poms(adj_mode), SDE_EVTLOG_FUNC_CASE1); } if (intf_mode == INTF_MODE_VIDEO) { for (i = 0; i < sde_enc->num_phys_encs; i++) sde_enc->phys_encs[i] = sde_enc->phys_cmd_encs[i]; sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_CMD_MODE; SDE_EVT32(DRMID(&sde_enc->base), intf_mode, msm_is_mode_seamless_poms(adj_mode), SDE_EVTLOG_FUNC_CASE2); SDE_DEBUG_ENC(sde_enc, "switch to command physical encoder\n"); } } static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) Loading @@ -2796,6 +2834,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct sde_connector *sde_conn = NULL; struct sde_rm_hw_iter dsc_iter, pp_iter; struct sde_rm_hw_request request_hw; enum sde_intf_mode intf_mode; int i = 0, ret; if (!drm_enc) { Loading Loading @@ -2852,6 +2892,11 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, return; } } intf_mode = sde_encoder_get_intf_mode(drm_enc); /* Switch pysical encoder */ if (msm_is_mode_seamless_poms(adj_mode)) 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)) { Loading Loading @@ -3265,8 +3310,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) phys->ops.enable(phys); } if (sde_enc->misr_enable && (sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_VID_MODE) && phys->ops.setup_misr) if (sde_enc->misr_enable && phys->ops.setup_misr && (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE))) phys->ops.setup_misr(phys, true, sde_enc->misr_frame_count); } Loading Loading @@ -3622,7 +3667,8 @@ static void sde_encoder_frame_done_callback( { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; bool trigger = true, is_cmd_mode; bool trigger = true; bool is_cmd_mode = false; enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE; if (!drm_enc || !sde_enc->cur_master) { Loading @@ -3633,8 +3679,8 @@ static void sde_encoder_frame_done_callback( sde_enc->crtc_frame_event_cb_data.connector = sde_enc->cur_master->connector; is_cmd_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE; if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR Loading Loading @@ -3953,8 +3999,8 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc) return; } is_vid_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_VID_MODE; if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE)) is_vid_mode = true; /* don't perform flush/start operations for slave encoders */ for (i = 0; i < sde_enc->num_phys_encs; i++) { Loading Loading @@ -4161,7 +4207,7 @@ static void _sde_encoder_update_master(struct drm_encoder *drm_enc, } } bool sde_encoder_check_mode(struct drm_encoder *drm_enc, u32 mode) bool sde_encoder_check_curr_mode(struct drm_encoder *drm_enc, u32 mode) { struct sde_encoder_virt *sde_enc; struct msm_display_info *disp_info; Loading @@ -4174,7 +4220,7 @@ bool sde_encoder_check_mode(struct drm_encoder *drm_enc, u32 mode) sde_enc = to_sde_encoder_virt(drm_enc); disp_info = &sde_enc->disp_info; return (disp_info->capabilities & mode); return (disp_info->curr_panel_mode == mode); } void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) Loading Loading @@ -4208,7 +4254,8 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) /* update only for command mode primary ctl */ if ((phys == sde_enc->cur_master) && (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) && ctl->ops.trigger_pending) ctl->ops.trigger_pending(ctl); } Loading Loading @@ -4697,7 +4744,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, if (sde_enc->cur_master && sde_enc->cur_master->connector && disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) sde_enc->frame_trigger_mode = sde_connector_get_property( sde_enc->cur_master->connector->state, CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); Loading Loading @@ -5225,11 +5272,12 @@ static void sde_encoder_early_unregister(struct drm_encoder *encoder) } static int sde_encoder_virt_add_phys_encs( u32 display_caps, struct msm_display_info *disp_info, struct sde_encoder_virt *sde_enc, struct sde_enc_phys_init_params *params) { struct sde_encoder_phys *enc = NULL; u32 display_caps = disp_info->capabilities; SDE_DEBUG_ENC(sde_enc, "\n"); Loading @@ -5253,8 +5301,7 @@ static int sde_encoder_virt_add_phys_encs( return !enc ? -EINVAL : PTR_ERR(enc); } sde_enc->phys_encs[sde_enc->num_phys_encs] = enc; ++sde_enc->num_phys_encs; sde_enc->phys_vid_encs[sde_enc->num_phys_encs] = enc; } if (display_caps & MSM_DISPLAY_CAP_CMD_MODE) { Loading @@ -5265,10 +5312,17 @@ static int sde_encoder_virt_add_phys_encs( PTR_ERR(enc)); return !enc ? -EINVAL : PTR_ERR(enc); } sde_enc->phys_cmd_encs[sde_enc->num_phys_encs] = enc; } if (disp_info->curr_panel_mode == MSM_DISPLAY_VIDEO_MODE) sde_enc->phys_encs[sde_enc->num_phys_encs] = sde_enc->phys_vid_encs[sde_enc->num_phys_encs]; else sde_enc->phys_encs[sde_enc->num_phys_encs] = sde_enc->phys_cmd_encs[sde_enc->num_phys_encs]; sde_enc->phys_encs[sde_enc->num_phys_encs] = enc; ++sde_enc->num_phys_encs; } return 0; } Loading Loading @@ -5418,7 +5472,7 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc, &phys_params); else ret = sde_encoder_virt_add_phys_encs( disp_info->capabilities, disp_info, sde_enc, &phys_params); if (ret) Loading @@ -5428,12 +5482,19 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc, } for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; struct sde_encoder_phys *vid_phys = sde_enc->phys_vid_encs[i]; struct sde_encoder_phys *cmd_phys = sde_enc->phys_cmd_encs[i]; if (phys) { atomic_set(&phys->vsync_cnt, 0); atomic_set(&phys->underrun_cnt, 0); if (vid_phys) { atomic_set(&vid_phys->vsync_cnt, 0); atomic_set(&vid_phys->underrun_cnt, 0); } if (cmd_phys) { atomic_set(&cmd_phys->vsync_cnt, 0); atomic_set(&cmd_phys->underrun_cnt, 0); } } mutex_unlock(&sde_enc->enc_lock); Loading Loading @@ -5508,7 +5569,7 @@ struct drm_encoder *sde_encoder_init( sde_enc->rsc_client = NULL; } if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { if (disp_info->curr_panel_mode == MSM_DISPLAY_CMD_MODE) { ret = _sde_encoder_input_handler(sde_enc); if (ret) SDE_ERROR( Loading Loading
drivers/gpu/drm/msm/msm_atomic.c +3 −2 Original line number Diff line number Diff line /* * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (C) 2014 Red Hat * Author: Rob Clark <robdclark@gmail.com> * Loading Loading @@ -87,7 +87,8 @@ static inline bool _msm_seamless_for_crtc(struct drm_atomic_state *state, int conn_cnt = 0; if (msm_is_mode_seamless(&crtc_state->mode) || msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode)) msm_is_mode_seamless_vrr(&crtc_state->adjusted_mode) || msm_is_mode_seamless_poms(&crtc_state->adjusted_mode)) return true; if (msm_is_mode_seamless_dms(&crtc_state->adjusted_mode) && !enable) Loading
drivers/gpu/drm/msm/msm_drv.h +13 −1 Original line number Diff line number Diff line Loading @@ -248,6 +248,18 @@ enum msm_display_caps { MSM_DISPLAY_CAP_MST_MODE = BIT(5), }; /** * enum panel_mode - panel operation mode * @MSM_DISPLAY_VIDEO_MODE: video mode panel * @MSM_DISPLAY_CMD_MODE: Command mode panel * @MODE_MAX: */ enum panel_op_mode { MSM_DISPLAY_VIDEO_MODE = 0, MSM_DISPLAY_CMD_MODE, MSM_DISPLAY_MODE_MAX, }; /** * enum msm_event_wait - type of HW events to wait for * @MSM_ENC_COMMIT_DONE - wait for the driver to flush the registers to HW Loading Loading @@ -484,7 +496,7 @@ struct msm_mode_info { struct msm_display_info { int intf_type; uint32_t capabilities; enum panel_op_mode curr_panel_mode; uint32_t num_of_h_tiles; uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; Loading
drivers/gpu/drm/msm/msm_kms.h +9 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ #define MSM_MODE_FLAG_SEAMLESS_DMS (1<<2) /* Request to switch the fps */ #define MSM_MODE_FLAG_SEAMLESS_VRR (1<<3) /* Request to switch the panel mode */ #define MSM_MODE_FLAG_SEAMLESS_POMS (1<<4) /* As there are different display controller blocks depending on the * snapdragon version, the kms support is split out and the appropriate Loading Loading @@ -212,6 +214,13 @@ static inline bool msm_is_mode_seamless_vrr(const struct drm_display_mode *mode) : false; } static inline bool msm_is_mode_seamless_poms( const struct drm_display_mode *mode) { return mode ? (mode->private_flags & MSM_MODE_FLAG_SEAMLESS_POMS) : false; } static inline bool msm_needs_vblank_pre_modeset( const struct drm_display_mode *mode) { Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +12 −10 Original line number Diff line number Diff line Loading @@ -1824,8 +1824,8 @@ int sde_crtc_get_secure_transition_ops(struct drm_crtc *crtc, */ drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { post_commit |= sde_encoder_check_mode(encoder, MSM_DISPLAY_CAP_VID_MODE); post_commit |= sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE); } SDE_DEBUG("crtc%d: secure_level %d old_valid_fb %d post_commit %d\n", Loading Loading @@ -3164,8 +3164,8 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, _sde_crtc_dest_scaler_setup(crtc); /* cancel the idle notify delayed work */ if (sde_encoder_check_mode(sde_crtc->mixers[0].encoder, MSM_DISPLAY_CAP_VID_MODE) && if (sde_encoder_check_curr_mode(sde_crtc->mixers[0].encoder, MSM_DISPLAY_VIDEO_MODE) && kthread_cancel_delayed_work_sync(&sde_crtc->idle_notify_work)) SDE_DEBUG("idle notify work cancelled\n"); Loading Loading @@ -3281,8 +3281,9 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc, _sde_crtc_wait_for_fences(crtc); /* schedule the idle notify delayed work */ if (idle_time && sde_encoder_check_mode(sde_crtc->mixers[0].encoder, MSM_DISPLAY_CAP_VID_MODE)) { if (idle_time && sde_encoder_check_curr_mode( sde_crtc->mixers[0].encoder, MSM_DISPLAY_VIDEO_MODE)) { kthread_queue_delayed_work(&event_thread->worker, &sde_crtc->idle_notify_work, msecs_to_jiffies(idle_time)); Loading Loading @@ -4373,8 +4374,8 @@ static int _sde_crtc_check_secure_state_smmu_translation(struct drm_crtc *crtc, drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { is_video_mode |= sde_encoder_check_mode(encoder, MSM_DISPLAY_CAP_VID_MODE); is_video_mode |= sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE); } /* Loading Loading @@ -5059,8 +5060,9 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc, cstate = to_sde_crtc_state(state); drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) { is_vid |= sde_encoder_check_mode(encoder, MSM_DISPLAY_CAP_VID_MODE); if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE)) is_vid = true; if (is_vid) break; } Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +95 −34 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ enum sde_enc_rc_states { * @te_source: vsync source pin information * @num_phys_encs: Actual number of physical encoders contained. * @phys_encs: Container of physical encoders managed. * @phys_vid_encs: Video physical encoders for panel mode switch. * @phys_cmd_encs: Command physical encoders for panel mode switch. * @cur_master: Pointer to the current master in this mode. Optimization * Only valid after enable. Cleared as disable. * @hw_pp Handle to the pingpong blocks used for the display. No. Loading Loading @@ -235,6 +237,8 @@ struct sde_encoder_virt { unsigned int num_phys_encs; struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct sde_encoder_phys *phys_vid_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct sde_encoder_phys *phys_cmd_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL]; struct sde_encoder_phys *cur_master; struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC]; struct sde_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC]; Loading Loading @@ -767,8 +771,16 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc) sde_rsc_client_destroy(sde_enc->rsc_client); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; struct sde_encoder_phys *phys; phys = sde_enc->phys_vid_encs[i]; if (phys && phys->ops.destroy) { phys->ops.destroy(phys); --sde_enc->num_phys_encs; sde_enc->phys_encs[i] = NULL; } phys = sde_enc->phys_cmd_encs[i]; if (phys && phys->ops.destroy) { phys->ops.destroy(phys); --sde_enc->num_phys_encs; Loading Loading @@ -1789,7 +1801,7 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc, return; } if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_CMD_MODE)) { if (is_dummy) vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0 - sde_enc->te_source; Loading Loading @@ -1999,9 +2011,9 @@ static int _sde_encoder_update_rsc_client( if (sde_encoder_in_clone_mode(drm_enc) || !disp_info->is_primary || (disp_info->is_primary && qsync_mode)) rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE; else if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) rsc_state = enable ? SDE_RSC_CMD_STATE : SDE_RSC_IDLE_STATE; else if (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE) else if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE)) rsc_state = enable ? SDE_RSC_VID_STATE : SDE_RSC_IDLE_STATE; SDE_EVT32(rsc_state, qsync_mode); Loading Loading @@ -2139,14 +2151,15 @@ 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, is_primary; bool is_cmd_mode = false, is_primary; sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; sde_kms = to_sde_kms(priv->kms); is_cmd_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE; 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); Loading Loading @@ -2722,9 +2735,8 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, } sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; is_vid_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_VID_MODE; if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE)) is_vid_mode = true; /* * when idle_pc is not supported, process only KICKOFF, STOP and MODESET * events and return early for other events (ie wb display). Loading Loading @@ -2783,6 +2795,32 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, return ret; } static void sde_encoder_virt_mode_switch(enum sde_intf_mode intf_mode, struct sde_encoder_virt *sde_enc, struct drm_display_mode *adj_mode) { int i = 0; if (intf_mode == INTF_MODE_CMD) { for (i = 0; i < sde_enc->num_phys_encs; i++) sde_enc->phys_encs[i] = sde_enc->phys_vid_encs[i]; sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_VIDEO_MODE; SDE_DEBUG_ENC(sde_enc, "switch to video physical encoder\n"); SDE_EVT32(DRMID(&sde_enc->base), intf_mode, msm_is_mode_seamless_poms(adj_mode), SDE_EVTLOG_FUNC_CASE1); } if (intf_mode == INTF_MODE_VIDEO) { for (i = 0; i < sde_enc->num_phys_encs; i++) sde_enc->phys_encs[i] = sde_enc->phys_cmd_encs[i]; sde_enc->disp_info.curr_panel_mode = MSM_DISPLAY_CMD_MODE; SDE_EVT32(DRMID(&sde_enc->base), intf_mode, msm_is_mode_seamless_poms(adj_mode), SDE_EVTLOG_FUNC_CASE2); SDE_DEBUG_ENC(sde_enc, "switch to command physical encoder\n"); } } static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) Loading @@ -2796,6 +2834,8 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct sde_connector *sde_conn = NULL; struct sde_rm_hw_iter dsc_iter, pp_iter; struct sde_rm_hw_request request_hw; enum sde_intf_mode intf_mode; int i = 0, ret; if (!drm_enc) { Loading Loading @@ -2852,6 +2892,11 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, return; } } intf_mode = sde_encoder_get_intf_mode(drm_enc); /* Switch pysical encoder */ if (msm_is_mode_seamless_poms(adj_mode)) 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)) { Loading Loading @@ -3265,8 +3310,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) phys->ops.enable(phys); } if (sde_enc->misr_enable && (sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_VID_MODE) && phys->ops.setup_misr) if (sde_enc->misr_enable && phys->ops.setup_misr && (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_VIDEO_MODE))) phys->ops.setup_misr(phys, true, sde_enc->misr_frame_count); } Loading Loading @@ -3622,7 +3667,8 @@ static void sde_encoder_frame_done_callback( { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); unsigned int i; bool trigger = true, is_cmd_mode; bool trigger = true; bool is_cmd_mode = false; enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE; if (!drm_enc || !sde_enc->cur_master) { Loading @@ -3633,8 +3679,8 @@ static void sde_encoder_frame_done_callback( sde_enc->crtc_frame_event_cb_data.connector = sde_enc->cur_master->connector; is_cmd_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE; if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; if (event & (SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_ERROR Loading Loading @@ -3953,8 +3999,8 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc) return; } is_vid_mode = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_VID_MODE; if (sde_encoder_check_curr_mode(&sde_enc->base, MSM_DISPLAY_VIDEO_MODE)) is_vid_mode = true; /* don't perform flush/start operations for slave encoders */ for (i = 0; i < sde_enc->num_phys_encs; i++) { Loading Loading @@ -4161,7 +4207,7 @@ static void _sde_encoder_update_master(struct drm_encoder *drm_enc, } } bool sde_encoder_check_mode(struct drm_encoder *drm_enc, u32 mode) bool sde_encoder_check_curr_mode(struct drm_encoder *drm_enc, u32 mode) { struct sde_encoder_virt *sde_enc; struct msm_display_info *disp_info; Loading @@ -4174,7 +4220,7 @@ bool sde_encoder_check_mode(struct drm_encoder *drm_enc, u32 mode) sde_enc = to_sde_encoder_virt(drm_enc); disp_info = &sde_enc->disp_info; return (disp_info->capabilities & mode); return (disp_info->curr_panel_mode == mode); } void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) Loading Loading @@ -4208,7 +4254,8 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc) /* update only for command mode primary ctl */ if ((phys == sde_enc->cur_master) && (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) && ctl->ops.trigger_pending) ctl->ops.trigger_pending(ctl); } Loading Loading @@ -4697,7 +4744,7 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, if (sde_enc->cur_master && sde_enc->cur_master->connector && disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) sde_enc->frame_trigger_mode = sde_connector_get_property( sde_enc->cur_master->connector->state, CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); Loading Loading @@ -5225,11 +5272,12 @@ static void sde_encoder_early_unregister(struct drm_encoder *encoder) } static int sde_encoder_virt_add_phys_encs( u32 display_caps, struct msm_display_info *disp_info, struct sde_encoder_virt *sde_enc, struct sde_enc_phys_init_params *params) { struct sde_encoder_phys *enc = NULL; u32 display_caps = disp_info->capabilities; SDE_DEBUG_ENC(sde_enc, "\n"); Loading @@ -5253,8 +5301,7 @@ static int sde_encoder_virt_add_phys_encs( return !enc ? -EINVAL : PTR_ERR(enc); } sde_enc->phys_encs[sde_enc->num_phys_encs] = enc; ++sde_enc->num_phys_encs; sde_enc->phys_vid_encs[sde_enc->num_phys_encs] = enc; } if (display_caps & MSM_DISPLAY_CAP_CMD_MODE) { Loading @@ -5265,10 +5312,17 @@ static int sde_encoder_virt_add_phys_encs( PTR_ERR(enc)); return !enc ? -EINVAL : PTR_ERR(enc); } sde_enc->phys_cmd_encs[sde_enc->num_phys_encs] = enc; } if (disp_info->curr_panel_mode == MSM_DISPLAY_VIDEO_MODE) sde_enc->phys_encs[sde_enc->num_phys_encs] = sde_enc->phys_vid_encs[sde_enc->num_phys_encs]; else sde_enc->phys_encs[sde_enc->num_phys_encs] = sde_enc->phys_cmd_encs[sde_enc->num_phys_encs]; sde_enc->phys_encs[sde_enc->num_phys_encs] = enc; ++sde_enc->num_phys_encs; } return 0; } Loading Loading @@ -5418,7 +5472,7 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc, &phys_params); else ret = sde_encoder_virt_add_phys_encs( disp_info->capabilities, disp_info, sde_enc, &phys_params); if (ret) Loading @@ -5428,12 +5482,19 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc, } for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; struct sde_encoder_phys *vid_phys = sde_enc->phys_vid_encs[i]; struct sde_encoder_phys *cmd_phys = sde_enc->phys_cmd_encs[i]; if (phys) { atomic_set(&phys->vsync_cnt, 0); atomic_set(&phys->underrun_cnt, 0); if (vid_phys) { atomic_set(&vid_phys->vsync_cnt, 0); atomic_set(&vid_phys->underrun_cnt, 0); } if (cmd_phys) { atomic_set(&cmd_phys->vsync_cnt, 0); atomic_set(&cmd_phys->underrun_cnt, 0); } } mutex_unlock(&sde_enc->enc_lock); Loading Loading @@ -5508,7 +5569,7 @@ struct drm_encoder *sde_encoder_init( sde_enc->rsc_client = NULL; } if (disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) { if (disp_info->curr_panel_mode == MSM_DISPLAY_CMD_MODE) { ret = _sde_encoder_input_handler(sde_enc); if (ret) SDE_ERROR( Loading