xref: /linux/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c (revision 34dc1baba215b826e454b8d19e4f24adbeb7d00d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  */
5 
6 #include <linux/delay.h>
7 #include "dpu_hwio.h"
8 #include "dpu_hw_ctl.h"
9 #include "dpu_kms.h"
10 #include "dpu_trace.h"
11 
12 #define   CTL_LAYER(lm)                 \
13 	(((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
14 #define   CTL_LAYER_EXT(lm)             \
15 	(0x40 + (((lm) - LM_0) * 0x004))
16 #define   CTL_LAYER_EXT2(lm)             \
17 	(0x70 + (((lm) - LM_0) * 0x004))
18 #define   CTL_LAYER_EXT3(lm)             \
19 	(0xA0 + (((lm) - LM_0) * 0x004))
20 #define CTL_LAYER_EXT4(lm)             \
21 	(0xB8 + (((lm) - LM_0) * 0x004))
22 #define   CTL_TOP                       0x014
23 #define   CTL_FLUSH                     0x018
24 #define   CTL_START                     0x01C
25 #define   CTL_PREPARE                   0x0d0
26 #define   CTL_SW_RESET                  0x030
27 #define   CTL_LAYER_EXTN_OFFSET         0x40
28 #define   CTL_MERGE_3D_ACTIVE           0x0E4
29 #define   CTL_DSC_ACTIVE                0x0E8
30 #define   CTL_WB_ACTIVE                 0x0EC
31 #define   CTL_INTF_ACTIVE               0x0F4
32 #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
33 #define   CTL_MERGE_3D_FLUSH            0x100
34 #define   CTL_DSC_FLUSH                0x104
35 #define   CTL_WB_FLUSH                  0x108
36 #define   CTL_INTF_FLUSH                0x110
37 #define   CTL_INTF_MASTER               0x134
38 #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
39 
40 #define CTL_MIXER_BORDER_OUT            BIT(24)
41 #define CTL_FLUSH_MASK_CTL              BIT(17)
42 
43 #define DPU_REG_RESET_TIMEOUT_US        2000
44 #define  MERGE_3D_IDX   23
45 #define  DSC_IDX        22
46 #define  INTF_IDX       31
47 #define WB_IDX          16
48 #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
49 #define CTL_INVALID_BIT                 0xffff
50 #define CTL_DEFAULT_GROUP_ID		0xf
51 
52 static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
53 	CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
54 	1, 2, 3, 4, 5};
55 
56 static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,
57 		enum dpu_lm lm)
58 {
59 	int i;
60 	int stages = -EINVAL;
61 
62 	for (i = 0; i < count; i++) {
63 		if (lm == mixer[i].id) {
64 			stages = mixer[i].sblk->maxblendstages;
65 			break;
66 		}
67 	}
68 
69 	return stages;
70 }
71 
72 static inline u32 dpu_hw_ctl_get_flush_register(struct dpu_hw_ctl *ctx)
73 {
74 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
75 
76 	return DPU_REG_READ(c, CTL_FLUSH);
77 }
78 
79 static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
80 {
81 	trace_dpu_hw_ctl_trigger_start(ctx->pending_flush_mask,
82 				       dpu_hw_ctl_get_flush_register(ctx));
83 	DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
84 }
85 
86 static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
87 {
88 	return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
89 }
90 
91 static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
92 {
93 	trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
94 					 dpu_hw_ctl_get_flush_register(ctx));
95 	DPU_REG_WRITE(&ctx->hw, CTL_PREPARE, 0x1);
96 }
97 
98 static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
99 {
100 	trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,
101 				     dpu_hw_ctl_get_flush_register(ctx));
102 	ctx->pending_flush_mask = 0x0;
103 	ctx->pending_intf_flush_mask = 0;
104 	ctx->pending_wb_flush_mask = 0;
105 	ctx->pending_merge_3d_flush_mask = 0;
106 	ctx->pending_dsc_flush_mask = 0;
107 
108 	memset(ctx->pending_dspp_flush_mask, 0,
109 		sizeof(ctx->pending_dspp_flush_mask));
110 }
111 
112 static inline void dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl *ctx,
113 		u32 flushbits)
114 {
115 	trace_dpu_hw_ctl_update_pending_flush(flushbits,
116 					      ctx->pending_flush_mask);
117 	ctx->pending_flush_mask |= flushbits;
118 }
119 
120 static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
121 {
122 	return ctx->pending_flush_mask;
123 }
124 
125 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
126 {
127 	int dspp;
128 
129 	if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
130 		DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
131 				ctx->pending_merge_3d_flush_mask);
132 	if (ctx->pending_flush_mask & BIT(INTF_IDX))
133 		DPU_REG_WRITE(&ctx->hw, CTL_INTF_FLUSH,
134 				ctx->pending_intf_flush_mask);
135 	if (ctx->pending_flush_mask & BIT(WB_IDX))
136 		DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,
137 				ctx->pending_wb_flush_mask);
138 
139 	if (ctx->pending_flush_mask & BIT(DSPP_IDX))
140 		for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) {
141 			if (ctx->pending_dspp_flush_mask[dspp - DSPP_0])
142 				DPU_REG_WRITE(&ctx->hw,
143 				CTL_DSPP_n_FLUSH(dspp - DSPP_0),
144 				ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
145 		}
146 
147 	if (ctx->pending_flush_mask & BIT(DSC_IDX))
148 		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
149 			      ctx->pending_dsc_flush_mask);
150 
151 	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
152 }
153 
154 static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx)
155 {
156 	trace_dpu_hw_ctl_trigger_pending_flush(ctx->pending_flush_mask,
157 				     dpu_hw_ctl_get_flush_register(ctx));
158 	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
159 }
160 
161 static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,
162 	enum dpu_sspp sspp)
163 {
164 	switch (sspp) {
165 	case SSPP_VIG0:
166 		ctx->pending_flush_mask |=  BIT(0);
167 		break;
168 	case SSPP_VIG1:
169 		ctx->pending_flush_mask |= BIT(1);
170 		break;
171 	case SSPP_VIG2:
172 		ctx->pending_flush_mask |= BIT(2);
173 		break;
174 	case SSPP_VIG3:
175 		ctx->pending_flush_mask |= BIT(18);
176 		break;
177 	case SSPP_RGB0:
178 		ctx->pending_flush_mask |= BIT(3);
179 		break;
180 	case SSPP_RGB1:
181 		ctx->pending_flush_mask |= BIT(4);
182 		break;
183 	case SSPP_RGB2:
184 		ctx->pending_flush_mask |= BIT(5);
185 		break;
186 	case SSPP_RGB3:
187 		ctx->pending_flush_mask |= BIT(19);
188 		break;
189 	case SSPP_DMA0:
190 		ctx->pending_flush_mask |= BIT(11);
191 		break;
192 	case SSPP_DMA1:
193 		ctx->pending_flush_mask |= BIT(12);
194 		break;
195 	case SSPP_DMA2:
196 		ctx->pending_flush_mask |= BIT(24);
197 		break;
198 	case SSPP_DMA3:
199 		ctx->pending_flush_mask |= BIT(25);
200 		break;
201 	case SSPP_DMA4:
202 		ctx->pending_flush_mask |= BIT(13);
203 		break;
204 	case SSPP_DMA5:
205 		ctx->pending_flush_mask |= BIT(14);
206 		break;
207 	case SSPP_CURSOR0:
208 		ctx->pending_flush_mask |= BIT(22);
209 		break;
210 	case SSPP_CURSOR1:
211 		ctx->pending_flush_mask |= BIT(23);
212 		break;
213 	default:
214 		break;
215 	}
216 }
217 
218 static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx,
219 	enum dpu_lm lm)
220 {
221 	switch (lm) {
222 	case LM_0:
223 		ctx->pending_flush_mask |= BIT(6);
224 		break;
225 	case LM_1:
226 		ctx->pending_flush_mask |= BIT(7);
227 		break;
228 	case LM_2:
229 		ctx->pending_flush_mask |= BIT(8);
230 		break;
231 	case LM_3:
232 		ctx->pending_flush_mask |= BIT(9);
233 		break;
234 	case LM_4:
235 		ctx->pending_flush_mask |= BIT(10);
236 		break;
237 	case LM_5:
238 		ctx->pending_flush_mask |= BIT(20);
239 		break;
240 	default:
241 		break;
242 	}
243 
244 	ctx->pending_flush_mask |= CTL_FLUSH_MASK_CTL;
245 }
246 
247 static void dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,
248 		enum dpu_intf intf)
249 {
250 	switch (intf) {
251 	case INTF_0:
252 		ctx->pending_flush_mask |= BIT(31);
253 		break;
254 	case INTF_1:
255 		ctx->pending_flush_mask |= BIT(30);
256 		break;
257 	case INTF_2:
258 		ctx->pending_flush_mask |= BIT(29);
259 		break;
260 	case INTF_3:
261 		ctx->pending_flush_mask |= BIT(28);
262 		break;
263 	default:
264 		break;
265 	}
266 }
267 
268 static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
269 		enum dpu_wb wb)
270 {
271 	switch (wb) {
272 	case WB_0:
273 	case WB_1:
274 	case WB_2:
275 		ctx->pending_flush_mask |= BIT(WB_IDX);
276 		break;
277 	default:
278 		break;
279 	}
280 }
281 
282 static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
283 		enum dpu_wb wb)
284 {
285 	ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
286 	ctx->pending_flush_mask |= BIT(WB_IDX);
287 }
288 
289 static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
290 		enum dpu_intf intf)
291 {
292 	ctx->pending_intf_flush_mask |= BIT(intf - INTF_0);
293 	ctx->pending_flush_mask |= BIT(INTF_IDX);
294 }
295 
296 static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
297 		enum dpu_merge_3d merge_3d)
298 {
299 	ctx->pending_merge_3d_flush_mask |= BIT(merge_3d - MERGE_3D_0);
300 	ctx->pending_flush_mask |= BIT(MERGE_3D_IDX);
301 }
302 
303 static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
304 						   enum dpu_dsc dsc_num)
305 {
306 	ctx->pending_dsc_flush_mask |= BIT(dsc_num - DSC_0);
307 	ctx->pending_flush_mask |= BIT(DSC_IDX);
308 }
309 
310 static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
311 	enum dpu_dspp dspp, u32 dspp_sub_blk)
312 {
313 	switch (dspp) {
314 	case DSPP_0:
315 		ctx->pending_flush_mask |= BIT(13);
316 		break;
317 	case DSPP_1:
318 		ctx->pending_flush_mask |= BIT(14);
319 		break;
320 	case DSPP_2:
321 		ctx->pending_flush_mask |= BIT(15);
322 		break;
323 	case DSPP_3:
324 		ctx->pending_flush_mask |= BIT(21);
325 		break;
326 	default:
327 		break;
328 	}
329 }
330 
331 static void dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(
332 	struct dpu_hw_ctl *ctx,	enum dpu_dspp dspp, u32 dspp_sub_blk)
333 {
334 	if (dspp >= DSPP_MAX)
335 		return;
336 
337 	switch (dspp_sub_blk) {
338 	case DPU_DSPP_PCC:
339 		ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4);
340 		break;
341 	default:
342 		return;
343 	}
344 
345 	ctx->pending_flush_mask |= BIT(DSPP_IDX);
346 }
347 
348 static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
349 {
350 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
351 	ktime_t timeout;
352 	u32 status;
353 
354 	timeout = ktime_add_us(ktime_get(), timeout_us);
355 
356 	/*
357 	 * it takes around 30us to have mdp finish resetting its ctl path
358 	 * poll every 50us so that reset should be completed at 1st poll
359 	 */
360 	do {
361 		status = DPU_REG_READ(c, CTL_SW_RESET);
362 		status &= 0x1;
363 		if (status)
364 			usleep_range(20, 50);
365 	} while (status && ktime_compare_safe(ktime_get(), timeout) < 0);
366 
367 	return status;
368 }
369 
370 static int dpu_hw_ctl_reset_control(struct dpu_hw_ctl *ctx)
371 {
372 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
373 
374 	pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx);
375 	DPU_REG_WRITE(c, CTL_SW_RESET, 0x1);
376 	if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US))
377 		return -EINVAL;
378 
379 	return 0;
380 }
381 
382 static int dpu_hw_ctl_wait_reset_status(struct dpu_hw_ctl *ctx)
383 {
384 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
385 	u32 status;
386 
387 	status = DPU_REG_READ(c, CTL_SW_RESET);
388 	status &= 0x01;
389 	if (!status)
390 		return 0;
391 
392 	pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx);
393 	if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US)) {
394 		pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx);
395 		return -EINVAL;
396 	}
397 
398 	return 0;
399 }
400 
401 static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx)
402 {
403 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
404 	int i;
405 
406 	for (i = 0; i < ctx->mixer_count; i++) {
407 		enum dpu_lm mixer_id = ctx->mixer_hw_caps[i].id;
408 
409 		DPU_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
410 		DPU_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
411 		DPU_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
412 		DPU_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
413 	}
414 
415 	DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
416 }
417 
418 struct ctl_blend_config {
419 	int idx, shift, ext_shift;
420 };
421 
422 static const struct ctl_blend_config ctl_blend_config[][2] = {
423 	[SSPP_NONE] = { { -1 }, { -1 } },
424 	[SSPP_MAX] =  { { -1 }, { -1 } },
425 	[SSPP_VIG0] = { { 0, 0,  0  }, { 3, 0 } },
426 	[SSPP_VIG1] = { { 0, 3,  2  }, { 3, 4 } },
427 	[SSPP_VIG2] = { { 0, 6,  4  }, { 3, 8 } },
428 	[SSPP_VIG3] = { { 0, 26, 6  }, { 3, 12 } },
429 	[SSPP_RGB0] = { { 0, 9,  8  }, { -1 } },
430 	[SSPP_RGB1] = { { 0, 12, 10 }, { -1 } },
431 	[SSPP_RGB2] = { { 0, 15, 12 }, { -1 } },
432 	[SSPP_RGB3] = { { 0, 29, 14 }, { -1 } },
433 	[SSPP_DMA0] = { { 0, 18, 16 }, { 2, 8 } },
434 	[SSPP_DMA1] = { { 0, 21, 18 }, { 2, 12 } },
435 	[SSPP_DMA2] = { { 2, 0      }, { 2, 16 } },
436 	[SSPP_DMA3] = { { 2, 4      }, { 2, 20 } },
437 	[SSPP_DMA4] = { { 4, 0      }, { 4, 8 } },
438 	[SSPP_DMA5] = { { 4, 4      }, { 4, 12 } },
439 	[SSPP_CURSOR0] =  { { 1, 20 }, { -1 } },
440 	[SSPP_CURSOR1] =  { { 1, 26 }, { -1 } },
441 };
442 
443 static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
444 	enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
445 {
446 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
447 	u32 mix, ext, mix_ext;
448 	u32 mixercfg[5] = { 0 };
449 	int i, j;
450 	int stages;
451 	int pipes_per_stage;
452 
453 	stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
454 	if (stages < 0)
455 		return;
456 
457 	if (test_bit(DPU_MIXER_SOURCESPLIT,
458 		&ctx->mixer_hw_caps->features))
459 		pipes_per_stage = PIPES_PER_STAGE;
460 	else
461 		pipes_per_stage = 1;
462 
463 	mixercfg[0] = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */
464 
465 	if (!stage_cfg)
466 		goto exit;
467 
468 	for (i = 0; i <= stages; i++) {
469 		/* overflow to ext register if 'i + 1 > 7' */
470 		mix = (i + 1) & 0x7;
471 		ext = i >= 7;
472 		mix_ext = (i + 1) & 0xf;
473 
474 		for (j = 0 ; j < pipes_per_stage; j++) {
475 			enum dpu_sspp_multirect_index rect_index =
476 				stage_cfg->multirect_index[i][j];
477 			enum dpu_sspp pipe = stage_cfg->stage[i][j];
478 			const struct ctl_blend_config *cfg =
479 				&ctl_blend_config[pipe][rect_index == DPU_SSPP_RECT_1];
480 
481 			/*
482 			 * CTL_LAYER has 3-bit field (and extra bits in EXT register),
483 			 * all EXT registers has 4-bit fields.
484 			 */
485 			if (cfg->idx == -1) {
486 				continue;
487 			} else if (cfg->idx == 0) {
488 				mixercfg[0] |= mix << cfg->shift;
489 				mixercfg[1] |= ext << cfg->ext_shift;
490 			} else {
491 				mixercfg[cfg->idx] |= mix_ext << cfg->shift;
492 			}
493 		}
494 	}
495 
496 exit:
497 	DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg[0]);
498 	DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg[1]);
499 	DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg[2]);
500 	DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg[3]);
501 	if ((test_bit(DPU_CTL_HAS_LAYER_EXT4, &ctx->caps->features)))
502 		DPU_REG_WRITE(c, CTL_LAYER_EXT4(lm), mixercfg[4]);
503 }
504 
505 
506 static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
507 		struct dpu_hw_intf_cfg *cfg)
508 {
509 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
510 	u32 intf_active = 0;
511 	u32 wb_active = 0;
512 	u32 mode_sel = 0;
513 
514 	/* CTL_TOP[31:28] carries group_id to collate CTL paths
515 	 * per VM. Explicitly disable it until VM support is
516 	 * added in SW. Power on reset value is not disable.
517 	 */
518 	if ((test_bit(DPU_CTL_VM_CFG, &ctx->caps->features)))
519 		mode_sel = CTL_DEFAULT_GROUP_ID  << 28;
520 
521 	if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
522 		mode_sel |= BIT(17);
523 
524 	intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
525 	wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
526 
527 	if (cfg->intf)
528 		intf_active |= BIT(cfg->intf - INTF_0);
529 
530 	if (cfg->wb)
531 		wb_active |= BIT(cfg->wb - WB_0);
532 
533 	DPU_REG_WRITE(c, CTL_TOP, mode_sel);
534 	DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
535 	DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
536 
537 	if (cfg->merge_3d)
538 		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
539 			      BIT(cfg->merge_3d - MERGE_3D_0));
540 
541 	if (cfg->dsc)
542 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
543 }
544 
545 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
546 		struct dpu_hw_intf_cfg *cfg)
547 {
548 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
549 	u32 intf_cfg = 0;
550 
551 	intf_cfg |= (cfg->intf & 0xF) << 4;
552 
553 	if (cfg->mode_3d) {
554 		intf_cfg |= BIT(19);
555 		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
556 	}
557 
558 	if (cfg->wb)
559 		intf_cfg |= (cfg->wb & 0x3) + 2;
560 
561 	switch (cfg->intf_mode_sel) {
562 	case DPU_CTL_MODE_SEL_VID:
563 		intf_cfg &= ~BIT(17);
564 		intf_cfg &= ~(0x3 << 15);
565 		break;
566 	case DPU_CTL_MODE_SEL_CMD:
567 		intf_cfg |= BIT(17);
568 		intf_cfg |= ((cfg->stream_sel & 0x3) << 15);
569 		break;
570 	default:
571 		pr_err("unknown interface type %d\n", cfg->intf_mode_sel);
572 		return;
573 	}
574 
575 	DPU_REG_WRITE(c, CTL_TOP, intf_cfg);
576 }
577 
578 static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
579 		struct dpu_hw_intf_cfg *cfg)
580 {
581 	struct dpu_hw_blk_reg_map *c = &ctx->hw;
582 	u32 intf_active = 0;
583 	u32 wb_active = 0;
584 	u32 merge3d_active = 0;
585 	u32 dsc_active;
586 
587 	/*
588 	 * This API resets each portion of the CTL path namely,
589 	 * clearing the sspps staged on the lm, merge_3d block,
590 	 * interfaces , writeback etc to ensure clean teardown of the pipeline.
591 	 * This will be used for writeback to begin with to have a
592 	 * proper teardown of the writeback session but upon further
593 	 * validation, this can be extended to all interfaces.
594 	 */
595 	if (cfg->merge_3d) {
596 		merge3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE);
597 		merge3d_active &= ~BIT(cfg->merge_3d - MERGE_3D_0);
598 		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
599 				merge3d_active);
600 	}
601 
602 	dpu_hw_ctl_clear_all_blendstages(ctx);
603 
604 	if (cfg->intf) {
605 		intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
606 		intf_active &= ~BIT(cfg->intf - INTF_0);
607 		DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
608 	}
609 
610 	if (cfg->wb) {
611 		wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
612 		wb_active &= ~BIT(cfg->wb - WB_0);
613 		DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
614 	}
615 
616 	if (cfg->dsc) {
617 		dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);
618 		dsc_active &= ~cfg->dsc;
619 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
620 	}
621 }
622 
623 static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
624 	unsigned long *fetch_active)
625 {
626 	int i;
627 	u32 val = 0;
628 
629 	if (fetch_active) {
630 		for (i = 0; i < SSPP_MAX; i++) {
631 			if (test_bit(i, fetch_active) &&
632 				fetch_tbl[i] != CTL_INVALID_BIT)
633 				val |= BIT(fetch_tbl[i]);
634 		}
635 	}
636 
637 	DPU_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);
638 }
639 
640 static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
641 		unsigned long cap)
642 {
643 	if (cap & BIT(DPU_CTL_ACTIVE_CFG)) {
644 		ops->trigger_flush = dpu_hw_ctl_trigger_flush_v1;
645 		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1;
646 		ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
647 		ops->update_pending_flush_intf =
648 			dpu_hw_ctl_update_pending_flush_intf_v1;
649 		ops->update_pending_flush_merge_3d =
650 			dpu_hw_ctl_update_pending_flush_merge_3d_v1;
651 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
652 		ops->update_pending_flush_dsc =
653 			dpu_hw_ctl_update_pending_flush_dsc_v1;
654 	} else {
655 		ops->trigger_flush = dpu_hw_ctl_trigger_flush;
656 		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
657 		ops->update_pending_flush_intf =
658 			dpu_hw_ctl_update_pending_flush_intf;
659 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
660 	}
661 	ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
662 	ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
663 	ops->get_pending_flush = dpu_hw_ctl_get_pending_flush;
664 	ops->get_flush_register = dpu_hw_ctl_get_flush_register;
665 	ops->trigger_start = dpu_hw_ctl_trigger_start;
666 	ops->is_started = dpu_hw_ctl_is_started;
667 	ops->trigger_pending = dpu_hw_ctl_trigger_pending;
668 	ops->reset = dpu_hw_ctl_reset_control;
669 	ops->wait_reset_status = dpu_hw_ctl_wait_reset_status;
670 	ops->clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages;
671 	ops->setup_blendstage = dpu_hw_ctl_setup_blendstage;
672 	ops->update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp;
673 	ops->update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer;
674 	if (cap & BIT(DPU_CTL_DSPP_SUB_BLOCK_FLUSH))
675 		ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks;
676 	else
677 		ops->update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp;
678 
679 	if (cap & BIT(DPU_CTL_FETCH_ACTIVE))
680 		ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
681 };
682 
683 struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
684 		void __iomem *addr,
685 		u32 mixer_count,
686 		const struct dpu_lm_cfg *mixer)
687 {
688 	struct dpu_hw_ctl *c;
689 
690 	c = kzalloc(sizeof(*c), GFP_KERNEL);
691 	if (!c)
692 		return ERR_PTR(-ENOMEM);
693 
694 	c->hw.blk_addr = addr + cfg->base;
695 	c->hw.log_mask = DPU_DBG_MASK_CTL;
696 
697 	c->caps = cfg;
698 	_setup_ctl_ops(&c->ops, c->caps->features);
699 	c->idx = cfg->id;
700 	c->mixer_count = mixer_count;
701 	c->mixer_hw_caps = mixer;
702 
703 	return c;
704 }
705 
706 void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx)
707 {
708 	kfree(ctx);
709 }
710