disp: msm: sde: fix cwb, dp and wb tear down sequence
CWB, DP and WB displays tear down sequence must reset 3d_merge, ctl, pingpong_binding, etc. MDP HW blocks. This change fixes the tear down sequence register programming. It also moves flush sw reset before encoder_disable call. That allows CWB tear down to update the flush configuration on primary ctl path. Change-Id: I21c521b39456af4144cf836c65d46a25c985f51d Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
这个提交包含在:
@@ -3383,10 +3383,10 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
|
|||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
|
|
||||||
if (wb_enc) {
|
phys_enc->hw_ctl->ops.reset(phys_enc->hw_ctl);
|
||||||
if (sde_encoder_helper_reset_mixers(phys_enc, NULL))
|
sde_encoder_helper_reset_mixers(phys_enc, NULL);
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (wb_enc) {
|
||||||
if (wb_enc->hw_wb->ops.bind_pingpong_blk) {
|
if (wb_enc->hw_wb->ops.bind_pingpong_blk) {
|
||||||
wb_enc->hw_wb->ops.bind_pingpong_blk(wb_enc->hw_wb,
|
wb_enc->hw_wb->ops.bind_pingpong_blk(wb_enc->hw_wb,
|
||||||
false, phys_enc->hw_pp->idx);
|
false, phys_enc->hw_pp->idx);
|
||||||
@@ -4182,34 +4182,22 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *drm_enc)
|
|||||||
struct sde_encoder_phys *phys;
|
struct sde_encoder_phys *phys;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct sde_hw_ctl *ctl;
|
struct sde_hw_ctl *ctl;
|
||||||
struct msm_display_info *disp_info;
|
|
||||||
|
|
||||||
if (!drm_enc) {
|
if (!drm_enc) {
|
||||||
SDE_ERROR("invalid encoder\n");
|
SDE_ERROR("invalid encoder\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sde_enc = to_sde_encoder_virt(drm_enc);
|
sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
disp_info = &sde_enc->disp_info;
|
|
||||||
|
|
||||||
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||||
phys = sde_enc->phys_encs[i];
|
phys = sde_enc->phys_encs[i];
|
||||||
|
|
||||||
if (phys && phys->hw_ctl) {
|
if (phys && phys->hw_ctl && (phys == sde_enc->cur_master) &&
|
||||||
|
sde_encoder_check_curr_mode(drm_enc,
|
||||||
|
MSM_DISPLAY_CMD_MODE)) {
|
||||||
ctl = phys->hw_ctl;
|
ctl = phys->hw_ctl;
|
||||||
/*
|
if (ctl->ops.trigger_pending)
|
||||||
* avoid clearing the pending flush during the first
|
|
||||||
* frame update after idle power collpase as the
|
|
||||||
* restore path would have updated the pending flush
|
|
||||||
*/
|
|
||||||
if (!sde_enc->idle_pc_restore &&
|
|
||||||
ctl->ops.clear_pending_flush)
|
|
||||||
ctl->ops.clear_pending_flush(ctl);
|
|
||||||
|
|
||||||
/* update only for command mode primary ctl */
|
/* update only for command mode primary ctl */
|
||||||
if ((phys == sde_enc->cur_master) &&
|
|
||||||
(sde_encoder_check_curr_mode(drm_enc,
|
|
||||||
MSM_DISPLAY_CMD_MODE))
|
|
||||||
&& ctl->ops.trigger_pending)
|
|
||||||
ctl->ops.trigger_pending(ctl);
|
ctl->ops.trigger_pending(ctl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4934,6 +4922,7 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
|
|||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
struct sde_encoder_phys *phys;
|
struct sde_encoder_phys *phys;
|
||||||
int i;
|
int i;
|
||||||
|
struct sde_hw_ctl *ctl;
|
||||||
|
|
||||||
if (!drm_enc) {
|
if (!drm_enc) {
|
||||||
SDE_ERROR("invalid encoder\n");
|
SDE_ERROR("invalid encoder\n");
|
||||||
@@ -4945,6 +4934,18 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc)
|
|||||||
phys = sde_enc->phys_encs[i];
|
phys = sde_enc->phys_encs[i];
|
||||||
if (phys && phys->ops.prepare_commit)
|
if (phys && phys->ops.prepare_commit)
|
||||||
phys->ops.prepare_commit(phys);
|
phys->ops.prepare_commit(phys);
|
||||||
|
|
||||||
|
if (phys && phys->hw_ctl) {
|
||||||
|
ctl = phys->hw_ctl;
|
||||||
|
/*
|
||||||
|
* avoid clearing the pending flush during the first
|
||||||
|
* frame update after idle power collpase as the
|
||||||
|
* restore path would have updated the pending flush
|
||||||
|
*/
|
||||||
|
if (!sde_enc->idle_pc_restore &&
|
||||||
|
ctl->ops.clear_pending_flush)
|
||||||
|
ctl->ops.clear_pending_flush(ctl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -499,7 +499,7 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc,
|
|||||||
hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx);
|
hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx);
|
||||||
|
|
||||||
if (hw_ctl->ops.update_cwb_cfg) {
|
if (hw_ctl->ops.update_cwb_cfg) {
|
||||||
hw_ctl->ops.update_cwb_cfg(hw_ctl, &intf_cfg);
|
hw_ctl->ops.update_cwb_cfg(hw_ctl, &intf_cfg, enable);
|
||||||
SDE_DEBUG("in CWB mode on CTL_%d PP-%d merge3d:%d\n",
|
SDE_DEBUG("in CWB mode on CTL_%d PP-%d merge3d:%d\n",
|
||||||
hw_ctl->idx - CTL_0,
|
hw_ctl->idx - CTL_0,
|
||||||
hw_pp->idx - PINGPONG_0,
|
hw_pp->idx - PINGPONG_0,
|
||||||
@@ -816,7 +816,7 @@ static int sde_encoder_phys_wb_atomic_check(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void _sde_encoder_phys_wb_update_cwb_flush(
|
static void _sde_encoder_phys_wb_update_cwb_flush(
|
||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc, bool enable)
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys_wb *wb_enc;
|
struct sde_encoder_phys_wb *wb_enc;
|
||||||
struct sde_hw_wb *hw_wb;
|
struct sde_hw_wb *hw_wb;
|
||||||
@@ -878,7 +878,7 @@ static void _sde_encoder_phys_wb_update_cwb_flush(
|
|||||||
|
|
||||||
if (hw_wb->ops.program_cwb_ctrl)
|
if (hw_wb->ops.program_cwb_ctrl)
|
||||||
hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx,
|
hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx,
|
||||||
src_pp_idx, dspp_out);
|
src_pp_idx, dspp_out, enable);
|
||||||
|
|
||||||
if (hw_ctl->ops.update_bitmask_cwb)
|
if (hw_ctl->ops.update_bitmask_cwb)
|
||||||
hw_ctl->ops.update_bitmask_cwb(hw_ctl,
|
hw_ctl->ops.update_bitmask_cwb(hw_ctl,
|
||||||
@@ -1321,7 +1321,7 @@ static int sde_encoder_phys_wb_prepare_for_kickoff(
|
|||||||
|
|
||||||
_sde_encoder_phys_wb_update_flush(phys_enc);
|
_sde_encoder_phys_wb_update_flush(phys_enc);
|
||||||
|
|
||||||
_sde_encoder_phys_wb_update_cwb_flush(phys_enc);
|
_sde_encoder_phys_wb_update_cwb_flush(phys_enc, true);
|
||||||
|
|
||||||
/* vote for iommu/clk/bus */
|
/* vote for iommu/clk/bus */
|
||||||
wb_enc->start_time = ktime_get();
|
wb_enc->start_time = ktime_get();
|
||||||
@@ -1559,6 +1559,7 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
|
|||||||
/* avoid reset frame for CWB */
|
/* avoid reset frame for CWB */
|
||||||
if (phys_enc->in_clone_mode) {
|
if (phys_enc->in_clone_mode) {
|
||||||
_sde_encoder_phys_wb_setup_cwb(phys_enc, false);
|
_sde_encoder_phys_wb_setup_cwb(phys_enc, false);
|
||||||
|
_sde_encoder_phys_wb_update_cwb_flush(phys_enc, false);
|
||||||
phys_enc->in_clone_mode = false;
|
phys_enc->in_clone_mode = false;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@@ -1012,12 +1012,8 @@ static int sde_hw_ctl_reset_post_disable(struct sde_hw_ctl *ctx,
|
|||||||
struct sde_hw_intf_cfg_v1 *cfg, u32 merge_3d_idx)
|
struct sde_hw_intf_cfg_v1 *cfg, u32 merge_3d_idx)
|
||||||
{
|
{
|
||||||
struct sde_hw_blk_reg_map *c;
|
struct sde_hw_blk_reg_map *c;
|
||||||
u32 intf_active = 0;
|
u32 intf_active = 0, wb_active = 0, merge_3d_active = 0;
|
||||||
u32 intf_flush = 0;
|
u32 intf_flush = 0, wb_flush = 0;
|
||||||
u32 merge_3d_active = 0;
|
|
||||||
u32 merge_3d_flush = 0;
|
|
||||||
u32 wb_active = 0;
|
|
||||||
u32 wb_flush = 0;
|
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
if (!ctx || !cfg) {
|
if (!ctx || !cfg) {
|
||||||
@@ -1042,25 +1038,30 @@ static int sde_hw_ctl_reset_post_disable(struct sde_hw_ctl *ctx,
|
|||||||
|
|
||||||
if (merge_3d_idx) {
|
if (merge_3d_idx) {
|
||||||
/* disable and flush merge3d_blk */
|
/* disable and flush merge3d_blk */
|
||||||
merge_3d_flush = BIT(merge_3d_idx - MERGE_3D_0);
|
ctx->flush.pending_merge_3d_flush_mask =
|
||||||
|
BIT(merge_3d_idx - MERGE_3D_0);
|
||||||
merge_3d_active &= ~BIT(merge_3d_idx - MERGE_3D_0);
|
merge_3d_active &= ~BIT(merge_3d_idx - MERGE_3D_0);
|
||||||
ctx->flush.pending_merge_3d_flush_mask = merge_3d_flush;
|
|
||||||
SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active);
|
SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
sde_hw_ctl_clear_all_blendstages(ctx);
|
sde_hw_ctl_clear_all_blendstages(ctx);
|
||||||
|
|
||||||
ctx->flush.pending_intf_flush_mask = intf_flush;
|
if (cfg->intf_count) {
|
||||||
ctx->flush.pending_wb_flush_mask = wb_flush;
|
ctx->flush.pending_intf_flush_mask = intf_flush;
|
||||||
|
UPDATE_MASK(ctx->flush.pending_flush_mask, INTF_IDX, 1);
|
||||||
|
SDE_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
|
||||||
SDE_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
|
}
|
||||||
SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
|
|
||||||
|
|
||||||
|
if (cfg->wb_count) {
|
||||||
|
ctx->flush.pending_wb_flush_mask = wb_flush;
|
||||||
|
UPDATE_MASK(ctx->flush.pending_flush_mask, WB_IDX, 1);
|
||||||
|
SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sde_hw_ctl_update_cwb_cfg(struct sde_hw_ctl *ctx,
|
static int sde_hw_ctl_update_cwb_cfg(struct sde_hw_ctl *ctx,
|
||||||
struct sde_hw_intf_cfg_v1 *cfg)
|
struct sde_hw_intf_cfg_v1 *cfg, bool enable)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u32 cwb_active = 0;
|
u32 cwb_active = 0;
|
||||||
@@ -1084,11 +1085,16 @@ static int sde_hw_ctl_update_cwb_cfg(struct sde_hw_ctl *ctx,
|
|||||||
merge_3d_active |= BIT(cfg->merge_3d[i] - MERGE_3D_0);
|
merge_3d_active |= BIT(cfg->merge_3d[i] - MERGE_3D_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
wb_active = BIT(2);
|
if (enable) {
|
||||||
SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
|
wb_active = BIT(2);
|
||||||
SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active);
|
SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
|
||||||
SDE_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active);
|
SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active);
|
||||||
|
SDE_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active);
|
||||||
|
} else {
|
||||||
|
SDE_REG_WRITE(c, CTL_WB_ACTIVE, 0x0);
|
||||||
|
SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, 0x0);
|
||||||
|
SDE_REG_WRITE(c, CTL_CWB_ACTIVE, 0x0);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -249,10 +249,11 @@ struct sde_hw_ctl_ops {
|
|||||||
/** update cwb for ctl_path
|
/** update cwb for ctl_path
|
||||||
* @ctx : ctl path ctx pointer
|
* @ctx : ctl path ctx pointer
|
||||||
* @cfg : interface config structure pointer
|
* @cfg : interface config structure pointer
|
||||||
|
* @enable : enable/disable the cwb hw block
|
||||||
* @Return: error code
|
* @Return: error code
|
||||||
*/
|
*/
|
||||||
int (*update_cwb_cfg)(struct sde_hw_ctl *ctx,
|
int (*update_cwb_cfg)(struct sde_hw_ctl *ctx,
|
||||||
struct sde_hw_intf_cfg_v1 *cfg);
|
struct sde_hw_intf_cfg_v1 *cfg, bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup ctl_path interface config for SDE_CTL_ACTIVE_CFG
|
* Setup ctl_path interface config for SDE_CTL_ACTIVE_CFG
|
||||||
|
@@ -368,13 +368,13 @@ static void sde_hw_intf_bind_pingpong_blk(
|
|||||||
mux_cfg = SDE_REG_READ(c, INTF_MUX);
|
mux_cfg = SDE_REG_READ(c, INTF_MUX);
|
||||||
mux_cfg &= ~0xf;
|
mux_cfg &= ~0xf;
|
||||||
|
|
||||||
if (enable)
|
if (enable) {
|
||||||
mux_cfg |= (pp - PINGPONG_0) & 0x7;
|
mux_cfg |= (pp - PINGPONG_0) & 0x7;
|
||||||
else
|
if (intf->cfg.split_link_en)
|
||||||
mux_cfg |= 0xf;
|
mux_cfg = 0x60000;
|
||||||
|
} else {
|
||||||
if (intf->cfg.split_link_en)
|
mux_cfg = 0xf000f;
|
||||||
mux_cfg = 0x60000;
|
}
|
||||||
|
|
||||||
SDE_REG_WRITE(c, INTF_MUX, mux_cfg);
|
SDE_REG_WRITE(c, INTF_MUX, mux_cfg);
|
||||||
}
|
}
|
||||||
|
@@ -85,6 +85,9 @@ static void _sde_hw_cwb_ctrl_init(struct sde_mdss_cfg *m,
|
|||||||
b->length = CWB_CTRL_BLK_SIZE * m->pingpong_count;
|
b->length = CWB_CTRL_BLK_SIZE * m->pingpong_count;
|
||||||
b->hwversion = m->hwversion;
|
b->hwversion = m->hwversion;
|
||||||
b->log_mask = SDE_DBG_MASK_WB;
|
b->log_mask = SDE_DBG_MASK_WB;
|
||||||
|
|
||||||
|
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, "cwb", b->blk_off,
|
||||||
|
b->blk_off + b->length, 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,8 +281,8 @@ static void sde_hw_wb_bind_pingpong_blk(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx,
|
static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx,
|
||||||
const enum sde_cwb cur_idx,
|
const enum sde_cwb cur_idx, const enum sde_cwb data_src,
|
||||||
const enum sde_cwb data_src, bool dspp_out)
|
bool dspp_out, bool enable)
|
||||||
{
|
{
|
||||||
struct sde_hw_blk_reg_map *c;
|
struct sde_hw_blk_reg_map *c;
|
||||||
u32 blk_base;
|
u32 blk_base;
|
||||||
@@ -290,8 +293,13 @@ static void sde_hw_wb_program_cwb_ctrl(struct sde_hw_wb *ctx,
|
|||||||
c = &ctx->cwb_hw;
|
c = &ctx->cwb_hw;
|
||||||
blk_base = CWB_CTRL_BLK_SIZE * (cur_idx - CWB_0);
|
blk_base = CWB_CTRL_BLK_SIZE * (cur_idx - CWB_0);
|
||||||
|
|
||||||
SDE_REG_WRITE(c, blk_base + CWB_CTRL_SRC_SEL, data_src - CWB_0);
|
if (enable) {
|
||||||
SDE_REG_WRITE(c, blk_base + CWB_CTRL_MODE, dspp_out);
|
SDE_REG_WRITE(c, blk_base + CWB_CTRL_SRC_SEL, data_src - CWB_0);
|
||||||
|
SDE_REG_WRITE(c, blk_base + CWB_CTRL_MODE, dspp_out);
|
||||||
|
} else {
|
||||||
|
SDE_REG_WRITE(c, blk_base + CWB_CTRL_SRC_SEL, 0xf);
|
||||||
|
SDE_REG_WRITE(c, blk_base + CWB_CTRL_MODE, 0x0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
|
static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
|
||||||
|
@@ -136,9 +136,10 @@ struct sde_hw_wb_ops {
|
|||||||
* @pp_idx: Current CWB block index to poram
|
* @pp_idx: Current CWB block index to poram
|
||||||
* @data_src: Source CWB/PingPong block index
|
* @data_src: Source CWB/PingPong block index
|
||||||
* @dspp_out: Tap dspp output or default LM output
|
* @dspp_out: Tap dspp output or default LM output
|
||||||
|
* @enable: enable or disable the CWB path to tap the output
|
||||||
*/
|
*/
|
||||||
void (*program_cwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_cwb cwb,
|
void (*program_cwb_ctrl)(struct sde_hw_wb *ctx, const enum sde_cwb cwb,
|
||||||
const enum sde_cwb data_src, bool dspp_out);
|
const enum sde_cwb data_src, bool dspp_out, bool enable);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
在新工单中引用
屏蔽一个用户