1
2
3
4
5
6
7
8
9#include <linux/iommu.h>
10
11#include <drm/drmP.h>
12#include <drm/drm_atomic.h>
13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_fb_cma_helper.h>
15#include <drm/drm_gem_cma_helper.h>
16#include <drm/drm_gem_framebuffer_helper.h>
17#include <drm/drm_plane_helper.h>
18#include <drm/drm_print.h>
19
20#include "malidp_hw.h"
21#include "malidp_drv.h"
22
23
24#define MALIDP_LAYER_FORMAT 0x000
25#define LAYER_FORMAT_MASK 0x3f
26#define MALIDP_LAYER_CONTROL 0x004
27#define LAYER_ENABLE (1 << 0)
28#define LAYER_FLOWCFG_MASK 7
29#define LAYER_FLOWCFG(x) (((x) & LAYER_FLOWCFG_MASK) << 1)
30#define LAYER_FLOWCFG_SCALE_SE 3
31#define LAYER_ROT_OFFSET 8
32#define LAYER_H_FLIP (1 << 10)
33#define LAYER_V_FLIP (1 << 11)
34#define LAYER_ROT_MASK (0xf << 8)
35#define LAYER_COMP_MASK (0x3 << 12)
36#define LAYER_COMP_PIXEL (0x3 << 12)
37#define LAYER_COMP_PLANE (0x2 << 12)
38#define LAYER_PMUL_ENABLE (0x1 << 14)
39#define LAYER_ALPHA_OFFSET (16)
40#define LAYER_ALPHA_MASK (0xff)
41#define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
42#define MALIDP_LAYER_COMPOSE 0x008
43#define MALIDP_LAYER_SIZE 0x00c
44#define LAYER_H_VAL(x) (((x) & 0x1fff) << 0)
45#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
46#define MALIDP_LAYER_COMP_SIZE 0x010
47#define MALIDP_LAYER_OFFSET 0x014
48#define MALIDP550_LS_ENABLE 0x01c
49#define MALIDP550_LS_R1_IN_SIZE 0x020
50
51#define MODIFIERS_COUNT_MAX 15
52
53
54
55
56
57
58
59#define MALIDP_ALPHA_LUT 0xffaa5500
60
61
62#define MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES (SZ_4K | SZ_64K)
63#define MALIDP_MMU_PREFETCH_FULL_PGSIZES (SZ_1M | SZ_2M)
64
65
66#define MALIDP_MMU_PREFETCH_READAHEAD 8
67
68static void malidp_de_plane_destroy(struct drm_plane *plane)
69{
70 struct malidp_plane *mp = to_malidp_plane(plane);
71
72 drm_plane_cleanup(plane);
73 kfree(mp);
74}
75
76
77
78
79
80
81static void malidp_plane_reset(struct drm_plane *plane)
82{
83 struct malidp_plane_state *state = to_malidp_plane_state(plane->state);
84
85 if (state)
86 __drm_atomic_helper_plane_destroy_state(&state->base);
87 kfree(state);
88 plane->state = NULL;
89 state = kzalloc(sizeof(*state), GFP_KERNEL);
90 if (state)
91 __drm_atomic_helper_plane_reset(plane, &state->base);
92}
93
94static struct
95drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
96{
97 struct malidp_plane_state *state, *m_state;
98
99 if (!plane->state)
100 return NULL;
101
102 state = kmalloc(sizeof(*state), GFP_KERNEL);
103 if (!state)
104 return NULL;
105
106 m_state = to_malidp_plane_state(plane->state);
107 __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
108 state->rotmem_size = m_state->rotmem_size;
109 state->format = m_state->format;
110 state->n_planes = m_state->n_planes;
111
112 state->mmu_prefetch_mode = m_state->mmu_prefetch_mode;
113 state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize;
114
115 return &state->base;
116}
117
118static void malidp_destroy_plane_state(struct drm_plane *plane,
119 struct drm_plane_state *state)
120{
121 struct malidp_plane_state *m_state = to_malidp_plane_state(state);
122
123 __drm_atomic_helper_plane_destroy_state(state);
124 kfree(m_state);
125}
126
127static const char * const prefetch_mode_names[] = {
128 [MALIDP_PREFETCH_MODE_NONE] = "MMU_PREFETCH_NONE",
129 [MALIDP_PREFETCH_MODE_PARTIAL] = "MMU_PREFETCH_PARTIAL",
130 [MALIDP_PREFETCH_MODE_FULL] = "MMU_PREFETCH_FULL",
131};
132
133static void malidp_plane_atomic_print_state(struct drm_printer *p,
134 const struct drm_plane_state *state)
135{
136 struct malidp_plane_state *ms = to_malidp_plane_state(state);
137
138 drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
139 drm_printf(p, "\tformat_id=%u\n", ms->format);
140 drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
141 drm_printf(p, "\tmmu_prefetch_mode=%s\n",
142 prefetch_mode_names[ms->mmu_prefetch_mode]);
143 drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
144}
145
146bool malidp_format_mod_supported(struct drm_device *drm,
147 u32 format, u64 modifier)
148{
149 const struct drm_format_info *info;
150 const u64 *modifiers;
151 struct malidp_drm *malidp = drm->dev_private;
152 const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
153
154 if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
155 return false;
156
157
158 if (modifier == DRM_FORMAT_MOD_LINEAR) {
159
160
161
162
163 return !malidp_hw_format_is_afbc_only(format);
164 }
165
166 if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
167 DRM_ERROR("Unknown modifier (not Arm)\n");
168 return false;
169 }
170
171 if (modifier &
172 ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
173 DRM_DEBUG_KMS("Unsupported modifiers\n");
174 return false;
175 }
176
177 modifiers = malidp_format_modifiers;
178
179
180 if (WARN_ON_ONCE((modifier & AFBC_SPLIT) && !(modifier & AFBC_SPARSE)))
181 return false;
182
183
184 if (WARN_ON_ONCE((modifier & AFBC_CBR) && (modifier & AFBC_YTR)))
185 return false;
186
187 while (*modifiers != DRM_FORMAT_MOD_INVALID) {
188 if (*modifiers == modifier)
189 break;
190
191 modifiers++;
192 }
193
194
195 if (*modifiers == DRM_FORMAT_MOD_INVALID) {
196 DRM_DEBUG_KMS("Unsupported modifier\n");
197 return false;
198 }
199
200 info = drm_format_info(format);
201
202 if (info->num_planes != 1) {
203 DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
204 return false;
205 }
206
207 if (malidp_hw_format_is_linear_only(format) == true) {
208 DRM_DEBUG_KMS("Given format (0x%x) is supported is linear mode only\n",
209 format);
210 return false;
211 }
212
213
214
215
216
217 if (!(info->is_yuv) != !!(modifier & AFBC_FORMAT_MOD_YTR)) {
218 DRM_DEBUG_KMS("AFBC_FORMAT_MOD_YTR is %s for %s formats\n",
219 info->is_yuv ? "disallowed" : "mandatory",
220 info->is_yuv ? "YUV" : "RGB");
221 return false;
222 }
223
224 if (modifier & AFBC_SPLIT) {
225 if (!info->is_yuv) {
226 if (info->cpp[0] <= 2) {
227 DRM_DEBUG_KMS("RGB formats <= 16bpp are not supported with SPLIT\n");
228 return false;
229 }
230 }
231
232 if ((info->hsub != 1) || (info->vsub != 1)) {
233 if (!(format == DRM_FORMAT_YUV420_10BIT &&
234 (map->features & MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT))) {
235 DRM_DEBUG_KMS("Formats which are sub-sampled should never be split\n");
236 return false;
237 }
238 }
239 }
240
241 if (modifier & AFBC_CBR) {
242 if ((info->hsub == 1) || (info->vsub == 1)) {
243 DRM_DEBUG_KMS("Formats which are not sub-sampled should not have CBR set\n");
244 return false;
245 }
246 }
247
248 return true;
249}
250
251static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
252 u32 format, u64 modifier)
253{
254 return malidp_format_mod_supported(plane->dev, format, modifier);
255}
256
257static const struct drm_plane_funcs malidp_de_plane_funcs = {
258 .update_plane = drm_atomic_helper_update_plane,
259 .disable_plane = drm_atomic_helper_disable_plane,
260 .destroy = malidp_de_plane_destroy,
261 .reset = malidp_plane_reset,
262 .atomic_duplicate_state = malidp_duplicate_plane_state,
263 .atomic_destroy_state = malidp_destroy_plane_state,
264 .atomic_print_state = malidp_plane_atomic_print_state,
265 .format_mod_supported = malidp_format_mod_supported_per_plane,
266};
267
268static int malidp_se_check_scaling(struct malidp_plane *mp,
269 struct drm_plane_state *state)
270{
271 struct drm_crtc_state *crtc_state =
272 drm_atomic_get_existing_crtc_state(state->state, state->crtc);
273 struct malidp_crtc_state *mc;
274 u32 src_w, src_h;
275 int ret;
276
277 if (!crtc_state)
278 return -EINVAL;
279
280 mc = to_malidp_crtc_state(crtc_state);
281
282 ret = drm_atomic_helper_check_plane_state(state, crtc_state,
283 0, INT_MAX, true, true);
284 if (ret)
285 return ret;
286
287 if (state->rotation & MALIDP_ROTATED_MASK) {
288 src_w = state->src_h >> 16;
289 src_h = state->src_w >> 16;
290 } else {
291 src_w = state->src_w >> 16;
292 src_h = state->src_h >> 16;
293 }
294
295 if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) {
296
297 mc->scaled_planes_mask &= ~(mp->layer->id);
298 return 0;
299 }
300
301 if (mp->layer->id & (DE_SMART | DE_GRAPHICS2))
302 return -EINVAL;
303
304 mc->scaled_planes_mask |= mp->layer->id;
305
306 return 0;
307}
308
309static u32 malidp_get_pgsize_bitmap(struct malidp_plane *mp)
310{
311 u32 pgsize_bitmap = 0;
312
313 if (iommu_present(&platform_bus_type)) {
314 struct iommu_domain *mmu_dom =
315 iommu_get_domain_for_dev(mp->base.dev->dev);
316
317 if (mmu_dom)
318 pgsize_bitmap = mmu_dom->pgsize_bitmap;
319 }
320
321 return pgsize_bitmap;
322}
323
324
325
326
327
328
329
330static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
331 u32 pgsize)
332{
333 int i;
334
335 for (i = 0; i < ms->n_planes; i++) {
336 struct drm_gem_object *obj;
337 struct drm_gem_cma_object *cma_obj;
338 struct sg_table *sgt;
339 struct scatterlist *sgl;
340
341 obj = drm_gem_fb_get_obj(ms->base.fb, i);
342 cma_obj = to_drm_gem_cma_obj(obj);
343
344 if (cma_obj->sgt)
345 sgt = cma_obj->sgt;
346 else
347 sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
348
349 if (!sgt)
350 return false;
351
352 sgl = sgt->sgl;
353
354 while (sgl) {
355 if (sgl->length < pgsize) {
356 if (!cma_obj->sgt)
357 kfree(sgt);
358 return false;
359 }
360
361 sgl = sg_next(sgl);
362 }
363 if (!cma_obj->sgt)
364 kfree(sgt);
365 }
366
367 return true;
368}
369
370
371
372
373
374static bool malidp_partial_prefetch_supported(u32 format, u64 modifier,
375 unsigned int rotation)
376{
377 bool afbc, sparse;
378
379
380 if (rotation & (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
381 DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X))
382 return false;
383
384 afbc = modifier & DRM_FORMAT_MOD_ARM_AFBC(0);
385 sparse = modifier & AFBC_FORMAT_MOD_SPARSE;
386
387 switch (format) {
388 case DRM_FORMAT_ARGB2101010:
389 case DRM_FORMAT_RGBA1010102:
390 case DRM_FORMAT_BGRA1010102:
391 case DRM_FORMAT_ARGB8888:
392 case DRM_FORMAT_RGBA8888:
393 case DRM_FORMAT_BGRA8888:
394 case DRM_FORMAT_XRGB8888:
395 case DRM_FORMAT_XBGR8888:
396 case DRM_FORMAT_RGBX8888:
397 case DRM_FORMAT_BGRX8888:
398 case DRM_FORMAT_RGB888:
399 case DRM_FORMAT_RGBA5551:
400 case DRM_FORMAT_RGB565:
401
402 return true;
403
404 case DRM_FORMAT_ABGR2101010:
405 case DRM_FORMAT_ABGR8888:
406 case DRM_FORMAT_ABGR1555:
407 case DRM_FORMAT_BGR565:
408
409 return (!afbc) || (afbc && sparse);
410
411 case DRM_FORMAT_BGR888:
412
413 return !afbc;
414
415 case DRM_FORMAT_YUYV:
416 case DRM_FORMAT_UYVY:
417 case DRM_FORMAT_NV12:
418 case DRM_FORMAT_YUV420:
419
420 return false;
421
422 default:
423 return false;
424 }
425}
426
427
428
429
430
431
432
433static enum mmu_prefetch_mode malidp_mmu_prefetch_select_mode
434 (struct malidp_plane_state *ms, u32 *pgsize_bitmap)
435{
436 u32 pgsizes;
437
438
439 pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_FULL_PGSIZES;
440
441 while (pgsizes) {
442 u32 largest_pgsize = 1 << __fls(pgsizes);
443
444 if (malidp_check_pages_threshold(ms, largest_pgsize)) {
445 *pgsize_bitmap = largest_pgsize;
446 return MALIDP_PREFETCH_MODE_FULL;
447 }
448
449 pgsizes -= largest_pgsize;
450 }
451
452
453 pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES;
454
455 if (malidp_partial_prefetch_supported(ms->base.fb->format->format,
456 ms->base.fb->modifier,
457 ms->base.rotation)) {
458
459 *pgsize_bitmap = 1 << __ffs(pgsizes);
460 return MALIDP_PREFETCH_MODE_PARTIAL;
461 }
462 *pgsize_bitmap = 0;
463 return MALIDP_PREFETCH_MODE_NONE;
464}
465
466static u32 malidp_calc_mmu_control_value(enum mmu_prefetch_mode mode,
467 u8 readahead, u8 n_planes, u32 pgsize)
468{
469 u32 mmu_ctrl = 0;
470
471 if (mode != MALIDP_PREFETCH_MODE_NONE) {
472 mmu_ctrl |= MALIDP_MMU_CTRL_EN;
473
474 if (mode == MALIDP_PREFETCH_MODE_PARTIAL) {
475 mmu_ctrl |= MALIDP_MMU_CTRL_MODE;
476 mmu_ctrl |= MALIDP_MMU_CTRL_PP_NUM_REQ(readahead);
477 }
478
479 if (pgsize == SZ_64K || pgsize == SZ_2M) {
480 int i;
481
482 for (i = 0; i < n_planes; i++)
483 mmu_ctrl |= MALIDP_MMU_CTRL_PX_PS(i);
484 }
485 }
486
487 return mmu_ctrl;
488}
489
490static void malidp_de_prefetch_settings(struct malidp_plane *mp,
491 struct malidp_plane_state *ms)
492{
493 if (!mp->layer->mmu_ctrl_offset)
494 return;
495
496
497 ms->mmu_prefetch_pgsize = malidp_get_pgsize_bitmap(mp);
498 ms->mmu_prefetch_mode =
499 malidp_mmu_prefetch_select_mode(ms, &ms->mmu_prefetch_pgsize);
500}
501
502static int malidp_de_plane_check(struct drm_plane *plane,
503 struct drm_plane_state *state)
504{
505 struct malidp_plane *mp = to_malidp_plane(plane);
506 struct malidp_plane_state *ms = to_malidp_plane_state(state);
507 bool rotated = state->rotation & MALIDP_ROTATED_MASK;
508 struct drm_framebuffer *fb;
509 u16 pixel_alpha = state->pixel_blend_mode;
510 int i, ret;
511 unsigned int block_w, block_h;
512
513 if (!state->crtc || !state->fb)
514 return 0;
515
516 fb = state->fb;
517
518 ms->format = malidp_hw_get_format_id(&mp->hwdev->hw->map,
519 mp->layer->id, fb->format->format,
520 !!fb->modifier);
521 if (ms->format == MALIDP_INVALID_FORMAT_ID)
522 return -EINVAL;
523
524 ms->n_planes = fb->format->num_planes;
525 for (i = 0; i < ms->n_planes; i++) {
526 u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
527
528 if (((fb->pitches[i] * drm_format_info_block_height(fb->format, i))
529 & (alignment - 1)) && !(fb->modifier)) {
530 DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
531 fb->pitches[i], i);
532 return -EINVAL;
533 }
534 }
535
536 block_w = drm_format_info_block_width(fb->format, 0);
537 block_h = drm_format_info_block_height(fb->format, 0);
538 if (fb->width % block_w || fb->height % block_h) {
539 DRM_DEBUG_KMS("Buffer width/height needs to be a multiple of tile sizes");
540 return -EINVAL;
541 }
542 if ((state->src_x >> 16) % block_w || (state->src_y >> 16) % block_h) {
543 DRM_DEBUG_KMS("Plane src_x/src_y needs to be a multiple of tile sizes");
544 return -EINVAL;
545 }
546
547 if ((state->crtc_w > mp->hwdev->max_line_size) ||
548 (state->crtc_h > mp->hwdev->max_line_size) ||
549 (state->crtc_w < mp->hwdev->min_line_size) ||
550 (state->crtc_h < mp->hwdev->min_line_size))
551 return -EINVAL;
552
553
554
555
556
557
558 if (ms->n_planes == 3 &&
559 !(mp->hwdev->hw->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
560 (state->fb->pitches[1] != state->fb->pitches[2]))
561 return -EINVAL;
562
563 ret = malidp_se_check_scaling(mp, state);
564 if (ret)
565 return ret;
566
567
568 if (state->rotation != DRM_MODE_ROTATE_0) {
569 if (mp->layer->rot == ROTATE_NONE)
570 return -EINVAL;
571 if ((mp->layer->rot == ROTATE_COMPRESSED) && !(fb->modifier))
572 return -EINVAL;
573
574
575
576
577 if ((fb->format->format == DRM_FORMAT_RGB888 ||
578 fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier))
579 return -EINVAL;
580 }
581
582
583 if (mp->layer->id == DE_SMART && fb->modifier) {
584 DRM_ERROR("AFBC framebuffer not supported in SMART layer");
585 return -EINVAL;
586 }
587
588 ms->rotmem_size = 0;
589 if (state->rotation & MALIDP_ROTATED_MASK) {
590 int val;
591
592 val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_w,
593 state->crtc_h,
594 fb->format->format,
595 !!(fb->modifier));
596 if (val < 0)
597 return val;
598
599 ms->rotmem_size = val;
600 }
601
602
603 if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
604 (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) &&
605 fb->format->has_alpha)
606 return -EINVAL;
607
608 malidp_de_prefetch_settings(mp, ms);
609
610 return 0;
611}
612
613static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
614 int num_planes, unsigned int pitches[3])
615{
616 int i;
617 int num_strides = num_planes;
618
619 if (!mp->layer->stride_offset)
620 return;
621
622 if (num_planes == 3)
623 num_strides = (mp->hwdev->hw->features &
624 MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
625
626
627
628
629
630
631 for (i = 0; i < num_strides; ++i) {
632 unsigned int block_h = drm_format_info_block_height(mp->base.state->fb->format, i);
633
634 malidp_hw_write(mp->hwdev, pitches[i] * block_h,
635 mp->layer->base +
636 mp->layer->stride_offset + i * 4);
637 }
638}
639
640static const s16
641malidp_yuv2rgb_coeffs[][DRM_COLOR_RANGE_MAX][MALIDP_COLORADJ_NUM_COEFFS] = {
642 [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
643 1192, 0, 1634,
644 1192, -401, -832,
645 1192, 2066, 0,
646 64, 512, 512
647 },
648 [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
649 1024, 0, 1436,
650 1024, -352, -731,
651 1024, 1815, 0,
652 0, 512, 512
653 },
654 [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
655 1192, 0, 1836,
656 1192, -218, -546,
657 1192, 2163, 0,
658 64, 512, 512
659 },
660 [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
661 1024, 0, 1613,
662 1024, -192, -479,
663 1024, 1900, 0,
664 0, 512, 512
665 },
666 [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
667 1024, 0, 1476,
668 1024, -165, -572,
669 1024, 1884, 0,
670 0, 512, 512
671 },
672 [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = {
673 1024, 0, 1510,
674 1024, -168, -585,
675 1024, 1927, 0,
676 0, 512, 512
677 }
678};
679
680static void malidp_de_set_color_encoding(struct malidp_plane *plane,
681 enum drm_color_encoding enc,
682 enum drm_color_range range)
683{
684 unsigned int i;
685
686 for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
687
688 malidp_hw_write(plane->hwdev, malidp_yuv2rgb_coeffs[enc][range][i],
689 plane->layer->base + plane->layer->yuv2rgb_offset +
690 i * 4);
691 }
692}
693
694static void malidp_de_set_mmu_control(struct malidp_plane *mp,
695 struct malidp_plane_state *ms)
696{
697 u32 mmu_ctrl;
698
699
700 if (!mp->layer->mmu_ctrl_offset)
701 return;
702
703 mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode,
704 MALIDP_MMU_PREFETCH_READAHEAD,
705 ms->n_planes,
706 ms->mmu_prefetch_pgsize);
707
708 malidp_hw_write(mp->hwdev, mmu_ctrl,
709 mp->layer->base + mp->layer->mmu_ctrl_offset);
710}
711
712static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
713 struct malidp_plane *mp,
714 int plane_index)
715{
716 dma_addr_t paddr;
717 u16 ptr;
718 struct drm_plane *plane = &mp->base;
719 bool afbc = fb->modifier ? true : false;
720
721 ptr = mp->layer->ptr + (plane_index << 4);
722
723
724
725
726
727
728
729
730 if (!afbc) {
731 paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
732 plane_index);
733 } else {
734 struct drm_gem_cma_object *obj;
735
736 obj = drm_fb_cma_get_gem_obj(fb, plane_index);
737
738 if (WARN_ON(!obj))
739 return;
740 paddr = obj->paddr;
741 }
742
743 malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
744 malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
745}
746
747static void malidp_de_set_plane_afbc(struct drm_plane *plane)
748{
749 struct malidp_plane *mp;
750 u32 src_w, src_h, val = 0, src_x, src_y;
751 struct drm_framebuffer *fb = plane->state->fb;
752
753 mp = to_malidp_plane(plane);
754
755
756 if (!mp->layer->afbc_decoder_offset)
757 return;
758
759 if (!fb->modifier) {
760 malidp_hw_write(mp->hwdev, 0, mp->layer->afbc_decoder_offset);
761 return;
762 }
763
764
765 src_w = plane->state->src_w >> 16;
766 src_h = plane->state->src_h >> 16;
767 src_x = plane->state->src_x >> 16;
768 src_y = plane->state->src_y >> 16;
769
770 val = ((fb->width - (src_x + src_w)) << MALIDP_AD_CROP_RIGHT_OFFSET) |
771 src_x;
772 malidp_hw_write(mp->hwdev, val,
773 mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_H);
774
775 val = ((fb->height - (src_y + src_h)) << MALIDP_AD_CROP_BOTTOM_OFFSET) |
776 src_y;
777 malidp_hw_write(mp->hwdev, val,
778 mp->layer->afbc_decoder_offset + MALIDP_AD_CROP_V);
779
780 val = MALIDP_AD_EN;
781 if (fb->modifier & AFBC_FORMAT_MOD_SPLIT)
782 val |= MALIDP_AD_BS;
783 if (fb->modifier & AFBC_FORMAT_MOD_YTR)
784 val |= MALIDP_AD_YTR;
785
786 malidp_hw_write(mp->hwdev, val, mp->layer->afbc_decoder_offset);
787}
788
789static void malidp_de_plane_update(struct drm_plane *plane,
790 struct drm_plane_state *old_state)
791{
792 struct malidp_plane *mp;
793 struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
794 struct drm_plane_state *state = plane->state;
795 u16 pixel_alpha = state->pixel_blend_mode;
796 u8 plane_alpha = state->alpha >> 8;
797 u32 src_w, src_h, dest_w, dest_h, val;
798 int i;
799 struct drm_framebuffer *fb = plane->state->fb;
800
801 mp = to_malidp_plane(plane);
802
803
804
805
806
807 if (fb->modifier) {
808 src_w = fb->width;
809 src_h = fb->height;
810 } else {
811
812 src_w = state->src_w >> 16;
813 src_h = state->src_h >> 16;
814 }
815
816 dest_w = state->crtc_w;
817 dest_h = state->crtc_h;
818
819 val = malidp_hw_read(mp->hwdev, mp->layer->base);
820 val = (val & ~LAYER_FORMAT_MASK) | ms->format;
821 malidp_hw_write(mp->hwdev, val, mp->layer->base);
822
823 for (i = 0; i < ms->n_planes; i++)
824 malidp_set_plane_base_addr(fb, mp, i);
825
826 malidp_de_set_mmu_control(mp, ms);
827
828 malidp_de_set_plane_pitches(mp, ms->n_planes,
829 state->fb->pitches);
830
831 if ((plane->state->color_encoding != old_state->color_encoding) ||
832 (plane->state->color_range != old_state->color_range))
833 malidp_de_set_color_encoding(mp, plane->state->color_encoding,
834 plane->state->color_range);
835
836 malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
837 mp->layer->base + MALIDP_LAYER_SIZE);
838
839 malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
840 mp->layer->base + MALIDP_LAYER_COMP_SIZE);
841
842 malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
843 LAYER_V_VAL(state->crtc_y),
844 mp->layer->base + MALIDP_LAYER_OFFSET);
845
846 if (mp->layer->id == DE_SMART) {
847
848
849
850
851 malidp_hw_write(mp->hwdev, 1,
852 mp->layer->base + MALIDP550_LS_ENABLE);
853 malidp_hw_write(mp->hwdev,
854 LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
855 mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
856 }
857
858 malidp_de_set_plane_afbc(plane);
859
860
861 val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
862 val &= ~LAYER_ROT_MASK;
863
864
865 if (state->rotation & DRM_MODE_ROTATE_MASK)
866 val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
867 LAYER_ROT_OFFSET;
868 if (state->rotation & DRM_MODE_REFLECT_X)
869 val |= LAYER_H_FLIP;
870 if (state->rotation & DRM_MODE_REFLECT_Y)
871 val |= LAYER_V_FLIP;
872
873 val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff));
874
875 if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
876 val |= LAYER_COMP_PLANE;
877 } else if (state->fb->format->has_alpha) {
878
879 switch (pixel_alpha) {
880 case DRM_MODE_BLEND_PREMULTI:
881 val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
882 break;
883 case DRM_MODE_BLEND_COVERAGE:
884 val |= LAYER_COMP_PIXEL;
885 break;
886 }
887 }
888 val |= LAYER_ALPHA(plane_alpha);
889
890 val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
891 if (state->crtc) {
892 struct malidp_crtc_state *m =
893 to_malidp_crtc_state(state->crtc->state);
894
895 if (m->scaler_config.scale_enable &&
896 m->scaler_config.plane_src_id == mp->layer->id)
897 val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE);
898 }
899
900
901 val |= LAYER_ENABLE;
902
903 malidp_hw_write(mp->hwdev, val,
904 mp->layer->base + MALIDP_LAYER_CONTROL);
905}
906
907static void malidp_de_plane_disable(struct drm_plane *plane,
908 struct drm_plane_state *state)
909{
910 struct malidp_plane *mp = to_malidp_plane(plane);
911
912 malidp_hw_clearbits(mp->hwdev,
913 LAYER_ENABLE | LAYER_FLOWCFG(LAYER_FLOWCFG_MASK),
914 mp->layer->base + MALIDP_LAYER_CONTROL);
915}
916
917static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = {
918 .atomic_check = malidp_de_plane_check,
919 .atomic_update = malidp_de_plane_update,
920 .atomic_disable = malidp_de_plane_disable,
921};
922
923int malidp_de_planes_init(struct drm_device *drm)
924{
925 struct malidp_drm *malidp = drm->dev_private;
926 const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
927 struct malidp_plane *plane = NULL;
928 enum drm_plane_type plane_type;
929 unsigned long crtcs = 1 << drm->mode_config.num_crtc;
930 unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
931 DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
932 unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
933 BIT(DRM_MODE_BLEND_PREMULTI) |
934 BIT(DRM_MODE_BLEND_COVERAGE);
935 u32 *formats;
936 int ret, i = 0, j = 0, n;
937 u64 supported_modifiers[MODIFIERS_COUNT_MAX];
938 const u64 *modifiers;
939
940 modifiers = malidp_format_modifiers;
941
942 if (!(map->features & MALIDP_DEVICE_AFBC_SUPPORT_SPLIT)) {
943
944
945
946
947 while (*modifiers != DRM_FORMAT_MOD_INVALID) {
948 if (!(*modifiers & AFBC_SPLIT))
949 supported_modifiers[j++] = *modifiers;
950
951 modifiers++;
952 }
953 supported_modifiers[j++] = DRM_FORMAT_MOD_INVALID;
954 modifiers = supported_modifiers;
955 }
956
957 formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
958 if (!formats) {
959 ret = -ENOMEM;
960 goto cleanup;
961 }
962
963 for (i = 0; i < map->n_layers; i++) {
964 u8 id = map->layers[i].id;
965
966 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
967 if (!plane) {
968 ret = -ENOMEM;
969 goto cleanup;
970 }
971
972
973 for (n = 0, j = 0; j < map->n_pixel_formats; j++) {
974 if ((map->pixel_formats[j].layer & id) == id)
975 formats[n++] = map->pixel_formats[j].format;
976 }
977
978 plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
979 DRM_PLANE_TYPE_OVERLAY;
980
981
982
983
984 ret = drm_universal_plane_init(drm, &plane->base, crtcs,
985 &malidp_de_plane_funcs, formats, n,
986 (id == DE_SMART) ? NULL : modifiers, plane_type,
987 NULL);
988
989 if (ret < 0)
990 goto cleanup;
991
992 drm_plane_helper_add(&plane->base,
993 &malidp_de_plane_helper_funcs);
994 plane->hwdev = malidp->dev;
995 plane->layer = &map->layers[i];
996
997 drm_plane_create_alpha_property(&plane->base);
998 drm_plane_create_blend_mode_property(&plane->base, blend_caps);
999
1000 if (id == DE_SMART) {
1001
1002 continue;
1003 }
1004
1005 drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, flags);
1006 malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
1007 plane->layer->base + MALIDP_LAYER_COMPOSE);
1008
1009
1010 if (id & (DE_VIDEO1 | DE_VIDEO2)) {
1011
1012 enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601;
1013 enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE;
1014
1015 ret = drm_plane_create_color_properties(&plane->base,
1016 BIT(DRM_COLOR_YCBCR_BT601) | \
1017 BIT(DRM_COLOR_YCBCR_BT709) | \
1018 BIT(DRM_COLOR_YCBCR_BT2020),
1019 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \
1020 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1021 enc, range);
1022 if (!ret)
1023
1024 malidp_de_set_color_encoding(plane, enc, range);
1025 else
1026 DRM_WARN("Failed to create video layer %d color properties\n", id);
1027 }
1028 }
1029
1030 kfree(formats);
1031
1032 return 0;
1033
1034cleanup:
1035 kfree(formats);
1036
1037 return ret;
1038}
1039