diff --git a/msm/msm_atomic.c b/msm/msm_atomic.c index 26d321589e..a6e656bbe9 100644 --- a/msm/msm_atomic.c +++ b/msm/msm_atomic.c @@ -747,6 +747,16 @@ int msm_atomic_commit(struct drm_device *dev, c->plane_mask |= (1 << drm_plane_index(plane)); } + /* Protection for prepare_fence callback */ +retry: + ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex, + state->acquire_ctx); + + if (ret == -EDEADLK) { + drm_modeset_backoff(state->acquire_ctx); + goto retry; + } + /* * Wait for pending updates on any of the same crtc's and then * mark our set of crtc's as busy: diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index faced95531..0ba53efe92 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -3895,8 +3895,11 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, } } - /* Early out if simple ctl reset succeeded */ - if (i == sde_crtc->num_ctls) + /* + * Early out if simple ctl reset succeeded or reset is + * being performed after timeout + */ + if (i == sde_crtc->num_ctls || crtc->state == old_state) return 0; SDE_DEBUG("crtc%d: issuing hard reset\n", DRMID(crtc)); @@ -3999,6 +4002,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE); + sde_crtc->kickoff_in_progress = true; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { if (encoder->crtc != crtc) continue; @@ -4060,6 +4064,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, sde_encoder_kickoff(encoder, false, true); } + sde_crtc->kickoff_in_progress = false; /* store the event after frame trigger */ if (sde_crtc->event) { @@ -6565,6 +6570,9 @@ static int _sde_debugfs_fence_status_show(struct seq_file *s, void *data) dev = crtc->dev; cstate = to_sde_crtc_state(crtc->state); + if (!sde_crtc->kickoff_in_progress) + goto skip_input_fence; + /* Dump input fence info */ seq_puts(s, "===Input fence===\n"); drm_atomic_crtc_for_each_plane(plane, crtc) { @@ -6592,6 +6600,7 @@ static int _sde_debugfs_fence_status_show(struct seq_file *s, void *data) } } +skip_input_fence: /* Dump release fence info */ seq_puts(s, "\n"); seq_puts(s, "===Release fence===\n"); @@ -7097,6 +7106,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) atomic_set(&sde_crtc->frame_pending, 0); sde_crtc->enabled = false; + sde_crtc->kickoff_in_progress = false; /* Below parameters are for fps calculation for sysfs node */ sde_crtc->fps_info.fps_periodic_duration = DEFAULT_FPS_PERIOD_1_SEC; diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index b6e7e3f469..ff0a6632cc 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -29,6 +29,7 @@ #include "sde_core_perf.h" #include "sde_hw_ds.h" #include "sde_color_processing.h" +#include "sde_encoder.h" #define SDE_CRTC_NAME_SIZE 12 @@ -285,6 +286,7 @@ struct sde_frame_data { * @ad_active : list containing ad properties that are active * @crtc_lock : crtc lock around create, destroy and access. * @frame_pending : Whether or not an update is pending + * @kickoff_in_progress : boolean entry to check if kickoff is in progress * @frame_events : static allocation of in-flight frame events * @frame_event_list : available frame event list * @spin_lock : spin lock for transaction status, etc... @@ -379,6 +381,7 @@ struct sde_crtc { struct list_head frame_event_list; spinlock_t spin_lock; spinlock_t fevent_spin_lock; + bool kickoff_in_progress; /* for handling internal event thread */ struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT]; @@ -634,12 +637,15 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state, /** * sde_crtc_request_frame_reset - requests for next frame reset * @crtc: Pointer to drm crtc object + * @encoder: Pointer to drm encoder object */ -static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc) +static inline int sde_crtc_request_frame_reset(struct drm_crtc *crtc, + struct drm_encoder *encoder) { struct sde_crtc *sde_crtc = to_sde_crtc(crtc); - if (sde_crtc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) + if (sde_crtc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START || + !sde_encoder_is_dsi_display(encoder)) sde_crtc_reset_hw(crtc, crtc->state, false); return 0; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 987753d312..a16dc2b869 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2094,7 +2094,8 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, sw_event, sde_enc->rc_state); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_ERROR); goto end; - } else if (sde_crtc_frame_pending(sde_enc->crtc)) { + } else if (sde_crtc_frame_pending(sde_enc->crtc) || + sde_crtc->kickoff_in_progress) { SDE_DEBUG_ENC(sde_enc, "skip idle entry"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR); diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index ffd0954b0e..ff889745bf 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -1415,20 +1415,27 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info = {0}; - int ret; + struct sde_connector *c_conn; bool frame_pending = true; struct sde_hw_ctl *ctl; unsigned long lock_flags; + int ret, timeout_ms; - if (!phys_enc || !phys_enc->hw_ctl) { + if (!phys_enc || !phys_enc->hw_ctl || !phys_enc->connector) { SDE_ERROR("invalid argument(s)\n"); return -EINVAL; } ctl = phys_enc->hw_ctl; + c_conn = to_sde_connector(phys_enc->connector); + timeout_ms = KICKOFF_TIMEOUT_MS; + + if (c_conn->lp_mode == SDE_MODE_DPMS_LP1 || + c_conn->lp_mode == SDE_MODE_DPMS_LP2) + timeout_ms = (KICKOFF_TIMEOUT_MS) * 2; wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt; - wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; + wait_info.timeout_ms = timeout_ms; /* slave encoder doesn't enable for ppsplit */ if (_sde_encoder_phys_is_ppsplit_slave(phys_enc)) diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 3b7de3940d..ba72738f4f 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -839,6 +839,13 @@ static int sde_encoder_phys_wb_atomic_check( return -EINVAL; } + if (fmt->chroma_sample == SDE_CHROMA_H2V1 || + fmt->chroma_sample == SDE_CHROMA_H1V2) { + SDE_ERROR("invalid chroma sample type in output format %x\n", + fmt->base.pixel_format); + return -EINVAL; + } + if (SDE_FORMAT_IS_UBWC(fmt) && !(wb_cfg->features & BIT(SDE_WB_UBWC))) { SDE_ERROR("invalid output format %x\n", fmt->base.pixel_format); diff --git a/msm/sde/sde_hw_dsc_1_2.c b/msm/sde/sde_hw_dsc_1_2.c index 58d6c7c3fa..5237bd3b0f 100644 --- a/msm/sde/sde_hw_dsc_1_2.c +++ b/msm/sde/sde_hw_dsc_1_2.c @@ -63,12 +63,12 @@ static int _dsc_calc_ob_max_addr(struct sde_hw_dsc *hw_dsc, int num_ss) idx = hw_dsc->idx; - if ((idx == DSC_0) || (idx == DSC_1)) { + if (!(hw_dsc->caps->features & BIT(SDE_DSC_NATIVE_422_EN))) { if (num_ss == 1) return 2399; else if (num_ss == 2) return 1199; - } else if ((idx == DSC_2) || (idx == DSC_3)) { + } else { if (num_ss == 1) return 1199; else if (num_ss == 2) diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 330583f88f..a6020506c0 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1581,7 +1581,7 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, ret = sde_encoder_wait_for_event(encoder, MSM_ENC_COMMIT_DONE); if (ret && ret != -EWOULDBLOCK) { SDE_ERROR("wait for commit done returned %d\n", ret); - sde_crtc_request_frame_reset(crtc); + sde_crtc_request_frame_reset(crtc, encoder); break; } @@ -1601,7 +1601,7 @@ static void sde_kms_prepare_fence(struct msm_kms *kms, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - int i, rc; + int i; if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) { SDE_ERROR("invalid argument(s)\n"); @@ -1609,15 +1609,6 @@ static void sde_kms_prepare_fence(struct msm_kms *kms, } SDE_ATRACE_BEGIN("sde_kms_prepare_fence"); -retry: - /* attempt to acquire ww mutex for connection */ - rc = drm_modeset_lock(&old_state->dev->mode_config.connection_mutex, - old_state->acquire_ctx); - - if (rc == -EDEADLK) { - drm_modeset_backoff(old_state->acquire_ctx); - goto retry; - } /* old_state actually contains updated crtc pointers */ for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { @@ -3565,6 +3556,11 @@ static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms, if (sde_encoder_in_clone_mode(conn->encoder)) continue; + crtc_id = drm_crtc_index(conn->state->crtc); + if (priv->disp_thread[crtc_id].thread) + kthread_flush_worker( + &priv->disp_thread[crtc_id].worker); + ret = sde_encoder_wait_for_event(conn->encoder, MSM_ENC_TX_COMPLETE); if (ret && ret != -EWOULDBLOCK) { @@ -3572,7 +3568,6 @@ static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms, "[conn: %d] wait for commit done returned %d\n", conn->base.id, ret); } else if (!ret) { - crtc_id = drm_crtc_index(conn->state->crtc); if (priv->event_thread[crtc_id].thread) kthread_flush_worker( &priv->event_thread[crtc_id].worker);