197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 225fdd593SJeykumar Sankaran /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. 325fdd593SJeykumar Sankaran */ 425fdd593SJeykumar Sankaran 525fdd593SJeykumar Sankaran #include <linux/delay.h> 625fdd593SJeykumar Sankaran #include "dpu_hwio.h" 725fdd593SJeykumar Sankaran #include "dpu_hw_ctl.h" 825fdd593SJeykumar Sankaran #include "dpu_kms.h" 9812eeeb6SSean Paul #include "dpu_trace.h" 1025fdd593SJeykumar Sankaran 1125fdd593SJeykumar Sankaran #define CTL_LAYER(lm) \ 1225fdd593SJeykumar Sankaran (((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004)) 1325fdd593SJeykumar Sankaran #define CTL_LAYER_EXT(lm) \ 1425fdd593SJeykumar Sankaran (0x40 + (((lm) - LM_0) * 0x004)) 1525fdd593SJeykumar Sankaran #define CTL_LAYER_EXT2(lm) \ 1625fdd593SJeykumar Sankaran (0x70 + (((lm) - LM_0) * 0x004)) 1725fdd593SJeykumar Sankaran #define CTL_LAYER_EXT3(lm) \ 1825fdd593SJeykumar Sankaran (0xA0 + (((lm) - LM_0) * 0x004)) 1925fdd593SJeykumar Sankaran #define CTL_TOP 0x014 2025fdd593SJeykumar Sankaran #define CTL_FLUSH 0x018 2125fdd593SJeykumar Sankaran #define CTL_START 0x01C 2225fdd593SJeykumar Sankaran #define CTL_PREPARE 0x0d0 2325fdd593SJeykumar Sankaran #define CTL_SW_RESET 0x030 2425fdd593SJeykumar Sankaran #define CTL_LAYER_EXTN_OFFSET 0x40 2525fdd593SJeykumar Sankaran 2625fdd593SJeykumar Sankaran #define CTL_MIXER_BORDER_OUT BIT(24) 2725fdd593SJeykumar Sankaran #define CTL_FLUSH_MASK_CTL BIT(17) 2825fdd593SJeykumar Sankaran 2925fdd593SJeykumar Sankaran #define DPU_REG_RESET_TIMEOUT_US 2000 3025fdd593SJeykumar Sankaran 31abda0d92SStephen Boyd static const struct dpu_ctl_cfg *_ctl_offset(enum dpu_ctl ctl, 32abda0d92SStephen Boyd const struct dpu_mdss_cfg *m, 3325fdd593SJeykumar Sankaran void __iomem *addr, 3425fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *b) 3525fdd593SJeykumar Sankaran { 3625fdd593SJeykumar Sankaran int i; 3725fdd593SJeykumar Sankaran 3825fdd593SJeykumar Sankaran for (i = 0; i < m->ctl_count; i++) { 3925fdd593SJeykumar Sankaran if (ctl == m->ctl[i].id) { 4025fdd593SJeykumar Sankaran b->base_off = addr; 4125fdd593SJeykumar Sankaran b->blk_off = m->ctl[i].base; 4225fdd593SJeykumar Sankaran b->length = m->ctl[i].len; 4325fdd593SJeykumar Sankaran b->hwversion = m->hwversion; 4425fdd593SJeykumar Sankaran b->log_mask = DPU_DBG_MASK_CTL; 4525fdd593SJeykumar Sankaran return &m->ctl[i]; 4625fdd593SJeykumar Sankaran } 4725fdd593SJeykumar Sankaran } 4825fdd593SJeykumar Sankaran return ERR_PTR(-ENOMEM); 4925fdd593SJeykumar Sankaran } 5025fdd593SJeykumar Sankaran 5125fdd593SJeykumar Sankaran static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count, 5225fdd593SJeykumar Sankaran enum dpu_lm lm) 5325fdd593SJeykumar Sankaran { 5425fdd593SJeykumar Sankaran int i; 5525fdd593SJeykumar Sankaran int stages = -EINVAL; 5625fdd593SJeykumar Sankaran 5725fdd593SJeykumar Sankaran for (i = 0; i < count; i++) { 5825fdd593SJeykumar Sankaran if (lm == mixer[i].id) { 5925fdd593SJeykumar Sankaran stages = mixer[i].sblk->maxblendstages; 6025fdd593SJeykumar Sankaran break; 6125fdd593SJeykumar Sankaran } 6225fdd593SJeykumar Sankaran } 6325fdd593SJeykumar Sankaran 6425fdd593SJeykumar Sankaran return stages; 6525fdd593SJeykumar Sankaran } 6625fdd593SJeykumar Sankaran 67812eeeb6SSean Paul static inline u32 dpu_hw_ctl_get_flush_register(struct dpu_hw_ctl *ctx) 68812eeeb6SSean Paul { 69812eeeb6SSean Paul struct dpu_hw_blk_reg_map *c = &ctx->hw; 70812eeeb6SSean Paul 71812eeeb6SSean Paul return DPU_REG_READ(c, CTL_FLUSH); 72812eeeb6SSean Paul } 73812eeeb6SSean Paul 7425fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx) 7525fdd593SJeykumar Sankaran { 76812eeeb6SSean Paul trace_dpu_hw_ctl_trigger_start(ctx->pending_flush_mask, 77812eeeb6SSean Paul dpu_hw_ctl_get_flush_register(ctx)); 7825fdd593SJeykumar Sankaran DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1); 7925fdd593SJeykumar Sankaran } 8025fdd593SJeykumar Sankaran 8125fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx) 8225fdd593SJeykumar Sankaran { 83812eeeb6SSean Paul trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask, 84812eeeb6SSean Paul dpu_hw_ctl_get_flush_register(ctx)); 8525fdd593SJeykumar Sankaran DPU_REG_WRITE(&ctx->hw, CTL_PREPARE, 0x1); 8625fdd593SJeykumar Sankaran } 8725fdd593SJeykumar Sankaran 8825fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx) 8925fdd593SJeykumar Sankaran { 90812eeeb6SSean Paul trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask, 91812eeeb6SSean Paul dpu_hw_ctl_get_flush_register(ctx)); 9225fdd593SJeykumar Sankaran ctx->pending_flush_mask = 0x0; 9325fdd593SJeykumar Sankaran } 9425fdd593SJeykumar Sankaran 9525fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl *ctx, 9625fdd593SJeykumar Sankaran u32 flushbits) 9725fdd593SJeykumar Sankaran { 98812eeeb6SSean Paul trace_dpu_hw_ctl_update_pending_flush(flushbits, 99812eeeb6SSean Paul ctx->pending_flush_mask); 10025fdd593SJeykumar Sankaran ctx->pending_flush_mask |= flushbits; 10125fdd593SJeykumar Sankaran } 10225fdd593SJeykumar Sankaran 10325fdd593SJeykumar Sankaran static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx) 10425fdd593SJeykumar Sankaran { 10525fdd593SJeykumar Sankaran return ctx->pending_flush_mask; 10625fdd593SJeykumar Sankaran } 10725fdd593SJeykumar Sankaran 10825fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx) 10925fdd593SJeykumar Sankaran { 110812eeeb6SSean Paul trace_dpu_hw_ctl_trigger_pending_flush(ctx->pending_flush_mask, 111812eeeb6SSean Paul dpu_hw_ctl_get_flush_register(ctx)); 11225fdd593SJeykumar Sankaran DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask); 11325fdd593SJeykumar Sankaran } 11425fdd593SJeykumar Sankaran 11558fba464SSean Paul static uint32_t dpu_hw_ctl_get_bitmask_sspp(struct dpu_hw_ctl *ctx, 11625fdd593SJeykumar Sankaran enum dpu_sspp sspp) 11725fdd593SJeykumar Sankaran { 11825fdd593SJeykumar Sankaran uint32_t flushbits = 0; 11925fdd593SJeykumar Sankaran 12025fdd593SJeykumar Sankaran switch (sspp) { 12125fdd593SJeykumar Sankaran case SSPP_VIG0: 12225fdd593SJeykumar Sankaran flushbits = BIT(0); 12325fdd593SJeykumar Sankaran break; 12425fdd593SJeykumar Sankaran case SSPP_VIG1: 12525fdd593SJeykumar Sankaran flushbits = BIT(1); 12625fdd593SJeykumar Sankaran break; 12725fdd593SJeykumar Sankaran case SSPP_VIG2: 12825fdd593SJeykumar Sankaran flushbits = BIT(2); 12925fdd593SJeykumar Sankaran break; 13025fdd593SJeykumar Sankaran case SSPP_VIG3: 13125fdd593SJeykumar Sankaran flushbits = BIT(18); 13225fdd593SJeykumar Sankaran break; 13325fdd593SJeykumar Sankaran case SSPP_RGB0: 13425fdd593SJeykumar Sankaran flushbits = BIT(3); 13525fdd593SJeykumar Sankaran break; 13625fdd593SJeykumar Sankaran case SSPP_RGB1: 13725fdd593SJeykumar Sankaran flushbits = BIT(4); 13825fdd593SJeykumar Sankaran break; 13925fdd593SJeykumar Sankaran case SSPP_RGB2: 14025fdd593SJeykumar Sankaran flushbits = BIT(5); 14125fdd593SJeykumar Sankaran break; 14225fdd593SJeykumar Sankaran case SSPP_RGB3: 14325fdd593SJeykumar Sankaran flushbits = BIT(19); 14425fdd593SJeykumar Sankaran break; 14525fdd593SJeykumar Sankaran case SSPP_DMA0: 14625fdd593SJeykumar Sankaran flushbits = BIT(11); 14725fdd593SJeykumar Sankaran break; 14825fdd593SJeykumar Sankaran case SSPP_DMA1: 14925fdd593SJeykumar Sankaran flushbits = BIT(12); 15025fdd593SJeykumar Sankaran break; 15125fdd593SJeykumar Sankaran case SSPP_DMA2: 15225fdd593SJeykumar Sankaran flushbits = BIT(24); 15325fdd593SJeykumar Sankaran break; 15425fdd593SJeykumar Sankaran case SSPP_DMA3: 15525fdd593SJeykumar Sankaran flushbits = BIT(25); 15625fdd593SJeykumar Sankaran break; 15725fdd593SJeykumar Sankaran case SSPP_CURSOR0: 15825fdd593SJeykumar Sankaran flushbits = BIT(22); 15925fdd593SJeykumar Sankaran break; 16025fdd593SJeykumar Sankaran case SSPP_CURSOR1: 16125fdd593SJeykumar Sankaran flushbits = BIT(23); 16225fdd593SJeykumar Sankaran break; 16325fdd593SJeykumar Sankaran default: 16425fdd593SJeykumar Sankaran break; 16525fdd593SJeykumar Sankaran } 16625fdd593SJeykumar Sankaran 16725fdd593SJeykumar Sankaran return flushbits; 16825fdd593SJeykumar Sankaran } 16925fdd593SJeykumar Sankaran 17058fba464SSean Paul static uint32_t dpu_hw_ctl_get_bitmask_mixer(struct dpu_hw_ctl *ctx, 17125fdd593SJeykumar Sankaran enum dpu_lm lm) 17225fdd593SJeykumar Sankaran { 17325fdd593SJeykumar Sankaran uint32_t flushbits = 0; 17425fdd593SJeykumar Sankaran 17525fdd593SJeykumar Sankaran switch (lm) { 17625fdd593SJeykumar Sankaran case LM_0: 17725fdd593SJeykumar Sankaran flushbits = BIT(6); 17825fdd593SJeykumar Sankaran break; 17925fdd593SJeykumar Sankaran case LM_1: 18025fdd593SJeykumar Sankaran flushbits = BIT(7); 18125fdd593SJeykumar Sankaran break; 18225fdd593SJeykumar Sankaran case LM_2: 18325fdd593SJeykumar Sankaran flushbits = BIT(8); 18425fdd593SJeykumar Sankaran break; 18525fdd593SJeykumar Sankaran case LM_3: 18625fdd593SJeykumar Sankaran flushbits = BIT(9); 18725fdd593SJeykumar Sankaran break; 18825fdd593SJeykumar Sankaran case LM_4: 18925fdd593SJeykumar Sankaran flushbits = BIT(10); 19025fdd593SJeykumar Sankaran break; 19125fdd593SJeykumar Sankaran case LM_5: 19225fdd593SJeykumar Sankaran flushbits = BIT(20); 19325fdd593SJeykumar Sankaran break; 19425fdd593SJeykumar Sankaran default: 19525fdd593SJeykumar Sankaran return -EINVAL; 19625fdd593SJeykumar Sankaran } 19725fdd593SJeykumar Sankaran 19825fdd593SJeykumar Sankaran flushbits |= CTL_FLUSH_MASK_CTL; 19925fdd593SJeykumar Sankaran 20025fdd593SJeykumar Sankaran return flushbits; 20125fdd593SJeykumar Sankaran } 20225fdd593SJeykumar Sankaran 20358fba464SSean Paul static int dpu_hw_ctl_get_bitmask_intf(struct dpu_hw_ctl *ctx, 20425fdd593SJeykumar Sankaran u32 *flushbits, enum dpu_intf intf) 20525fdd593SJeykumar Sankaran { 20625fdd593SJeykumar Sankaran switch (intf) { 20725fdd593SJeykumar Sankaran case INTF_0: 20825fdd593SJeykumar Sankaran *flushbits |= BIT(31); 20925fdd593SJeykumar Sankaran break; 21025fdd593SJeykumar Sankaran case INTF_1: 21125fdd593SJeykumar Sankaran *flushbits |= BIT(30); 21225fdd593SJeykumar Sankaran break; 21325fdd593SJeykumar Sankaran case INTF_2: 21425fdd593SJeykumar Sankaran *flushbits |= BIT(29); 21525fdd593SJeykumar Sankaran break; 21625fdd593SJeykumar Sankaran case INTF_3: 21725fdd593SJeykumar Sankaran *flushbits |= BIT(28); 21825fdd593SJeykumar Sankaran break; 21925fdd593SJeykumar Sankaran default: 22025fdd593SJeykumar Sankaran return -EINVAL; 22125fdd593SJeykumar Sankaran } 22225fdd593SJeykumar Sankaran return 0; 22325fdd593SJeykumar Sankaran } 22425fdd593SJeykumar Sankaran 22525fdd593SJeykumar Sankaran static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us) 22625fdd593SJeykumar Sankaran { 22725fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *c = &ctx->hw; 22825fdd593SJeykumar Sankaran ktime_t timeout; 22925fdd593SJeykumar Sankaran u32 status; 23025fdd593SJeykumar Sankaran 23125fdd593SJeykumar Sankaran timeout = ktime_add_us(ktime_get(), timeout_us); 23225fdd593SJeykumar Sankaran 23325fdd593SJeykumar Sankaran /* 23425fdd593SJeykumar Sankaran * it takes around 30us to have mdp finish resetting its ctl path 23525fdd593SJeykumar Sankaran * poll every 50us so that reset should be completed at 1st poll 23625fdd593SJeykumar Sankaran */ 23725fdd593SJeykumar Sankaran do { 23825fdd593SJeykumar Sankaran status = DPU_REG_READ(c, CTL_SW_RESET); 23925fdd593SJeykumar Sankaran status &= 0x1; 24025fdd593SJeykumar Sankaran if (status) 24125fdd593SJeykumar Sankaran usleep_range(20, 50); 24225fdd593SJeykumar Sankaran } while (status && ktime_compare_safe(ktime_get(), timeout) < 0); 24325fdd593SJeykumar Sankaran 24425fdd593SJeykumar Sankaran return status; 24525fdd593SJeykumar Sankaran } 24625fdd593SJeykumar Sankaran 24725fdd593SJeykumar Sankaran static int dpu_hw_ctl_reset_control(struct dpu_hw_ctl *ctx) 24825fdd593SJeykumar Sankaran { 24925fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *c = &ctx->hw; 25025fdd593SJeykumar Sankaran 25125fdd593SJeykumar Sankaran pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx); 25225fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_SW_RESET, 0x1); 25325fdd593SJeykumar Sankaran if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US)) 25425fdd593SJeykumar Sankaran return -EINVAL; 25525fdd593SJeykumar Sankaran 25625fdd593SJeykumar Sankaran return 0; 25725fdd593SJeykumar Sankaran } 25825fdd593SJeykumar Sankaran 25925fdd593SJeykumar Sankaran static int dpu_hw_ctl_wait_reset_status(struct dpu_hw_ctl *ctx) 26025fdd593SJeykumar Sankaran { 26125fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *c = &ctx->hw; 26225fdd593SJeykumar Sankaran u32 status; 26325fdd593SJeykumar Sankaran 26425fdd593SJeykumar Sankaran status = DPU_REG_READ(c, CTL_SW_RESET); 26525fdd593SJeykumar Sankaran status &= 0x01; 26625fdd593SJeykumar Sankaran if (!status) 26725fdd593SJeykumar Sankaran return 0; 26825fdd593SJeykumar Sankaran 26925fdd593SJeykumar Sankaran pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx); 27025fdd593SJeykumar Sankaran if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US)) { 27125fdd593SJeykumar Sankaran pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx); 27225fdd593SJeykumar Sankaran return -EINVAL; 27325fdd593SJeykumar Sankaran } 27425fdd593SJeykumar Sankaran 27525fdd593SJeykumar Sankaran return 0; 27625fdd593SJeykumar Sankaran } 27725fdd593SJeykumar Sankaran 27825fdd593SJeykumar Sankaran static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx) 27925fdd593SJeykumar Sankaran { 28025fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *c = &ctx->hw; 28125fdd593SJeykumar Sankaran int i; 28225fdd593SJeykumar Sankaran 28325fdd593SJeykumar Sankaran for (i = 0; i < ctx->mixer_count; i++) { 28425fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER(LM_0 + i), 0); 28525fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER_EXT(LM_0 + i), 0); 28625fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER_EXT2(LM_0 + i), 0); 28725fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER_EXT3(LM_0 + i), 0); 28825fdd593SJeykumar Sankaran } 28925fdd593SJeykumar Sankaran } 29025fdd593SJeykumar Sankaran 29125fdd593SJeykumar Sankaran static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx, 29225fdd593SJeykumar Sankaran enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg) 29325fdd593SJeykumar Sankaran { 29425fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *c = &ctx->hw; 29525fdd593SJeykumar Sankaran u32 mixercfg = 0, mixercfg_ext = 0, mix, ext; 29625fdd593SJeykumar Sankaran u32 mixercfg_ext2 = 0, mixercfg_ext3 = 0; 29725fdd593SJeykumar Sankaran int i, j; 298dfdb3be4SColin Ian King int stages; 29925fdd593SJeykumar Sankaran int pipes_per_stage; 30025fdd593SJeykumar Sankaran 30125fdd593SJeykumar Sankaran stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm); 30225fdd593SJeykumar Sankaran if (stages < 0) 30325fdd593SJeykumar Sankaran return; 30425fdd593SJeykumar Sankaran 30525fdd593SJeykumar Sankaran if (test_bit(DPU_MIXER_SOURCESPLIT, 30625fdd593SJeykumar Sankaran &ctx->mixer_hw_caps->features)) 30725fdd593SJeykumar Sankaran pipes_per_stage = PIPES_PER_STAGE; 30825fdd593SJeykumar Sankaran else 30925fdd593SJeykumar Sankaran pipes_per_stage = 1; 31025fdd593SJeykumar Sankaran 31125fdd593SJeykumar Sankaran mixercfg = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */ 31225fdd593SJeykumar Sankaran 31325fdd593SJeykumar Sankaran if (!stage_cfg) 31425fdd593SJeykumar Sankaran goto exit; 31525fdd593SJeykumar Sankaran 31625fdd593SJeykumar Sankaran for (i = 0; i <= stages; i++) { 31725fdd593SJeykumar Sankaran /* overflow to ext register if 'i + 1 > 7' */ 31825fdd593SJeykumar Sankaran mix = (i + 1) & 0x7; 31925fdd593SJeykumar Sankaran ext = i >= 7; 32025fdd593SJeykumar Sankaran 32125fdd593SJeykumar Sankaran for (j = 0 ; j < pipes_per_stage; j++) { 32225fdd593SJeykumar Sankaran enum dpu_sspp_multirect_index rect_index = 32325fdd593SJeykumar Sankaran stage_cfg->multirect_index[i][j]; 32425fdd593SJeykumar Sankaran 32525fdd593SJeykumar Sankaran switch (stage_cfg->stage[i][j]) { 32625fdd593SJeykumar Sankaran case SSPP_VIG0: 32725fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 32825fdd593SJeykumar Sankaran mixercfg_ext3 |= ((i + 1) & 0xF) << 0; 32925fdd593SJeykumar Sankaran } else { 33025fdd593SJeykumar Sankaran mixercfg |= mix << 0; 33125fdd593SJeykumar Sankaran mixercfg_ext |= ext << 0; 33225fdd593SJeykumar Sankaran } 33325fdd593SJeykumar Sankaran break; 33425fdd593SJeykumar Sankaran case SSPP_VIG1: 33525fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 33625fdd593SJeykumar Sankaran mixercfg_ext3 |= ((i + 1) & 0xF) << 4; 33725fdd593SJeykumar Sankaran } else { 33825fdd593SJeykumar Sankaran mixercfg |= mix << 3; 33925fdd593SJeykumar Sankaran mixercfg_ext |= ext << 2; 34025fdd593SJeykumar Sankaran } 34125fdd593SJeykumar Sankaran break; 34225fdd593SJeykumar Sankaran case SSPP_VIG2: 34325fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 34425fdd593SJeykumar Sankaran mixercfg_ext3 |= ((i + 1) & 0xF) << 8; 34525fdd593SJeykumar Sankaran } else { 34625fdd593SJeykumar Sankaran mixercfg |= mix << 6; 34725fdd593SJeykumar Sankaran mixercfg_ext |= ext << 4; 34825fdd593SJeykumar Sankaran } 34925fdd593SJeykumar Sankaran break; 35025fdd593SJeykumar Sankaran case SSPP_VIG3: 35125fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 35225fdd593SJeykumar Sankaran mixercfg_ext3 |= ((i + 1) & 0xF) << 12; 35325fdd593SJeykumar Sankaran } else { 35425fdd593SJeykumar Sankaran mixercfg |= mix << 26; 35525fdd593SJeykumar Sankaran mixercfg_ext |= ext << 6; 35625fdd593SJeykumar Sankaran } 35725fdd593SJeykumar Sankaran break; 35825fdd593SJeykumar Sankaran case SSPP_RGB0: 35925fdd593SJeykumar Sankaran mixercfg |= mix << 9; 36025fdd593SJeykumar Sankaran mixercfg_ext |= ext << 8; 36125fdd593SJeykumar Sankaran break; 36225fdd593SJeykumar Sankaran case SSPP_RGB1: 36325fdd593SJeykumar Sankaran mixercfg |= mix << 12; 36425fdd593SJeykumar Sankaran mixercfg_ext |= ext << 10; 36525fdd593SJeykumar Sankaran break; 36625fdd593SJeykumar Sankaran case SSPP_RGB2: 36725fdd593SJeykumar Sankaran mixercfg |= mix << 15; 36825fdd593SJeykumar Sankaran mixercfg_ext |= ext << 12; 36925fdd593SJeykumar Sankaran break; 37025fdd593SJeykumar Sankaran case SSPP_RGB3: 37125fdd593SJeykumar Sankaran mixercfg |= mix << 29; 37225fdd593SJeykumar Sankaran mixercfg_ext |= ext << 14; 37325fdd593SJeykumar Sankaran break; 37425fdd593SJeykumar Sankaran case SSPP_DMA0: 37525fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 37625fdd593SJeykumar Sankaran mixercfg_ext2 |= ((i + 1) & 0xF) << 8; 37725fdd593SJeykumar Sankaran } else { 37825fdd593SJeykumar Sankaran mixercfg |= mix << 18; 37925fdd593SJeykumar Sankaran mixercfg_ext |= ext << 16; 38025fdd593SJeykumar Sankaran } 38125fdd593SJeykumar Sankaran break; 38225fdd593SJeykumar Sankaran case SSPP_DMA1: 38325fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 38425fdd593SJeykumar Sankaran mixercfg_ext2 |= ((i + 1) & 0xF) << 12; 38525fdd593SJeykumar Sankaran } else { 38625fdd593SJeykumar Sankaran mixercfg |= mix << 21; 38725fdd593SJeykumar Sankaran mixercfg_ext |= ext << 18; 38825fdd593SJeykumar Sankaran } 38925fdd593SJeykumar Sankaran break; 39025fdd593SJeykumar Sankaran case SSPP_DMA2: 39125fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 39225fdd593SJeykumar Sankaran mixercfg_ext2 |= ((i + 1) & 0xF) << 16; 39325fdd593SJeykumar Sankaran } else { 39425fdd593SJeykumar Sankaran mix |= (i + 1) & 0xF; 39525fdd593SJeykumar Sankaran mixercfg_ext2 |= mix << 0; 39625fdd593SJeykumar Sankaran } 39725fdd593SJeykumar Sankaran break; 39825fdd593SJeykumar Sankaran case SSPP_DMA3: 39925fdd593SJeykumar Sankaran if (rect_index == DPU_SSPP_RECT_1) { 40025fdd593SJeykumar Sankaran mixercfg_ext2 |= ((i + 1) & 0xF) << 20; 40125fdd593SJeykumar Sankaran } else { 40225fdd593SJeykumar Sankaran mix |= (i + 1) & 0xF; 40325fdd593SJeykumar Sankaran mixercfg_ext2 |= mix << 4; 40425fdd593SJeykumar Sankaran } 40525fdd593SJeykumar Sankaran break; 40625fdd593SJeykumar Sankaran case SSPP_CURSOR0: 40725fdd593SJeykumar Sankaran mixercfg_ext |= ((i + 1) & 0xF) << 20; 40825fdd593SJeykumar Sankaran break; 40925fdd593SJeykumar Sankaran case SSPP_CURSOR1: 41025fdd593SJeykumar Sankaran mixercfg_ext |= ((i + 1) & 0xF) << 26; 41125fdd593SJeykumar Sankaran break; 41225fdd593SJeykumar Sankaran default: 41325fdd593SJeykumar Sankaran break; 41425fdd593SJeykumar Sankaran } 41525fdd593SJeykumar Sankaran } 41625fdd593SJeykumar Sankaran } 41725fdd593SJeykumar Sankaran 41825fdd593SJeykumar Sankaran exit: 41925fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg); 42025fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg_ext); 42125fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg_ext2); 42225fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg_ext3); 42325fdd593SJeykumar Sankaran } 42425fdd593SJeykumar Sankaran 42525fdd593SJeykumar Sankaran static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx, 42625fdd593SJeykumar Sankaran struct dpu_hw_intf_cfg *cfg) 42725fdd593SJeykumar Sankaran { 42825fdd593SJeykumar Sankaran struct dpu_hw_blk_reg_map *c = &ctx->hw; 42925fdd593SJeykumar Sankaran u32 intf_cfg = 0; 43025fdd593SJeykumar Sankaran 43125fdd593SJeykumar Sankaran intf_cfg |= (cfg->intf & 0xF) << 4; 43225fdd593SJeykumar Sankaran 43325fdd593SJeykumar Sankaran if (cfg->mode_3d) { 43425fdd593SJeykumar Sankaran intf_cfg |= BIT(19); 43525fdd593SJeykumar Sankaran intf_cfg |= (cfg->mode_3d - 0x1) << 20; 43625fdd593SJeykumar Sankaran } 43725fdd593SJeykumar Sankaran 43825fdd593SJeykumar Sankaran switch (cfg->intf_mode_sel) { 43925fdd593SJeykumar Sankaran case DPU_CTL_MODE_SEL_VID: 44025fdd593SJeykumar Sankaran intf_cfg &= ~BIT(17); 44125fdd593SJeykumar Sankaran intf_cfg &= ~(0x3 << 15); 44225fdd593SJeykumar Sankaran break; 44325fdd593SJeykumar Sankaran case DPU_CTL_MODE_SEL_CMD: 44425fdd593SJeykumar Sankaran intf_cfg |= BIT(17); 44525fdd593SJeykumar Sankaran intf_cfg |= ((cfg->stream_sel & 0x3) << 15); 44625fdd593SJeykumar Sankaran break; 44725fdd593SJeykumar Sankaran default: 44825fdd593SJeykumar Sankaran pr_err("unknown interface type %d\n", cfg->intf_mode_sel); 44925fdd593SJeykumar Sankaran return; 45025fdd593SJeykumar Sankaran } 45125fdd593SJeykumar Sankaran 45225fdd593SJeykumar Sankaran DPU_REG_WRITE(c, CTL_TOP, intf_cfg); 45325fdd593SJeykumar Sankaran } 45425fdd593SJeykumar Sankaran 45525fdd593SJeykumar Sankaran static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops, 45625fdd593SJeykumar Sankaran unsigned long cap) 45725fdd593SJeykumar Sankaran { 45825fdd593SJeykumar Sankaran ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush; 45925fdd593SJeykumar Sankaran ops->update_pending_flush = dpu_hw_ctl_update_pending_flush; 46025fdd593SJeykumar Sankaran ops->get_pending_flush = dpu_hw_ctl_get_pending_flush; 46125fdd593SJeykumar Sankaran ops->trigger_flush = dpu_hw_ctl_trigger_flush; 46225fdd593SJeykumar Sankaran ops->get_flush_register = dpu_hw_ctl_get_flush_register; 46325fdd593SJeykumar Sankaran ops->trigger_start = dpu_hw_ctl_trigger_start; 46425fdd593SJeykumar Sankaran ops->trigger_pending = dpu_hw_ctl_trigger_pending; 46525fdd593SJeykumar Sankaran ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg; 46625fdd593SJeykumar Sankaran ops->reset = dpu_hw_ctl_reset_control; 46725fdd593SJeykumar Sankaran ops->wait_reset_status = dpu_hw_ctl_wait_reset_status; 46825fdd593SJeykumar Sankaran ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages; 46925fdd593SJeykumar Sankaran ops->setup_blendstage = dpu_hw_ctl_setup_blendstage; 47025fdd593SJeykumar Sankaran ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp; 47125fdd593SJeykumar Sankaran ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer; 47225fdd593SJeykumar Sankaran ops->get_bitmask_intf = dpu_hw_ctl_get_bitmask_intf; 47325fdd593SJeykumar Sankaran }; 47425fdd593SJeykumar Sankaran 47553edf462SJordan Crouse static struct dpu_hw_blk_ops dpu_hw_ops; 47625fdd593SJeykumar Sankaran 47725fdd593SJeykumar Sankaran struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx, 47825fdd593SJeykumar Sankaran void __iomem *addr, 479abda0d92SStephen Boyd const struct dpu_mdss_cfg *m) 48025fdd593SJeykumar Sankaran { 48125fdd593SJeykumar Sankaran struct dpu_hw_ctl *c; 482abda0d92SStephen Boyd const struct dpu_ctl_cfg *cfg; 48325fdd593SJeykumar Sankaran 48425fdd593SJeykumar Sankaran c = kzalloc(sizeof(*c), GFP_KERNEL); 48525fdd593SJeykumar Sankaran if (!c) 48625fdd593SJeykumar Sankaran return ERR_PTR(-ENOMEM); 48725fdd593SJeykumar Sankaran 48825fdd593SJeykumar Sankaran cfg = _ctl_offset(idx, m, addr, &c->hw); 48925fdd593SJeykumar Sankaran if (IS_ERR_OR_NULL(cfg)) { 49025fdd593SJeykumar Sankaran kfree(c); 49125fdd593SJeykumar Sankaran pr_err("failed to create dpu_hw_ctl %d\n", idx); 49225fdd593SJeykumar Sankaran return ERR_PTR(-EINVAL); 49325fdd593SJeykumar Sankaran } 49425fdd593SJeykumar Sankaran 49525fdd593SJeykumar Sankaran c->caps = cfg; 49625fdd593SJeykumar Sankaran _setup_ctl_ops(&c->ops, c->caps->features); 49725fdd593SJeykumar Sankaran c->idx = idx; 49825fdd593SJeykumar Sankaran c->mixer_count = m->mixer_count; 49925fdd593SJeykumar Sankaran c->mixer_hw_caps = m->mixer; 50025fdd593SJeykumar Sankaran 50153edf462SJordan Crouse dpu_hw_blk_init(&c->base, DPU_HW_BLK_CTL, idx, &dpu_hw_ops); 50225fdd593SJeykumar Sankaran 50325fdd593SJeykumar Sankaran return c; 50425fdd593SJeykumar Sankaran } 50525fdd593SJeykumar Sankaran 50625fdd593SJeykumar Sankaran void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx) 50725fdd593SJeykumar Sankaran { 50825fdd593SJeykumar Sankaran if (ctx) 50925fdd593SJeykumar Sankaran dpu_hw_blk_destroy(&ctx->base); 51025fdd593SJeykumar Sankaran kfree(ctx); 51125fdd593SJeykumar Sankaran } 512