disp: msm: sde: add support for hw-fence feature

Starting mdss 9.0, dpu supports triggering
the frame fetch through hw-fencing. This change
adds support for this hw-fence feature.

Change-Id: Icc7d0b69fc2a51103d14612f5ac89b44a47ed826
Signed-off-by: Ingrid Gallardo <quic_ingridg@quicinc.com>
Signed-off-by: Christina Oliveira <quic_coliveir@quicinc.com>
Этот коммит содержится в:
Christina Oliveira
2022-05-04 14:50:15 -07:00
коммит произвёл Gerrit - the friendly Code Review server
родитель 487e4ebec2
Коммит 640c8111d3
20 изменённых файлов: 1444 добавлений и 113 удалений

Просмотреть файл

@@ -44,6 +44,7 @@
#include "sde_hw_qdss.h"
#include "sde_encoder_dce.h"
#include "sde_vm.h"
#include "sde_fence.h"
#define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\
(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
@@ -3297,6 +3298,13 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
sde_encoder_virt_reset(drm_enc);
}
static void _trigger_encoder_hw_fences_override(struct sde_kms *sde_kms, struct sde_hw_ctl *ctl)
{
/* trigger hw-fences override signal */
if (sde_kms && sde_kms->catalog->hw_fence_rev && ctl->ops.hw_fence_trigger_sw_override)
ctl->ops.hw_fence_trigger_sw_override(ctl);
}
void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
struct sde_encoder_phys_wb *wb_enc)
{
@@ -3378,6 +3386,8 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
}
}
_trigger_encoder_hw_fences_override(phys_enc->sde_kms, ctl);
sde_crtc_disable_cp_features(sde_enc->base.crtc);
ctl->ops.get_pending_flush(ctl, &cfg);
SDE_EVT32(DRMID(phys_enc->parent), cfg.pending_flush_mask);
@@ -3691,6 +3701,25 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
return 0;
}
/**
* _sde_encoder_update_retire_txq - update tx queue for a retire hw fence
* phys: Pointer to physical encoder structure
*
*/
static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys)
{
struct sde_connector *c_conn;
c_conn = to_sde_connector(phys->connector);
if (!c_conn) {
SDE_ERROR("invalid connector");
return;
}
if (c_conn->hwfence_wb_retire_fences_enable)
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false);
}
/**
* _sde_encoder_trigger_flush - trigger flush for a physical encoder
* drm_enc: Pointer to drm encoder structure
@@ -3898,6 +3927,21 @@ void sde_encoder_helper_hw_reset(struct sde_encoder_phys *phys_enc)
phys_enc->enable_state = SDE_ENC_ENABLED;
}
void sde_encoder_helper_update_out_fence_txq(struct sde_encoder_virt *sde_enc, bool is_vid)
{
struct sde_crtc *sde_crtc;
if (!sde_enc || !sde_enc->crtc) {
SDE_ERROR("invalid encoder %d\n", !sde_enc);
return;
}
sde_crtc = to_sde_crtc(sde_enc->crtc);
SDE_EVT32(DRMID(sde_enc->crtc), is_vid);
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid);
}
/**
* _sde_encoder_kickoff_phys - handle physical encoder kickoff
* Iterate through the physical encoders and perform consolidated flush
@@ -3987,8 +4031,7 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc,
pending_kickoff_cnt =
sde_encoder_phys_inc_pending(phys);
SDE_EVT32(pending_kickoff_cnt,
pending_flush.pending_flush_mask,
SDE_EVTLOG_FUNC_CASE2);
pending_flush.pending_flush_mask, SDE_EVTLOG_FUNC_CASE2);
}
}
@@ -4572,6 +4615,10 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed)
SDE_EVT32(DRMID(drm_enc), i, SDE_EVTLOG_FUNC_CASE1);
}
/* update txq for any output retire hw-fence (wb-path) */
if (sde_enc->cur_master)
_sde_encoder_update_retire_txq(sde_enc->cur_master);
/* All phys encs are ready to go, trigger the kickoff */
_sde_encoder_kickoff_phys(sde_enc, config_changed);
@@ -5907,6 +5954,33 @@ bool sde_encoder_needs_dsc_disable(struct drm_encoder *drm_enc)
return TOPOLOGY_DSC_MODE(conn_state->old_topology_name);
}
struct sde_hw_ctl *sde_encoder_get_hw_ctl(struct sde_connector *c_conn)
{
struct drm_encoder *drm_enc;
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *cur_master;
struct sde_hw_ctl *hw_ctl = NULL;
if (!c_conn || !c_conn->hwfence_wb_retire_fences_enable)
goto exit;
/* get encoder to find the hw_ctl for this connector */
drm_enc = c_conn->encoder;
if (!drm_enc)
goto exit;
sde_enc = to_sde_encoder_virt(drm_enc);
cur_master = sde_enc->phys_encs[0];
if (!cur_master || !cur_master->hw_ctl)
goto exit;
hw_ctl = cur_master->hw_ctl;
SDE_DEBUG("conn hw_ctl idx:%d intf_mode:%d\n", hw_ctl->idx, cur_master->intf_mode);
exit:
return hw_ctl;
}
void sde_encoder_add_data_to_minidump_va(struct drm_encoder *drm_enc)
{
struct sde_encoder_virt *sde_enc;