xref: /linux/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c (revision 42422993cf28d456778ee9168d73758ec037cd51)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3  */
4 
5 #include "dpu_hwio.h"
6 #include "dpu_hw_catalog.h"
7 #include "dpu_hw_lm.h"
8 #include "dpu_hw_sspp.h"
9 #include "dpu_kms.h"
10 
11 #include "msm_mdss.h"
12 
13 #include <drm/drm_file.h>
14 
15 #define DPU_FETCH_CONFIG_RESET_VALUE   0x00000087
16 
17 /* SSPP registers */
18 #define SSPP_SRC_SIZE                      0x00
19 #define SSPP_SRC_XY                        0x08
20 #define SSPP_OUT_SIZE                      0x0c
21 #define SSPP_OUT_XY                        0x10
22 #define SSPP_SRC0_ADDR                     0x14
23 #define SSPP_SRC1_ADDR                     0x18
24 #define SSPP_SRC2_ADDR                     0x1C
25 #define SSPP_SRC3_ADDR                     0x20
26 #define SSPP_SRC_YSTRIDE0                  0x24
27 #define SSPP_SRC_YSTRIDE1                  0x28
28 #define SSPP_SRC_FORMAT                    0x30
29 #define SSPP_SRC_UNPACK_PATTERN            0x34
30 #define SSPP_SRC_OP_MODE                   0x38
31 #define SSPP_SRC_CONSTANT_COLOR            0x3c
32 #define SSPP_EXCL_REC_CTL                  0x40
33 #define SSPP_UBWC_STATIC_CTRL              0x44
34 #define SSPP_FETCH_CONFIG                  0x48
35 #define SSPP_DANGER_LUT                    0x60
36 #define SSPP_SAFE_LUT                      0x64
37 #define SSPP_CREQ_LUT                      0x68
38 #define SSPP_QOS_CTRL                      0x6C
39 #define SSPP_SRC_ADDR_SW_STATUS            0x70
40 #define SSPP_CREQ_LUT_0                    0x74
41 #define SSPP_CREQ_LUT_1                    0x78
42 #define SSPP_DECIMATION_CONFIG             0xB4
43 #define SSPP_SW_PIX_EXT_C0_LR              0x100
44 #define SSPP_SW_PIX_EXT_C0_TB              0x104
45 #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS      0x108
46 #define SSPP_SW_PIX_EXT_C1C2_LR            0x110
47 #define SSPP_SW_PIX_EXT_C1C2_TB            0x114
48 #define SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS    0x118
49 #define SSPP_SW_PIX_EXT_C3_LR              0x120
50 #define SSPP_SW_PIX_EXT_C3_TB              0x124
51 #define SSPP_SW_PIX_EXT_C3_REQ_PIXELS      0x128
52 #define SSPP_TRAFFIC_SHAPER                0x130
53 #define SSPP_CDP_CNTL                      0x134
54 #define SSPP_UBWC_ERROR_STATUS             0x138
55 #define SSPP_CDP_CNTL_REC1                 0x13c
56 #define SSPP_TRAFFIC_SHAPER_PREFILL        0x150
57 #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL   0x154
58 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
59 #define SSPP_OUT_SIZE_REC1                 0x160
60 #define SSPP_OUT_XY_REC1                   0x164
61 #define SSPP_SRC_XY_REC1                   0x168
62 #define SSPP_SRC_SIZE_REC1                 0x16C
63 #define SSPP_MULTIRECT_OPMODE              0x170
64 #define SSPP_SRC_FORMAT_REC1               0x174
65 #define SSPP_SRC_UNPACK_PATTERN_REC1       0x178
66 #define SSPP_SRC_OP_MODE_REC1              0x17C
67 #define SSPP_SRC_CONSTANT_COLOR_REC1       0x180
68 #define SSPP_EXCL_REC_SIZE_REC1            0x184
69 #define SSPP_EXCL_REC_XY_REC1              0x188
70 #define SSPP_EXCL_REC_SIZE                 0x1B4
71 #define SSPP_EXCL_REC_XY                   0x1B8
72 #define SSPP_CLK_CTRL                      0x330
73 
74 /* SSPP_SRC_OP_MODE & OP_MODE_REC1 */
75 #define MDSS_MDP_OP_DEINTERLACE            BIT(22)
76 #define MDSS_MDP_OP_DEINTERLACE_ODD        BIT(23)
77 #define MDSS_MDP_OP_IGC_ROM_1              BIT(18)
78 #define MDSS_MDP_OP_IGC_ROM_0              BIT(17)
79 #define MDSS_MDP_OP_IGC_EN                 BIT(16)
80 #define MDSS_MDP_OP_FLIP_UD                BIT(14)
81 #define MDSS_MDP_OP_FLIP_LR                BIT(13)
82 #define MDSS_MDP_OP_BWC_EN                 BIT(0)
83 #define MDSS_MDP_OP_PE_OVERRIDE            BIT(31)
84 #define MDSS_MDP_OP_BWC_LOSSLESS           (0 << 1)
85 #define MDSS_MDP_OP_BWC_Q_HIGH             (1 << 1)
86 #define MDSS_MDP_OP_BWC_Q_MED              (2 << 1)
87 
88 /* SSPP_QOS_CTRL */
89 #define SSPP_QOS_CTRL_VBLANK_EN            BIT(16)
90 #define SSPP_QOS_CTRL_DANGER_SAFE_EN       BIT(0)
91 #define SSPP_QOS_CTRL_DANGER_VBLANK_MASK   0x3
92 #define SSPP_QOS_CTRL_DANGER_VBLANK_OFF    4
93 #define SSPP_QOS_CTRL_CREQ_VBLANK_MASK     0x3
94 #define SSPP_QOS_CTRL_CREQ_VBLANK_OFF      20
95 
96 /* DPU_SSPP_SCALER_QSEED2 */
97 #define SSPP_VIG_OP_MODE                   0x0
98 #define SCALE_CONFIG                       0x04
99 #define COMP0_3_PHASE_STEP_X               0x10
100 #define COMP0_3_PHASE_STEP_Y               0x14
101 #define COMP1_2_PHASE_STEP_X               0x18
102 #define COMP1_2_PHASE_STEP_Y               0x1c
103 #define COMP0_3_INIT_PHASE_X               0x20
104 #define COMP0_3_INIT_PHASE_Y               0x24
105 #define COMP1_2_INIT_PHASE_X               0x28
106 #define COMP1_2_INIT_PHASE_Y               0x2C
107 #define VIG_0_QSEED2_SHARP                 0x30
108 
109 /* SSPP_TRAFFIC_SHAPER and _REC1 */
110 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
111 
112 /*
113  * Definitions for ViG op modes
114  */
115 #define VIG_OP_CSC_DST_DATAFMT BIT(19)
116 #define VIG_OP_CSC_SRC_DATAFMT BIT(18)
117 #define VIG_OP_CSC_EN          BIT(17)
118 #define VIG_OP_MEM_PROT_CONT   BIT(15)
119 #define VIG_OP_MEM_PROT_VAL    BIT(14)
120 #define VIG_OP_MEM_PROT_SAT    BIT(13)
121 #define VIG_OP_MEM_PROT_HUE    BIT(12)
122 #define VIG_OP_HIST            BIT(8)
123 #define VIG_OP_SKY_COL         BIT(7)
124 #define VIG_OP_FOIL            BIT(6)
125 #define VIG_OP_SKIN_COL        BIT(5)
126 #define VIG_OP_PA_EN           BIT(4)
127 #define VIG_OP_PA_SAT_ZERO_EXP BIT(2)
128 #define VIG_OP_MEM_PROT_BLEND  BIT(1)
129 
130 /*
131  * Definitions for CSC 10 op modes
132  */
133 #define SSPP_VIG_CSC_10_OP_MODE            0x0
134 #define VIG_CSC_10_SRC_DATAFMT BIT(1)
135 #define VIG_CSC_10_EN          BIT(0)
136 #define CSC_10BIT_OFFSET       4
137 
138 /* traffic shaper clock in Hz */
139 #define TS_CLK			19200000
140 
141 
142 static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
143 {
144 	struct dpu_hw_sspp *ctx = pipe->sspp;
145 	u32 mode_mask;
146 
147 	if (!ctx)
148 		return;
149 
150 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
151 		/**
152 		 * if rect index is RECT_SOLO, we cannot expect a
153 		 * virtual plane sharing the same SSPP id. So we go
154 		 * and disable multirect
155 		 */
156 		mode_mask = 0;
157 	} else {
158 		mode_mask = DPU_REG_READ(&ctx->hw, SSPP_MULTIRECT_OPMODE);
159 		mode_mask |= pipe->multirect_index;
160 		if (pipe->multirect_mode == DPU_SSPP_MULTIRECT_TIME_MX)
161 			mode_mask |= BIT(2);
162 		else
163 			mode_mask &= ~BIT(2);
164 	}
165 
166 	DPU_REG_WRITE(&ctx->hw, SSPP_MULTIRECT_OPMODE, mode_mask);
167 }
168 
169 static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx,
170 		u32 mask, u8 en)
171 {
172 	const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
173 	u32 opmode;
174 
175 	if (!test_bit(DPU_SSPP_SCALER_QSEED2, &ctx->cap->features) ||
176 		!test_bit(DPU_SSPP_CSC, &ctx->cap->features))
177 		return;
178 
179 	opmode = DPU_REG_READ(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE);
180 
181 	if (en)
182 		opmode |= mask;
183 	else
184 		opmode &= ~mask;
185 
186 	DPU_REG_WRITE(&ctx->hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE, opmode);
187 }
188 
189 static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx,
190 		u32 mask, u8 en)
191 {
192 	const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
193 	u32 opmode;
194 
195 	opmode = DPU_REG_READ(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE);
196 	if (en)
197 		opmode |= mask;
198 	else
199 		opmode &= ~mask;
200 
201 	DPU_REG_WRITE(&ctx->hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE, opmode);
202 }
203 
204 /*
205  * Setup source pixel format, flip,
206  */
207 static void dpu_hw_sspp_setup_format(struct dpu_sw_pipe *pipe,
208 		const struct dpu_format *fmt, u32 flags)
209 {
210 	struct dpu_hw_sspp *ctx = pipe->sspp;
211 	struct dpu_hw_blk_reg_map *c;
212 	u32 chroma_samp, unpack, src_format;
213 	u32 opmode = 0;
214 	u32 fast_clear = 0;
215 	u32 op_mode_off, unpack_pat_off, format_off;
216 
217 	if (!ctx || !fmt)
218 		return;
219 
220 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
221 	    pipe->multirect_index == DPU_SSPP_RECT_0) {
222 		op_mode_off = SSPP_SRC_OP_MODE;
223 		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
224 		format_off = SSPP_SRC_FORMAT;
225 	} else {
226 		op_mode_off = SSPP_SRC_OP_MODE_REC1;
227 		unpack_pat_off = SSPP_SRC_UNPACK_PATTERN_REC1;
228 		format_off = SSPP_SRC_FORMAT_REC1;
229 	}
230 
231 	c = &ctx->hw;
232 	opmode = DPU_REG_READ(c, op_mode_off);
233 	opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
234 			MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
235 
236 	if (flags & DPU_SSPP_FLIP_LR)
237 		opmode |= MDSS_MDP_OP_FLIP_LR;
238 	if (flags & DPU_SSPP_FLIP_UD)
239 		opmode |= MDSS_MDP_OP_FLIP_UD;
240 
241 	chroma_samp = fmt->chroma_sample;
242 	if (flags & DPU_SSPP_SOURCE_ROTATED_90) {
243 		if (chroma_samp == DPU_CHROMA_H2V1)
244 			chroma_samp = DPU_CHROMA_H1V2;
245 		else if (chroma_samp == DPU_CHROMA_H1V2)
246 			chroma_samp = DPU_CHROMA_H2V1;
247 	}
248 
249 	src_format = (chroma_samp << 23) | (fmt->fetch_planes << 19) |
250 		(fmt->bits[C3_ALPHA] << 6) | (fmt->bits[C2_R_Cr] << 4) |
251 		(fmt->bits[C1_B_Cb] << 2) | (fmt->bits[C0_G_Y] << 0);
252 
253 	if (flags & DPU_SSPP_ROT_90)
254 		src_format |= BIT(11); /* ROT90 */
255 
256 	if (fmt->alpha_enable && fmt->fetch_planes == DPU_PLANE_INTERLEAVED)
257 		src_format |= BIT(8); /* SRCC3_EN */
258 
259 	if (flags & DPU_SSPP_SOLID_FILL)
260 		src_format |= BIT(22);
261 
262 	unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |
263 		(fmt->element[1] << 8) | (fmt->element[0] << 0);
264 	src_format |= ((fmt->unpack_count - 1) << 12) |
265 		(fmt->unpack_tight << 17) |
266 		(fmt->unpack_align_msb << 18) |
267 		((fmt->bpp - 1) << 9);
268 
269 	if (fmt->fetch_mode != DPU_FETCH_LINEAR) {
270 		if (DPU_FORMAT_IS_UBWC(fmt))
271 			opmode |= MDSS_MDP_OP_BWC_EN;
272 		src_format |= (fmt->fetch_mode & 3) << 30; /*FRAME_FORMAT */
273 		DPU_REG_WRITE(c, SSPP_FETCH_CONFIG,
274 			DPU_FETCH_CONFIG_RESET_VALUE |
275 			ctx->ubwc->highest_bank_bit << 18);
276 		switch (ctx->ubwc->ubwc_enc_version) {
277 		case UBWC_1_0:
278 			fast_clear = fmt->alpha_enable ? BIT(31) : 0;
279 			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
280 					fast_clear | (ctx->ubwc->ubwc_swizzle & 0x1) |
281 					BIT(8) |
282 					(ctx->ubwc->highest_bank_bit << 4));
283 			break;
284 		case UBWC_2_0:
285 			fast_clear = fmt->alpha_enable ? BIT(31) : 0;
286 			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
287 					fast_clear | (ctx->ubwc->ubwc_swizzle) |
288 					(ctx->ubwc->highest_bank_bit << 4));
289 			break;
290 		case UBWC_3_0:
291 			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
292 					BIT(30) | (ctx->ubwc->ubwc_swizzle) |
293 					(ctx->ubwc->highest_bank_bit << 4));
294 			break;
295 		case UBWC_4_0:
296 			DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
297 					DPU_FORMAT_IS_YUV(fmt) ? 0 : BIT(30));
298 			break;
299 		}
300 	}
301 
302 	opmode |= MDSS_MDP_OP_PE_OVERRIDE;
303 
304 	/* if this is YUV pixel format, enable CSC */
305 	if (DPU_FORMAT_IS_YUV(fmt))
306 		src_format |= BIT(15);
307 
308 	if (DPU_FORMAT_IS_DX(fmt))
309 		src_format |= BIT(14);
310 
311 	/* update scaler opmode, if appropriate */
312 	if (test_bit(DPU_SSPP_CSC, &ctx->cap->features))
313 		_sspp_setup_opmode(ctx, VIG_OP_CSC_EN | VIG_OP_CSC_SRC_DATAFMT,
314 			DPU_FORMAT_IS_YUV(fmt));
315 	else if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features))
316 		_sspp_setup_csc10_opmode(ctx,
317 			VIG_CSC_10_EN | VIG_CSC_10_SRC_DATAFMT,
318 			DPU_FORMAT_IS_YUV(fmt));
319 
320 	DPU_REG_WRITE(c, format_off, src_format);
321 	DPU_REG_WRITE(c, unpack_pat_off, unpack);
322 	DPU_REG_WRITE(c, op_mode_off, opmode);
323 
324 	/* clear previous UBWC error */
325 	DPU_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
326 }
327 
328 static void dpu_hw_sspp_setup_pe_config(struct dpu_hw_sspp *ctx,
329 		struct dpu_hw_pixel_ext *pe_ext)
330 {
331 	struct dpu_hw_blk_reg_map *c;
332 	u8 color;
333 	u32 lr_pe[4], tb_pe[4], tot_req_pixels[4];
334 	const u32 bytemask = 0xff;
335 	const u32 shortmask = 0xffff;
336 
337 	if (!ctx || !pe_ext)
338 		return;
339 
340 	c = &ctx->hw;
341 
342 	/* program SW pixel extension override for all pipes*/
343 	for (color = 0; color < DPU_MAX_PLANES; color++) {
344 		/* color 2 has the same set of registers as color 1 */
345 		if (color == 2)
346 			continue;
347 
348 		lr_pe[color] = ((pe_ext->right_ftch[color] & bytemask) << 24)|
349 			((pe_ext->right_rpt[color] & bytemask) << 16)|
350 			((pe_ext->left_ftch[color] & bytemask) << 8)|
351 			(pe_ext->left_rpt[color] & bytemask);
352 
353 		tb_pe[color] = ((pe_ext->btm_ftch[color] & bytemask) << 24)|
354 			((pe_ext->btm_rpt[color] & bytemask) << 16)|
355 			((pe_ext->top_ftch[color] & bytemask) << 8)|
356 			(pe_ext->top_rpt[color] & bytemask);
357 
358 		tot_req_pixels[color] = (((pe_ext->roi_h[color] +
359 			pe_ext->num_ext_pxls_top[color] +
360 			pe_ext->num_ext_pxls_btm[color]) & shortmask) << 16) |
361 			((pe_ext->roi_w[color] +
362 			pe_ext->num_ext_pxls_left[color] +
363 			pe_ext->num_ext_pxls_right[color]) & shortmask);
364 	}
365 
366 	/* color 0 */
367 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_LR, lr_pe[0]);
368 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_TB, tb_pe[0]);
369 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C0_REQ_PIXELS,
370 			tot_req_pixels[0]);
371 
372 	/* color 1 and color 2 */
373 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_LR, lr_pe[1]);
374 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_TB, tb_pe[1]);
375 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C1C2_REQ_PIXELS,
376 			tot_req_pixels[1]);
377 
378 	/* color 3 */
379 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_LR, lr_pe[3]);
380 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_TB, lr_pe[3]);
381 	DPU_REG_WRITE(c, SSPP_SW_PIX_EXT_C3_REQ_PIXELS,
382 			tot_req_pixels[3]);
383 }
384 
385 static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_sspp *ctx,
386 		struct dpu_hw_scaler3_cfg *scaler3_cfg,
387 		const struct dpu_format *format)
388 {
389 	if (!ctx || !scaler3_cfg)
390 		return;
391 
392 	dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg,
393 			ctx->cap->sblk->scaler_blk.base,
394 			ctx->cap->sblk->scaler_blk.version,
395 			format);
396 }
397 
398 static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_sspp *ctx)
399 {
400 	if (!ctx)
401 		return 0;
402 
403 	return dpu_hw_get_scaler3_ver(&ctx->hw,
404 				      ctx->cap->sblk->scaler_blk.base);
405 }
406 
407 /*
408  * dpu_hw_sspp_setup_rects()
409  */
410 static void dpu_hw_sspp_setup_rects(struct dpu_sw_pipe *pipe,
411 		struct dpu_sw_pipe_cfg *cfg)
412 {
413 	struct dpu_hw_sspp *ctx = pipe->sspp;
414 	struct dpu_hw_blk_reg_map *c;
415 	u32 src_size, src_xy, dst_size, dst_xy;
416 	u32 src_size_off, src_xy_off, out_size_off, out_xy_off;
417 
418 	if (!ctx || !cfg)
419 		return;
420 
421 	c = &ctx->hw;
422 
423 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
424 	    pipe->multirect_index == DPU_SSPP_RECT_0) {
425 		src_size_off = SSPP_SRC_SIZE;
426 		src_xy_off = SSPP_SRC_XY;
427 		out_size_off = SSPP_OUT_SIZE;
428 		out_xy_off = SSPP_OUT_XY;
429 	} else {
430 		src_size_off = SSPP_SRC_SIZE_REC1;
431 		src_xy_off = SSPP_SRC_XY_REC1;
432 		out_size_off = SSPP_OUT_SIZE_REC1;
433 		out_xy_off = SSPP_OUT_XY_REC1;
434 	}
435 
436 
437 	/* src and dest rect programming */
438 	src_xy = (cfg->src_rect.y1 << 16) | cfg->src_rect.x1;
439 	src_size = (drm_rect_height(&cfg->src_rect) << 16) |
440 		   drm_rect_width(&cfg->src_rect);
441 	dst_xy = (cfg->dst_rect.y1 << 16) | cfg->dst_rect.x1;
442 	dst_size = (drm_rect_height(&cfg->dst_rect) << 16) |
443 		drm_rect_width(&cfg->dst_rect);
444 
445 	/* rectangle register programming */
446 	DPU_REG_WRITE(c, src_size_off, src_size);
447 	DPU_REG_WRITE(c, src_xy_off, src_xy);
448 	DPU_REG_WRITE(c, out_size_off, dst_size);
449 	DPU_REG_WRITE(c, out_xy_off, dst_xy);
450 }
451 
452 static void dpu_hw_sspp_setup_sourceaddress(struct dpu_sw_pipe *pipe,
453 		struct dpu_hw_fmt_layout *layout)
454 {
455 	struct dpu_hw_sspp *ctx = pipe->sspp;
456 	u32 ystride0, ystride1;
457 	int i;
458 
459 	if (!ctx)
460 		return;
461 
462 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
463 		for (i = 0; i < ARRAY_SIZE(layout->plane_addr); i++)
464 			DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR + i * 0x4,
465 					layout->plane_addr[i]);
466 	} else if (pipe->multirect_index == DPU_SSPP_RECT_0) {
467 		DPU_REG_WRITE(&ctx->hw, SSPP_SRC0_ADDR,
468 				layout->plane_addr[0]);
469 		DPU_REG_WRITE(&ctx->hw, SSPP_SRC2_ADDR,
470 				layout->plane_addr[2]);
471 	} else {
472 		DPU_REG_WRITE(&ctx->hw, SSPP_SRC1_ADDR,
473 				layout->plane_addr[0]);
474 		DPU_REG_WRITE(&ctx->hw, SSPP_SRC3_ADDR,
475 				layout->plane_addr[2]);
476 	}
477 
478 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO) {
479 		ystride0 = (layout->plane_pitch[0]) |
480 			(layout->plane_pitch[1] << 16);
481 		ystride1 = (layout->plane_pitch[2]) |
482 			(layout->plane_pitch[3] << 16);
483 	} else {
484 		ystride0 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE0);
485 		ystride1 = DPU_REG_READ(&ctx->hw, SSPP_SRC_YSTRIDE1);
486 
487 		if (pipe->multirect_index == DPU_SSPP_RECT_0) {
488 			ystride0 = (ystride0 & 0xFFFF0000) |
489 				(layout->plane_pitch[0] & 0x0000FFFF);
490 			ystride1 = (ystride1 & 0xFFFF0000)|
491 				(layout->plane_pitch[2] & 0x0000FFFF);
492 		} else {
493 			ystride0 = (ystride0 & 0x0000FFFF) |
494 				((layout->plane_pitch[0] << 16) &
495 				 0xFFFF0000);
496 			ystride1 = (ystride1 & 0x0000FFFF) |
497 				((layout->plane_pitch[2] << 16) &
498 				 0xFFFF0000);
499 		}
500 	}
501 
502 	DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE0, ystride0);
503 	DPU_REG_WRITE(&ctx->hw, SSPP_SRC_YSTRIDE1, ystride1);
504 }
505 
506 static void dpu_hw_sspp_setup_csc(struct dpu_hw_sspp *ctx,
507 		const struct dpu_csc_cfg *data)
508 {
509 	u32 offset;
510 	bool csc10 = false;
511 
512 	if (!ctx || !data)
513 		return;
514 
515 	offset = ctx->cap->sblk->csc_blk.base;
516 
517 	if (test_bit(DPU_SSPP_CSC_10BIT, &ctx->cap->features)) {
518 		offset += CSC_10BIT_OFFSET;
519 		csc10 = true;
520 	}
521 
522 	dpu_hw_csc_setup(&ctx->hw, offset, data, csc10);
523 }
524 
525 static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)
526 {
527 	struct dpu_hw_sspp *ctx = pipe->sspp;
528 	struct dpu_hw_fmt_layout cfg;
529 
530 	if (!ctx)
531 		return;
532 
533 	/* cleanup source addresses */
534 	memset(&cfg, 0, sizeof(cfg));
535 	ctx->ops.setup_sourceaddress(pipe, &cfg);
536 
537 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
538 	    pipe->multirect_index == DPU_SSPP_RECT_0)
539 		DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR, color);
540 	else
541 		DPU_REG_WRITE(&ctx->hw, SSPP_SRC_CONSTANT_COLOR_REC1,
542 				color);
543 }
544 
545 static void dpu_hw_sspp_setup_qos_lut(struct dpu_hw_sspp *ctx,
546 				      struct dpu_hw_qos_cfg *cfg)
547 {
548 	if (!ctx || !cfg)
549 		return;
550 
551 	_dpu_hw_setup_qos_lut(&ctx->hw, SSPP_DANGER_LUT,
552 			      test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features),
553 			      cfg);
554 }
555 
556 static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx,
557 				       bool danger_safe_en)
558 {
559 	if (!ctx)
560 		return;
561 
562 	DPU_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL,
563 		      danger_safe_en ? SSPP_QOS_CTRL_DANGER_SAFE_EN : 0);
564 }
565 
566 static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,
567 				  const struct dpu_format *fmt,
568 				  bool enable)
569 {
570 	struct dpu_hw_sspp *ctx = pipe->sspp;
571 	u32 cdp_cntl_offset = 0;
572 
573 	if (!ctx)
574 		return;
575 
576 	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||
577 	    pipe->multirect_index == DPU_SSPP_RECT_0)
578 		cdp_cntl_offset = SSPP_CDP_CNTL;
579 	else
580 		cdp_cntl_offset = SSPP_CDP_CNTL_REC1;
581 
582 	dpu_setup_cdp(&ctx->hw, cdp_cntl_offset, fmt, enable);
583 }
584 
585 static bool dpu_hw_sspp_setup_clk_force_ctrl(struct dpu_hw_sspp *ctx, bool enable)
586 {
587 	static const struct dpu_clk_ctrl_reg sspp_clk_ctrl = {
588 		.reg_off = SSPP_CLK_CTRL,
589 		.bit_off = 0
590 	};
591 
592 	return dpu_hw_clk_force_ctrl(&ctx->hw, &sspp_clk_ctrl, enable);
593 }
594 
595 static void _setup_layer_ops(struct dpu_hw_sspp *c,
596 		unsigned long features, const struct dpu_mdss_version *mdss_rev)
597 {
598 	c->ops.setup_format = dpu_hw_sspp_setup_format;
599 	c->ops.setup_rects = dpu_hw_sspp_setup_rects;
600 	c->ops.setup_sourceaddress = dpu_hw_sspp_setup_sourceaddress;
601 	c->ops.setup_solidfill = dpu_hw_sspp_setup_solidfill;
602 	c->ops.setup_pe = dpu_hw_sspp_setup_pe_config;
603 
604 	if (test_bit(DPU_SSPP_QOS, &features)) {
605 		c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut;
606 		c->ops.setup_qos_ctrl = dpu_hw_sspp_setup_qos_ctrl;
607 	}
608 
609 	if (test_bit(DPU_SSPP_CSC, &features) ||
610 		test_bit(DPU_SSPP_CSC_10BIT, &features))
611 		c->ops.setup_csc = dpu_hw_sspp_setup_csc;
612 
613 	if (test_bit(DPU_SSPP_SMART_DMA_V1, &c->cap->features) ||
614 		test_bit(DPU_SSPP_SMART_DMA_V2, &c->cap->features))
615 		c->ops.setup_multirect = dpu_hw_sspp_setup_multirect;
616 
617 	if (test_bit(DPU_SSPP_SCALER_QSEED3, &features) ||
618 			test_bit(DPU_SSPP_SCALER_QSEED3LITE, &features) ||
619 			test_bit(DPU_SSPP_SCALER_QSEED4, &features)) {
620 		c->ops.setup_scaler = _dpu_hw_sspp_setup_scaler3;
621 		c->ops.get_scaler_ver = _dpu_hw_sspp_get_scaler3_ver;
622 	}
623 
624 	if (test_bit(DPU_SSPP_CDP, &features))
625 		c->ops.setup_cdp = dpu_hw_sspp_setup_cdp;
626 
627 	if (mdss_rev->core_major_ver >= 9)
628 		c->ops.setup_clk_force_ctrl = dpu_hw_sspp_setup_clk_force_ctrl;
629 }
630 
631 #ifdef CONFIG_DEBUG_FS
632 int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, struct dpu_kms *kms,
633 			      struct dentry *entry)
634 {
635 	const struct dpu_sspp_cfg *cfg = hw_pipe->cap;
636 	const struct dpu_sspp_sub_blks *sblk = cfg->sblk;
637 	struct dentry *debugfs_root;
638 	char sspp_name[32];
639 
640 	snprintf(sspp_name, sizeof(sspp_name), "%d", hw_pipe->idx);
641 
642 	/* create overall sub-directory for the pipe */
643 	debugfs_root =
644 		debugfs_create_dir(sspp_name, entry);
645 
646 	/* don't error check these */
647 	debugfs_create_xul("features", 0600,
648 			debugfs_root, (unsigned long *)&hw_pipe->cap->features);
649 
650 	/* add register dump support */
651 	dpu_debugfs_create_regset32("src_blk", 0400,
652 			debugfs_root,
653 			cfg->base,
654 			cfg->len,
655 			kms);
656 
657 	if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) ||
658 			cfg->features & BIT(DPU_SSPP_SCALER_QSEED3LITE) ||
659 			cfg->features & BIT(DPU_SSPP_SCALER_QSEED2) ||
660 			cfg->features & BIT(DPU_SSPP_SCALER_QSEED4))
661 		dpu_debugfs_create_regset32("scaler_blk", 0400,
662 				debugfs_root,
663 				sblk->scaler_blk.base + cfg->base,
664 				sblk->scaler_blk.len,
665 				kms);
666 
667 	if (cfg->features & BIT(DPU_SSPP_CSC) ||
668 			cfg->features & BIT(DPU_SSPP_CSC_10BIT))
669 		dpu_debugfs_create_regset32("csc_blk", 0400,
670 				debugfs_root,
671 				sblk->csc_blk.base + cfg->base,
672 				sblk->csc_blk.len,
673 				kms);
674 
675 	debugfs_create_u32("xin_id",
676 			0400,
677 			debugfs_root,
678 			(u32 *) &cfg->xin_id);
679 	debugfs_create_u32("clk_ctrl",
680 			0400,
681 			debugfs_root,
682 			(u32 *) &cfg->clk_ctrl);
683 
684 	return 0;
685 }
686 #endif
687 
688 struct dpu_hw_sspp *dpu_hw_sspp_init(const struct dpu_sspp_cfg *cfg,
689 		void __iomem *addr, const struct msm_mdss_data *mdss_data,
690 		const struct dpu_mdss_version *mdss_rev)
691 {
692 	struct dpu_hw_sspp *hw_pipe;
693 
694 	if (!addr)
695 		return ERR_PTR(-EINVAL);
696 
697 	hw_pipe = kzalloc(sizeof(*hw_pipe), GFP_KERNEL);
698 	if (!hw_pipe)
699 		return ERR_PTR(-ENOMEM);
700 
701 	hw_pipe->hw.blk_addr = addr + cfg->base;
702 	hw_pipe->hw.log_mask = DPU_DBG_MASK_SSPP;
703 
704 	/* Assign ops */
705 	hw_pipe->ubwc = mdss_data;
706 	hw_pipe->idx = cfg->id;
707 	hw_pipe->cap = cfg;
708 	_setup_layer_ops(hw_pipe, hw_pipe->cap->features, mdss_rev);
709 
710 	return hw_pipe;
711 }
712 
713 void dpu_hw_sspp_destroy(struct dpu_hw_sspp *ctx)
714 {
715 	kfree(ctx);
716 }
717 
718