1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
6 #include <linux/dma-mapping.h>
7 #include <linux/iommu.h>
8 #include <linux/interconnect.h>
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <drm/drm_fourcc.h>
13 #include <drm/drm_framebuffer.h>
14 #include <drm/drm_gem_atomic_helper.h>
19 static void tegra_plane_destroy(struct drm_plane
*plane
)
21 struct tegra_plane
*p
= to_tegra_plane(plane
);
23 drm_plane_cleanup(plane
);
27 static void tegra_plane_reset(struct drm_plane
*plane
)
29 struct tegra_plane
*p
= to_tegra_plane(plane
);
30 struct tegra_plane_state
*state
;
34 __drm_atomic_helper_plane_destroy_state(plane
->state
);
39 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
41 plane
->state
= &state
->base
;
42 plane
->state
->plane
= plane
;
43 plane
->state
->zpos
= p
->index
;
44 plane
->state
->normalized_zpos
= p
->index
;
46 for (i
= 0; i
< 3; i
++)
47 state
->iova
[i
] = DMA_MAPPING_ERROR
;
51 static struct drm_plane_state
*
52 tegra_plane_atomic_duplicate_state(struct drm_plane
*plane
)
54 struct tegra_plane_state
*state
= to_tegra_plane_state(plane
->state
);
55 struct tegra_plane_state
*copy
;
58 copy
= kmalloc(sizeof(*copy
), GFP_KERNEL
);
62 __drm_atomic_helper_plane_duplicate_state(plane
, ©
->base
);
63 copy
->tiling
= state
->tiling
;
64 copy
->format
= state
->format
;
65 copy
->swap
= state
->swap
;
66 copy
->reflect_x
= state
->reflect_x
;
67 copy
->reflect_y
= state
->reflect_y
;
68 copy
->opaque
= state
->opaque
;
69 copy
->total_peak_memory_bandwidth
= state
->total_peak_memory_bandwidth
;
70 copy
->peak_memory_bandwidth
= state
->peak_memory_bandwidth
;
71 copy
->avg_memory_bandwidth
= state
->avg_memory_bandwidth
;
73 for (i
= 0; i
< 2; i
++)
74 copy
->blending
[i
] = state
->blending
[i
];
76 for (i
= 0; i
< 3; i
++) {
77 copy
->iova
[i
] = DMA_MAPPING_ERROR
;
84 static void tegra_plane_atomic_destroy_state(struct drm_plane
*plane
,
85 struct drm_plane_state
*state
)
87 __drm_atomic_helper_plane_destroy_state(state
);
91 static bool tegra_plane_supports_sector_layout(struct drm_plane
*plane
)
93 struct drm_crtc
*crtc
;
95 drm_for_each_crtc(crtc
, plane
->dev
) {
96 if (plane
->possible_crtcs
& drm_crtc_mask(crtc
)) {
97 struct tegra_dc
*dc
= to_tegra_dc(crtc
);
99 if (!dc
->soc
->supports_sector_layout
)
107 static bool tegra_plane_format_mod_supported(struct drm_plane
*plane
,
111 const struct drm_format_info
*info
= drm_format_info(format
);
113 if (modifier
== DRM_FORMAT_MOD_LINEAR
)
116 /* check for the sector layout bit */
117 if (fourcc_mod_is_vendor(modifier
, NVIDIA
)) {
118 if (modifier
& DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT
) {
119 if (!tegra_plane_supports_sector_layout(plane
))
124 if (info
->num_planes
== 1)
130 const struct drm_plane_funcs tegra_plane_funcs
= {
131 .update_plane
= drm_atomic_helper_update_plane
,
132 .disable_plane
= drm_atomic_helper_disable_plane
,
133 .destroy
= tegra_plane_destroy
,
134 .reset
= tegra_plane_reset
,
135 .atomic_duplicate_state
= tegra_plane_atomic_duplicate_state
,
136 .atomic_destroy_state
= tegra_plane_atomic_destroy_state
,
137 .format_mod_supported
= tegra_plane_format_mod_supported
,
140 static int tegra_dc_pin(struct tegra_dc
*dc
, struct tegra_plane_state
*state
)
145 for (i
= 0; i
< state
->base
.fb
->format
->num_planes
; i
++) {
146 struct tegra_bo
*bo
= tegra_fb_get_plane(state
->base
.fb
, i
);
147 struct host1x_bo_mapping
*map
;
149 map
= host1x_bo_pin(dc
->dev
, &bo
->base
, DMA_TO_DEVICE
, &dc
->client
.cache
);
155 if (!dc
->client
.group
) {
157 * The display controller needs contiguous memory, so
158 * fail if the buffer is discontiguous and we fail to
159 * map its SG table to a single contiguous chunk of
160 * I/O virtual memory.
162 if (map
->chunks
> 1) {
167 state
->iova
[i
] = map
->phys
;
169 state
->iova
[i
] = bo
->iova
;
178 dev_err(dc
->dev
, "failed to map plane %u: %d\n", i
, err
);
181 host1x_bo_unpin(state
->map
[i
]);
182 state
->iova
[i
] = DMA_MAPPING_ERROR
;
183 state
->map
[i
] = NULL
;
189 static void tegra_dc_unpin(struct tegra_dc
*dc
, struct tegra_plane_state
*state
)
193 for (i
= 0; i
< state
->base
.fb
->format
->num_planes
; i
++) {
194 host1x_bo_unpin(state
->map
[i
]);
195 state
->iova
[i
] = DMA_MAPPING_ERROR
;
196 state
->map
[i
] = NULL
;
200 int tegra_plane_prepare_fb(struct drm_plane
*plane
,
201 struct drm_plane_state
*state
)
203 struct tegra_dc
*dc
= to_tegra_dc(state
->crtc
);
209 err
= drm_gem_plane_helper_prepare_fb(plane
, state
);
213 return tegra_dc_pin(dc
, to_tegra_plane_state(state
));
216 void tegra_plane_cleanup_fb(struct drm_plane
*plane
,
217 struct drm_plane_state
*state
)
219 struct tegra_dc
*dc
= to_tegra_dc(state
->crtc
);
222 tegra_dc_unpin(dc
, to_tegra_plane_state(state
));
225 static int tegra_plane_calculate_memory_bandwidth(struct drm_plane_state
*state
)
227 struct tegra_plane_state
*tegra_state
= to_tegra_plane_state(state
);
228 unsigned int i
, bpp
, dst_w
, dst_h
, src_w
, src_h
, mul
;
229 const struct tegra_dc_soc_info
*soc
;
230 const struct drm_format_info
*fmt
;
231 struct drm_crtc_state
*crtc_state
;
232 u64 avg_bandwidth
, peak_bandwidth
;
237 crtc_state
= drm_atomic_get_new_crtc_state(state
->state
, state
->crtc
);
241 src_w
= drm_rect_width(&state
->src
) >> 16;
242 src_h
= drm_rect_height(&state
->src
) >> 16;
243 dst_w
= drm_rect_width(&state
->dst
);
244 dst_h
= drm_rect_height(&state
->dst
);
246 fmt
= state
->fb
->format
;
247 soc
= to_tegra_dc(state
->crtc
)->soc
;
250 * Note that real memory bandwidth vary depending on format and
251 * memory layout, we are not taking that into account because small
252 * estimation error isn't important since bandwidth is rounded up
255 for (i
= 0, bpp
= 0; i
< fmt
->num_planes
; i
++) {
256 unsigned int bpp_plane
= fmt
->cpp
[i
] * 8;
259 * Sub-sampling is relevant for chroma planes only and vertical
260 * readouts are not cached, hence only horizontal sub-sampling
264 bpp_plane
/= fmt
->hsub
;
269 /* average bandwidth in kbytes/sec */
270 avg_bandwidth
= min(src_w
, dst_w
) * min(src_h
, dst_h
);
271 avg_bandwidth
*= drm_mode_vrefresh(&crtc_state
->adjusted_mode
);
272 avg_bandwidth
= DIV_ROUND_UP(avg_bandwidth
* bpp
, 8) + 999;
273 do_div(avg_bandwidth
, 1000);
275 /* mode.clock in kHz, peak bandwidth in kbytes/sec */
276 peak_bandwidth
= DIV_ROUND_UP(crtc_state
->adjusted_mode
.clock
* bpp
, 8);
279 * Tegra30/114 Memory Controller can't interleave DC memory requests
280 * for the tiled windows because DC uses 16-bytes atom, while DDR3
281 * uses 32-bytes atom. Hence there is x2 memory overfetch for tiled
282 * framebuffer and DDR3 on these SoCs.
284 if (soc
->plane_tiled_memory_bandwidth_x2
&&
285 tegra_state
->tiling
.mode
== TEGRA_BO_TILING_MODE_TILED
)
290 /* ICC bandwidth in kbytes/sec */
291 tegra_state
->peak_memory_bandwidth
= kBps_to_icc(peak_bandwidth
) * mul
;
292 tegra_state
->avg_memory_bandwidth
= kBps_to_icc(avg_bandwidth
) * mul
;
297 int tegra_plane_state_add(struct tegra_plane
*plane
,
298 struct drm_plane_state
*state
)
300 struct drm_crtc_state
*crtc_state
;
301 struct tegra_dc_state
*tegra
;
304 /* Propagate errors from allocation or locking failures. */
305 crtc_state
= drm_atomic_get_crtc_state(state
->state
, state
->crtc
);
306 if (IS_ERR(crtc_state
))
307 return PTR_ERR(crtc_state
);
309 /* Check plane state for visibility and calculate clipping bounds */
310 err
= drm_atomic_helper_check_plane_state(state
, crtc_state
,
311 0, INT_MAX
, true, true);
315 err
= tegra_plane_calculate_memory_bandwidth(state
);
319 tegra
= to_dc_state(crtc_state
);
321 tegra
->planes
|= WIN_A_ACT_REQ
<< plane
->index
;
326 int tegra_plane_format(u32 fourcc
, u32
*format
, u32
*swap
)
328 /* assume no swapping of fetched data */
330 *swap
= BYTE_SWAP_NOSWAP
;
333 case DRM_FORMAT_ARGB4444
:
334 *format
= WIN_COLOR_DEPTH_B4G4R4A4
;
337 case DRM_FORMAT_ARGB1555
:
338 *format
= WIN_COLOR_DEPTH_B5G5R5A1
;
341 case DRM_FORMAT_RGB565
:
342 *format
= WIN_COLOR_DEPTH_B5G6R5
;
345 case DRM_FORMAT_RGBA5551
:
346 *format
= WIN_COLOR_DEPTH_A1B5G5R5
;
349 case DRM_FORMAT_ARGB8888
:
350 *format
= WIN_COLOR_DEPTH_B8G8R8A8
;
353 case DRM_FORMAT_ABGR8888
:
354 *format
= WIN_COLOR_DEPTH_R8G8B8A8
;
357 case DRM_FORMAT_ABGR4444
:
358 *format
= WIN_COLOR_DEPTH_R4G4B4A4
;
361 case DRM_FORMAT_ABGR1555
:
362 *format
= WIN_COLOR_DEPTH_R5G5B5A
;
365 case DRM_FORMAT_BGRA5551
:
366 *format
= WIN_COLOR_DEPTH_AR5G5B5
;
369 case DRM_FORMAT_XRGB1555
:
370 *format
= WIN_COLOR_DEPTH_B5G5R5X1
;
373 case DRM_FORMAT_RGBX5551
:
374 *format
= WIN_COLOR_DEPTH_X1B5G5R5
;
377 case DRM_FORMAT_XBGR1555
:
378 *format
= WIN_COLOR_DEPTH_R5G5B5X1
;
381 case DRM_FORMAT_BGRX5551
:
382 *format
= WIN_COLOR_DEPTH_X1R5G5B5
;
385 case DRM_FORMAT_BGR565
:
386 *format
= WIN_COLOR_DEPTH_R5G6B5
;
389 case DRM_FORMAT_BGRA8888
:
390 *format
= WIN_COLOR_DEPTH_A8R8G8B8
;
393 case DRM_FORMAT_RGBA8888
:
394 *format
= WIN_COLOR_DEPTH_A8B8G8R8
;
397 case DRM_FORMAT_XRGB8888
:
398 *format
= WIN_COLOR_DEPTH_B8G8R8X8
;
401 case DRM_FORMAT_XBGR8888
:
402 *format
= WIN_COLOR_DEPTH_R8G8B8X8
;
405 case DRM_FORMAT_UYVY
:
406 *format
= WIN_COLOR_DEPTH_YCbCr422
;
409 case DRM_FORMAT_YUYV
:
413 *format
= WIN_COLOR_DEPTH_YCbCr422
;
414 *swap
= BYTE_SWAP_SWAP2
;
417 case DRM_FORMAT_YVYU
:
421 *format
= WIN_COLOR_DEPTH_YCbCr422
;
422 *swap
= BYTE_SWAP_SWAP4
;
425 case DRM_FORMAT_VYUY
:
429 *format
= WIN_COLOR_DEPTH_YCbCr422
;
430 *swap
= BYTE_SWAP_SWAP4HW
;
433 case DRM_FORMAT_YUV420
:
434 *format
= WIN_COLOR_DEPTH_YCbCr420P
;
437 case DRM_FORMAT_YUV422
:
438 *format
= WIN_COLOR_DEPTH_YCbCr422P
;
441 case DRM_FORMAT_YUV444
:
442 *format
= WIN_COLOR_DEPTH_YCbCr444P
;
445 case DRM_FORMAT_NV12
:
446 *format
= WIN_COLOR_DEPTH_YCbCr420SP
;
449 case DRM_FORMAT_NV21
:
450 *format
= WIN_COLOR_DEPTH_YCrCb420SP
;
453 case DRM_FORMAT_NV16
:
454 *format
= WIN_COLOR_DEPTH_YCbCr422SP
;
457 case DRM_FORMAT_NV61
:
458 *format
= WIN_COLOR_DEPTH_YCrCb422SP
;
461 case DRM_FORMAT_NV24
:
462 *format
= WIN_COLOR_DEPTH_YCbCr444SP
;
465 case DRM_FORMAT_NV42
:
466 *format
= WIN_COLOR_DEPTH_YCrCb444SP
;
476 bool tegra_plane_format_is_indexed(unsigned int format
)
479 case WIN_COLOR_DEPTH_P1
:
480 case WIN_COLOR_DEPTH_P2
:
481 case WIN_COLOR_DEPTH_P4
:
482 case WIN_COLOR_DEPTH_P8
:
489 bool tegra_plane_format_is_yuv(unsigned int format
, unsigned int *planes
, unsigned int *bpc
)
492 case WIN_COLOR_DEPTH_YCbCr422
:
493 case WIN_COLOR_DEPTH_YUV422
:
502 case WIN_COLOR_DEPTH_YCbCr420P
:
503 case WIN_COLOR_DEPTH_YUV420P
:
504 case WIN_COLOR_DEPTH_YCbCr422P
:
505 case WIN_COLOR_DEPTH_YUV422P
:
506 case WIN_COLOR_DEPTH_YCbCr422R
:
507 case WIN_COLOR_DEPTH_YUV422R
:
508 case WIN_COLOR_DEPTH_YCbCr422RA
:
509 case WIN_COLOR_DEPTH_YUV422RA
:
510 case WIN_COLOR_DEPTH_YCbCr444P
:
519 case WIN_COLOR_DEPTH_YCrCb420SP
:
520 case WIN_COLOR_DEPTH_YCbCr420SP
:
521 case WIN_COLOR_DEPTH_YCrCb422SP
:
522 case WIN_COLOR_DEPTH_YCbCr422SP
:
523 case WIN_COLOR_DEPTH_YCrCb444SP
:
524 case WIN_COLOR_DEPTH_YCbCr444SP
:
540 static bool __drm_format_has_alpha(u32 format
)
543 case DRM_FORMAT_ARGB1555
:
544 case DRM_FORMAT_RGBA5551
:
545 case DRM_FORMAT_ABGR8888
:
546 case DRM_FORMAT_ARGB8888
:
553 static int tegra_plane_format_get_alpha(unsigned int opaque
,
556 if (tegra_plane_format_is_yuv(opaque
, NULL
, NULL
)) {
562 case WIN_COLOR_DEPTH_B5G5R5X1
:
563 *alpha
= WIN_COLOR_DEPTH_B5G5R5A1
;
566 case WIN_COLOR_DEPTH_X1B5G5R5
:
567 *alpha
= WIN_COLOR_DEPTH_A1B5G5R5
;
570 case WIN_COLOR_DEPTH_R8G8B8X8
:
571 *alpha
= WIN_COLOR_DEPTH_R8G8B8A8
;
574 case WIN_COLOR_DEPTH_B8G8R8X8
:
575 *alpha
= WIN_COLOR_DEPTH_B8G8R8A8
;
578 case WIN_COLOR_DEPTH_B5G6R5
:
587 * This is applicable to Tegra20 and Tegra30 only where the opaque formats can
588 * be emulated using the alpha formats and alpha blending disabled.
590 static int tegra_plane_setup_opacity(struct tegra_plane
*tegra
,
591 struct tegra_plane_state
*state
)
596 switch (state
->format
) {
597 case WIN_COLOR_DEPTH_B5G5R5A1
:
598 case WIN_COLOR_DEPTH_A1B5G5R5
:
599 case WIN_COLOR_DEPTH_R8G8B8A8
:
600 case WIN_COLOR_DEPTH_B8G8R8A8
:
601 state
->opaque
= false;
605 err
= tegra_plane_format_get_alpha(state
->format
, &format
);
609 state
->format
= format
;
610 state
->opaque
= true;
617 static int tegra_plane_check_transparency(struct tegra_plane
*tegra
,
618 struct tegra_plane_state
*state
)
620 struct drm_plane_state
*old
, *plane_state
;
621 struct drm_plane
*plane
;
623 old
= drm_atomic_get_old_plane_state(state
->base
.state
, &tegra
->base
);
625 /* check if zpos / transparency changed */
626 if (old
->normalized_zpos
== state
->base
.normalized_zpos
&&
627 to_tegra_plane_state(old
)->opaque
== state
->opaque
)
630 /* include all sibling planes into this commit */
631 drm_for_each_plane(plane
, tegra
->base
.dev
) {
632 struct tegra_plane
*p
= to_tegra_plane(plane
);
634 /* skip this plane and planes on different CRTCs */
635 if (p
== tegra
|| p
->dc
!= tegra
->dc
)
638 plane_state
= drm_atomic_get_plane_state(state
->base
.state
,
640 if (IS_ERR(plane_state
))
641 return PTR_ERR(plane_state
);
647 static unsigned int tegra_plane_get_overlap_index(struct tegra_plane
*plane
,
648 struct tegra_plane
*other
)
650 unsigned int index
= 0, i
;
652 WARN_ON(plane
== other
);
654 for (i
= 0; i
< 3; i
++) {
655 if (i
== plane
->index
)
658 if (i
== other
->index
)
667 static void tegra_plane_update_transparency(struct tegra_plane
*tegra
,
668 struct tegra_plane_state
*state
)
670 struct drm_plane_state
*new;
671 struct drm_plane
*plane
;
674 for_each_new_plane_in_state(state
->base
.state
, plane
, new, i
) {
675 struct tegra_plane
*p
= to_tegra_plane(plane
);
678 /* skip this plane and planes on different CRTCs */
679 if (p
== tegra
|| p
->dc
!= tegra
->dc
)
682 index
= tegra_plane_get_overlap_index(tegra
, p
);
684 if (new->fb
&& __drm_format_has_alpha(new->fb
->format
->format
))
685 state
->blending
[index
].alpha
= true;
687 state
->blending
[index
].alpha
= false;
689 if (new->normalized_zpos
> state
->base
.normalized_zpos
)
690 state
->blending
[index
].top
= true;
692 state
->blending
[index
].top
= false;
695 * Missing framebuffer means that plane is disabled, in this
696 * case mark B / C window as top to be able to differentiate
697 * windows indices order in regards to zPos for the middle
698 * window X / Y registers programming.
701 state
->blending
[index
].top
= (index
== 1);
705 static int tegra_plane_setup_transparency(struct tegra_plane
*tegra
,
706 struct tegra_plane_state
*state
)
708 struct tegra_plane_state
*tegra_state
;
709 struct drm_plane_state
*new;
710 struct drm_plane
*plane
;
714 * If planes zpos / transparency changed, sibling planes blending
715 * state may require adjustment and in this case they will be included
716 * into this atom commit, otherwise blending state is unchanged.
718 err
= tegra_plane_check_transparency(tegra
, state
);
723 * All planes are now in the atomic state, walk them up and update
724 * transparency state for each plane.
726 drm_for_each_plane(plane
, tegra
->base
.dev
) {
727 struct tegra_plane
*p
= to_tegra_plane(plane
);
729 /* skip planes on different CRTCs */
730 if (p
->dc
!= tegra
->dc
)
733 new = drm_atomic_get_new_plane_state(state
->base
.state
, plane
);
734 tegra_state
= to_tegra_plane_state(new);
737 * There is no need to update blending state for the disabled
741 tegra_plane_update_transparency(p
, tegra_state
);
747 int tegra_plane_setup_legacy_state(struct tegra_plane
*tegra
,
748 struct tegra_plane_state
*state
)
752 err
= tegra_plane_setup_opacity(tegra
, state
);
756 err
= tegra_plane_setup_transparency(tegra
, state
);
763 static const char * const tegra_plane_icc_names
[TEGRA_DC_LEGACY_PLANES_NUM
] = {
764 "wina", "winb", "winc", NULL
, NULL
, NULL
, "cursor",
767 int tegra_plane_interconnect_init(struct tegra_plane
*plane
)
769 const char *icc_name
= tegra_plane_icc_names
[plane
->index
];
770 struct device
*dev
= plane
->dc
->dev
;
771 struct tegra_dc
*dc
= plane
->dc
;
774 if (WARN_ON(plane
->index
>= TEGRA_DC_LEGACY_PLANES_NUM
) ||
775 WARN_ON(!tegra_plane_icc_names
[plane
->index
]))
778 plane
->icc_mem
= devm_of_icc_get(dev
, icc_name
);
779 err
= PTR_ERR_OR_ZERO(plane
->icc_mem
);
781 return dev_err_probe(dev
, err
, "failed to get %s interconnect\n",
784 /* plane B on T20/30 has a dedicated memory client for a 6-tap vertical filter */
785 if (plane
->index
== 1 && dc
->soc
->has_win_b_vfilter_mem_client
) {
786 plane
->icc_mem_vfilter
= devm_of_icc_get(dev
, "winb-vfilter");
787 err
= PTR_ERR_OR_ZERO(plane
->icc_mem_vfilter
);
789 return dev_err_probe(dev
, err
, "failed to get %s interconnect\n",