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