Loading drivers/gpu/drm/msm/sde/sde_encoder_phys.h +5 −1 Original line number Diff line number Diff line Loading @@ -202,7 +202,9 @@ struct sde_encoder_phys_ops { * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel * @INTR_IDX_WB_DONE: Writeback done interrupt for WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP2 for Concurrent WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB * @INTR_IDX_PP3_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB * @INTR_IDX_PP4_OVFL: Pingpong overflow interrupt on PP4 for Concurrent WB * @INTR_IDX_PP5_OVFL: Pingpong overflow interrupt on PP5 for Concurrent WB * @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning * autorefresh has triggered a double buffer flip */ Loading @@ -216,6 +218,8 @@ enum sde_intr_idx { INTR_IDX_WB_DONE, INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, INTR_IDX_MAX, }; Loading drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +126 −21 Original line number Diff line number Diff line Loading @@ -33,6 +33,11 @@ #define TO_S15D16(_x_) ((_x_) << 7) #define MULTIPLE_CONN_DETECTED(x) (x > 1) static const u32 cwb_irq_tbl[PINGPONG_MAX] = {SDE_NONE, SDE_NONE, INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, SDE_NONE, SDE_NONE}; /** * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix * Loading Loading @@ -471,26 +476,66 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); struct sde_hw_wb *hw_wb = wb_enc->hw_wb; struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl; struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc); struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp; bool need_merge = crtc->num_mixers > 1 ? true : false; int i = 0; if (!phys_enc->in_clone_mode) { SDE_DEBUG("not in CWB mode. early return\n"); return; } if (!hw_pp || !hw_ctl || !hw_wb || hw_pp->idx >= PINGPONG_MAX) { SDE_ERROR("invalid hw resources - return\n"); return; } hw_ctl = crtc->mixers[0].hw_ctl; if (hw_ctl && hw_ctl->ops.setup_intf_cfg_v1 && test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { struct sde_hw_intf_cfg_v1 intf_cfg = { 0, }; for (i = 0; i < crtc->num_mixers; i++) intf_cfg.cwb[intf_cfg.cwb_count++] = (enum sde_cwb)(hw_pp->idx + i); if (enable && hw_pp->merge_3d && (intf_cfg.merge_3d_count < MAX_MERGE_3D_PER_CTL_V1) && need_merge) intf_cfg.merge_3d[intf_cfg.merge_3d_count++] = hw_pp->merge_3d->idx; if (hw_pp->ops.setup_3d_mode) hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ? BLEND_3D_H_ROW_INT : 0); if (hw_wb->ops.bind_pingpong_blk) hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx); if (hw_ctl->ops.update_cwb_cfg) { hw_ctl->ops.update_cwb_cfg(hw_ctl, &intf_cfg); SDE_DEBUG("in CWB mode on CTL_%d PP-%d merge3d:%d\n", hw_ctl->idx - CTL_0, hw_pp->idx - PINGPONG_0, hw_pp->merge_3d ? hw_pp->merge_3d->idx - MERGE_3D_0 : -1); } } else { struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; memset(intf_cfg, 0, sizeof(struct sde_hw_intf_cfg)); intf_cfg->intf = SDE_NONE; intf_cfg->wb = hw_wb->idx; hw_ctl = crtc->mixers[0].hw_ctl; if (hw_ctl && hw_ctl->ops.update_wb_cfg) { hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable); SDE_DEBUG("in CWB mode adding WB for CTL_%d\n", hw_ctl->idx - CTL_0); } } } /** * sde_encoder_phys_wb_setup_cdp - setup chroma down prefetch block * @phys_enc: Pointer to physical encoder Loading Loading @@ -801,9 +846,15 @@ static void _sde_encoder_phys_wb_update_cwb_flush( struct sde_hw_wb *hw_wb; struct sde_hw_ctl *hw_ctl; struct sde_hw_cdm *hw_cdm; struct sde_hw_pingpong *hw_pp; struct sde_crtc *crtc; struct sde_crtc_state *crtc_state; int capture_point = 0; int i = 0; int cwb_capture_mode = 0; enum sde_cwb cwb_idx = 0; enum sde_cwb src_pp_idx = 0; bool dspp_out = false; bool need_merge = false; if (!phys_enc->in_clone_mode) { SDE_DEBUG("not in CWB mode. early return\n"); Loading @@ -813,30 +864,59 @@ static void _sde_encoder_phys_wb_update_cwb_flush( wb_enc = to_sde_encoder_phys_wb(phys_enc); crtc = to_sde_crtc(wb_enc->crtc); crtc_state = to_sde_crtc_state(wb_enc->crtc->state); cwb_capture_mode = sde_crtc_get_property(crtc_state, CRTC_PROP_CAPTURE_OUTPUT); hw_pp = phys_enc->hw_pp; hw_wb = wb_enc->hw_wb; hw_cdm = phys_enc->hw_cdm; /* In CWB mode, program actual source master sde_hw_ctl from crtc */ hw_ctl = crtc->mixers[0].hw_ctl; if (!hw_ctl) { SDE_DEBUG("[wb:%d] no ctl assigned for CWB\n", hw_wb->idx - WB_0); if (!hw_ctl || !hw_wb || !hw_pp) { SDE_ERROR("[wb] HW resource not available for CWB\n"); return; } capture_point = sde_crtc_get_property(crtc_state, CRTC_PROP_CAPTURE_OUTPUT); /* treating LM idx of primary display ctl path as source ping-pong idx*/ src_pp_idx = (enum sde_cwb)crtc->mixers[0].hw_lm->idx; cwb_idx = (enum sde_cwb)hw_pp->idx; dspp_out = (cwb_capture_mode == CAPTURE_DSPP_OUT); need_merge = (crtc->num_mixers > 1) ? true : false; phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, crtc->num_mixers == CRTC_DUAL_MIXERS, capture_point == CAPTURE_DSPP_OUT); if (src_pp_idx > LM_0 || ((cwb_idx + crtc->num_mixers) > CWB_MAX)) { SDE_ERROR("invalid hw config for CWB\n"); return; } if (hw_ctl->ops.update_bitmask_wb) hw_ctl->ops.update_bitmask_wb(hw_ctl, hw_wb->idx, 1); if (hw_ctl->ops.update_bitmask_cdm && hw_cdm) hw_ctl->ops.update_bitmask_cdm(hw_ctl, hw_cdm->idx, 1); if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { for (i = 0; i < crtc->num_mixers; i++) { cwb_idx = (enum sde_cwb) (hw_pp->idx + i); src_pp_idx = (enum sde_cwb) (src_pp_idx + i); if (hw_wb->ops.program_cwb_ctrl) hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx, src_pp_idx, dspp_out); if (hw_ctl->ops.update_bitmask_cwb) hw_ctl->ops.update_bitmask_cwb(hw_ctl, cwb_idx, 1); } if (need_merge && hw_ctl->ops.update_bitmask_merge3d && hw_pp && hw_pp->merge_3d) hw_ctl->ops.update_bitmask_merge3d(hw_ctl, hw_pp->merge_3d->idx, 1); } else { phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, need_merge, dspp_out); } } /** Loading Loading @@ -1035,6 +1115,7 @@ static void sde_encoder_phys_wb_irq_ctrl( struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys); int index = 0; int pp = 0; if (!wb_enc) return; Loading @@ -1042,21 +1123,25 @@ static void sde_encoder_phys_wb_irq_ctrl( if (wb_enc->bypass_irqreg) return; pp = phys->hw_pp->idx - PINGPONG_0; if ((pp + CRTC_DUAL_MIXERS) >= PINGPONG_MAX) { SDE_ERROR("invalid pingpong index for WB or CWB\n"); return; } if (enable) { sde_encoder_helper_register_irq(phys, INTR_IDX_WB_DONE); if (phys->in_clone_mode) { for (index = 0; index < CRTC_DUAL_MIXERS; index++) sde_encoder_helper_register_irq(phys, index ? INTR_IDX_PP3_OVFL : INTR_IDX_PP2_OVFL); cwb_irq_tbl[index + pp]); } } else { sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE); if (phys->in_clone_mode) { for (index = 0; index < CRTC_DUAL_MIXERS; index++) sde_encoder_helper_unregister_irq(phys, index ? INTR_IDX_PP3_OVFL : INTR_IDX_PP2_OVFL); cwb_irq_tbl[index + pp]); } } } Loading Loading @@ -1733,6 +1818,26 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; irq = &phys_enc->irq[INTR_IDX_PP4_OVFL]; INIT_LIST_HEAD(&irq->cb.list); irq->name = "pp4_overflow"; irq->hw_idx = CWB_4; irq->irq_idx = -1; irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; irq->intr_idx = INTR_IDX_PP4_OVFL; irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; irq = &phys_enc->irq[INTR_IDX_PP5_OVFL]; INIT_LIST_HEAD(&irq->cb.list); irq->name = "pp5_overflow"; irq->hw_idx = CWB_5; irq->irq_idx = -1; irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; irq->intr_idx = INTR_IDX_PP5_OVFL; irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; /* create internal buffer for disable logic */ if (_sde_encoder_phys_wb_init_internal_fb(wb_enc, DRM_FORMAT_RGB888, 2, 1, 6)) { Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.c +5 −1 Original line number Diff line number Diff line Loading @@ -1876,8 +1876,11 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_WB_INPUT_CTRL, &wb->features); if (sde_cfg->has_cwb_support) if (sde_cfg->has_cwb_support) { set_bit(SDE_WB_HAS_CWB, &wb->features); if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_WB_CWB_CTRL, &wb->features); } for (j = 0; j < sde_cfg->mdp_count; j++) { sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].reg_off = Loading Loading @@ -3567,6 +3570,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->vbif_qos_nlvl = 8; sde_cfg->ts_prefill_rev = 2; } else if (IS_SM8150_TARGET(hw_rev)) { sde_cfg->has_cwb_support = true; sde_cfg->has_wb_ubwc = true; sde_cfg->has_qsync = true; sde_cfg->perf.min_prefill_lines = 24; Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.h +2 −0 Original line number Diff line number Diff line Loading @@ -329,6 +329,7 @@ enum { * @SDE_WB_INPUT_CTRL Writeback supports from which pp block input pixel * data arrives. * @SDE_WB_HAS_CWB Writeback block supports concurrent writeback * @SDE_WB_CWB_CTRL Separate CWB control is available for configuring * @SDE_WB_MAX maximum value */ enum { Loading @@ -349,6 +350,7 @@ enum { SDE_WB_CDP, SDE_WB_INPUT_CTRL, SDE_WB_HAS_CWB, SDE_WB_CWB_CTRL, SDE_WB_MAX }; Loading drivers/gpu/drm/msm/sde/sde_hw_ctl.c +34 −0 Original line number Diff line number Diff line Loading @@ -954,6 +954,39 @@ static int sde_hw_ctl_reset_post_te_disable(struct sde_hw_ctl *ctx, return 0; } static int sde_hw_ctl_update_cwb_cfg(struct sde_hw_ctl *ctx, struct sde_hw_intf_cfg_v1 *cfg) { int i; u32 cwb_active = 0; u32 merge_3d_active = 0; u32 wb_active = 0; struct sde_hw_blk_reg_map *c; if (!ctx) return -EINVAL; c = &ctx->hw; cwb_active = SDE_REG_READ(c, CTL_CWB_ACTIVE); for (i = 0; i < cfg->cwb_count; i++) { if (cfg->cwb[i]) cwb_active |= BIT(cfg->cwb[i] - CWB_0); } merge_3d_active = SDE_REG_READ(c, CTL_MERGE_3D_ACTIVE); for (i = 0; i < cfg->merge_3d_count; i++) { if (cfg->merge_3d[i]) merge_3d_active |= BIT(cfg->merge_3d[i] - MERGE_3D_0); } wb_active = BIT(2); SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); SDE_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); return 0; } static int sde_hw_ctl_dsc_cfg(struct sde_hw_ctl *ctx, struct sde_ctl_dsc_cfg *cfg) { Loading Loading @@ -1098,6 +1131,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->trigger_flush = sde_hw_ctl_trigger_flush_v1; ops->setup_intf_cfg_v1 = sde_hw_ctl_intf_cfg_v1; ops->update_cwb_cfg = sde_hw_ctl_update_cwb_cfg; ops->setup_dsc_cfg = sde_hw_ctl_dsc_cfg; ops->update_bitmask_cdm = sde_hw_ctl_update_bitmask_cdm_v1; Loading Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys.h +5 −1 Original line number Diff line number Diff line Loading @@ -202,7 +202,9 @@ struct sde_encoder_phys_ops { * @INTR_IDX_RDPTR: Readpointer done unterrupt for cmd mode panel * @INTR_IDX_WB_DONE: Writeback done interrupt for WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP2 for Concurrent WB * @INTR_IDX_PP2_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB * @INTR_IDX_PP3_OVFL: Pingpong overflow interrupt on PP3 for Concurrent WB * @INTR_IDX_PP4_OVFL: Pingpong overflow interrupt on PP4 for Concurrent WB * @INTR_IDX_PP5_OVFL: Pingpong overflow interrupt on PP5 for Concurrent WB * @INTR_IDX_AUTOREFRESH_DONE: Autorefresh done for cmd mode panel meaning * autorefresh has triggered a double buffer flip */ Loading @@ -216,6 +218,8 @@ enum sde_intr_idx { INTR_IDX_WB_DONE, INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, INTR_IDX_MAX, }; Loading
drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +126 −21 Original line number Diff line number Diff line Loading @@ -33,6 +33,11 @@ #define TO_S15D16(_x_) ((_x_) << 7) #define MULTIPLE_CONN_DETECTED(x) (x > 1) static const u32 cwb_irq_tbl[PINGPONG_MAX] = {SDE_NONE, SDE_NONE, INTR_IDX_PP2_OVFL, INTR_IDX_PP3_OVFL, INTR_IDX_PP4_OVFL, INTR_IDX_PP5_OVFL, SDE_NONE, SDE_NONE}; /** * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix * Loading Loading @@ -471,26 +476,66 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); struct sde_hw_wb *hw_wb = wb_enc->hw_wb; struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl; struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc); struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp; bool need_merge = crtc->num_mixers > 1 ? true : false; int i = 0; if (!phys_enc->in_clone_mode) { SDE_DEBUG("not in CWB mode. early return\n"); return; } if (!hw_pp || !hw_ctl || !hw_wb || hw_pp->idx >= PINGPONG_MAX) { SDE_ERROR("invalid hw resources - return\n"); return; } hw_ctl = crtc->mixers[0].hw_ctl; if (hw_ctl && hw_ctl->ops.setup_intf_cfg_v1 && test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { struct sde_hw_intf_cfg_v1 intf_cfg = { 0, }; for (i = 0; i < crtc->num_mixers; i++) intf_cfg.cwb[intf_cfg.cwb_count++] = (enum sde_cwb)(hw_pp->idx + i); if (enable && hw_pp->merge_3d && (intf_cfg.merge_3d_count < MAX_MERGE_3D_PER_CTL_V1) && need_merge) intf_cfg.merge_3d[intf_cfg.merge_3d_count++] = hw_pp->merge_3d->idx; if (hw_pp->ops.setup_3d_mode) hw_pp->ops.setup_3d_mode(hw_pp, (enable && need_merge) ? BLEND_3D_H_ROW_INT : 0); if (hw_wb->ops.bind_pingpong_blk) hw_wb->ops.bind_pingpong_blk(hw_wb, enable, hw_pp->idx); if (hw_ctl->ops.update_cwb_cfg) { hw_ctl->ops.update_cwb_cfg(hw_ctl, &intf_cfg); SDE_DEBUG("in CWB mode on CTL_%d PP-%d merge3d:%d\n", hw_ctl->idx - CTL_0, hw_pp->idx - PINGPONG_0, hw_pp->merge_3d ? hw_pp->merge_3d->idx - MERGE_3D_0 : -1); } } else { struct sde_hw_intf_cfg *intf_cfg = &phys_enc->intf_cfg; memset(intf_cfg, 0, sizeof(struct sde_hw_intf_cfg)); intf_cfg->intf = SDE_NONE; intf_cfg->wb = hw_wb->idx; hw_ctl = crtc->mixers[0].hw_ctl; if (hw_ctl && hw_ctl->ops.update_wb_cfg) { hw_ctl->ops.update_wb_cfg(hw_ctl, intf_cfg, enable); SDE_DEBUG("in CWB mode adding WB for CTL_%d\n", hw_ctl->idx - CTL_0); } } } /** * sde_encoder_phys_wb_setup_cdp - setup chroma down prefetch block * @phys_enc: Pointer to physical encoder Loading Loading @@ -801,9 +846,15 @@ static void _sde_encoder_phys_wb_update_cwb_flush( struct sde_hw_wb *hw_wb; struct sde_hw_ctl *hw_ctl; struct sde_hw_cdm *hw_cdm; struct sde_hw_pingpong *hw_pp; struct sde_crtc *crtc; struct sde_crtc_state *crtc_state; int capture_point = 0; int i = 0; int cwb_capture_mode = 0; enum sde_cwb cwb_idx = 0; enum sde_cwb src_pp_idx = 0; bool dspp_out = false; bool need_merge = false; if (!phys_enc->in_clone_mode) { SDE_DEBUG("not in CWB mode. early return\n"); Loading @@ -813,30 +864,59 @@ static void _sde_encoder_phys_wb_update_cwb_flush( wb_enc = to_sde_encoder_phys_wb(phys_enc); crtc = to_sde_crtc(wb_enc->crtc); crtc_state = to_sde_crtc_state(wb_enc->crtc->state); cwb_capture_mode = sde_crtc_get_property(crtc_state, CRTC_PROP_CAPTURE_OUTPUT); hw_pp = phys_enc->hw_pp; hw_wb = wb_enc->hw_wb; hw_cdm = phys_enc->hw_cdm; /* In CWB mode, program actual source master sde_hw_ctl from crtc */ hw_ctl = crtc->mixers[0].hw_ctl; if (!hw_ctl) { SDE_DEBUG("[wb:%d] no ctl assigned for CWB\n", hw_wb->idx - WB_0); if (!hw_ctl || !hw_wb || !hw_pp) { SDE_ERROR("[wb] HW resource not available for CWB\n"); return; } capture_point = sde_crtc_get_property(crtc_state, CRTC_PROP_CAPTURE_OUTPUT); /* treating LM idx of primary display ctl path as source ping-pong idx*/ src_pp_idx = (enum sde_cwb)crtc->mixers[0].hw_lm->idx; cwb_idx = (enum sde_cwb)hw_pp->idx; dspp_out = (cwb_capture_mode == CAPTURE_DSPP_OUT); need_merge = (crtc->num_mixers > 1) ? true : false; phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, crtc->num_mixers == CRTC_DUAL_MIXERS, capture_point == CAPTURE_DSPP_OUT); if (src_pp_idx > LM_0 || ((cwb_idx + crtc->num_mixers) > CWB_MAX)) { SDE_ERROR("invalid hw config for CWB\n"); return; } if (hw_ctl->ops.update_bitmask_wb) hw_ctl->ops.update_bitmask_wb(hw_ctl, hw_wb->idx, 1); if (hw_ctl->ops.update_bitmask_cdm && hw_cdm) hw_ctl->ops.update_bitmask_cdm(hw_ctl, hw_cdm->idx, 1); if (test_bit(SDE_WB_CWB_CTRL, &hw_wb->caps->features)) { for (i = 0; i < crtc->num_mixers; i++) { cwb_idx = (enum sde_cwb) (hw_pp->idx + i); src_pp_idx = (enum sde_cwb) (src_pp_idx + i); if (hw_wb->ops.program_cwb_ctrl) hw_wb->ops.program_cwb_ctrl(hw_wb, cwb_idx, src_pp_idx, dspp_out); if (hw_ctl->ops.update_bitmask_cwb) hw_ctl->ops.update_bitmask_cwb(hw_ctl, cwb_idx, 1); } if (need_merge && hw_ctl->ops.update_bitmask_merge3d && hw_pp && hw_pp->merge_3d) hw_ctl->ops.update_bitmask_merge3d(hw_ctl, hw_pp->merge_3d->idx, 1); } else { phys_enc->hw_mdptop->ops.set_cwb_ppb_cntl(phys_enc->hw_mdptop, need_merge, dspp_out); } } /** Loading Loading @@ -1035,6 +1115,7 @@ static void sde_encoder_phys_wb_irq_ctrl( struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys); int index = 0; int pp = 0; if (!wb_enc) return; Loading @@ -1042,21 +1123,25 @@ static void sde_encoder_phys_wb_irq_ctrl( if (wb_enc->bypass_irqreg) return; pp = phys->hw_pp->idx - PINGPONG_0; if ((pp + CRTC_DUAL_MIXERS) >= PINGPONG_MAX) { SDE_ERROR("invalid pingpong index for WB or CWB\n"); return; } if (enable) { sde_encoder_helper_register_irq(phys, INTR_IDX_WB_DONE); if (phys->in_clone_mode) { for (index = 0; index < CRTC_DUAL_MIXERS; index++) sde_encoder_helper_register_irq(phys, index ? INTR_IDX_PP3_OVFL : INTR_IDX_PP2_OVFL); cwb_irq_tbl[index + pp]); } } else { sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE); if (phys->in_clone_mode) { for (index = 0; index < CRTC_DUAL_MIXERS; index++) sde_encoder_helper_unregister_irq(phys, index ? INTR_IDX_PP3_OVFL : INTR_IDX_PP2_OVFL); cwb_irq_tbl[index + pp]); } } } Loading Loading @@ -1733,6 +1818,26 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; irq = &phys_enc->irq[INTR_IDX_PP4_OVFL]; INIT_LIST_HEAD(&irq->cb.list); irq->name = "pp4_overflow"; irq->hw_idx = CWB_4; irq->irq_idx = -1; irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; irq->intr_idx = INTR_IDX_PP4_OVFL; irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; irq = &phys_enc->irq[INTR_IDX_PP5_OVFL]; INIT_LIST_HEAD(&irq->cb.list); irq->name = "pp5_overflow"; irq->hw_idx = CWB_5; irq->irq_idx = -1; irq->intr_type = SDE_IRQ_TYPE_CWB_OVERFLOW; irq->intr_idx = INTR_IDX_PP5_OVFL; irq->cb.arg = wb_enc; irq->cb.func = sde_encoder_phys_cwb_ovflow; /* create internal buffer for disable logic */ if (_sde_encoder_phys_wb_init_internal_fb(wb_enc, DRM_FORMAT_RGB888, 2, 1, 6)) { Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.c +5 −1 Original line number Diff line number Diff line Loading @@ -1876,8 +1876,11 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_WB_INPUT_CTRL, &wb->features); if (sde_cfg->has_cwb_support) if (sde_cfg->has_cwb_support) { set_bit(SDE_WB_HAS_CWB, &wb->features); if (IS_SDE_CTL_REV_100(sde_cfg->ctl_rev)) set_bit(SDE_WB_CWB_CTRL, &wb->features); } for (j = 0; j < sde_cfg->mdp_count; j++) { sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].reg_off = Loading Loading @@ -3567,6 +3570,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->vbif_qos_nlvl = 8; sde_cfg->ts_prefill_rev = 2; } else if (IS_SM8150_TARGET(hw_rev)) { sde_cfg->has_cwb_support = true; sde_cfg->has_wb_ubwc = true; sde_cfg->has_qsync = true; sde_cfg->perf.min_prefill_lines = 24; Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.h +2 −0 Original line number Diff line number Diff line Loading @@ -329,6 +329,7 @@ enum { * @SDE_WB_INPUT_CTRL Writeback supports from which pp block input pixel * data arrives. * @SDE_WB_HAS_CWB Writeback block supports concurrent writeback * @SDE_WB_CWB_CTRL Separate CWB control is available for configuring * @SDE_WB_MAX maximum value */ enum { Loading @@ -349,6 +350,7 @@ enum { SDE_WB_CDP, SDE_WB_INPUT_CTRL, SDE_WB_HAS_CWB, SDE_WB_CWB_CTRL, SDE_WB_MAX }; Loading
drivers/gpu/drm/msm/sde/sde_hw_ctl.c +34 −0 Original line number Diff line number Diff line Loading @@ -954,6 +954,39 @@ static int sde_hw_ctl_reset_post_te_disable(struct sde_hw_ctl *ctx, return 0; } static int sde_hw_ctl_update_cwb_cfg(struct sde_hw_ctl *ctx, struct sde_hw_intf_cfg_v1 *cfg) { int i; u32 cwb_active = 0; u32 merge_3d_active = 0; u32 wb_active = 0; struct sde_hw_blk_reg_map *c; if (!ctx) return -EINVAL; c = &ctx->hw; cwb_active = SDE_REG_READ(c, CTL_CWB_ACTIVE); for (i = 0; i < cfg->cwb_count; i++) { if (cfg->cwb[i]) cwb_active |= BIT(cfg->cwb[i] - CWB_0); } merge_3d_active = SDE_REG_READ(c, CTL_MERGE_3D_ACTIVE); for (i = 0; i < cfg->merge_3d_count; i++) { if (cfg->merge_3d[i]) merge_3d_active |= BIT(cfg->merge_3d[i] - MERGE_3D_0); } wb_active = BIT(2); SDE_REG_WRITE(c, CTL_WB_ACTIVE, wb_active); SDE_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active); SDE_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active); return 0; } static int sde_hw_ctl_dsc_cfg(struct sde_hw_ctl *ctx, struct sde_ctl_dsc_cfg *cfg) { Loading Loading @@ -1098,6 +1131,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->trigger_flush = sde_hw_ctl_trigger_flush_v1; ops->setup_intf_cfg_v1 = sde_hw_ctl_intf_cfg_v1; ops->update_cwb_cfg = sde_hw_ctl_update_cwb_cfg; ops->setup_dsc_cfg = sde_hw_ctl_dsc_cfg; ops->update_bitmask_cdm = sde_hw_ctl_update_bitmask_cdm_v1; Loading