1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
4 */
5
6 #include <linux/errno.h>
7 #include <linux/printk.h>
8
9 #include <drm/drm_atomic_state_helper.h>
10 #include <drm/drm_fb_dma_helper.h>
11 #include <drm/drm_fourcc.h>
12 #include <drm/drm_gem_dma_helper.h>
13 #include <drm/drm_print.h>
14
15 #include "vs_plane.h"
16
drm_format_to_vs_format(u32 drm_format,struct vs_format * vs_format)17 int drm_format_to_vs_format(u32 drm_format, struct vs_format *vs_format)
18 {
19 switch (drm_format) {
20 case DRM_FORMAT_XRGB4444:
21 case DRM_FORMAT_RGBX4444:
22 case DRM_FORMAT_XBGR4444:
23 case DRM_FORMAT_BGRX4444:
24 vs_format->color = VSDC_COLOR_FORMAT_X4R4G4B4;
25 break;
26 case DRM_FORMAT_ARGB4444:
27 case DRM_FORMAT_RGBA4444:
28 case DRM_FORMAT_ABGR4444:
29 case DRM_FORMAT_BGRA4444:
30 vs_format->color = VSDC_COLOR_FORMAT_A4R4G4B4;
31 break;
32 case DRM_FORMAT_XRGB1555:
33 case DRM_FORMAT_RGBX5551:
34 case DRM_FORMAT_XBGR1555:
35 case DRM_FORMAT_BGRX5551:
36 vs_format->color = VSDC_COLOR_FORMAT_X1R5G5B5;
37 break;
38 case DRM_FORMAT_ARGB1555:
39 case DRM_FORMAT_RGBA5551:
40 case DRM_FORMAT_ABGR1555:
41 case DRM_FORMAT_BGRA5551:
42 vs_format->color = VSDC_COLOR_FORMAT_A1R5G5B5;
43 break;
44 case DRM_FORMAT_RGB565:
45 case DRM_FORMAT_BGR565:
46 vs_format->color = VSDC_COLOR_FORMAT_R5G6B5;
47 break;
48 case DRM_FORMAT_XRGB8888:
49 case DRM_FORMAT_RGBX8888:
50 case DRM_FORMAT_XBGR8888:
51 case DRM_FORMAT_BGRX8888:
52 vs_format->color = VSDC_COLOR_FORMAT_X8R8G8B8;
53 break;
54 case DRM_FORMAT_ARGB8888:
55 case DRM_FORMAT_RGBA8888:
56 case DRM_FORMAT_ABGR8888:
57 case DRM_FORMAT_BGRA8888:
58 vs_format->color = VSDC_COLOR_FORMAT_A8R8G8B8;
59 break;
60 case DRM_FORMAT_ARGB2101010:
61 case DRM_FORMAT_RGBA1010102:
62 case DRM_FORMAT_ABGR2101010:
63 case DRM_FORMAT_BGRA1010102:
64 vs_format->color = VSDC_COLOR_FORMAT_A2R10G10B10;
65 break;
66 default:
67 return -EINVAL;
68 }
69
70 switch (drm_format) {
71 case DRM_FORMAT_RGBX4444:
72 case DRM_FORMAT_RGBA4444:
73 case DRM_FORMAT_RGBX5551:
74 case DRM_FORMAT_RGBA5551:
75 case DRM_FORMAT_RGBX8888:
76 case DRM_FORMAT_RGBA8888:
77 case DRM_FORMAT_RGBA1010102:
78 vs_format->swizzle = VSDC_SWIZZLE_RGBA;
79 break;
80 case DRM_FORMAT_XBGR4444:
81 case DRM_FORMAT_ABGR4444:
82 case DRM_FORMAT_XBGR1555:
83 case DRM_FORMAT_ABGR1555:
84 case DRM_FORMAT_BGR565:
85 case DRM_FORMAT_XBGR8888:
86 case DRM_FORMAT_ABGR8888:
87 case DRM_FORMAT_ABGR2101010:
88 vs_format->swizzle = VSDC_SWIZZLE_ABGR;
89 break;
90 case DRM_FORMAT_BGRX4444:
91 case DRM_FORMAT_BGRA4444:
92 case DRM_FORMAT_BGRX5551:
93 case DRM_FORMAT_BGRA5551:
94 case DRM_FORMAT_BGRX8888:
95 case DRM_FORMAT_BGRA8888:
96 case DRM_FORMAT_BGRA1010102:
97 vs_format->swizzle = VSDC_SWIZZLE_BGRA;
98 break;
99 default:
100 /* N/A for YUV formats */
101 vs_format->swizzle = VSDC_SWIZZLE_ARGB;
102 }
103
104 /* N/A for non-YUV formats */
105 vs_format->uv_swizzle = false;
106
107 return 0;
108 }
109
vs_fb_get_dma_addr(struct drm_framebuffer * fb,const struct drm_rect * src_rect)110 dma_addr_t vs_fb_get_dma_addr(struct drm_framebuffer *fb,
111 const struct drm_rect *src_rect)
112 {
113 struct drm_gem_dma_object *gem;
114 dma_addr_t dma_addr;
115
116 /* Get the physical address of the buffer in memory */
117 gem = drm_fb_dma_get_gem_obj(fb, 0);
118
119 /* Compute the start of the displayed memory */
120 dma_addr = gem->dma_addr + fb->offsets[0];
121
122 /* Fixup framebuffer address for src coordinates */
123 dma_addr += drm_format_info_min_pitch(fb->format, 0,
124 src_rect->x1 >> 16);
125 dma_addr += (src_rect->y1 >> 16) * fb->pitches[0];
126
127 return dma_addr;
128 }
129
vs_plane_duplicate_state(struct drm_plane * plane)130 struct drm_plane_state *vs_plane_duplicate_state(struct drm_plane *plane)
131 {
132 struct vs_plane_state *vs_state, *vs_state_old;
133
134 if (drm_WARN_ON(plane->dev, !plane->state))
135 return NULL;
136
137 vs_state_old = to_vs_plane_state(plane->state);
138
139 vs_state = kzalloc_obj(*vs_state);
140 if (!vs_state)
141 return NULL;
142
143 __drm_atomic_helper_plane_duplicate_state(plane, &vs_state->base);
144
145 memcpy(&vs_state->format, &vs_state_old->format,
146 sizeof(struct vs_format));
147
148 return &vs_state->base;
149 }
150
vs_plane_destroy_state(struct drm_plane * plane,struct drm_plane_state * state)151 void vs_plane_destroy_state(struct drm_plane *plane,
152 struct drm_plane_state *state)
153 {
154 __drm_atomic_helper_plane_destroy_state(state);
155 kfree(state);
156 }
157
158 /* Called during init to allocate the plane's atomic state. */
vs_plane_reset(struct drm_plane * plane)159 void vs_plane_reset(struct drm_plane *plane)
160 {
161 struct vs_plane_state *vs_state;
162
163 if (plane->state) {
164 __drm_atomic_helper_plane_destroy_state(plane->state);
165 kfree(plane->state);
166 plane->state = NULL;
167 }
168
169 vs_state = kzalloc_obj(*vs_state);
170 if (!vs_state)
171 return;
172
173 __drm_atomic_helper_plane_reset(plane, &vs_state->base);
174 }
175