disp: msm: sde: add hw fence support for prog line count
This change adds support for triggering output hw fence upon programmable line count. Change-Id: Ie4b8252e4f9a448a8c11d17696b9bb0ded81b04b Signed-off-by: Christina Oliveira <quic_coliveir@quicinc.com>
这个提交包含在:
@@ -4626,7 +4626,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
|
|||||||
* condition between txq update and the hw signal during ctl-done for partial updates
|
* condition between txq update and the hw signal during ctl-done for partial updates
|
||||||
*/
|
*/
|
||||||
if (test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) && !is_vid)
|
if (test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) && !is_vid)
|
||||||
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, false);
|
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, false, 0);
|
||||||
|
|
||||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||||
if (encoder->crtc != crtc)
|
if (encoder->crtc != crtc)
|
||||||
@@ -6543,6 +6543,16 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
|
|||||||
vfree(info);
|
vfree(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _is_crtc_intf_mode_wb(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
enum sde_intf_mode intf_mode = sde_crtc_get_intf_mode(crtc, crtc->state);
|
||||||
|
|
||||||
|
if ((intf_mode != INTF_MODE_WB_BLOCK) && (intf_mode != INTF_MODE_WB_LINE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
|
static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
|
||||||
const struct drm_crtc_state *state, uint64_t *val)
|
const struct drm_crtc_state *state, uint64_t *val)
|
||||||
{
|
{
|
||||||
@@ -6550,6 +6560,7 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
|
|||||||
struct sde_crtc_state *cstate;
|
struct sde_crtc_state *cstate;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
bool is_vid = false;
|
bool is_vid = false;
|
||||||
|
bool is_wb = false;
|
||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
struct sde_hw_ctl *hw_ctl = NULL;
|
struct sde_hw_ctl *hw_ctl = NULL;
|
||||||
static u32 count;
|
static u32 count;
|
||||||
@@ -6558,10 +6569,12 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
|
|||||||
cstate = to_sde_crtc_state(state);
|
cstate = to_sde_crtc_state(state);
|
||||||
|
|
||||||
drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) {
|
drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) {
|
||||||
if (sde_encoder_check_curr_mode(encoder,
|
if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_VIDEO_MODE))
|
||||||
MSM_DISPLAY_VIDEO_MODE))
|
|
||||||
is_vid = true;
|
is_vid = true;
|
||||||
if (is_vid)
|
else if (_is_crtc_intf_mode_wb(crtc))
|
||||||
|
is_wb = true;
|
||||||
|
|
||||||
|
if (is_vid || is_wb)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6570,7 +6583,7 @@ static int _sde_crtc_get_output_fence(struct drm_crtc *crtc,
|
|||||||
* to create a hw-fence for this ctl, whereas if hw_ctl is not passed to sde_fence, this
|
* to create a hw-fence for this ctl, whereas if hw_ctl is not passed to sde_fence, this
|
||||||
* won't use hw-fences for this output-fence.
|
* won't use hw-fences for this output-fence.
|
||||||
*/
|
*/
|
||||||
if (test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) &&
|
if (!is_wb && test_bit(HW_FENCE_OUT_FENCES_ENABLE, sde_crtc->hwfence_features_mask) &&
|
||||||
(count++ % sde_crtc->hwfence_out_fences_skip))
|
(count++ % sde_crtc->hwfence_out_fences_skip))
|
||||||
hw_ctl = _sde_crtc_get_hw_ctl(crtc);
|
hw_ctl = _sde_crtc_get_hw_ctl(crtc);
|
||||||
|
|
||||||
|
@@ -3709,6 +3709,7 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
|
|||||||
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_connector *c_conn;
|
struct sde_connector *c_conn;
|
||||||
|
int line_count;
|
||||||
|
|
||||||
c_conn = to_sde_connector(phys->connector);
|
c_conn = to_sde_connector(phys->connector);
|
||||||
if (!c_conn) {
|
if (!c_conn) {
|
||||||
@@ -3716,8 +3717,10 @@ static inline void _sde_encoder_update_retire_txq(struct sde_encoder_phys *phys)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line_count = sde_connector_get_property(phys->connector->state,
|
||||||
|
CONNECTOR_PROP_EARLY_FENCE_LINE);
|
||||||
if (c_conn->hwfence_wb_retire_fences_enable)
|
if (c_conn->hwfence_wb_retire_fences_enable)
|
||||||
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false);
|
sde_fence_update_hw_fences_txq(c_conn->retire_fence, false, line_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3939,7 +3942,7 @@ void sde_encoder_helper_update_out_fence_txq(struct sde_encoder_virt *sde_enc, b
|
|||||||
sde_crtc = to_sde_crtc(sde_enc->crtc);
|
sde_crtc = to_sde_crtc(sde_enc->crtc);
|
||||||
|
|
||||||
SDE_EVT32(DRMID(sde_enc->crtc), is_vid);
|
SDE_EVT32(DRMID(sde_enc->crtc), is_vid);
|
||||||
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid);
|
sde_fence_update_hw_fences_txq(sde_crtc->output_fence, is_vid, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -251,7 +251,7 @@ int sde_fence_register_hw_fences_wait(struct sde_hw_ctl *hw_ctl, struct dma_fenc
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _arm_output_hw_fence(struct sde_hw_ctl *hw_ctl)
|
static int _arm_output_hw_fence(struct sde_hw_ctl *hw_ctl, u32 line_count)
|
||||||
{
|
{
|
||||||
struct sde_hw_fence_data *data;
|
struct sde_hw_fence_data *data;
|
||||||
u32 ipcc_out_signal;
|
u32 ipcc_out_signal;
|
||||||
@@ -284,12 +284,16 @@ static int _arm_output_hw_fence(struct sde_hw_ctl *hw_ctl)
|
|||||||
SDE_EVT32_VERBOSE(ctl_id, ipcc_out_signal);
|
SDE_EVT32_VERBOSE(ctl_id, ipcc_out_signal);
|
||||||
|
|
||||||
/* arm dpu to trigger output fence signal once ready */
|
/* arm dpu to trigger output fence signal once ready */
|
||||||
hw_ctl->ops.hw_fence_trigger_output_fence(hw_ctl, HW_FENCE_TRIGGER_SEL_CTRL_DONE);
|
if (line_count)
|
||||||
|
hw_ctl->ops.hw_fence_trigger_output_fence(hw_ctl,
|
||||||
|
HW_FENCE_TRIGGER_SEL_PROG_LINE_COUNT);
|
||||||
|
else
|
||||||
|
hw_ctl->ops.hw_fence_trigger_output_fence(hw_ctl, HW_FENCE_TRIGGER_SEL_CTRL_DONE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sde_fence_arm_output_hw_fence(struct sde_fence_context *ctx)
|
static int _sde_fence_arm_output_hw_fence(struct sde_fence_context *ctx, u32 line_count)
|
||||||
{
|
{
|
||||||
struct sde_hw_ctl *hw_ctl = NULL;
|
struct sde_hw_ctl *hw_ctl = NULL;
|
||||||
struct sde_fence *fc, *next;
|
struct sde_fence *fc, *next;
|
||||||
@@ -326,13 +330,13 @@ static int _sde_fence_arm_output_hw_fence(struct sde_fence_context *ctx)
|
|||||||
|
|
||||||
/* arm dpu to trigger output hw-fence ipcc signal upon completion */
|
/* arm dpu to trigger output hw-fence ipcc signal upon completion */
|
||||||
if (hw_ctl)
|
if (hw_ctl)
|
||||||
_arm_output_hw_fence(hw_ctl);
|
_arm_output_hw_fence(hw_ctl, line_count);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update output hw_fences txq */
|
/* update output hw_fences txq */
|
||||||
int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode)
|
int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode, u32 line_count)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct sde_hw_fence_data *data;
|
struct sde_hw_fence_data *data;
|
||||||
@@ -404,8 +408,8 @@ exit:
|
|||||||
spin_unlock(&ctx->list_lock);
|
spin_unlock(&ctx->list_lock);
|
||||||
|
|
||||||
/* arm dpu to trigger output hw-fence ipcc signal upon completion in vid-mode */
|
/* arm dpu to trigger output hw-fence ipcc signal upon completion in vid-mode */
|
||||||
if (txq_updated && hw_ctl)
|
if ((txq_updated && hw_ctl) || line_count)
|
||||||
_sde_fence_arm_output_hw_fence(ctx);
|
_sde_fence_arm_output_hw_fence(ctx, line_count);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -175,10 +175,11 @@ int sde_fence_register_hw_fences_wait(struct sde_hw_ctl *hw_ctl, struct dma_fenc
|
|||||||
*
|
*
|
||||||
* @ctx: sde fence context
|
* @ctx: sde fence context
|
||||||
* @vid_mode: is video-mode update
|
* @vid_mode: is video-mode update
|
||||||
|
* @line_count: prog line count value, must be non-zero
|
||||||
*
|
*
|
||||||
* Returns: Zero on success, otherwise returns an error code.
|
* Returns: Zero on success, otherwise returns an error code.
|
||||||
*/
|
*/
|
||||||
int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode);
|
int sde_fence_update_hw_fences_txq(struct sde_fence_context *ctx, bool vid_mode, u32 line_count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_fence_update_input_hw_fence_signal - updates input-fence ipcc signal in dpu and enables
|
* sde_fence_update_input_hw_fence_signal - updates input-fence ipcc signal in dpu and enables
|
||||||
|
在新工单中引用
屏蔽一个用户