197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
225fdd593SJeykumar Sankaran /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
36d084806SAbhinav Kumar  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
425fdd593SJeykumar Sankaran  */
525fdd593SJeykumar Sankaran 
625fdd593SJeykumar Sankaran #include <linux/delay.h>
725fdd593SJeykumar Sankaran #include "dpu_hwio.h"
825fdd593SJeykumar Sankaran #include "dpu_hw_ctl.h"
925fdd593SJeykumar Sankaran #include "dpu_kms.h"
10812eeeb6SSean Paul #include "dpu_trace.h"
1125fdd593SJeykumar Sankaran 
1225fdd593SJeykumar Sankaran #define   CTL_LAYER(lm)                 \
1325fdd593SJeykumar Sankaran 	(((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
1425fdd593SJeykumar Sankaran #define   CTL_LAYER_EXT(lm)             \
1525fdd593SJeykumar Sankaran 	(0x40 + (((lm) - LM_0) * 0x004))
1625fdd593SJeykumar Sankaran #define   CTL_LAYER_EXT2(lm)             \
1725fdd593SJeykumar Sankaran 	(0x70 + (((lm) - LM_0) * 0x004))
1825fdd593SJeykumar Sankaran #define   CTL_LAYER_EXT3(lm)             \
1925fdd593SJeykumar Sankaran 	(0xA0 + (((lm) - LM_0) * 0x004))
20e92a4ae1SDmitry Baryshkov #define CTL_LAYER_EXT4(lm)             \
21e92a4ae1SDmitry Baryshkov 	(0xB8 + (((lm) - LM_0) * 0x004))
2225fdd593SJeykumar Sankaran #define   CTL_TOP                       0x014
2325fdd593SJeykumar Sankaran #define   CTL_FLUSH                     0x018
2425fdd593SJeykumar Sankaran #define   CTL_START                     0x01C
2525fdd593SJeykumar Sankaran #define   CTL_PREPARE                   0x0d0
2625fdd593SJeykumar Sankaran #define   CTL_SW_RESET                  0x030
2725fdd593SJeykumar Sankaran #define   CTL_LAYER_EXTN_OFFSET         0x40
28c40e6c67SDmitry Baryshkov #define   CTL_MERGE_3D_ACTIVE           0x0E4
29*83a58b20SKalyan Thota #define   CTL_DSC_ACTIVE                0x0E8
306d084806SAbhinav Kumar #define   CTL_WB_ACTIVE                 0x0EC
3173bfb790SKalyan Thota #define   CTL_INTF_ACTIVE               0x0F4
32*83a58b20SKalyan Thota #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
33c40e6c67SDmitry Baryshkov #define   CTL_MERGE_3D_FLUSH            0x100
3477f6da90SVinod Koul #define   CTL_DSC_FLUSH                0x104
356d084806SAbhinav Kumar #define   CTL_WB_FLUSH                  0x108
3673bfb790SKalyan Thota #define   CTL_INTF_FLUSH                0x110
3773bfb790SKalyan Thota #define   CTL_INTF_MASTER               0x134
38*83a58b20SKalyan Thota #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
3925fdd593SJeykumar Sankaran 
4025fdd593SJeykumar Sankaran #define CTL_MIXER_BORDER_OUT            BIT(24)
4125fdd593SJeykumar Sankaran #define CTL_FLUSH_MASK_CTL              BIT(17)
4225fdd593SJeykumar Sankaran 
4325fdd593SJeykumar Sankaran #define DPU_REG_RESET_TIMEOUT_US        2000
44c40e6c67SDmitry Baryshkov #define  MERGE_3D_IDX   23
4577f6da90SVinod Koul #define  DSC_IDX        22
4673bfb790SKalyan Thota #define  INTF_IDX       31
476d084806SAbhinav Kumar #define WB_IDX          16
48*83a58b20SKalyan Thota #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
49b3652e87SKrishna Manikandan #define CTL_INVALID_BIT                 0xffff
5044bf8704SKalyan Thota #define CTL_DEFAULT_GROUP_ID		0xf
51b3652e87SKrishna Manikandan 
52b3652e87SKrishna Manikandan static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
53b3652e87SKrishna Manikandan 	CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
54b3652e87SKrishna Manikandan 	1, 2, 3, CTL_INVALID_BIT, CTL_INVALID_BIT};
5525fdd593SJeykumar Sankaran 
56abda0d92SStephen Boyd static const struct dpu_ctl_cfg *_ctl_offset(enum dpu_ctl ctl,
57abda0d92SStephen Boyd 		const struct dpu_mdss_cfg *m,
5825fdd593SJeykumar Sankaran 		void __iomem *addr,
5925fdd593SJeykumar Sankaran 		struct dpu_hw_blk_reg_map *b)
6025fdd593SJeykumar Sankaran {
6125fdd593SJeykumar Sankaran 	int i;
6225fdd593SJeykumar Sankaran 
6325fdd593SJeykumar Sankaran 	for (i = 0; i < m->ctl_count; i++) {
6425fdd593SJeykumar Sankaran 		if (ctl == m->ctl[i].id) {
659403f9a4SDmitry Baryshkov 			b->blk_addr = addr + m->ctl[i].base;
6625fdd593SJeykumar Sankaran 			b->log_mask = DPU_DBG_MASK_CTL;
6725fdd593SJeykumar Sankaran 			return &m->ctl[i];
6825fdd593SJeykumar Sankaran 		}
6925fdd593SJeykumar Sankaran 	}
7025fdd593SJeykumar Sankaran 	return ERR_PTR(-ENOMEM);
7125fdd593SJeykumar Sankaran }
7225fdd593SJeykumar Sankaran 
7325fdd593SJeykumar Sankaran static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,
7425fdd593SJeykumar Sankaran 		enum dpu_lm lm)
7525fdd593SJeykumar Sankaran {
7625fdd593SJeykumar Sankaran 	int i;
7725fdd593SJeykumar Sankaran 	int stages = -EINVAL;
7825fdd593SJeykumar Sankaran 
7925fdd593SJeykumar Sankaran 	for (i = 0; i < count; i++) {
8025fdd593SJeykumar Sankaran 		if (lm == mixer[i].id) {
8125fdd593SJeykumar Sankaran 			stages = mixer[i].sblk->maxblendstages;
8225fdd593SJeykumar Sankaran 			break;
8325fdd593SJeykumar Sankaran 		}
8425fdd593SJeykumar Sankaran 	}
8525fdd593SJeykumar Sankaran 
8625fdd593SJeykumar Sankaran 	return stages;
8725fdd593SJeykumar Sankaran }
8825fdd593SJeykumar Sankaran 
89812eeeb6SSean Paul static inline u32 dpu_hw_ctl_get_flush_register(struct dpu_hw_ctl *ctx)
90812eeeb6SSean Paul {
91812eeeb6SSean Paul 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
92812eeeb6SSean Paul 
93812eeeb6SSean Paul 	return DPU_REG_READ(c, CTL_FLUSH);
94812eeeb6SSean Paul }
95812eeeb6SSean Paul 
9625fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
9725fdd593SJeykumar Sankaran {
98812eeeb6SSean Paul 	trace_dpu_hw_ctl_trigger_start(ctx->pending_flush_mask,
99812eeeb6SSean Paul 				       dpu_hw_ctl_get_flush_register(ctx));
10025fdd593SJeykumar Sankaran 	DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
10125fdd593SJeykumar Sankaran }
10225fdd593SJeykumar Sankaran 
10378706798SAngeloGioacchino Del Regno static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
10478706798SAngeloGioacchino Del Regno {
10578706798SAngeloGioacchino Del Regno 	return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
10678706798SAngeloGioacchino Del Regno }
10778706798SAngeloGioacchino Del Regno 
10825fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
10925fdd593SJeykumar Sankaran {
110812eeeb6SSean Paul 	trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
111812eeeb6SSean Paul 					 dpu_hw_ctl_get_flush_register(ctx));
11225fdd593SJeykumar Sankaran 	DPU_REG_WRITE(&ctx->hw, CTL_PREPARE, 0x1);
11325fdd593SJeykumar Sankaran }
11425fdd593SJeykumar Sankaran 
11525fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
11625fdd593SJeykumar Sankaran {
117812eeeb6SSean Paul 	trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,
118812eeeb6SSean Paul 				     dpu_hw_ctl_get_flush_register(ctx));
11925fdd593SJeykumar Sankaran 	ctx->pending_flush_mask = 0x0;
120*83a58b20SKalyan Thota 
121*83a58b20SKalyan Thota 	memset(ctx->pending_dspp_flush_mask, 0,
122*83a58b20SKalyan Thota 		sizeof(ctx->pending_dspp_flush_mask));
12325fdd593SJeykumar Sankaran }
12425fdd593SJeykumar Sankaran 
12525fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl *ctx,
12625fdd593SJeykumar Sankaran 		u32 flushbits)
12725fdd593SJeykumar Sankaran {
128812eeeb6SSean Paul 	trace_dpu_hw_ctl_update_pending_flush(flushbits,
129812eeeb6SSean Paul 					      ctx->pending_flush_mask);
13025fdd593SJeykumar Sankaran 	ctx->pending_flush_mask |= flushbits;
13125fdd593SJeykumar Sankaran }
13225fdd593SJeykumar Sankaran 
13325fdd593SJeykumar Sankaran static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
13425fdd593SJeykumar Sankaran {
13525fdd593SJeykumar Sankaran 	return ctx->pending_flush_mask;
13625fdd593SJeykumar Sankaran }
13725fdd593SJeykumar Sankaran 
13873bfb790SKalyan Thota static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
13973bfb790SKalyan Thota {
140*83a58b20SKalyan Thota 	int dspp;
141*83a58b20SKalyan Thota 
142c40e6c67SDmitry Baryshkov 	if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
143c40e6c67SDmitry Baryshkov 		DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
144c40e6c67SDmitry Baryshkov 				ctx->pending_merge_3d_flush_mask);
14573bfb790SKalyan Thota 	if (ctx->pending_flush_mask & BIT(INTF_IDX))
14673bfb790SKalyan Thota 		DPU_REG_WRITE(&ctx->hw, CTL_INTF_FLUSH,
14773bfb790SKalyan Thota 				ctx->pending_intf_flush_mask);
1486d084806SAbhinav Kumar 	if (ctx->pending_flush_mask & BIT(WB_IDX))
1496d084806SAbhinav Kumar 		DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,
1506d084806SAbhinav Kumar 				ctx->pending_wb_flush_mask);
15173bfb790SKalyan Thota 
152*83a58b20SKalyan Thota 	if (ctx->pending_flush_mask & BIT(DSPP_IDX))
153*83a58b20SKalyan Thota 		for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) {
154*83a58b20SKalyan Thota 			if (ctx->pending_dspp_flush_mask[dspp - DSPP_0])
155*83a58b20SKalyan Thota 				DPU_REG_WRITE(&ctx->hw,
156*83a58b20SKalyan Thota 				CTL_DSPP_n_FLUSH(dspp - DSPP_0),
157*83a58b20SKalyan Thota 				ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
158*83a58b20SKalyan Thota 		}
15973bfb790SKalyan Thota 	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
16073bfb790SKalyan Thota }
16173bfb790SKalyan Thota 
16225fdd593SJeykumar Sankaran static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx)
16325fdd593SJeykumar Sankaran {
164812eeeb6SSean Paul 	trace_dpu_hw_ctl_trigger_pending_flush(ctx->pending_flush_mask,
165812eeeb6SSean Paul 				     dpu_hw_ctl_get_flush_register(ctx));
16625fdd593SJeykumar Sankaran 	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
16725fdd593SJeykumar Sankaran }
16825fdd593SJeykumar Sankaran 
1693cde792aSDmitry Baryshkov static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,
17025fdd593SJeykumar Sankaran 	enum dpu_sspp sspp)
17125fdd593SJeykumar Sankaran {
17225fdd593SJeykumar Sankaran 	switch (sspp) {
17325fdd593SJeykumar Sankaran 	case SSPP_VIG0:
1743cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |=  BIT(0);
17525fdd593SJeykumar Sankaran 		break;
17625fdd593SJeykumar Sankaran 	case SSPP_VIG1:
1773cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(1);
17825fdd593SJeykumar Sankaran 		break;
17925fdd593SJeykumar Sankaran 	case SSPP_VIG2:
1803cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(2);
18125fdd593SJeykumar Sankaran 		break;
18225fdd593SJeykumar Sankaran 	case SSPP_VIG3:
1833cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(18);
18425fdd593SJeykumar Sankaran 		break;
18525fdd593SJeykumar Sankaran 	case SSPP_RGB0:
1863cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(3);
18725fdd593SJeykumar Sankaran 		break;
18825fdd593SJeykumar Sankaran 	case SSPP_RGB1:
1893cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(4);
19025fdd593SJeykumar Sankaran 		break;
19125fdd593SJeykumar Sankaran 	case SSPP_RGB2:
1923cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(5);
19325fdd593SJeykumar Sankaran 		break;
19425fdd593SJeykumar Sankaran 	case SSPP_RGB3:
1953cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(19);
19625fdd593SJeykumar Sankaran 		break;
19725fdd593SJeykumar Sankaran 	case SSPP_DMA0:
1983cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(11);
19925fdd593SJeykumar Sankaran 		break;
20025fdd593SJeykumar Sankaran 	case SSPP_DMA1:
2013cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(12);
20225fdd593SJeykumar Sankaran 		break;
20325fdd593SJeykumar Sankaran 	case SSPP_DMA2:
2043cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(24);
20525fdd593SJeykumar Sankaran 		break;
20625fdd593SJeykumar Sankaran 	case SSPP_DMA3:
2073cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(25);
20825fdd593SJeykumar Sankaran 		break;
20925fdd593SJeykumar Sankaran 	case SSPP_CURSOR0:
2103cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(22);
21125fdd593SJeykumar Sankaran 		break;
21225fdd593SJeykumar Sankaran 	case SSPP_CURSOR1:
2133cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(23);
21425fdd593SJeykumar Sankaran 		break;
21525fdd593SJeykumar Sankaran 	default:
21625fdd593SJeykumar Sankaran 		break;
21725fdd593SJeykumar Sankaran 	}
21825fdd593SJeykumar Sankaran }
21925fdd593SJeykumar Sankaran 
2203cde792aSDmitry Baryshkov static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx,
22125fdd593SJeykumar Sankaran 	enum dpu_lm lm)
22225fdd593SJeykumar Sankaran {
22325fdd593SJeykumar Sankaran 	switch (lm) {
22425fdd593SJeykumar Sankaran 	case LM_0:
2253cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(6);
22625fdd593SJeykumar Sankaran 		break;
22725fdd593SJeykumar Sankaran 	case LM_1:
2283cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(7);
22925fdd593SJeykumar Sankaran 		break;
23025fdd593SJeykumar Sankaran 	case LM_2:
2313cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(8);
23225fdd593SJeykumar Sankaran 		break;
23325fdd593SJeykumar Sankaran 	case LM_3:
2343cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(9);
23525fdd593SJeykumar Sankaran 		break;
23625fdd593SJeykumar Sankaran 	case LM_4:
2373cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(10);
23825fdd593SJeykumar Sankaran 		break;
23925fdd593SJeykumar Sankaran 	case LM_5:
2403cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(20);
24125fdd593SJeykumar Sankaran 		break;
24225fdd593SJeykumar Sankaran 	default:
2433cde792aSDmitry Baryshkov 		break;
24425fdd593SJeykumar Sankaran 	}
24525fdd593SJeykumar Sankaran 
2463cde792aSDmitry Baryshkov 	ctx->pending_flush_mask |= CTL_FLUSH_MASK_CTL;
24725fdd593SJeykumar Sankaran }
24825fdd593SJeykumar Sankaran 
249d8199c85SDmitry Baryshkov static void dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,
250d8199c85SDmitry Baryshkov 		enum dpu_intf intf)
25125fdd593SJeykumar Sankaran {
25225fdd593SJeykumar Sankaran 	switch (intf) {
25325fdd593SJeykumar Sankaran 	case INTF_0:
254d8199c85SDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(31);
25525fdd593SJeykumar Sankaran 		break;
25625fdd593SJeykumar Sankaran 	case INTF_1:
257d8199c85SDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(30);
25825fdd593SJeykumar Sankaran 		break;
25925fdd593SJeykumar Sankaran 	case INTF_2:
260d8199c85SDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(29);
26125fdd593SJeykumar Sankaran 		break;
26225fdd593SJeykumar Sankaran 	case INTF_3:
263d8199c85SDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(28);
26425fdd593SJeykumar Sankaran 		break;
26525fdd593SJeykumar Sankaran 	default:
266d8199c85SDmitry Baryshkov 		break;
26725fdd593SJeykumar Sankaran 	}
26825fdd593SJeykumar Sankaran }
26925fdd593SJeykumar Sankaran 
2706d084806SAbhinav Kumar static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
2716d084806SAbhinav Kumar 		enum dpu_wb wb)
2726d084806SAbhinav Kumar {
2736d084806SAbhinav Kumar 	switch (wb) {
2746d084806SAbhinav Kumar 	case WB_0:
2756d084806SAbhinav Kumar 	case WB_1:
2766d084806SAbhinav Kumar 	case WB_2:
2776d084806SAbhinav Kumar 		ctx->pending_flush_mask |= BIT(WB_IDX);
27888334f8cSAbhinav Kumar 		break;
2796d084806SAbhinav Kumar 	default:
2806d084806SAbhinav Kumar 		break;
2816d084806SAbhinav Kumar 	}
2826d084806SAbhinav Kumar }
2836d084806SAbhinav Kumar 
2846d084806SAbhinav Kumar static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
2856d084806SAbhinav Kumar 		enum dpu_wb wb)
2866d084806SAbhinav Kumar {
2876d084806SAbhinav Kumar 	ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
2886d084806SAbhinav Kumar 	ctx->pending_flush_mask |= BIT(WB_IDX);
2896d084806SAbhinav Kumar }
2906d084806SAbhinav Kumar 
291d8199c85SDmitry Baryshkov static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
292d8199c85SDmitry Baryshkov 		enum dpu_intf intf)
29373bfb790SKalyan Thota {
294d8199c85SDmitry Baryshkov 	ctx->pending_intf_flush_mask |= BIT(intf - INTF_0);
295d8199c85SDmitry Baryshkov 	ctx->pending_flush_mask |= BIT(INTF_IDX);
29673bfb790SKalyan Thota }
29773bfb790SKalyan Thota 
298c40e6c67SDmitry Baryshkov static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
299c40e6c67SDmitry Baryshkov 		enum dpu_merge_3d merge_3d)
300c40e6c67SDmitry Baryshkov {
301c40e6c67SDmitry Baryshkov 	ctx->pending_merge_3d_flush_mask |= BIT(merge_3d - MERGE_3D_0);
302c40e6c67SDmitry Baryshkov 	ctx->pending_flush_mask |= BIT(MERGE_3D_IDX);
303c40e6c67SDmitry Baryshkov }
304c40e6c67SDmitry Baryshkov 
3053cde792aSDmitry Baryshkov static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
306*83a58b20SKalyan Thota 	enum dpu_dspp dspp, u32 dspp_sub_blk)
307e47616dfSKalyan Thota {
308e47616dfSKalyan Thota 	switch (dspp) {
309e47616dfSKalyan Thota 	case DSPP_0:
3103cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(13);
311e47616dfSKalyan Thota 		break;
312e47616dfSKalyan Thota 	case DSPP_1:
3133cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(14);
314e47616dfSKalyan Thota 		break;
315e47616dfSKalyan Thota 	case DSPP_2:
3163cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(15);
317e47616dfSKalyan Thota 		break;
318e47616dfSKalyan Thota 	case DSPP_3:
3193cde792aSDmitry Baryshkov 		ctx->pending_flush_mask |= BIT(21);
320e47616dfSKalyan Thota 		break;
321e47616dfSKalyan Thota 	default:
3223cde792aSDmitry Baryshkov 		break;
323e47616dfSKalyan Thota 	}
324e47616dfSKalyan Thota }
325e47616dfSKalyan Thota 
326*83a58b20SKalyan Thota static void dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(
327*83a58b20SKalyan Thota 	struct dpu_hw_ctl *ctx,	enum dpu_dspp dspp, u32 dspp_sub_blk)
328*83a58b20SKalyan Thota {
329*83a58b20SKalyan Thota 	if (dspp >= DSPP_MAX)
330*83a58b20SKalyan Thota 		return;
331*83a58b20SKalyan Thota 
332*83a58b20SKalyan Thota 	switch (dspp_sub_blk) {
333*83a58b20SKalyan Thota 	case DPU_DSPP_IGC:
334*83a58b20SKalyan Thota 		ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(2);
335*83a58b20SKalyan Thota 		break;
336*83a58b20SKalyan Thota 	case DPU_DSPP_PCC:
337*83a58b20SKalyan Thota 		ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4);
338*83a58b20SKalyan Thota 		break;
339*83a58b20SKalyan Thota 	case DPU_DSPP_GC:
340*83a58b20SKalyan Thota 		ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(5);
341*83a58b20SKalyan Thota 		break;
342*83a58b20SKalyan Thota 	default:
343*83a58b20SKalyan Thota 		return;
344*83a58b20SKalyan Thota 	}
345*83a58b20SKalyan Thota 
346*83a58b20SKalyan Thota 	ctx->pending_flush_mask |= BIT(DSPP_IDX);
347*83a58b20SKalyan Thota }
348*83a58b20SKalyan Thota 
34925fdd593SJeykumar Sankaran static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
35025fdd593SJeykumar Sankaran {
35125fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
35225fdd593SJeykumar Sankaran 	ktime_t timeout;
35325fdd593SJeykumar Sankaran 	u32 status;
35425fdd593SJeykumar Sankaran 
35525fdd593SJeykumar Sankaran 	timeout = ktime_add_us(ktime_get(), timeout_us);
35625fdd593SJeykumar Sankaran 
35725fdd593SJeykumar Sankaran 	/*
35825fdd593SJeykumar Sankaran 	 * it takes around 30us to have mdp finish resetting its ctl path
35925fdd593SJeykumar Sankaran 	 * poll every 50us so that reset should be completed at 1st poll
36025fdd593SJeykumar Sankaran 	 */
36125fdd593SJeykumar Sankaran 	do {
36225fdd593SJeykumar Sankaran 		status = DPU_REG_READ(c, CTL_SW_RESET);
36325fdd593SJeykumar Sankaran 		status &= 0x1;
36425fdd593SJeykumar Sankaran 		if (status)
36525fdd593SJeykumar Sankaran 			usleep_range(20, 50);
36625fdd593SJeykumar Sankaran 	} while (status && ktime_compare_safe(ktime_get(), timeout) < 0);
36725fdd593SJeykumar Sankaran 
36825fdd593SJeykumar Sankaran 	return status;
36925fdd593SJeykumar Sankaran }
37025fdd593SJeykumar Sankaran 
37125fdd593SJeykumar Sankaran static int dpu_hw_ctl_reset_control(struct dpu_hw_ctl *ctx)
37225fdd593SJeykumar Sankaran {
37325fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
37425fdd593SJeykumar Sankaran 
37525fdd593SJeykumar Sankaran 	pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx);
37625fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, CTL_SW_RESET, 0x1);
37725fdd593SJeykumar Sankaran 	if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US))
37825fdd593SJeykumar Sankaran 		return -EINVAL;
37925fdd593SJeykumar Sankaran 
38025fdd593SJeykumar Sankaran 	return 0;
38125fdd593SJeykumar Sankaran }
38225fdd593SJeykumar Sankaran 
38325fdd593SJeykumar Sankaran static int dpu_hw_ctl_wait_reset_status(struct dpu_hw_ctl *ctx)
38425fdd593SJeykumar Sankaran {
38525fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
38625fdd593SJeykumar Sankaran 	u32 status;
38725fdd593SJeykumar Sankaran 
38825fdd593SJeykumar Sankaran 	status = DPU_REG_READ(c, CTL_SW_RESET);
38925fdd593SJeykumar Sankaran 	status &= 0x01;
39025fdd593SJeykumar Sankaran 	if (!status)
39125fdd593SJeykumar Sankaran 		return 0;
39225fdd593SJeykumar Sankaran 
39325fdd593SJeykumar Sankaran 	pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx);
39425fdd593SJeykumar Sankaran 	if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US)) {
39525fdd593SJeykumar Sankaran 		pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx);
39625fdd593SJeykumar Sankaran 		return -EINVAL;
39725fdd593SJeykumar Sankaran 	}
39825fdd593SJeykumar Sankaran 
39925fdd593SJeykumar Sankaran 	return 0;
40025fdd593SJeykumar Sankaran }
40125fdd593SJeykumar Sankaran 
40225fdd593SJeykumar Sankaran static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx)
40325fdd593SJeykumar Sankaran {
40425fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
40525fdd593SJeykumar Sankaran 	int i;
40625fdd593SJeykumar Sankaran 
40725fdd593SJeykumar Sankaran 	for (i = 0; i < ctx->mixer_count; i++) {
408a41cdb69SDmitry Baryshkov 		enum dpu_lm mixer_id = ctx->mixer_hw_caps[i].id;
409a41cdb69SDmitry Baryshkov 
410a41cdb69SDmitry Baryshkov 		DPU_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
411a41cdb69SDmitry Baryshkov 		DPU_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
412a41cdb69SDmitry Baryshkov 		DPU_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
413a41cdb69SDmitry Baryshkov 		DPU_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
41425fdd593SJeykumar Sankaran 	}
415b3652e87SKrishna Manikandan 
416b3652e87SKrishna Manikandan 	DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
41725fdd593SJeykumar Sankaran }
41825fdd593SJeykumar Sankaran 
4194488f71fSDmitry Baryshkov struct ctl_blend_config {
4204488f71fSDmitry Baryshkov 	int idx, shift, ext_shift;
4214488f71fSDmitry Baryshkov };
4224488f71fSDmitry Baryshkov 
4234488f71fSDmitry Baryshkov static const struct ctl_blend_config ctl_blend_config[][2] = {
4244488f71fSDmitry Baryshkov 	[SSPP_NONE] = { { -1 }, { -1 } },
4254488f71fSDmitry Baryshkov 	[SSPP_MAX] =  { { -1 }, { -1 } },
4264488f71fSDmitry Baryshkov 	[SSPP_VIG0] = { { 0, 0,  0  }, { 3, 0 } },
4274488f71fSDmitry Baryshkov 	[SSPP_VIG1] = { { 0, 3,  2  }, { 3, 4 } },
4284488f71fSDmitry Baryshkov 	[SSPP_VIG2] = { { 0, 6,  4  }, { 3, 8 } },
4294488f71fSDmitry Baryshkov 	[SSPP_VIG3] = { { 0, 26, 6  }, { 3, 12 } },
4304488f71fSDmitry Baryshkov 	[SSPP_RGB0] = { { 0, 9,  8  }, { -1 } },
4314488f71fSDmitry Baryshkov 	[SSPP_RGB1] = { { 0, 12, 10 }, { -1 } },
4324488f71fSDmitry Baryshkov 	[SSPP_RGB2] = { { 0, 15, 12 }, { -1 } },
4334488f71fSDmitry Baryshkov 	[SSPP_RGB3] = { { 0, 29, 14 }, { -1 } },
4344488f71fSDmitry Baryshkov 	[SSPP_DMA0] = { { 0, 18, 16 }, { 2, 8 } },
4354488f71fSDmitry Baryshkov 	[SSPP_DMA1] = { { 0, 21, 18 }, { 2, 12 } },
4364488f71fSDmitry Baryshkov 	[SSPP_DMA2] = { { 2, 0      }, { 2, 16 } },
4374488f71fSDmitry Baryshkov 	[SSPP_DMA3] = { { 2, 4      }, { 2, 20 } },
4384488f71fSDmitry Baryshkov 	[SSPP_DMA4] = { { 4, 0      }, { 4, 8 } },
4394488f71fSDmitry Baryshkov 	[SSPP_DMA5] = { { 4, 4      }, { 4, 12 } },
4404488f71fSDmitry Baryshkov 	[SSPP_CURSOR0] =  { { 1, 20 }, { -1 } },
4414488f71fSDmitry Baryshkov 	[SSPP_CURSOR1] =  { { 1, 26 }, { -1 } },
4424488f71fSDmitry Baryshkov };
4434488f71fSDmitry Baryshkov 
44425fdd593SJeykumar Sankaran static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
44525fdd593SJeykumar Sankaran 	enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
44625fdd593SJeykumar Sankaran {
44725fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
4482c36dc91SDmitry Baryshkov 	u32 mix, ext, mix_ext;
4494488f71fSDmitry Baryshkov 	u32 mixercfg[5] = { 0 };
45025fdd593SJeykumar Sankaran 	int i, j;
451dfdb3be4SColin Ian King 	int stages;
45225fdd593SJeykumar Sankaran 	int pipes_per_stage;
45325fdd593SJeykumar Sankaran 
45425fdd593SJeykumar Sankaran 	stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
45525fdd593SJeykumar Sankaran 	if (stages < 0)
45625fdd593SJeykumar Sankaran 		return;
45725fdd593SJeykumar Sankaran 
45825fdd593SJeykumar Sankaran 	if (test_bit(DPU_MIXER_SOURCESPLIT,
45925fdd593SJeykumar Sankaran 		&ctx->mixer_hw_caps->features))
46025fdd593SJeykumar Sankaran 		pipes_per_stage = PIPES_PER_STAGE;
46125fdd593SJeykumar Sankaran 	else
46225fdd593SJeykumar Sankaran 		pipes_per_stage = 1;
46325fdd593SJeykumar Sankaran 
4644488f71fSDmitry Baryshkov 	mixercfg[0] = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */
46525fdd593SJeykumar Sankaran 
46625fdd593SJeykumar Sankaran 	if (!stage_cfg)
46725fdd593SJeykumar Sankaran 		goto exit;
46825fdd593SJeykumar Sankaran 
46925fdd593SJeykumar Sankaran 	for (i = 0; i <= stages; i++) {
47025fdd593SJeykumar Sankaran 		/* overflow to ext register if 'i + 1 > 7' */
47125fdd593SJeykumar Sankaran 		mix = (i + 1) & 0x7;
47225fdd593SJeykumar Sankaran 		ext = i >= 7;
4732c36dc91SDmitry Baryshkov 		mix_ext = (i + 1) & 0xf;
47425fdd593SJeykumar Sankaran 
47525fdd593SJeykumar Sankaran 		for (j = 0 ; j < pipes_per_stage; j++) {
47625fdd593SJeykumar Sankaran 			enum dpu_sspp_multirect_index rect_index =
47725fdd593SJeykumar Sankaran 				stage_cfg->multirect_index[i][j];
4784488f71fSDmitry Baryshkov 			enum dpu_sspp pipe = stage_cfg->stage[i][j];
4794488f71fSDmitry Baryshkov 			const struct ctl_blend_config *cfg =
4804488f71fSDmitry Baryshkov 				&ctl_blend_config[pipe][rect_index == DPU_SSPP_RECT_1];
48125fdd593SJeykumar Sankaran 
4824488f71fSDmitry Baryshkov 			/*
4834488f71fSDmitry Baryshkov 			 * CTL_LAYER has 3-bit field (and extra bits in EXT register),
4844488f71fSDmitry Baryshkov 			 * all EXT registers has 4-bit fields.
4854488f71fSDmitry Baryshkov 			 */
4861c1ded39SDmitry Baryshkov 			if (cfg->idx == -1) {
4871c1ded39SDmitry Baryshkov 				continue;
4881c1ded39SDmitry Baryshkov 			} else if (cfg->idx == 0) {
4894488f71fSDmitry Baryshkov 				mixercfg[0] |= mix << cfg->shift;
4904488f71fSDmitry Baryshkov 				mixercfg[1] |= ext << cfg->ext_shift;
49125fdd593SJeykumar Sankaran 			} else {
4924488f71fSDmitry Baryshkov 				mixercfg[cfg->idx] |= mix_ext << cfg->shift;
49325fdd593SJeykumar Sankaran 			}
49425fdd593SJeykumar Sankaran 		}
49525fdd593SJeykumar Sankaran 	}
49625fdd593SJeykumar Sankaran 
49725fdd593SJeykumar Sankaran exit:
4984488f71fSDmitry Baryshkov 	DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg[0]);
4994488f71fSDmitry Baryshkov 	DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg[1]);
5004488f71fSDmitry Baryshkov 	DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg[2]);
5014488f71fSDmitry Baryshkov 	DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg[3]);
502e92a4ae1SDmitry Baryshkov 	if ((test_bit(DPU_CTL_HAS_LAYER_EXT4, &ctx->caps->features)))
5034488f71fSDmitry Baryshkov 		DPU_REG_WRITE(c, CTL_LAYER_EXT4(lm), mixercfg[4]);
50425fdd593SJeykumar Sankaran }
50525fdd593SJeykumar Sankaran 
50673bfb790SKalyan Thota 
50773bfb790SKalyan Thota static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
50873bfb790SKalyan Thota 		struct dpu_hw_intf_cfg *cfg)
50973bfb790SKalyan Thota {
51073bfb790SKalyan Thota 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
51173bfb790SKalyan Thota 	u32 intf_active = 0;
5126d084806SAbhinav Kumar 	u32 wb_active = 0;
51373bfb790SKalyan Thota 	u32 mode_sel = 0;
51473bfb790SKalyan Thota 
51544bf8704SKalyan Thota 	/* CTL_TOP[31:28] carries group_id to collate CTL paths
51644bf8704SKalyan Thota 	 * per VM. Explicitly disable it until VM support is
51744bf8704SKalyan Thota 	 * added in SW. Power on reset value is not disable.
51844bf8704SKalyan Thota 	 */
51944bf8704SKalyan Thota 	if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
52044bf8704SKalyan Thota 		mode_sel = CTL_DEFAULT_GROUP_ID  << 28;
52144bf8704SKalyan Thota 
52277f6da90SVinod Koul 	if (cfg->dsc)
52377f6da90SVinod Koul 		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
52477f6da90SVinod Koul 
52573bfb790SKalyan Thota 	if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
52673bfb790SKalyan Thota 		mode_sel |= BIT(17);
52773bfb790SKalyan Thota 
52873bfb790SKalyan Thota 	intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
5296d084806SAbhinav Kumar 	wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
5306d084806SAbhinav Kumar 
5316d084806SAbhinav Kumar 	if (cfg->intf)
53273bfb790SKalyan Thota 		intf_active |= BIT(cfg->intf - INTF_0);
53373bfb790SKalyan Thota 
5346d084806SAbhinav Kumar 	if (cfg->wb)
5356d084806SAbhinav Kumar 		wb_active |= BIT(cfg->wb - WB_0);
5366d084806SAbhinav Kumar 
53773bfb790SKalyan Thota 	DPU_REG_WRITE(c, CTL_TOP, mode_sel);
53873bfb790SKalyan Thota 	DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
5396d084806SAbhinav Kumar 	DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
5406d084806SAbhinav Kumar 
54112aca1ceSKalyan Thota 	if (cfg->merge_3d)
54212aca1ceSKalyan Thota 		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
54312aca1ceSKalyan Thota 			      BIT(cfg->merge_3d - MERGE_3D_0));
54477f6da90SVinod Koul 	if (cfg->dsc) {
54577f6da90SVinod Koul 		DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, DSC_IDX);
54677f6da90SVinod Koul 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
54777f6da90SVinod Koul 	}
54873bfb790SKalyan Thota }
54973bfb790SKalyan Thota 
55025fdd593SJeykumar Sankaran static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
55125fdd593SJeykumar Sankaran 		struct dpu_hw_intf_cfg *cfg)
55225fdd593SJeykumar Sankaran {
55325fdd593SJeykumar Sankaran 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
55425fdd593SJeykumar Sankaran 	u32 intf_cfg = 0;
55525fdd593SJeykumar Sankaran 
55625fdd593SJeykumar Sankaran 	intf_cfg |= (cfg->intf & 0xF) << 4;
55725fdd593SJeykumar Sankaran 
55825fdd593SJeykumar Sankaran 	if (cfg->mode_3d) {
55925fdd593SJeykumar Sankaran 		intf_cfg |= BIT(19);
56025fdd593SJeykumar Sankaran 		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
56125fdd593SJeykumar Sankaran 	}
56225fdd593SJeykumar Sankaran 
5636d084806SAbhinav Kumar 	if (cfg->wb)
5646d084806SAbhinav Kumar 		intf_cfg |= (cfg->wb & 0x3) + 2;
5656d084806SAbhinav Kumar 
56625fdd593SJeykumar Sankaran 	switch (cfg->intf_mode_sel) {
56725fdd593SJeykumar Sankaran 	case DPU_CTL_MODE_SEL_VID:
56825fdd593SJeykumar Sankaran 		intf_cfg &= ~BIT(17);
56925fdd593SJeykumar Sankaran 		intf_cfg &= ~(0x3 << 15);
57025fdd593SJeykumar Sankaran 		break;
57125fdd593SJeykumar Sankaran 	case DPU_CTL_MODE_SEL_CMD:
57225fdd593SJeykumar Sankaran 		intf_cfg |= BIT(17);
57325fdd593SJeykumar Sankaran 		intf_cfg |= ((cfg->stream_sel & 0x3) << 15);
57425fdd593SJeykumar Sankaran 		break;
57525fdd593SJeykumar Sankaran 	default:
57625fdd593SJeykumar Sankaran 		pr_err("unknown interface type %d\n", cfg->intf_mode_sel);
57725fdd593SJeykumar Sankaran 		return;
57825fdd593SJeykumar Sankaran 	}
57925fdd593SJeykumar Sankaran 
58025fdd593SJeykumar Sankaran 	DPU_REG_WRITE(c, CTL_TOP, intf_cfg);
58125fdd593SJeykumar Sankaran }
58225fdd593SJeykumar Sankaran 
583e1a950eeSAbhinav Kumar static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
584e1a950eeSAbhinav Kumar 		struct dpu_hw_intf_cfg *cfg)
585e1a950eeSAbhinav Kumar {
586e1a950eeSAbhinav Kumar 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
587e1a950eeSAbhinav Kumar 	u32 intf_active = 0;
5886d084806SAbhinav Kumar 	u32 wb_active = 0;
589e1a950eeSAbhinav Kumar 	u32 merge3d_active = 0;
590e1a950eeSAbhinav Kumar 
591e1a950eeSAbhinav Kumar 	/*
592e1a950eeSAbhinav Kumar 	 * This API resets each portion of the CTL path namely,
593e1a950eeSAbhinav Kumar 	 * clearing the sspps staged on the lm, merge_3d block,
5946d084806SAbhinav Kumar 	 * interfaces , writeback etc to ensure clean teardown of the pipeline.
595e1a950eeSAbhinav Kumar 	 * This will be used for writeback to begin with to have a
596e1a950eeSAbhinav Kumar 	 * proper teardown of the writeback session but upon further
597e1a950eeSAbhinav Kumar 	 * validation, this can be extended to all interfaces.
598e1a950eeSAbhinav Kumar 	 */
599e1a950eeSAbhinav Kumar 	if (cfg->merge_3d) {
600e1a950eeSAbhinav Kumar 		merge3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE);
601e1a950eeSAbhinav Kumar 		merge3d_active &= ~BIT(cfg->merge_3d - MERGE_3D_0);
602e1a950eeSAbhinav Kumar 		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
603e1a950eeSAbhinav Kumar 				merge3d_active);
604e1a950eeSAbhinav Kumar 	}
605e1a950eeSAbhinav Kumar 
606e1a950eeSAbhinav Kumar 	dpu_hw_ctl_clear_all_blendstages(ctx);
607e1a950eeSAbhinav Kumar 
608e1a950eeSAbhinav Kumar 	if (cfg->intf) {
609e1a950eeSAbhinav Kumar 		intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
610e1a950eeSAbhinav Kumar 		intf_active &= ~BIT(cfg->intf - INTF_0);
611e1a950eeSAbhinav Kumar 		DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
612e1a950eeSAbhinav Kumar 	}
6136d084806SAbhinav Kumar 
6146d084806SAbhinav Kumar 	if (cfg->wb) {
6156d084806SAbhinav Kumar 		wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
6166d084806SAbhinav Kumar 		wb_active &= ~BIT(cfg->wb - WB_0);
6176d084806SAbhinav Kumar 		DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
6186d084806SAbhinav Kumar 	}
619e1a950eeSAbhinav Kumar }
620e1a950eeSAbhinav Kumar 
621b3652e87SKrishna Manikandan static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
622b3652e87SKrishna Manikandan 	unsigned long *fetch_active)
623b3652e87SKrishna Manikandan {
624b3652e87SKrishna Manikandan 	int i;
625b3652e87SKrishna Manikandan 	u32 val = 0;
626b3652e87SKrishna Manikandan 
627b3652e87SKrishna Manikandan 	if (fetch_active) {
628b3652e87SKrishna Manikandan 		for (i = 0; i < SSPP_MAX; i++) {
629b3652e87SKrishna Manikandan 			if (test_bit(i, fetch_active) &&
630b3652e87SKrishna Manikandan 				fetch_tbl[i] != CTL_INVALID_BIT)
631b3652e87SKrishna Manikandan 				val |= BIT(fetch_tbl[i]);
632b3652e87SKrishna Manikandan 		}
633b3652e87SKrishna Manikandan 	}
634b3652e87SKrishna Manikandan 
635b3652e87SKrishna Manikandan 	DPU_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);
636b3652e87SKrishna Manikandan }
637b3652e87SKrishna Manikandan 
63825fdd593SJeykumar Sankaran static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
63925fdd593SJeykumar Sankaran 		unsigned long cap)
64025fdd593SJeykumar Sankaran {
64173bfb790SKalyan Thota 	if (cap & BIT(DPU_CTL_ACTIVE_CFG)) {
64273bfb790SKalyan Thota 		ops->trigger_flush = dpu_hw_ctl_trigger_flush_v1;
64373bfb790SKalyan Thota 		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1;
644e1a950eeSAbhinav Kumar 		ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
645d8199c85SDmitry Baryshkov 		ops->update_pending_flush_intf =
646d8199c85SDmitry Baryshkov 			dpu_hw_ctl_update_pending_flush_intf_v1;
647c40e6c67SDmitry Baryshkov 		ops->update_pending_flush_merge_3d =
648c40e6c67SDmitry Baryshkov 			dpu_hw_ctl_update_pending_flush_merge_3d_v1;
6496d084806SAbhinav Kumar 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
65073bfb790SKalyan Thota 	} else {
65173bfb790SKalyan Thota 		ops->trigger_flush = dpu_hw_ctl_trigger_flush;
65273bfb790SKalyan Thota 		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
653d8199c85SDmitry Baryshkov 		ops->update_pending_flush_intf =
654d8199c85SDmitry Baryshkov 			dpu_hw_ctl_update_pending_flush_intf;
6556d084806SAbhinav Kumar 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
65673bfb790SKalyan Thota 	}
65725fdd593SJeykumar Sankaran 	ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
65825fdd593SJeykumar Sankaran 	ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
65925fdd593SJeykumar Sankaran 	ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;
66025fdd593SJeykumar Sankaran 	ops->get_flush_register = dpu_hw_ctl_get_flush_register;
66125fdd593SJeykumar Sankaran 	ops->trigger_start = dpu_hw_ctl_trigger_start;
66278706798SAngeloGioacchino Del Regno 	ops->is_started = dpu_hw_ctl_is_started;
66325fdd593SJeykumar Sankaran 	ops->trigger_pending = dpu_hw_ctl_trigger_pending;
66425fdd593SJeykumar Sankaran 	ops->reset = dpu_hw_ctl_reset_control;
66525fdd593SJeykumar Sankaran 	ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;
66625fdd593SJeykumar Sankaran 	ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages;
66725fdd593SJeykumar Sankaran 	ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
6683cde792aSDmitry Baryshkov 	ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp;
6693cde792aSDmitry Baryshkov 	ops->update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer;
670*83a58b20SKalyan Thota 	if (cap & BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH))
671*83a58b20SKalyan Thota 		ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks;
672*83a58b20SKalyan Thota 	else
6733cde792aSDmitry Baryshkov 		ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp;
674*83a58b20SKalyan Thota 
675b3652e87SKrishna Manikandan 	if (cap & BIT(DPU_CTL_FETCH_ACTIVE))
676b3652e87SKrishna Manikandan 		ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
67725fdd593SJeykumar Sankaran };
67825fdd593SJeykumar Sankaran 
67925fdd593SJeykumar Sankaran struct dpu_hw_ctl *dpu_hw_ctl_init(enum dpu_ctl idx,
68025fdd593SJeykumar Sankaran 		void __iomem *addr,
681abda0d92SStephen Boyd 		const struct dpu_mdss_cfg *m)
68225fdd593SJeykumar Sankaran {
68325fdd593SJeykumar Sankaran 	struct dpu_hw_ctl *c;
684abda0d92SStephen Boyd 	const struct dpu_ctl_cfg *cfg;
68525fdd593SJeykumar Sankaran 
68625fdd593SJeykumar Sankaran 	c = kzalloc(sizeof(*c), GFP_KERNEL);
68725fdd593SJeykumar Sankaran 	if (!c)
68825fdd593SJeykumar Sankaran 		return ERR_PTR(-ENOMEM);
68925fdd593SJeykumar Sankaran 
69025fdd593SJeykumar Sankaran 	cfg = _ctl_offset(idx, m, addr, &c->hw);
69125fdd593SJeykumar Sankaran 	if (IS_ERR_OR_NULL(cfg)) {
69225fdd593SJeykumar Sankaran 		kfree(c);
69325fdd593SJeykumar Sankaran 		pr_err("failed to create dpu_hw_ctl %d\n", idx);
69425fdd593SJeykumar Sankaran 		return ERR_PTR(-EINVAL);
69525fdd593SJeykumar Sankaran 	}
69625fdd593SJeykumar Sankaran 
69725fdd593SJeykumar Sankaran 	c->caps = cfg;
69825fdd593SJeykumar Sankaran 	_setup_ctl_ops(&c->ops, c->caps->features);
69925fdd593SJeykumar Sankaran 	c->idx = idx;
70025fdd593SJeykumar Sankaran 	c->mixer_count = m->mixer_count;
70125fdd593SJeykumar Sankaran 	c->mixer_hw_caps = m->mixer;
70225fdd593SJeykumar Sankaran 
70325fdd593SJeykumar Sankaran 	return c;
70425fdd593SJeykumar Sankaran }
70525fdd593SJeykumar Sankaran 
70625fdd593SJeykumar Sankaran void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx)
70725fdd593SJeykumar Sankaran {
70825fdd593SJeykumar Sankaran 	kfree(ctx);
70925fdd593SJeykumar Sankaran }
710