xref: /linux/drivers/gpu/drm/tegra/plane.c (revision 511c7023cf23421d1d0455b22c139fe1be1b9e87)
15acd3514SThierry Reding /*
25acd3514SThierry Reding  * Copyright (C) 2017 NVIDIA CORPORATION.  All rights reserved.
35acd3514SThierry Reding  *
45acd3514SThierry Reding  * This program is free software; you can redistribute it and/or modify
55acd3514SThierry Reding  * it under the terms of the GNU General Public License version 2 as
65acd3514SThierry Reding  * published by the Free Software Foundation.
75acd3514SThierry Reding  */
85acd3514SThierry Reding 
95acd3514SThierry Reding #include <drm/drm_atomic.h>
105acd3514SThierry Reding #include <drm/drm_atomic_helper.h>
115acd3514SThierry Reding #include <drm/drm_plane_helper.h>
125acd3514SThierry Reding 
135acd3514SThierry Reding #include "dc.h"
145acd3514SThierry Reding #include "plane.h"
155acd3514SThierry Reding 
165acd3514SThierry Reding static void tegra_plane_destroy(struct drm_plane *plane)
175acd3514SThierry Reding {
185acd3514SThierry Reding 	struct tegra_plane *p = to_tegra_plane(plane);
195acd3514SThierry Reding 
205acd3514SThierry Reding 	drm_plane_cleanup(plane);
215acd3514SThierry Reding 	kfree(p);
225acd3514SThierry Reding }
235acd3514SThierry Reding 
245acd3514SThierry Reding static void tegra_plane_reset(struct drm_plane *plane)
255acd3514SThierry Reding {
265acd3514SThierry Reding 	struct tegra_plane_state *state;
275acd3514SThierry Reding 
285acd3514SThierry Reding 	if (plane->state)
295acd3514SThierry Reding 		__drm_atomic_helper_plane_destroy_state(plane->state);
305acd3514SThierry Reding 
315acd3514SThierry Reding 	kfree(plane->state);
325acd3514SThierry Reding 	plane->state = NULL;
335acd3514SThierry Reding 
345acd3514SThierry Reding 	state = kzalloc(sizeof(*state), GFP_KERNEL);
355acd3514SThierry Reding 	if (state) {
365acd3514SThierry Reding 		plane->state = &state->base;
375acd3514SThierry Reding 		plane->state->plane = plane;
385acd3514SThierry Reding 	}
395acd3514SThierry Reding }
405acd3514SThierry Reding 
415acd3514SThierry Reding static struct drm_plane_state *
425acd3514SThierry Reding tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
435acd3514SThierry Reding {
445acd3514SThierry Reding 	struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
455acd3514SThierry Reding 	struct tegra_plane_state *copy;
465acd3514SThierry Reding 
475acd3514SThierry Reding 	copy = kmalloc(sizeof(*copy), GFP_KERNEL);
485acd3514SThierry Reding 	if (!copy)
495acd3514SThierry Reding 		return NULL;
505acd3514SThierry Reding 
515acd3514SThierry Reding 	__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
525acd3514SThierry Reding 	copy->tiling = state->tiling;
535acd3514SThierry Reding 	copy->format = state->format;
545acd3514SThierry Reding 	copy->swap = state->swap;
555acd3514SThierry Reding 
565acd3514SThierry Reding 	return &copy->base;
575acd3514SThierry Reding }
585acd3514SThierry Reding 
595acd3514SThierry Reding static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
605acd3514SThierry Reding 					     struct drm_plane_state *state)
615acd3514SThierry Reding {
625acd3514SThierry Reding 	__drm_atomic_helper_plane_destroy_state(state);
635acd3514SThierry Reding 	kfree(state);
645acd3514SThierry Reding }
655acd3514SThierry Reding 
665acd3514SThierry Reding const struct drm_plane_funcs tegra_plane_funcs = {
675acd3514SThierry Reding 	.update_plane = drm_atomic_helper_update_plane,
685acd3514SThierry Reding 	.disable_plane = drm_atomic_helper_disable_plane,
695acd3514SThierry Reding 	.destroy = tegra_plane_destroy,
705acd3514SThierry Reding 	.reset = tegra_plane_reset,
715acd3514SThierry Reding 	.atomic_duplicate_state = tegra_plane_atomic_duplicate_state,
725acd3514SThierry Reding 	.atomic_destroy_state = tegra_plane_atomic_destroy_state,
735acd3514SThierry Reding };
745acd3514SThierry Reding 
755acd3514SThierry Reding int tegra_plane_state_add(struct tegra_plane *plane,
765acd3514SThierry Reding 			  struct drm_plane_state *state)
775acd3514SThierry Reding {
785acd3514SThierry Reding 	struct drm_crtc_state *crtc_state;
795acd3514SThierry Reding 	struct tegra_dc_state *tegra;
805acd3514SThierry Reding 	struct drm_rect clip;
815acd3514SThierry Reding 	int err;
825acd3514SThierry Reding 
835acd3514SThierry Reding 	/* Propagate errors from allocation or locking failures. */
845acd3514SThierry Reding 	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
855acd3514SThierry Reding 	if (IS_ERR(crtc_state))
865acd3514SThierry Reding 		return PTR_ERR(crtc_state);
875acd3514SThierry Reding 
885acd3514SThierry Reding 	clip.x1 = 0;
895acd3514SThierry Reding 	clip.y1 = 0;
905acd3514SThierry Reding 	clip.x2 = crtc_state->mode.hdisplay;
915acd3514SThierry Reding 	clip.y2 = crtc_state->mode.vdisplay;
925acd3514SThierry Reding 
935acd3514SThierry Reding 	/* Check plane state for visibility and calculate clipping bounds */
945acd3514SThierry Reding 	err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
955acd3514SThierry Reding 						  0, INT_MAX, true, true);
965acd3514SThierry Reding 	if (err < 0)
975acd3514SThierry Reding 		return err;
985acd3514SThierry Reding 
995acd3514SThierry Reding 	tegra = to_dc_state(crtc_state);
1005acd3514SThierry Reding 
1015acd3514SThierry Reding 	tegra->planes |= WIN_A_ACT_REQ << plane->index;
1025acd3514SThierry Reding 
1035acd3514SThierry Reding 	return 0;
1045acd3514SThierry Reding }
1055acd3514SThierry Reding 
1065acd3514SThierry Reding int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
1075acd3514SThierry Reding {
1085acd3514SThierry Reding 	/* assume no swapping of fetched data */
1095acd3514SThierry Reding 	if (swap)
1105acd3514SThierry Reding 		*swap = BYTE_SWAP_NOSWAP;
1115acd3514SThierry Reding 
1125acd3514SThierry Reding 	switch (fourcc) {
113*511c7023SThierry Reding 	case DRM_FORMAT_ARGB4444:
114*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_B4G4R4A4;
1157772fdaeSThierry Reding 		break;
1167772fdaeSThierry Reding 
117*511c7023SThierry Reding 	case DRM_FORMAT_ARGB1555:
118*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_B5G5R5A1;
1195acd3514SThierry Reding 		break;
1205acd3514SThierry Reding 
121*511c7023SThierry Reding 	case DRM_FORMAT_RGB565:
122*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_B5G6R5;
123*511c7023SThierry Reding 		break;
124*511c7023SThierry Reding 
125*511c7023SThierry Reding 	case DRM_FORMAT_RGBA5551:
126*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_A1B5G5R5;
1277772fdaeSThierry Reding 		break;
1287772fdaeSThierry Reding 
1297772fdaeSThierry Reding 	case DRM_FORMAT_ARGB8888:
1305acd3514SThierry Reding 		*format = WIN_COLOR_DEPTH_B8G8R8A8;
1315acd3514SThierry Reding 		break;
1325acd3514SThierry Reding 
133*511c7023SThierry Reding 	case DRM_FORMAT_ABGR8888:
134*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_R8G8B8A8;
135*511c7023SThierry Reding 		break;
136*511c7023SThierry Reding 
137*511c7023SThierry Reding 	case DRM_FORMAT_ABGR4444:
138*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_R4G4B4A4;
139*511c7023SThierry Reding 		break;
140*511c7023SThierry Reding 
141*511c7023SThierry Reding 	case DRM_FORMAT_ABGR1555:
142*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_R5G5B5A;
143*511c7023SThierry Reding 		break;
144*511c7023SThierry Reding 
145*511c7023SThierry Reding 	case DRM_FORMAT_BGRA5551:
146*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_AR5G5B5;
147*511c7023SThierry Reding 		break;
148*511c7023SThierry Reding 
149*511c7023SThierry Reding 	case DRM_FORMAT_XRGB1555:
150*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_B5G5R5X1;
151*511c7023SThierry Reding 		break;
152*511c7023SThierry Reding 
153*511c7023SThierry Reding 	case DRM_FORMAT_RGBX5551:
154*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_X1B5G5R5;
155*511c7023SThierry Reding 		break;
156*511c7023SThierry Reding 
157*511c7023SThierry Reding 	case DRM_FORMAT_XBGR1555:
158*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_R5G5B5X1;
159*511c7023SThierry Reding 		break;
160*511c7023SThierry Reding 
161*511c7023SThierry Reding 	case DRM_FORMAT_BGRX5551:
162*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_X1R5G5B5;
163*511c7023SThierry Reding 		break;
164*511c7023SThierry Reding 
165*511c7023SThierry Reding 	case DRM_FORMAT_BGR565:
166*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_R5G6B5;
167*511c7023SThierry Reding 		break;
168*511c7023SThierry Reding 
169*511c7023SThierry Reding 	case DRM_FORMAT_BGRA8888:
170*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_A8R8G8B8;
171*511c7023SThierry Reding 		break;
172*511c7023SThierry Reding 
173*511c7023SThierry Reding 	case DRM_FORMAT_RGBA8888:
174*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_A8B8G8R8;
175*511c7023SThierry Reding 		break;
176*511c7023SThierry Reding 
177*511c7023SThierry Reding 	case DRM_FORMAT_XRGB8888:
178*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_B8G8R8X8;
179*511c7023SThierry Reding 		break;
180*511c7023SThierry Reding 
181*511c7023SThierry Reding 	case DRM_FORMAT_XBGR8888:
182*511c7023SThierry Reding 		*format = WIN_COLOR_DEPTH_R8G8B8X8;
1835acd3514SThierry Reding 		break;
1845acd3514SThierry Reding 
1855acd3514SThierry Reding 	case DRM_FORMAT_UYVY:
1865acd3514SThierry Reding 		*format = WIN_COLOR_DEPTH_YCbCr422;
1875acd3514SThierry Reding 		break;
1885acd3514SThierry Reding 
1895acd3514SThierry Reding 	case DRM_FORMAT_YUYV:
1905acd3514SThierry Reding 		if (!swap)
1915acd3514SThierry Reding 			return -EINVAL;
1925acd3514SThierry Reding 
1935acd3514SThierry Reding 		*format = WIN_COLOR_DEPTH_YCbCr422;
1945acd3514SThierry Reding 		*swap = BYTE_SWAP_SWAP2;
1955acd3514SThierry Reding 		break;
1965acd3514SThierry Reding 
1975acd3514SThierry Reding 	case DRM_FORMAT_YUV420:
1985acd3514SThierry Reding 		*format = WIN_COLOR_DEPTH_YCbCr420P;
1995acd3514SThierry Reding 		break;
2005acd3514SThierry Reding 
2015acd3514SThierry Reding 	case DRM_FORMAT_YUV422:
2025acd3514SThierry Reding 		*format = WIN_COLOR_DEPTH_YCbCr422P;
2035acd3514SThierry Reding 		break;
2045acd3514SThierry Reding 
2055acd3514SThierry Reding 	default:
2065acd3514SThierry Reding 		return -EINVAL;
2075acd3514SThierry Reding 	}
2085acd3514SThierry Reding 
2095acd3514SThierry Reding 	return 0;
2105acd3514SThierry Reding }
2115acd3514SThierry Reding 
2125acd3514SThierry Reding bool tegra_plane_format_is_yuv(unsigned int format, bool *planar)
2135acd3514SThierry Reding {
2145acd3514SThierry Reding 	switch (format) {
2155acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YCbCr422:
2165acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YUV422:
2175acd3514SThierry Reding 		if (planar)
2185acd3514SThierry Reding 			*planar = false;
2195acd3514SThierry Reding 
2205acd3514SThierry Reding 		return true;
2215acd3514SThierry Reding 
2225acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YCbCr420P:
2235acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YUV420P:
2245acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YCbCr422P:
2255acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YUV422P:
2265acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YCbCr422R:
2275acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YUV422R:
2285acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YCbCr422RA:
2295acd3514SThierry Reding 	case WIN_COLOR_DEPTH_YUV422RA:
2305acd3514SThierry Reding 		if (planar)
2315acd3514SThierry Reding 			*planar = true;
2325acd3514SThierry Reding 
2335acd3514SThierry Reding 		return true;
2345acd3514SThierry Reding 	}
2355acd3514SThierry Reding 
2365acd3514SThierry Reding 	if (planar)
2375acd3514SThierry Reding 		*planar = false;
2385acd3514SThierry Reding 
2395acd3514SThierry Reding 	return false;
2405acd3514SThierry Reding }
241