2 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <drm/drm_atomic.h>
10 #include <drm/drm_atomic_helper.h>
11 #include <drm/drm_plane_helper.h>
16 static void tegra_plane_destroy(struct drm_plane
*plane
)
18 struct tegra_plane
*p
= to_tegra_plane(plane
);
20 drm_plane_cleanup(plane
);
24 static void tegra_plane_reset(struct drm_plane
*plane
)
26 struct tegra_plane_state
*state
;
29 __drm_atomic_helper_plane_destroy_state(plane
->state
);
34 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
36 plane
->state
= &state
->base
;
37 plane
->state
->plane
= plane
;
41 static struct drm_plane_state
*
42 tegra_plane_atomic_duplicate_state(struct drm_plane
*plane
)
44 struct tegra_plane_state
*state
= to_tegra_plane_state(plane
->state
);
45 struct tegra_plane_state
*copy
;
48 copy
= kmalloc(sizeof(*copy
), GFP_KERNEL
);
52 __drm_atomic_helper_plane_duplicate_state(plane
, ©
->base
);
53 copy
->tiling
= state
->tiling
;
54 copy
->format
= state
->format
;
55 copy
->swap
= state
->swap
;
56 copy
->opaque
= state
->opaque
;
58 for (i
= 0; i
< 3; i
++)
59 copy
->dependent
[i
] = state
->dependent
[i
];
64 static void tegra_plane_atomic_destroy_state(struct drm_plane
*plane
,
65 struct drm_plane_state
*state
)
67 __drm_atomic_helper_plane_destroy_state(state
);
71 const struct drm_plane_funcs tegra_plane_funcs
= {
72 .update_plane
= drm_atomic_helper_update_plane
,
73 .disable_plane
= drm_atomic_helper_disable_plane
,
74 .destroy
= tegra_plane_destroy
,
75 .reset
= tegra_plane_reset
,
76 .atomic_duplicate_state
= tegra_plane_atomic_duplicate_state
,
77 .atomic_destroy_state
= tegra_plane_atomic_destroy_state
,
80 int tegra_plane_state_add(struct tegra_plane
*plane
,
81 struct drm_plane_state
*state
)
83 struct drm_crtc_state
*crtc_state
;
84 struct tegra_dc_state
*tegra
;
88 /* Propagate errors from allocation or locking failures. */
89 crtc_state
= drm_atomic_get_crtc_state(state
->state
, state
->crtc
);
90 if (IS_ERR(crtc_state
))
91 return PTR_ERR(crtc_state
);
95 clip
.x2
= crtc_state
->mode
.hdisplay
;
96 clip
.y2
= crtc_state
->mode
.vdisplay
;
98 /* Check plane state for visibility and calculate clipping bounds */
99 err
= drm_atomic_helper_check_plane_state(state
, crtc_state
, &clip
,
100 0, INT_MAX
, true, true);
104 tegra
= to_dc_state(crtc_state
);
106 tegra
->planes
|= WIN_A_ACT_REQ
<< plane
->index
;
111 int tegra_plane_format(u32 fourcc
, u32
*format
, u32
*swap
)
113 /* assume no swapping of fetched data */
115 *swap
= BYTE_SWAP_NOSWAP
;
118 case DRM_FORMAT_ARGB4444
:
119 *format
= WIN_COLOR_DEPTH_B4G4R4A4
;
122 case DRM_FORMAT_ARGB1555
:
123 *format
= WIN_COLOR_DEPTH_B5G5R5A1
;
126 case DRM_FORMAT_RGB565
:
127 *format
= WIN_COLOR_DEPTH_B5G6R5
;
130 case DRM_FORMAT_RGBA5551
:
131 *format
= WIN_COLOR_DEPTH_A1B5G5R5
;
134 case DRM_FORMAT_ARGB8888
:
135 *format
= WIN_COLOR_DEPTH_B8G8R8A8
;
138 case DRM_FORMAT_ABGR8888
:
139 *format
= WIN_COLOR_DEPTH_R8G8B8A8
;
142 case DRM_FORMAT_ABGR4444
:
143 *format
= WIN_COLOR_DEPTH_R4G4B4A4
;
146 case DRM_FORMAT_ABGR1555
:
147 *format
= WIN_COLOR_DEPTH_R5G5B5A
;
150 case DRM_FORMAT_BGRA5551
:
151 *format
= WIN_COLOR_DEPTH_AR5G5B5
;
154 case DRM_FORMAT_XRGB1555
:
155 *format
= WIN_COLOR_DEPTH_B5G5R5X1
;
158 case DRM_FORMAT_RGBX5551
:
159 *format
= WIN_COLOR_DEPTH_X1B5G5R5
;
162 case DRM_FORMAT_XBGR1555
:
163 *format
= WIN_COLOR_DEPTH_R5G5B5X1
;
166 case DRM_FORMAT_BGRX5551
:
167 *format
= WIN_COLOR_DEPTH_X1R5G5B5
;
170 case DRM_FORMAT_BGR565
:
171 *format
= WIN_COLOR_DEPTH_R5G6B5
;
174 case DRM_FORMAT_BGRA8888
:
175 *format
= WIN_COLOR_DEPTH_A8R8G8B8
;
178 case DRM_FORMAT_RGBA8888
:
179 *format
= WIN_COLOR_DEPTH_A8B8G8R8
;
182 case DRM_FORMAT_XRGB8888
:
183 *format
= WIN_COLOR_DEPTH_B8G8R8X8
;
186 case DRM_FORMAT_XBGR8888
:
187 *format
= WIN_COLOR_DEPTH_R8G8B8X8
;
190 case DRM_FORMAT_UYVY
:
191 *format
= WIN_COLOR_DEPTH_YCbCr422
;
194 case DRM_FORMAT_YUYV
:
198 *format
= WIN_COLOR_DEPTH_YCbCr422
;
199 *swap
= BYTE_SWAP_SWAP2
;
202 case DRM_FORMAT_YUV420
:
203 *format
= WIN_COLOR_DEPTH_YCbCr420P
;
206 case DRM_FORMAT_YUV422
:
207 *format
= WIN_COLOR_DEPTH_YCbCr422P
;
217 bool tegra_plane_format_is_yuv(unsigned int format
, bool *planar
)
220 case WIN_COLOR_DEPTH_YCbCr422
:
221 case WIN_COLOR_DEPTH_YUV422
:
227 case WIN_COLOR_DEPTH_YCbCr420P
:
228 case WIN_COLOR_DEPTH_YUV420P
:
229 case WIN_COLOR_DEPTH_YCbCr422P
:
230 case WIN_COLOR_DEPTH_YUV422P
:
231 case WIN_COLOR_DEPTH_YCbCr422R
:
232 case WIN_COLOR_DEPTH_YUV422R
:
233 case WIN_COLOR_DEPTH_YCbCr422RA
:
234 case WIN_COLOR_DEPTH_YUV422RA
:
247 static bool __drm_format_has_alpha(u32 format
)
250 case DRM_FORMAT_ARGB1555
:
251 case DRM_FORMAT_RGBA5551
:
252 case DRM_FORMAT_ABGR8888
:
253 case DRM_FORMAT_ARGB8888
:
261 * This is applicable to Tegra20 and Tegra30 only where the opaque formats can
262 * be emulated using the alpha formats and alpha blending disabled.
264 bool tegra_plane_format_has_alpha(unsigned int format
)
267 case WIN_COLOR_DEPTH_B5G5R5A1
:
268 case WIN_COLOR_DEPTH_A1B5G5R5
:
269 case WIN_COLOR_DEPTH_R8G8B8A8
:
270 case WIN_COLOR_DEPTH_B8G8R8A8
:
277 int tegra_plane_format_get_alpha(unsigned int opaque
, unsigned int *alpha
)
279 if (tegra_plane_format_is_yuv(opaque
, NULL
)) {
285 case WIN_COLOR_DEPTH_B5G5R5X1
:
286 *alpha
= WIN_COLOR_DEPTH_B5G5R5A1
;
289 case WIN_COLOR_DEPTH_X1B5G5R5
:
290 *alpha
= WIN_COLOR_DEPTH_A1B5G5R5
;
293 case WIN_COLOR_DEPTH_R8G8B8X8
:
294 *alpha
= WIN_COLOR_DEPTH_R8G8B8A8
;
297 case WIN_COLOR_DEPTH_B8G8R8X8
:
298 *alpha
= WIN_COLOR_DEPTH_B8G8R8A8
;
305 unsigned int tegra_plane_get_overlap_index(struct tegra_plane
*plane
,
306 struct tegra_plane
*other
)
308 unsigned int index
= 0, i
;
310 WARN_ON(plane
== other
);
312 for (i
= 0; i
< 3; i
++) {
313 if (i
== plane
->index
)
316 if (i
== other
->index
)
325 void tegra_plane_check_dependent(struct tegra_plane
*tegra
,
326 struct tegra_plane_state
*state
)
328 struct drm_plane_state
*old
, *new;
329 struct drm_plane
*plane
;
330 unsigned int zpos
[2];
333 for (i
= 0; i
< 3; i
++)
334 state
->dependent
[i
] = false;
336 for (i
= 0; i
< 2; i
++)
339 for_each_oldnew_plane_in_state(state
->base
.state
, plane
, old
, new, i
) {
340 struct tegra_plane
*p
= to_tegra_plane(plane
);
343 /* skip this plane and planes on different CRTCs */
344 if (p
== tegra
|| new->crtc
!= state
->base
.crtc
)
347 index
= tegra_plane_get_overlap_index(tegra
, p
);
350 * If any of the other planes is on top of this plane and uses
351 * a format with an alpha component, mark this plane as being
352 * dependent, meaning it's alpha value will be 1 minus the sum
353 * of alpha components of the overlapping planes.
355 if (p
->index
> tegra
->index
) {
356 if (__drm_format_has_alpha(new->fb
->format
->format
))
357 state
->dependent
[index
] = true;
359 /* keep track of the Z position */
360 zpos
[index
] = p
->index
;
365 * The region where three windows overlap is the intersection of the
366 * two regions where two windows overlap. It contributes to the area
367 * if any of the windows on top of it have an alpha component.
369 for (i
= 0; i
< 2; i
++)
370 state
->dependent
[2] = state
->dependent
[2] ||
374 * However, if any of the windows on top of this window is opaque, it
375 * will completely conceal this window within that area, so avoid the
376 * window from contributing to the area.
378 for (i
= 0; i
< 2; i
++) {
379 if (zpos
[i
] > tegra
->index
)
380 state
->dependent
[2] = state
->dependent
[2] &&