disp: msm: sde: add support for hwfence profiling
This change adds hwfence input and output fence profiling registers and debugfs to enable them. To enable input hw fences timestamps: echo 0x1 > /d/dri/0/debug/hw_fence_status To enable output hw fences timestamps: echo 0x2 > /d/dri/0/debug/hw_fence_status To enable both, input and output hw fences timestamps: echo 0x3 > /d/dri/0/debug/hw_fence_status. Change-Id: I269a38f3843a01ec8c0816890e50bb7d847a4ed9 Signed-off-by: Christina Oliveira <quic_coliveir@quicinc.com>
This commit is contained in:
@@ -3433,6 +3433,35 @@ static enum sde_wb sde_encoder_get_wb(struct sde_mdss_cfg *catalog,
|
||||
return WB_MAX;
|
||||
}
|
||||
|
||||
void sde_encoder_hw_fence_status(struct sde_kms *sde_kms,
|
||||
struct drm_crtc *crtc, struct sde_hw_ctl *hw_ctl)
|
||||
{
|
||||
u64 start_timestamp, end_timestamp;
|
||||
|
||||
if (!sde_kms || !hw_ctl || !sde_kms->hw_mdp) {
|
||||
SDE_ERROR("invalid inputs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sde_kms->debugfs_hw_fence & SDE_INPUT_HW_FENCE_TIMESTAMP)
|
||||
&& sde_kms->hw_mdp->ops.hw_fence_input_status) {
|
||||
|
||||
sde_kms->hw_mdp->ops.hw_fence_input_status(sde_kms->hw_mdp,
|
||||
&start_timestamp, &end_timestamp);
|
||||
trace_sde_hw_fence_status(crtc->base.id, "input",
|
||||
start_timestamp, end_timestamp);
|
||||
}
|
||||
|
||||
if ((sde_kms->debugfs_hw_fence & SDE_OUTPUT_HW_FENCE_TIMESTAMP)
|
||||
&& hw_ctl->ops.hw_fence_output_status) {
|
||||
|
||||
hw_ctl->ops.hw_fence_output_status(hw_ctl,
|
||||
&start_timestamp, &end_timestamp);
|
||||
trace_sde_hw_fence_status(crtc->base.id, "output",
|
||||
start_timestamp, end_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void sde_encoder_perf_uidle_status(struct sde_kms *sde_kms,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
@@ -3492,7 +3521,7 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
|
||||
unsigned long lock_flags;
|
||||
ktime_t ts = 0;
|
||||
|
||||
if (!drm_enc || !phy_enc)
|
||||
if (!drm_enc || !phy_enc || !phy_enc->sde_kms)
|
||||
return;
|
||||
|
||||
SDE_ATRACE_BEGIN("encoder_vblank_callback");
|
||||
@@ -3502,8 +3531,7 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
|
||||
* calculate accurate vsync timestamp when available
|
||||
* set current time otherwise
|
||||
*/
|
||||
if (phy_enc->sde_kms && test_bit(SDE_FEATURE_HW_VSYNC_TS,
|
||||
phy_enc->sde_kms->catalog->features))
|
||||
if (test_bit(SDE_FEATURE_HW_VSYNC_TS, phy_enc->sde_kms->catalog->features))
|
||||
ts = sde_encoder_calc_last_vsync_timestamp(drm_enc);
|
||||
if (!ts)
|
||||
ts = ktime_get();
|
||||
@@ -3515,10 +3543,12 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
|
||||
sde_enc->crtc_vblank_cb(sde_enc->crtc_vblank_cb_data, ts);
|
||||
spin_unlock_irqrestore(&sde_enc->enc_spinlock, lock_flags);
|
||||
|
||||
if (phy_enc->sde_kms &&
|
||||
phy_enc->sde_kms->catalog->uidle_cfg.debugfs_perf)
|
||||
if (phy_enc->sde_kms->catalog->uidle_cfg.debugfs_perf)
|
||||
sde_encoder_perf_uidle_status(phy_enc->sde_kms, sde_enc->crtc);
|
||||
|
||||
if (phy_enc->sde_kms->debugfs_hw_fence)
|
||||
sde_encoder_hw_fence_status(phy_enc->sde_kms, sde_enc->crtc, phy_enc->hw_ctl);
|
||||
|
||||
SDE_ATRACE_END("encoder_vblank_callback");
|
||||
}
|
||||
|
||||
@@ -3706,7 +3736,8 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
|
||||
* phys: Pointer to physical encoder structure
|
||||
*
|
||||
*/
|
||||
static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys)
|
||||
static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys,
|
||||
struct sde_kms *sde_kms)
|
||||
{
|
||||
struct sde_connector *c_conn;
|
||||
int line_count;
|
||||
@@ -3720,7 +3751,8 @@ static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys)
|
||||
line_count = sde_connector_get_property(phys->connector->state,
|
||||
CONNECTOR_PROP_EARLY_FENCE_LINE);
|
||||
if (c_conn->hwfence_wb_retire_fences_enable)
|
||||
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false, line_count);
|
||||
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false, line_count,
|
||||
sde_kms->debugfs_hw_fence);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3933,16 +3965,23 @@ void sde_encoder_helper_hw_reset(struct sde_encoder_phys *phys_enc)
|
||||
void sde_encoder_helper_update_out_fence_txq(struct sde_encoder_virt *sde_enc, bool is_vid)
|
||||
{
|
||||
struct sde_crtc *sde_crtc;
|
||||
struct sde_kms *sde_kms = NULL;
|
||||
|
||||
if (!sde_enc || !sde_enc->crtc) {
|
||||
SDE_ERROR("invalid encoder %d\n", !sde_enc);
|
||||
return;
|
||||
}
|
||||
sde_kms = sde_encoder_get_kms(&sde_enc->base);
|
||||
if (!sde_kms) {
|
||||
SDE_ERROR("invalid kms\n");
|
||||
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, 0);
|
||||
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid, 0, sde_kms ?
|
||||
sde_kms->debugfs_hw_fence : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4594,6 +4633,7 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
struct sde_encoder_phys *phys;
|
||||
struct sde_kms *sde_kms;
|
||||
unsigned int i;
|
||||
|
||||
if (!drm_enc) {
|
||||
@@ -4619,8 +4659,9 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed)
|
||||
}
|
||||
|
||||
/* update txq for any output retire hw-fence (wb-path) */
|
||||
sde_kms = sde_encoder_get_kms(&sde_enc->base);
|
||||
if (sde_enc->cur_master)
|
||||
_sde_encoder_update_retire_txq(sde_enc->cur_master);
|
||||
_sde_encoder_update_retire_txq(sde_enc->cur_master, sde_kms);
|
||||
|
||||
/* All phys encs are ready to go, trigger the kickoff */
|
||||
_sde_encoder_kickoff_phys(sde_enc, config_changed);
|
||||
|
Reference in New Issue
Block a user