diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index e6811e616a58..1764b9110ade 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -3324,11 +3325,6 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc, if (crtc->state->mode_changed || sde_kms->perf.catalog->uidle_cfg.dirty) sde_core_perf_crtc_update_uidle(crtc, true); - else if (!test_bit(SDE_CRTC_DIRTY_UIDLE, &sde_crtc->revalidate_mask) && - !sde_kms->perf.uidle_enabled) - sde_core_uidle_setup_ctl(crtc, false); - - test_and_clear_bit(SDE_CRTC_DIRTY_UIDLE, &sde_crtc->revalidate_mask); /* * Since CP properties use AXI buffer to program the @@ -3482,6 +3478,7 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc, struct sde_crtc_state *cstate; struct drm_encoder *enc; struct sde_kms *sde_kms; + u32 encoder_mask; if (!crtc || !state) { SDE_ERROR("invalid argument(s)\n"); @@ -3497,9 +3494,11 @@ static void sde_crtc_destroy_state(struct drm_crtc *crtc, return; } - SDE_DEBUG("crtc%d\n", crtc->base.id); + encoder_mask = state->encoder_mask ? state->encoder_mask : + crtc->state->encoder_mask; + SDE_DEBUG("crtc%d\n, encoder_mask=%d", crtc->base.id, encoder_mask); - drm_for_each_encoder_mask(enc, crtc->dev, state->encoder_mask) + drm_for_each_encoder_mask(enc, crtc->dev, encoder_mask) sde_rm_release(&sde_kms->rm, enc, true); __drm_atomic_helper_crtc_destroy_state(state); @@ -3999,7 +3998,6 @@ void sde_crtc_reset_sw_state(struct drm_crtc *crtc) /* mark other properties which need to be dirty for next update */ set_bit(SDE_CRTC_DIRTY_DIM_LAYERS, &sde_crtc->revalidate_mask); - set_bit(SDE_CRTC_DIRTY_UIDLE, &sde_crtc->revalidate_mask); if (cstate->num_ds_enabled) set_bit(SDE_CRTC_DIRTY_DEST_SCALER, cstate->dirty); } diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 43db78485c69..4071e4841485 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -399,7 +400,6 @@ struct sde_crtc { enum sde_crtc_dirty_flags { SDE_CRTC_DIRTY_DEST_SCALER, SDE_CRTC_DIRTY_DIM_LAYERS, - SDE_CRTC_DIRTY_UIDLE, SDE_CRTC_DIRTY_MAX, }; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 2f4ccf9ae938..d27b125bf01f 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -1376,20 +1377,9 @@ static int _sde_encoder_update_rsc_client( (rsc_config->prefill_lines != mode_info->prefill_lines) || (rsc_config->jitter_numer != mode_info->jitter_numer) || (rsc_config->jitter_denom != mode_info->jitter_denom)) { - rsc_config->fps = mode_info->frame_rate; rsc_config->vtotal = mode_info->vtotal; - /* - * for video mode, prefill lines should not go beyond vertical - * front porch for RSCC configuration. This will ensure bw - * downvotes are not sent within the active region. Additional - * -1 is to give one line time for rscc mode min_threshold. - */ - if (is_vid_mode && (mode_info->prefill_lines >= v_front_porch)) - rsc_config->prefill_lines = v_front_porch - 1; - else - rsc_config->prefill_lines = mode_info->prefill_lines; - + rsc_config->prefill_lines = mode_info->prefill_lines; rsc_config->jitter_numer = mode_info->jitter_numer; rsc_config->jitter_denom = mode_info->jitter_denom; sde_enc->rsc_state_init = false; @@ -1841,9 +1831,6 @@ static int _sde_encoder_rc_pre_modeset(struct drm_encoder *drm_enc, { int ret = 0; - /* cancel delayed off work, if any */ - _sde_encoder_rc_cancel_delayed(sde_enc, sw_event); - mutex_lock(&sde_enc->rc_lock); if (sde_enc->rc_state == SDE_ENC_RC_STATE_OFF) { @@ -1873,19 +1860,18 @@ static int _sde_encoder_rc_pre_modeset(struct drm_encoder *drm_enc, sde_enc->rc_state = SDE_ENC_RC_STATE_ON; } + if (sde_encoder_has_dsc_hw_rev_2(sde_enc)) + goto skip_wait; + ret = sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); if (ret && ret != -EWOULDBLOCK) { - SDE_ERROR_ENC(sde_enc, - "wait for commit done returned %d\n", - ret); - SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, - ret, SDE_EVTLOG_ERROR); + SDE_ERROR_ENC(sde_enc, "wait for commit done returned %d\n", ret); + SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, ret, SDE_EVTLOG_ERROR); ret = -EINVAL; goto end; } - sde_encoder_irq_control(drm_enc, false); - +skip_wait: SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_ENC_RC_STATE_MODESET, SDE_EVTLOG_FUNC_CASE5); @@ -1920,8 +1906,6 @@ static int _sde_encoder_rc_post_modeset(struct drm_encoder *drm_enc, goto end; } - sde_encoder_irq_control(drm_enc, true); - _sde_encoder_update_rsc_client(drm_enc, true); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, @@ -2373,6 +2357,9 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info); sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc); + /* cancel delayed off work, if any */ + kthread_cancel_delayed_work_sync(&sde_enc->delayed_off_work); + /* release resources before seamless mode change */ ret = sde_encoder_virt_modeset_rc(drm_enc, adj_mode, true); if (ret) @@ -2610,7 +2597,6 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc) &sde_enc->cur_master->intf_cfg_v1); _sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info, false); - sde_encoder_control_te(drm_enc, true); memset(&sde_enc->prv_conn_roi, 0, sizeof(sde_enc->prv_conn_roi)); memset(&sde_enc->cur_conn_roi, 0, sizeof(sde_enc->cur_conn_roi)); @@ -2713,6 +2699,7 @@ void sde_encoder_virt_restore(struct drm_encoder *drm_enc) sde_enc->cur_master->ops.restore(sde_enc->cur_master); _sde_encoder_virt_enable_helper(drm_enc); + sde_encoder_control_te(drm_enc, true); } static void sde_encoder_off_work(struct kthread_work *work) @@ -2735,6 +2722,7 @@ static void sde_encoder_off_work(struct kthread_work *work) static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = NULL; + bool has_master_enc = false; int i, ret = 0; struct msm_compression_info *comp_info = NULL; struct drm_display_mode *cur_mode = NULL; @@ -2761,18 +2749,19 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc), cur_mode->hdisplay, cur_mode->vdisplay); - sde_enc->cur_master = NULL; for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; if (phys && phys->ops.is_master && phys->ops.is_master(phys)) { SDE_DEBUG_ENC(sde_enc, "master is now idx %d\n", i); sde_enc->cur_master = phys; + has_master_enc = true; break; } } - if (!sde_enc->cur_master) { + if (!has_master_enc) { + sde_enc->cur_master = NULL; SDE_ERROR("virt encoder has no master! num_phys %d\n", i); return; } @@ -2794,6 +2783,9 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) return; } + /* turn off vsync_in to update tear check configuration */ + sde_encoder_control_te(drm_enc, false); + memset(&sde_enc->cur_master->intf_cfg_v1, 0, sizeof(sde_enc->cur_master->intf_cfg_v1)); @@ -2849,6 +2841,7 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) sde_enc->cur_master->ops.enable(sde_enc->cur_master); _sde_encoder_virt_enable_helper(drm_enc); + sde_encoder_control_te(drm_enc, true); } void sde_encoder_virt_reset(struct drm_encoder *drm_enc) diff --git a/msm/sde/sde_encoder_dce.c b/msm/sde/sde_encoder_dce.c index cde539fdd732..c299494c33df 100644 --- a/msm/sde/sde_encoder_dce.c +++ b/msm/sde/sde_encoder_dce.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. */ @@ -913,6 +914,26 @@ void sde_encoder_dce_set_bpp(struct msm_mode_info mode_info, sde_crtc->src_bpp, sde_crtc->target_bpp); } +bool sde_encoder_has_dsc_hw_rev_2(struct sde_encoder_virt *sde_enc) +{ + enum msm_display_compression_type comp_type; + int i; + + if (!sde_enc) + return false; + + comp_type = sde_enc->mode_info.comp_info.comp_type; + + if (comp_type != MSM_DISPLAY_COMPRESSION_DSC) + return false; + + for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) + if (sde_enc->hw_dsc[i]) + return test_bit(SDE_DSC_HW_REV_1_2, &sde_enc->hw_dsc[i]->caps->features); + + return false; +} + void sde_encoder_dce_disable(struct sde_encoder_virt *sde_enc) { enum msm_display_compression_type comp_type; diff --git a/msm/sde/sde_encoder_dce.h b/msm/sde/sde_encoder_dce.h index b217a03484fb..a406ee1c4d98 100644 --- a/msm/sde/sde_encoder_dce.h +++ b/msm/sde/sde_encoder_dce.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved. */ @@ -36,4 +37,10 @@ int sde_encoder_dce_setup(struct sde_encoder_virt *sde_enc, */ void sde_encoder_dce_flush(struct sde_encoder_virt *sde_enc); +/** + * sde_encoder_has_dsc_hw_rev_2 :checks if dsc_hw_rev_1_2 feature is enabled + * @sde_enc: pointer to virtual encoder structure + */ +bool sde_encoder_has_dsc_hw_rev_2(struct sde_encoder_virt *sde_enc); + #endif /* __SDE_ENCODER_DCE_H__ */ diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 802140bd28c0..f3de4a43b8e3 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -275,7 +276,6 @@ struct sde_encoder_irq { * @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes * @enable_state: Enable state tracking * @vblank_refcount: Reference count of vblank request - * @vblank_cached_refcount: Reference count of vblank cached request * @wbirq_refcount: Reference count of wb irq request * @vsync_cnt: Vsync count for the physical encoder * @underrun_cnt: Underrun count for the physical encoder @@ -325,7 +325,6 @@ struct sde_encoder_phys { enum sde_enc_enable_state enable_state; struct mutex *vblank_ctl_lock; atomic_t vblank_refcount; - atomic_t vblank_cached_refcount; atomic_t wbirq_refcount; atomic_t vsync_cnt; atomic_t underrun_cnt; diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 8dd05021abac..403573cecd26 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -340,8 +341,6 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx( { struct sde_encoder_irq *irq; struct sde_kms *sde_kms; - int ret = 0; - u32 vblank_refcount; if (!phys_enc->sde_kms || !phys_enc->hw_pp || !phys_enc->hw_ctl) { SDE_ERROR("invalid args %d %d %d\n", !phys_enc->sde_kms, @@ -356,39 +355,13 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx( sde_kms = phys_enc->sde_kms; - mutex_lock(phys_enc->vblank_ctl_lock); - vblank_refcount = atomic_read(&phys_enc->vblank_refcount); - if (vblank_refcount) { - ret = sde_encoder_helper_unregister_irq(phys_enc, - INTR_IDX_RDPTR); - if (ret) - SDE_ERROR( - "control vblank irq registration error %d\n", - ret); - if (vblank_refcount > 1) - SDE_ERROR( - "vblank_refcount mismatch detected, try to reset %d\n", - atomic_read(&phys_enc->vblank_refcount)); - else - atomic_set(&phys_enc->vblank_cached_refcount, 1); - - SDE_EVT32(DRMID(phys_enc->parent), - phys_enc->hw_pp->idx - PINGPONG_0, vblank_refcount, - atomic_read(&phys_enc->vblank_cached_refcount)); - } - atomic_set(&phys_enc->vblank_refcount, 0); - mutex_unlock(phys_enc->vblank_ctl_lock); - irq = &phys_enc->irq[INTR_IDX_CTL_START]; irq->hw_idx = phys_enc->hw_ctl->idx; - irq->irq_idx = -EINVAL; irq = &phys_enc->irq[INTR_IDX_PINGPONG]; irq->hw_idx = phys_enc->hw_pp->idx; - irq->irq_idx = -EINVAL; irq = &phys_enc->irq[INTR_IDX_RDPTR]; - irq->irq_idx = -EINVAL; if (phys_enc->has_intf_te) irq->hw_idx = phys_enc->hw_intf->idx; else @@ -396,17 +369,14 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx( irq = &phys_enc->irq[INTR_IDX_UNDERRUN]; irq->hw_idx = phys_enc->intf_idx; - irq->irq_idx = -EINVAL; irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE]; - irq->irq_idx = -EINVAL; if (phys_enc->has_intf_te) irq->hw_idx = phys_enc->hw_intf->idx; else irq->hw_idx = phys_enc->hw_pp->idx; irq = &phys_enc->irq[INTR_IDX_WRPTR]; - irq->irq_idx = -EINVAL; if (phys_enc->has_intf_te) irq->hw_idx = phys_enc->hw_intf->idx; else @@ -831,7 +801,7 @@ static int sde_encoder_phys_cmd_control_vblank_irq( struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc); int ret = 0; - u32 refcount, cached_refcount; + u32 refcount; struct sde_kms *sde_kms; if (!phys_enc || !phys_enc->hw_pp) { @@ -846,17 +816,11 @@ static int sde_encoder_phys_cmd_control_vblank_irq( goto end; refcount = atomic_read(&phys_enc->vblank_refcount); - cached_refcount = atomic_read(&phys_enc->vblank_cached_refcount); /* protect against negative */ if (!enable && refcount == 0) { - if (cached_refcount == 1) { - atomic_set(&phys_enc->vblank_cached_refcount, 0); - goto end; - } else { - ret = -EINVAL; - goto end; - } + ret = -EINVAL; + goto end; } SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n", @@ -876,11 +840,6 @@ static int sde_encoder_phys_cmd_control_vblank_irq( atomic_inc_return(&phys_enc->vblank_refcount); } - if (enable && cached_refcount) { - atomic_inc(&phys_enc->vblank_refcount); - atomic_set(&phys_enc->vblank_cached_refcount, 0); - } - end: mutex_unlock(phys_enc->vblank_ctl_lock); if (ret) { @@ -2129,7 +2088,6 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init( irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq; atomic_set(&phys_enc->vblank_refcount, 0); - atomic_set(&phys_enc->vblank_cached_refcount, 0); atomic_set(&phys_enc->pending_kickoff_cnt, 0); atomic_set(&phys_enc->pending_retire_fence_cnt, 0); atomic_set(&cmd_enc->pending_vblank_cnt, 0); diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index 7e444aa4dc79..2937de7088e9 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -1107,12 +1107,41 @@ exit: phys_enc->enable_state = SDE_ENC_DISABLED; } +static int sde_encoder_phys_vid_poll_for_active_region(struct sde_encoder_phys *phys_enc) +{ + struct sde_encoder_phys_vid *vid_enc; + struct intf_timing_params *timing; + u32 line_cnt, v_inactive, poll_time_us, trial = 0; + + if (!phys_enc || !phys_enc->hw_intf || !phys_enc->hw_intf->ops.get_line_count) + return -EINVAL; + + vid_enc = to_sde_encoder_phys_vid(phys_enc); + timing = &vid_enc->timing_params; + + /* if programmable fetch is not enabled return early */ + if (!programmable_fetch_get_num_lines(vid_enc, timing)) + return 0; + + poll_time_us = DIV_ROUND_UP(1000000, timing->vrefresh) / MAX_POLL_CNT; + v_inactive = timing->v_front_porch + timing->v_back_porch + timing->vsync_pulse_width; + + do { + usleep_range(poll_time_us, poll_time_us + 5); + line_cnt = phys_enc->hw_intf->ops.get_line_count(phys_enc->hw_intf); + trial++; + } while ((trial < MAX_POLL_CNT) || (line_cnt < v_inactive)); + + return (trial >= MAX_POLL_CNT) ? -ETIMEDOUT : 0; +} + static void sde_encoder_phys_vid_handle_post_kickoff( struct sde_encoder_phys *phys_enc) { unsigned long lock_flags; struct sde_encoder_phys_vid *vid_enc; u32 avr_mode; + u32 ret; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); @@ -1135,6 +1164,10 @@ static void sde_encoder_phys_vid_handle_post_kickoff( 1); spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); + + ret = sde_encoder_phys_vid_poll_for_active_region(phys_enc); + if (ret) + SDE_DEBUG_VIDENC(vid_enc, "poll for active failed ret:%d\n", ret); } phys_enc->enable_state = SDE_ENC_ENABLED; } diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index 5c4bc917d654..bc21321e3a9b 100644 --- a/msm/sde/sde_hw_intf.c +++ b/msm/sde/sde_hw_intf.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include @@ -543,20 +544,30 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, struct sde_hw_tear_check *te) { struct sde_hw_blk_reg_map *c; - int cfg; + u32 cfg = 0; + spinlock_t tearcheck_spinlock; if (!intf) return -EINVAL; + spin_lock_init(&tearcheck_spinlock); c = &intf->hw; - cfg = BIT(19); /* VSYNC_COUNTER_EN */ if (te->hw_vsync_mode) cfg |= BIT(20); cfg |= te->vsync_count; + /* + * Local spinlock is acquired here to avoid pre-emption + * as below register programming should be completed in + * less than 2^16 vsync clk cycles. + */ + spin_lock(&tearcheck_spinlock); + SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, + (te->start_pos + te->sync_threshold_start + 1)); SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg); + wmb(); /* disable vsync counter before updating single buffer registers */ SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_HEIGHT, te->sync_cfg_height); SDE_REG_WRITE(c, INTF_TEAR_VSYNC_INIT_VAL, te->vsync_init_val); SDE_REG_WRITE(c, INTF_TEAR_RD_PTR_IRQ, te->rd_ptr_irq); @@ -565,8 +576,9 @@ static int sde_hw_intf_setup_te_config(struct sde_hw_intf *intf, SDE_REG_WRITE(c, INTF_TEAR_SYNC_THRESH, ((te->sync_threshold_continue << 16) | te->sync_threshold_start)); - SDE_REG_WRITE(c, INTF_TEAR_SYNC_WRCOUNT, - (te->start_pos + te->sync_threshold_start + 1)); + cfg |= BIT(19); /* VSYNC_COUNTER_EN */ + SDE_REG_WRITE(c, INTF_TEAR_SYNC_CONFIG_VSYNC, cfg); + spin_unlock(&tearcheck_spinlock); return 0; } diff --git a/msm/sde/sde_hw_reg_dma_v1.c b/msm/sde/sde_hw_reg_dma_v1.c index 7b73dafecddc..917d76e0622b 100644 --- a/msm/sde/sde_hw_reg_dma_v1.c +++ b/msm/sde/sde_hw_reg_dma_v1.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1191,6 +1192,10 @@ static int last_cmd_v1(struct sde_hw_ctl *ctl, enum sde_reg_dma_queue q, //Lack of block support will be caught by kick_off memset(&hw, 0, sizeof(hw)); SET_UP_REG_DMA_REG(hw, reg_dma, kick_off.dma_type); + if (hw.hwversion == 0) { + DRM_ERROR("DMA type %d is unsupported\n", kick_off.dma_type); + return -EOPNOTSUPP; + } SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY, mode, ctl->idx, kick_off.queue_select, kick_off.dma_type, kick_off.op); diff --git a/msm/sde/sde_hw_uidle.c b/msm/sde/sde_hw_uidle.c index bb6915205c7e..858cf42a9f1c 100644 --- a/msm/sde/sde_hw_uidle.c +++ b/msm/sde/sde_hw_uidle.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * */ @@ -161,7 +162,7 @@ void sde_hw_uidle_setup_ctl(struct sde_hw_uidle *uidle, struct sde_uidle_ctl_cfg *cfg) { struct sde_hw_blk_reg_map *c = &uidle->hw; - u32 reg_val; + u32 reg_val, fal10_veto_regval = 0; reg_val = SDE_REG_READ(c, UIDLE_CTL); reg_val = (reg_val & ~BIT(31)) | (cfg->uidle_enable ? BIT(31) : 0); @@ -176,6 +177,9 @@ void sde_hw_uidle_setup_ctl(struct sde_hw_uidle *uidle, FAL10_EXIT_CNT_MSK); SDE_REG_WRITE(c, UIDLE_CTL, reg_val); + if (!cfg->uidle_enable) + fal10_veto_regval |= (BIT(31) | BIT(0)); + SDE_REG_WRITE(c, UIDLE_FAL10_VETO_OVERRIDE, fal10_veto_regval); } static void sde_hw_uilde_active_override(struct sde_hw_uidle *uidle, diff --git a/msm/sde/sde_irq.c b/msm/sde/sde_irq.c index 974c163a6770..b83b07dc1f87 100644 --- a/msm/sde/sde_irq.c +++ b/msm/sde/sde_irq.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. */ @@ -103,7 +104,7 @@ void sde_irq_preinstall(struct msm_kms *kms) } /* disable irq until power event enables it */ - if (!sde_kms->splash_data.num_splash_displays && !sde_kms->irq_enabled) + if (!sde_kms->irq_enabled) irq_set_status_flags(sde_kms->irq_num, IRQ_NOAUTOEN); } diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 6785c65754dd..b9609ec6fc0f 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -111,6 +112,8 @@ static int _sde_kms_mmu_destroy(struct sde_kms *sde_kms); static int _sde_kms_mmu_init(struct sde_kms *sde_kms); static int _sde_kms_register_events(struct msm_kms *kms, struct drm_mode_object *obj, u32 event, bool en); +static void sde_kms_handle_power_event(u32 event_type, void *usr); + bool sde_is_custom_client(void) { return sdecustom; @@ -2178,14 +2181,38 @@ static int sde_kms_postinit(struct msm_kms *kms) struct drm_crtc *crtc; struct drm_connector *conn; struct drm_connector_list_iter conn_iter; - int rc; + struct msm_drm_private *priv; + int i, rc; - if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev) { + if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev || + !sde_kms->dev->dev_private) { SDE_ERROR("invalid sde_kms\n"); return -EINVAL; } dev = sde_kms->dev; + priv = sde_kms->dev->dev_private; + + /* + * Handle (re)initializations during power enable, the sde power + * event call has to be after drm_irq_install to handle irq update. + */ + sde_kms_handle_power_event(SDE_POWER_EVENT_POST_ENABLE, sde_kms); + sde_kms->power_event = sde_power_handle_register_event(&priv->phandle, + SDE_POWER_EVENT_POST_ENABLE | + SDE_POWER_EVENT_PRE_DISABLE, + sde_kms_handle_power_event, sde_kms, "kms"); + + if (sde_kms->splash_data.num_splash_displays) { + SDE_DEBUG("Skipping MDP Resources disable\n"); + } else { + for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) + sde_power_data_bus_set_quota(&priv->phandle, i, + SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA, + SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA); + + pm_runtime_put_sync(sde_kms->dev->dev); + } rc = _sde_debugfs_init(sde_kms); if (rc) @@ -4686,7 +4713,7 @@ static int sde_kms_hw_init(struct msm_kms *kms) struct drm_device *dev; struct msm_drm_private *priv; struct platform_device *platformdev; - int i, irq_num, rc = -EINVAL; + int irq_num, rc = -EINVAL; if (!kms) { SDE_ERROR("invalid kms\n"); @@ -4735,26 +4762,6 @@ static int sde_kms_hw_init(struct msm_kms *kms) */ dev->mode_config.allow_fb_modifiers = true; - /* - * Handle (re)initializations during power enable - */ - sde_kms_handle_power_event(SDE_POWER_EVENT_POST_ENABLE, sde_kms); - sde_kms->power_event = sde_power_handle_register_event(&priv->phandle, - SDE_POWER_EVENT_POST_ENABLE | - SDE_POWER_EVENT_PRE_DISABLE, - sde_kms_handle_power_event, sde_kms, "kms"); - - if (sde_kms->splash_data.num_splash_displays) { - SDE_DEBUG("Skipping MDP Resources disable\n"); - } else { - for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) - sde_power_data_bus_set_quota(&priv->phandle, i, - SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA, - SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA); - - pm_runtime_put_sync(sde_kms->dev->dev); - } - sde_kms->affinity_notify.notify = sde_kms_irq_affinity_notify; sde_kms->affinity_notify.release = sde_kms_irq_affinity_release; diff --git a/msm/sde_rsc.c b/msm/sde_rsc.c index 4b4c13bca0a5..14d180568115 100644 --- a/msm/sde_rsc.c +++ b/msm/sde_rsc.c @@ -331,11 +331,7 @@ static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc, line_time_ns = div_u64(line_time_ns, rsc->cmd_config.vtotal); prefill_time_ns = line_time_ns * rsc->cmd_config.prefill_lines; - /* only take jitter into account for CMD mode */ - if (state == SDE_RSC_CMD_STATE) - total = frame_time_ns - frame_jitter - prefill_time_ns; - else - total = frame_time_ns - prefill_time_ns; + total = frame_time_ns - frame_jitter - prefill_time_ns; if (total < 0) { pr_err("invalid total time period time:%llu jiter_time:%llu blanking time:%llu\n",