1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 */
5
6 #include <linux/delay.h>
7
8 #include <drm/drm_managed.h>
9
10 #include "dpu_hwio.h"
11 #include "dpu_hw_ctl.h"
12 #include "dpu_kms.h"
13 #include "dpu_trace.h"
14
15 #define CTL_LAYER(lm) \
16 (((lm) == LM_5) ? (0x024) : (((lm) - LM_0) * 0x004))
17 #define CTL_LAYER_EXT(lm) \
18 (0x40 + (((lm) - LM_0) * 0x004))
19 #define CTL_LAYER_EXT2(lm) \
20 (0x70 + (((lm) - LM_0) * 0x004))
21 #define CTL_LAYER_EXT3(lm) \
22 (0xA0 + (((lm) - LM_0) * 0x004))
23 #define CTL_LAYER_EXT4(lm) \
24 (0xB8 + (((lm) - LM_0) * 0x004))
25 #define CTL_TOP 0x014
26 #define CTL_FLUSH 0x018
27 #define CTL_START 0x01C
28 #define CTL_PREPARE 0x0d0
29 #define CTL_SW_RESET 0x030
30 #define CTL_LAYER_EXTN_OFFSET 0x40
31 #define CTL_MERGE_3D_ACTIVE 0x0E4
32 #define CTL_DSC_ACTIVE 0x0E8
33 #define CTL_WB_ACTIVE 0x0EC
34 #define CTL_CWB_ACTIVE 0x0F0
35 #define CTL_INTF_ACTIVE 0x0F4
36 #define CTL_CDM_ACTIVE 0x0F8
37 #define CTL_FETCH_PIPE_ACTIVE 0x0FC
38 #define CTL_MERGE_3D_FLUSH 0x100
39 #define CTL_DSC_FLUSH 0x104
40 #define CTL_WB_FLUSH 0x108
41 #define CTL_CWB_FLUSH 0x10C
42 #define CTL_INTF_FLUSH 0x110
43 #define CTL_CDM_FLUSH 0x114
44 #define CTL_PERIPH_FLUSH 0x128
45 #define CTL_PIPE_ACTIVE 0x12c
46 #define CTL_LAYER_ACTIVE 0x130
47 #define CTL_INTF_MASTER 0x134
48 #define CTL_DSPP_n_FLUSH(n) ((0x13C) + ((n) * 4))
49
50 #define CTL_MIXER_BORDER_OUT BIT(24)
51 #define CTL_FLUSH_MASK_CTL BIT(17)
52
53 #define DPU_REG_RESET_TIMEOUT_US 2000
54 #define MERGE_3D_IDX 23
55 #define DSC_IDX 22
56 #define CDM_IDX 26
57 #define PERIPH_IDX 30
58 #define INTF_IDX 31
59 #define WB_IDX 16
60 #define CWB_IDX 28
61 #define DSPP_IDX 29 /* From DPU hw rev 7.x.x */
62 #define CTL_INVALID_BIT 0xffff
63 #define CTL_DEFAULT_GROUP_ID 0xf
64
65 static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
66 CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
67 1, 2, 3, 4, 5};
68
69 static const u32 lm_tbl[LM_MAX] = {CTL_INVALID_BIT, 0, 1, 2, 3, 4, 5, 6, 7};
70
_mixer_stages(const struct dpu_lm_cfg * mixer,int count,enum dpu_lm lm)71 static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,
72 enum dpu_lm lm)
73 {
74 int i;
75 int stages = -EINVAL;
76
77 for (i = 0; i < count; i++) {
78 if (lm == mixer[i].id) {
79 stages = mixer[i].sblk->maxblendstages;
80 break;
81 }
82 }
83
84 return stages;
85 }
86
dpu_hw_ctl_get_flush_register(struct dpu_hw_ctl * ctx)87 static inline u32 dpu_hw_ctl_get_flush_register(struct dpu_hw_ctl *ctx)
88 {
89 struct dpu_hw_blk_reg_map *c = &ctx->hw;
90
91 return DPU_REG_READ(c, CTL_FLUSH);
92 }
93
dpu_hw_ctl_trigger_start(struct dpu_hw_ctl * ctx)94 static inline void dpu_hw_ctl_trigger_start(struct dpu_hw_ctl *ctx)
95 {
96 trace_dpu_hw_ctl_trigger_start(ctx->pending_flush_mask,
97 dpu_hw_ctl_get_flush_register(ctx));
98 DPU_REG_WRITE(&ctx->hw, CTL_START, 0x1);
99 }
100
dpu_hw_ctl_is_started(struct dpu_hw_ctl * ctx)101 static inline bool dpu_hw_ctl_is_started(struct dpu_hw_ctl *ctx)
102 {
103 return !!(DPU_REG_READ(&ctx->hw, CTL_START) & BIT(0));
104 }
105
dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl * ctx)106 static inline void dpu_hw_ctl_trigger_pending(struct dpu_hw_ctl *ctx)
107 {
108 trace_dpu_hw_ctl_trigger_prepare(ctx->pending_flush_mask,
109 dpu_hw_ctl_get_flush_register(ctx));
110 DPU_REG_WRITE(&ctx->hw, CTL_PREPARE, 0x1);
111 }
112
dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl * ctx)113 static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
114 {
115 trace_dpu_hw_ctl_clear_pending_flush(ctx->pending_flush_mask,
116 dpu_hw_ctl_get_flush_register(ctx));
117 ctx->pending_flush_mask = 0x0;
118 ctx->pending_intf_flush_mask = 0;
119 ctx->pending_wb_flush_mask = 0;
120 ctx->pending_cwb_flush_mask = 0;
121 ctx->pending_periph_flush_mask = 0;
122 ctx->pending_merge_3d_flush_mask = 0;
123 ctx->pending_dsc_flush_mask = 0;
124 ctx->pending_cdm_flush_mask = 0;
125
126 memset(ctx->pending_dspp_flush_mask, 0,
127 sizeof(ctx->pending_dspp_flush_mask));
128 }
129
dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl * ctx,u32 flushbits)130 static inline void dpu_hw_ctl_update_pending_flush(struct dpu_hw_ctl *ctx,
131 u32 flushbits)
132 {
133 trace_dpu_hw_ctl_update_pending_flush(flushbits,
134 ctx->pending_flush_mask);
135 ctx->pending_flush_mask |= flushbits;
136 }
137
dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl * ctx)138 static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
139 {
140 return ctx->pending_flush_mask;
141 }
142
dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl * ctx)143 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
144 {
145 int dspp;
146
147 if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
148 DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
149 ctx->pending_merge_3d_flush_mask);
150 if (ctx->pending_flush_mask & BIT(INTF_IDX))
151 DPU_REG_WRITE(&ctx->hw, CTL_INTF_FLUSH,
152 ctx->pending_intf_flush_mask);
153 if (ctx->pending_flush_mask & BIT(WB_IDX))
154 DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,
155 ctx->pending_wb_flush_mask);
156 if (ctx->pending_flush_mask & BIT(CWB_IDX))
157 DPU_REG_WRITE(&ctx->hw, CTL_CWB_FLUSH,
158 ctx->pending_cwb_flush_mask);
159
160 if (ctx->pending_flush_mask & BIT(DSPP_IDX))
161 for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) {
162 if (ctx->pending_dspp_flush_mask[dspp - DSPP_0])
163 DPU_REG_WRITE(&ctx->hw,
164 CTL_DSPP_n_FLUSH(dspp - DSPP_0),
165 ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
166 }
167
168 if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
169 DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,
170 ctx->pending_periph_flush_mask);
171
172 if (ctx->pending_flush_mask & BIT(DSC_IDX))
173 DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
174 ctx->pending_dsc_flush_mask);
175
176 if (ctx->pending_flush_mask & BIT(CDM_IDX))
177 DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
178 ctx->pending_cdm_flush_mask);
179
180 DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
181 }
182
dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl * ctx)183 static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx)
184 {
185 trace_dpu_hw_ctl_trigger_pending_flush(ctx->pending_flush_mask,
186 dpu_hw_ctl_get_flush_register(ctx));
187 DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
188 }
189
dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl * ctx,enum dpu_sspp sspp)190 static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,
191 enum dpu_sspp sspp)
192 {
193 switch (sspp) {
194 case SSPP_VIG0:
195 ctx->pending_flush_mask |= BIT(0);
196 break;
197 case SSPP_VIG1:
198 ctx->pending_flush_mask |= BIT(1);
199 break;
200 case SSPP_VIG2:
201 ctx->pending_flush_mask |= BIT(2);
202 break;
203 case SSPP_VIG3:
204 ctx->pending_flush_mask |= BIT(18);
205 break;
206 case SSPP_RGB0:
207 ctx->pending_flush_mask |= BIT(3);
208 break;
209 case SSPP_RGB1:
210 ctx->pending_flush_mask |= BIT(4);
211 break;
212 case SSPP_RGB2:
213 ctx->pending_flush_mask |= BIT(5);
214 break;
215 case SSPP_RGB3:
216 ctx->pending_flush_mask |= BIT(19);
217 break;
218 case SSPP_DMA0:
219 ctx->pending_flush_mask |= BIT(11);
220 break;
221 case SSPP_DMA1:
222 ctx->pending_flush_mask |= BIT(12);
223 break;
224 case SSPP_DMA2:
225 ctx->pending_flush_mask |= BIT(24);
226 break;
227 case SSPP_DMA3:
228 ctx->pending_flush_mask |= BIT(25);
229 break;
230 case SSPP_DMA4:
231 ctx->pending_flush_mask |= BIT(13);
232 break;
233 case SSPP_DMA5:
234 ctx->pending_flush_mask |= BIT(14);
235 break;
236 case SSPP_CURSOR0:
237 ctx->pending_flush_mask |= BIT(22);
238 break;
239 case SSPP_CURSOR1:
240 ctx->pending_flush_mask |= BIT(23);
241 break;
242 default:
243 break;
244 }
245 }
246
dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl * ctx,enum dpu_lm lm)247 static void dpu_hw_ctl_update_pending_flush_mixer(struct dpu_hw_ctl *ctx,
248 enum dpu_lm lm)
249 {
250 switch (lm) {
251 case LM_0:
252 ctx->pending_flush_mask |= BIT(6);
253 break;
254 case LM_1:
255 ctx->pending_flush_mask |= BIT(7);
256 break;
257 case LM_2:
258 ctx->pending_flush_mask |= BIT(8);
259 break;
260 case LM_3:
261 ctx->pending_flush_mask |= BIT(9);
262 break;
263 case LM_4:
264 ctx->pending_flush_mask |= BIT(10);
265 break;
266 case LM_5:
267 ctx->pending_flush_mask |= BIT(20);
268 break;
269 case LM_6:
270 ctx->pending_flush_mask |= BIT(21);
271 break;
272 case LM_7:
273 ctx->pending_flush_mask |= BIT(27);
274 break;
275 default:
276 break;
277 }
278
279 ctx->pending_flush_mask |= CTL_FLUSH_MASK_CTL;
280 }
281
dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl * ctx,enum dpu_intf intf)282 static void dpu_hw_ctl_update_pending_flush_intf(struct dpu_hw_ctl *ctx,
283 enum dpu_intf intf)
284 {
285 switch (intf) {
286 case INTF_0:
287 ctx->pending_flush_mask |= BIT(31);
288 break;
289 case INTF_1:
290 ctx->pending_flush_mask |= BIT(30);
291 break;
292 case INTF_2:
293 ctx->pending_flush_mask |= BIT(29);
294 break;
295 case INTF_3:
296 ctx->pending_flush_mask |= BIT(28);
297 break;
298 default:
299 break;
300 }
301 }
302
dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl * ctx,enum dpu_wb wb)303 static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
304 enum dpu_wb wb)
305 {
306 switch (wb) {
307 case WB_0:
308 case WB_1:
309 case WB_2:
310 ctx->pending_flush_mask |= BIT(WB_IDX);
311 break;
312 default:
313 break;
314 }
315 }
316
dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl * ctx,enum dpu_cdm cdm_num)317 static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num)
318 {
319 /* update pending flush only if CDM_0 is flushed */
320 if (cdm_num == CDM_0)
321 ctx->pending_flush_mask |= BIT(CDM_IDX);
322 }
323
dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl * ctx,enum dpu_wb wb)324 static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
325 enum dpu_wb wb)
326 {
327 ctx->pending_wb_flush_mask |= BIT(wb - WB_0);
328 ctx->pending_flush_mask |= BIT(WB_IDX);
329 }
330
dpu_hw_ctl_update_pending_flush_cwb_v1(struct dpu_hw_ctl * ctx,enum dpu_cwb cwb)331 static void dpu_hw_ctl_update_pending_flush_cwb_v1(struct dpu_hw_ctl *ctx,
332 enum dpu_cwb cwb)
333 {
334 ctx->pending_cwb_flush_mask |= BIT(cwb - CWB_0);
335 ctx->pending_flush_mask |= BIT(CWB_IDX);
336 }
337
dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl * ctx,enum dpu_intf intf)338 static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
339 enum dpu_intf intf)
340 {
341 ctx->pending_intf_flush_mask |= BIT(intf - INTF_0);
342 ctx->pending_flush_mask |= BIT(INTF_IDX);
343 }
344
dpu_hw_ctl_update_pending_flush_periph_v1(struct dpu_hw_ctl * ctx,enum dpu_intf intf)345 static void dpu_hw_ctl_update_pending_flush_periph_v1(struct dpu_hw_ctl *ctx,
346 enum dpu_intf intf)
347 {
348 ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
349 ctx->pending_flush_mask |= BIT(PERIPH_IDX);
350 }
351
dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl * ctx,enum dpu_merge_3d merge_3d)352 static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
353 enum dpu_merge_3d merge_3d)
354 {
355 ctx->pending_merge_3d_flush_mask |= BIT(merge_3d - MERGE_3D_0);
356 ctx->pending_flush_mask |= BIT(MERGE_3D_IDX);
357 }
358
dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl * ctx,enum dpu_dsc dsc_num)359 static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
360 enum dpu_dsc dsc_num)
361 {
362 ctx->pending_dsc_flush_mask |= BIT(dsc_num - DSC_0);
363 ctx->pending_flush_mask |= BIT(DSC_IDX);
364 }
365
dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl * ctx,enum dpu_cdm cdm_num)366 static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx, enum dpu_cdm cdm_num)
367 {
368 ctx->pending_cdm_flush_mask |= BIT(cdm_num - CDM_0);
369 ctx->pending_flush_mask |= BIT(CDM_IDX);
370 }
371
dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl * ctx,enum dpu_dspp dspp,u32 dspp_sub_blk)372 static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
373 enum dpu_dspp dspp, u32 dspp_sub_blk)
374 {
375 switch (dspp) {
376 case DSPP_0:
377 ctx->pending_flush_mask |= BIT(13);
378 break;
379 case DSPP_1:
380 ctx->pending_flush_mask |= BIT(14);
381 break;
382 case DSPP_2:
383 ctx->pending_flush_mask |= BIT(15);
384 break;
385 case DSPP_3:
386 ctx->pending_flush_mask |= BIT(21);
387 break;
388 default:
389 break;
390 }
391 }
392
dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(struct dpu_hw_ctl * ctx,enum dpu_dspp dspp,u32 dspp_sub_blk)393 static void dpu_hw_ctl_update_pending_flush_dspp_sub_blocks(
394 struct dpu_hw_ctl *ctx, enum dpu_dspp dspp, u32 dspp_sub_blk)
395 {
396 if (dspp >= DSPP_MAX)
397 return;
398
399 switch (dspp_sub_blk) {
400 case DPU_DSPP_PCC:
401 ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(4);
402 break;
403 case DPU_DSPP_GC:
404 ctx->pending_dspp_flush_mask[dspp - DSPP_0] |= BIT(5);
405 break;
406 default:
407 return;
408 }
409
410 ctx->pending_flush_mask |= BIT(DSPP_IDX);
411 }
412
dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl * ctx,u32 timeout_us)413 static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
414 {
415 struct dpu_hw_blk_reg_map *c = &ctx->hw;
416 ktime_t timeout;
417 u32 status;
418
419 timeout = ktime_add_us(ktime_get(), timeout_us);
420
421 /*
422 * it takes around 30us to have mdp finish resetting its ctl path
423 * poll every 50us so that reset should be completed at 1st poll
424 */
425 do {
426 status = DPU_REG_READ(c, CTL_SW_RESET);
427 status &= 0x1;
428 if (status)
429 usleep_range(20, 50);
430 } while (status && ktime_compare_safe(ktime_get(), timeout) < 0);
431
432 return status;
433 }
434
dpu_hw_ctl_reset_control(struct dpu_hw_ctl * ctx)435 static int dpu_hw_ctl_reset_control(struct dpu_hw_ctl *ctx)
436 {
437 struct dpu_hw_blk_reg_map *c = &ctx->hw;
438
439 pr_debug("issuing hw ctl reset for ctl:%d\n", ctx->idx);
440 DPU_REG_WRITE(c, CTL_SW_RESET, 0x1);
441 if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US))
442 return -EINVAL;
443
444 return 0;
445 }
446
dpu_hw_ctl_wait_reset_status(struct dpu_hw_ctl * ctx)447 static int dpu_hw_ctl_wait_reset_status(struct dpu_hw_ctl *ctx)
448 {
449 struct dpu_hw_blk_reg_map *c = &ctx->hw;
450 u32 status;
451
452 status = DPU_REG_READ(c, CTL_SW_RESET);
453 status &= 0x01;
454 if (!status)
455 return 0;
456
457 pr_debug("hw ctl reset is set for ctl:%d\n", ctx->idx);
458 if (dpu_hw_ctl_poll_reset_status(ctx, DPU_REG_RESET_TIMEOUT_US)) {
459 pr_err("hw recovery is not complete for ctl:%d\n", ctx->idx);
460 return -EINVAL;
461 }
462
463 return 0;
464 }
465
dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl * ctx)466 static void dpu_hw_ctl_clear_all_blendstages(struct dpu_hw_ctl *ctx)
467 {
468 struct dpu_hw_blk_reg_map *c = &ctx->hw;
469 int i;
470
471 for (i = 0; i < ctx->mixer_count; i++) {
472 enum dpu_lm mixer_id = ctx->mixer_hw_caps[i].id;
473
474 DPU_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
475 DPU_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
476 DPU_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
477 DPU_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
478 }
479
480 DPU_REG_WRITE(c, CTL_FETCH_PIPE_ACTIVE, 0);
481 }
482
483 struct ctl_blend_config {
484 int idx, shift, ext_shift;
485 };
486
487 static const struct ctl_blend_config ctl_blend_config[][2] = {
488 [SSPP_NONE] = { { -1 }, { -1 } },
489 [SSPP_MAX] = { { -1 }, { -1 } },
490 [SSPP_VIG0] = { { 0, 0, 0 }, { 3, 0 } },
491 [SSPP_VIG1] = { { 0, 3, 2 }, { 3, 4 } },
492 [SSPP_VIG2] = { { 0, 6, 4 }, { 3, 8 } },
493 [SSPP_VIG3] = { { 0, 26, 6 }, { 3, 12 } },
494 [SSPP_RGB0] = { { 0, 9, 8 }, { -1 } },
495 [SSPP_RGB1] = { { 0, 12, 10 }, { -1 } },
496 [SSPP_RGB2] = { { 0, 15, 12 }, { -1 } },
497 [SSPP_RGB3] = { { 0, 29, 14 }, { -1 } },
498 [SSPP_DMA0] = { { 0, 18, 16 }, { 2, 8 } },
499 [SSPP_DMA1] = { { 0, 21, 18 }, { 2, 12 } },
500 [SSPP_DMA2] = { { 2, 0 }, { 2, 16 } },
501 [SSPP_DMA3] = { { 2, 4 }, { 2, 20 } },
502 [SSPP_DMA4] = { { 4, 0 }, { 4, 8 } },
503 [SSPP_DMA5] = { { 4, 4 }, { 4, 12 } },
504 [SSPP_CURSOR0] = { { 1, 20 }, { -1 } },
505 [SSPP_CURSOR1] = { { 1, 26 }, { -1 } },
506 };
507
dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl * ctx,enum dpu_lm lm,struct dpu_hw_stage_cfg * stage_cfg)508 static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
509 enum dpu_lm lm, struct dpu_hw_stage_cfg *stage_cfg)
510 {
511 struct dpu_hw_blk_reg_map *c = &ctx->hw;
512 u32 mix, ext, mix_ext;
513 u32 mixercfg[5] = { 0 };
514 int i, j;
515 int stages;
516 int pipes_per_stage;
517
518 stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
519 if (stages < 0)
520 return;
521
522 if (test_bit(DPU_MIXER_SOURCESPLIT,
523 &ctx->mixer_hw_caps->features))
524 pipes_per_stage = PIPES_PER_STAGE;
525 else
526 pipes_per_stage = 1;
527
528 mixercfg[0] = CTL_MIXER_BORDER_OUT; /* always set BORDER_OUT */
529
530 if (!stage_cfg)
531 goto exit;
532
533 for (i = 0; i <= stages; i++) {
534 /* overflow to ext register if 'i + 1 > 7' */
535 mix = (i + 1) & 0x7;
536 ext = i >= 7;
537 mix_ext = (i + 1) & 0xf;
538
539 for (j = 0 ; j < pipes_per_stage; j++) {
540 enum dpu_sspp_multirect_index rect_index =
541 stage_cfg->multirect_index[i][j];
542 enum dpu_sspp pipe = stage_cfg->stage[i][j];
543 const struct ctl_blend_config *cfg =
544 &ctl_blend_config[pipe][rect_index == DPU_SSPP_RECT_1];
545
546 /*
547 * CTL_LAYER has 3-bit field (and extra bits in EXT register),
548 * all EXT registers has 4-bit fields.
549 */
550 if (cfg->idx == -1) {
551 continue;
552 } else if (cfg->idx == 0) {
553 mixercfg[0] |= mix << cfg->shift;
554 mixercfg[1] |= ext << cfg->ext_shift;
555 } else {
556 mixercfg[cfg->idx] |= mix_ext << cfg->shift;
557 }
558 }
559 }
560
561 exit:
562 DPU_REG_WRITE(c, CTL_LAYER(lm), mixercfg[0]);
563 DPU_REG_WRITE(c, CTL_LAYER_EXT(lm), mixercfg[1]);
564 DPU_REG_WRITE(c, CTL_LAYER_EXT2(lm), mixercfg[2]);
565 DPU_REG_WRITE(c, CTL_LAYER_EXT3(lm), mixercfg[3]);
566 if (ctx->mdss_ver->core_major_ver >= 9)
567 DPU_REG_WRITE(c, CTL_LAYER_EXT4(lm), mixercfg[4]);
568 }
569
570
dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl * ctx,struct dpu_hw_intf_cfg * cfg)571 static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
572 struct dpu_hw_intf_cfg *cfg)
573 {
574 struct dpu_hw_blk_reg_map *c = &ctx->hw;
575 u32 intf_active = 0;
576 u32 dsc_active = 0;
577 u32 wb_active = 0;
578 u32 cwb_active = 0;
579 u32 mode_sel = 0;
580 u32 merge_3d_active = 0;
581
582 /* CTL_TOP[31:28] carries group_id to collate CTL paths
583 * per VM. Explicitly disable it until VM support is
584 * added in SW. Power on reset value is not disable.
585 */
586 if (ctx->mdss_ver->core_major_ver >= 7)
587 mode_sel = CTL_DEFAULT_GROUP_ID << 28;
588
589 if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
590 mode_sel |= BIT(17);
591
592 intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
593 wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
594 cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE);
595 dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);
596 merge_3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE);
597
598 if (cfg->intf)
599 intf_active |= BIT(cfg->intf - INTF_0);
600
601 if (cfg->wb)
602 wb_active |= BIT(cfg->wb - WB_0);
603
604 if (cfg->cwb)
605 cwb_active |= cfg->cwb;
606
607 if (cfg->dsc)
608 dsc_active |= cfg->dsc;
609
610 if (cfg->merge_3d)
611 merge_3d_active |= BIT(cfg->merge_3d - MERGE_3D_0);
612
613 DPU_REG_WRITE(c, CTL_TOP, mode_sel);
614 DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
615 DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
616 DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active);
617 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
618 DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, merge_3d_active);
619
620 if (cfg->intf_master)
621 DPU_REG_WRITE(c, CTL_INTF_MASTER, BIT(cfg->intf_master - INTF_0));
622
623 if (cfg->cdm)
624 DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
625 }
626
dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl * ctx,struct dpu_hw_intf_cfg * cfg)627 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
628 struct dpu_hw_intf_cfg *cfg)
629 {
630 struct dpu_hw_blk_reg_map *c = &ctx->hw;
631 u32 intf_cfg = 0;
632
633 intf_cfg |= (cfg->intf & 0xF) << 4;
634
635 if (cfg->mode_3d) {
636 intf_cfg |= BIT(19);
637 intf_cfg |= (cfg->mode_3d - 0x1) << 20;
638 }
639
640 if (cfg->wb)
641 intf_cfg |= (cfg->wb & 0x3) + 2;
642
643 switch (cfg->intf_mode_sel) {
644 case DPU_CTL_MODE_SEL_VID:
645 intf_cfg &= ~BIT(17);
646 intf_cfg &= ~(0x3 << 15);
647 break;
648 case DPU_CTL_MODE_SEL_CMD:
649 intf_cfg |= BIT(17);
650 intf_cfg |= ((cfg->stream_sel & 0x3) << 15);
651 break;
652 default:
653 pr_err("unknown interface type %d\n", cfg->intf_mode_sel);
654 return;
655 }
656
657 DPU_REG_WRITE(c, CTL_TOP, intf_cfg);
658 }
659
dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl * ctx,struct dpu_hw_intf_cfg * cfg)660 static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
661 struct dpu_hw_intf_cfg *cfg)
662 {
663 struct dpu_hw_blk_reg_map *c = &ctx->hw;
664 u32 intf_active = 0;
665 u32 intf_master = 0;
666 u32 wb_active = 0;
667 u32 cwb_active = 0;
668 u32 merge3d_active = 0;
669 u32 dsc_active;
670 u32 cdm_active;
671
672 /*
673 * This API resets each portion of the CTL path namely,
674 * clearing the sspps staged on the lm, merge_3d block,
675 * interfaces , writeback etc to ensure clean teardown of the pipeline.
676 * This will be used for writeback to begin with to have a
677 * proper teardown of the writeback session but upon further
678 * validation, this can be extended to all interfaces.
679 */
680 if (cfg->merge_3d) {
681 merge3d_active = DPU_REG_READ(c, CTL_MERGE_3D_ACTIVE);
682 merge3d_active &= ~BIT(cfg->merge_3d - MERGE_3D_0);
683 DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
684 merge3d_active);
685 }
686
687 if (ctx->ops.clear_all_blendstages)
688 ctx->ops.clear_all_blendstages(ctx);
689
690 if (ctx->ops.set_active_lms)
691 ctx->ops.set_active_lms(ctx, NULL);
692
693 if (ctx->ops.set_active_fetch_pipes)
694 ctx->ops.set_active_fetch_pipes(ctx, NULL);
695
696 if (ctx->ops.set_active_pipes)
697 ctx->ops.set_active_pipes(ctx, NULL);
698
699 if (cfg->intf) {
700 intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
701 intf_active &= ~BIT(cfg->intf - INTF_0);
702 DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
703
704 intf_master = DPU_REG_READ(c, CTL_INTF_MASTER);
705
706 /* Unset this intf as master, if it is the current master */
707 if (intf_master == BIT(cfg->intf - INTF_0)) {
708 DPU_DEBUG_DRIVER("Unsetting INTF_%d master\n", cfg->intf - INTF_0);
709 DPU_REG_WRITE(c, CTL_INTF_MASTER, 0);
710 }
711 }
712
713 if (cfg->cwb) {
714 cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE);
715 cwb_active &= ~cfg->cwb;
716 DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active);
717 }
718
719 if (cfg->wb) {
720 wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
721 wb_active &= ~BIT(cfg->wb - WB_0);
722 DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
723 }
724
725 if (cfg->dsc) {
726 dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);
727 dsc_active &= ~cfg->dsc;
728 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
729 }
730
731 if (cfg->cdm) {
732 cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
733 cdm_active &= ~cfg->cdm;
734 DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
735 }
736 }
737
dpu_hw_ctl_set_active_fetch_pipes(struct dpu_hw_ctl * ctx,unsigned long * fetch_active)738 static void dpu_hw_ctl_set_active_fetch_pipes(struct dpu_hw_ctl *ctx,
739 unsigned long *fetch_active)
740 {
741 int i;
742 u32 val = 0;
743
744 if (fetch_active) {
745 for (i = 0; i < SSPP_MAX; i++) {
746 if (test_bit(i, fetch_active) &&
747 fetch_tbl[i] != CTL_INVALID_BIT)
748 val |= BIT(fetch_tbl[i]);
749 }
750 }
751
752 DPU_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val);
753 }
754
dpu_hw_ctl_set_active_pipes(struct dpu_hw_ctl * ctx,unsigned long * active_pipes)755 static void dpu_hw_ctl_set_active_pipes(struct dpu_hw_ctl *ctx,
756 unsigned long *active_pipes)
757 {
758 int i;
759 u32 val = 0;
760
761 if (active_pipes) {
762 for (i = 0; i < SSPP_MAX; i++) {
763 if (test_bit(i, active_pipes) &&
764 fetch_tbl[i] != CTL_INVALID_BIT)
765 val |= BIT(fetch_tbl[i]);
766 }
767 }
768
769 DPU_REG_WRITE(&ctx->hw, CTL_PIPE_ACTIVE, val);
770 }
771
dpu_hw_ctl_set_active_lms(struct dpu_hw_ctl * ctx,unsigned long * active_lms)772 static void dpu_hw_ctl_set_active_lms(struct dpu_hw_ctl *ctx,
773 unsigned long *active_lms)
774 {
775 int i;
776 u32 val = 0;
777
778 if (active_lms) {
779 for (i = LM_0; i < LM_MAX; i++) {
780 if (test_bit(i, active_lms) &&
781 lm_tbl[i] != CTL_INVALID_BIT)
782 val |= BIT(lm_tbl[i]);
783 }
784 }
785
786 DPU_REG_WRITE(&ctx->hw, CTL_LAYER_ACTIVE, val);
787 }
788
789 /**
790 * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object.
791 * Should be called before accessing any ctl_path register.
792 * @dev: Corresponding device for devres management
793 * @cfg: ctl_path catalog entry for which driver object is required
794 * @addr: mapped register io address of MDP
795 * @mdss_ver: dpu core's major and minor versions
796 * @mixer_count: Number of mixers in @mixer
797 * @mixer: Pointer to an array of Layer Mixers defined in the catalog
798 */
dpu_hw_ctl_init(struct drm_device * dev,const struct dpu_ctl_cfg * cfg,void __iomem * addr,const struct dpu_mdss_version * mdss_ver,u32 mixer_count,const struct dpu_lm_cfg * mixer)799 struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
800 const struct dpu_ctl_cfg *cfg,
801 void __iomem *addr,
802 const struct dpu_mdss_version *mdss_ver,
803 u32 mixer_count,
804 const struct dpu_lm_cfg *mixer)
805 {
806 struct dpu_hw_ctl *c;
807
808 c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
809 if (!c)
810 return ERR_PTR(-ENOMEM);
811
812 c->hw.blk_addr = addr + cfg->base;
813 c->hw.log_mask = DPU_DBG_MASK_CTL;
814
815 c->caps = cfg;
816 c->mdss_ver = mdss_ver;
817
818 if (mdss_ver->core_major_ver >= 5) {
819 c->ops.trigger_flush = dpu_hw_ctl_trigger_flush_v1;
820 c->ops.setup_intf_cfg = dpu_hw_ctl_intf_cfg_v1;
821 c->ops.reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
822 c->ops.update_pending_flush_intf =
823 dpu_hw_ctl_update_pending_flush_intf_v1;
824
825 c->ops.update_pending_flush_periph =
826 dpu_hw_ctl_update_pending_flush_periph_v1;
827
828 c->ops.update_pending_flush_merge_3d =
829 dpu_hw_ctl_update_pending_flush_merge_3d_v1;
830 c->ops.update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
831 c->ops.update_pending_flush_cwb = dpu_hw_ctl_update_pending_flush_cwb_v1;
832 c->ops.update_pending_flush_dsc =
833 dpu_hw_ctl_update_pending_flush_dsc_v1;
834 c->ops.update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
835 } else {
836 c->ops.trigger_flush = dpu_hw_ctl_trigger_flush;
837 c->ops.setup_intf_cfg = dpu_hw_ctl_intf_cfg;
838 c->ops.update_pending_flush_intf =
839 dpu_hw_ctl_update_pending_flush_intf;
840 c->ops.update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
841 c->ops.update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
842 }
843 c->ops.clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
844 c->ops.update_pending_flush = dpu_hw_ctl_update_pending_flush;
845 c->ops.get_pending_flush = dpu_hw_ctl_get_pending_flush;
846 c->ops.get_flush_register = dpu_hw_ctl_get_flush_register;
847 c->ops.trigger_start = dpu_hw_ctl_trigger_start;
848 c->ops.is_started = dpu_hw_ctl_is_started;
849 c->ops.trigger_pending = dpu_hw_ctl_trigger_pending;
850 c->ops.reset = dpu_hw_ctl_reset_control;
851 c->ops.wait_reset_status = dpu_hw_ctl_wait_reset_status;
852 if (mdss_ver->core_major_ver < 12) {
853 c->ops.clear_all_blendstages = dpu_hw_ctl_clear_all_blendstages;
854 c->ops.setup_blendstage = dpu_hw_ctl_setup_blendstage;
855 } else {
856 c->ops.set_active_pipes = dpu_hw_ctl_set_active_pipes;
857 c->ops.set_active_lms = dpu_hw_ctl_set_active_lms;
858 }
859 c->ops.update_pending_flush_sspp = dpu_hw_ctl_update_pending_flush_sspp;
860 c->ops.update_pending_flush_mixer = dpu_hw_ctl_update_pending_flush_mixer;
861 if (mdss_ver->core_major_ver >= 7)
862 c->ops.update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp_sub_blocks;
863 else
864 c->ops.update_pending_flush_dspp = dpu_hw_ctl_update_pending_flush_dspp;
865
866 if (mdss_ver->core_major_ver >= 7)
867 c->ops.set_active_fetch_pipes = dpu_hw_ctl_set_active_fetch_pipes;
868
869 c->idx = cfg->id;
870 c->mixer_count = mixer_count;
871 c->mixer_hw_caps = mixer;
872
873 return c;
874 }
875