kernel: bump 5.15 to 5.15.100
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0422-drm-vc4-plane-Add-support-for-DRM_FORMAT_P030.patch
1 From fd317c55c0a5d9f8950b49d1efe32166a378cb26 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 15 Dec 2021 10:17:38 +0100
4 Subject: [PATCH] drm/vc4: plane: Add support for DRM_FORMAT_P030
5
6 The P030 format, used with the DRM_FORMAT_MOD_BROADCOM_SAND128 modifier,
7 is a format output by the video decoder on the BCM2711.
8
9 Add native support to the KMS planes for that format.
10
11 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
12 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
13 Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
14 Link: https://lore.kernel.org/r/20211215091739.135042-3-maxime@cerno.tech
15 ---
16 drivers/gpu/drm/vc4/vc4_plane.c | 127 ++++++++++++++++++++++++--------
17 1 file changed, 96 insertions(+), 31 deletions(-)
18
19 --- a/drivers/gpu/drm/vc4/vc4_plane.c
20 +++ b/drivers/gpu/drm/vc4/vc4_plane.c
21 @@ -33,6 +33,7 @@ static const struct hvs_format {
22 u32 hvs; /* HVS_FORMAT_* */
23 u32 pixel_order;
24 u32 pixel_order_hvs5;
25 + bool hvs5_only;
26 } hvs_formats[] = {
27 {
28 .drm = DRM_FORMAT_XRGB8888,
29 @@ -130,6 +131,12 @@ static const struct hvs_format {
30 .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
31 .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
32 },
33 + {
34 + .drm = DRM_FORMAT_P030,
35 + .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
36 + .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
37 + .hvs5_only = true,
38 + },
39 };
40
41 static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
42 @@ -760,47 +767,90 @@ static int vc4_plane_mode_set(struct drm
43 case DRM_FORMAT_MOD_BROADCOM_SAND128:
44 case DRM_FORMAT_MOD_BROADCOM_SAND256: {
45 uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
46 - u32 tile_w, tile, x_off, pix_per_tile;
47 -
48 - hvs_format = HVS_PIXEL_FORMAT_H264;
49 -
50 - switch (base_format_mod) {
51 - case DRM_FORMAT_MOD_BROADCOM_SAND64:
52 - tiling = SCALER_CTL0_TILING_64B;
53 - tile_w = 64;
54 - break;
55 - case DRM_FORMAT_MOD_BROADCOM_SAND128:
56 - tiling = SCALER_CTL0_TILING_128B;
57 - tile_w = 128;
58 - break;
59 - case DRM_FORMAT_MOD_BROADCOM_SAND256:
60 - tiling = SCALER_CTL0_TILING_256B_OR_T;
61 - tile_w = 256;
62 - break;
63 - default:
64 - break;
65 - }
66
67 if (param > SCALER_TILE_HEIGHT_MASK) {
68 - DRM_DEBUG_KMS("SAND height too large (%d)\n", param);
69 + DRM_DEBUG_KMS("SAND height too large (%d)\n",
70 + param);
71 return -EINVAL;
72 }
73
74 - pix_per_tile = tile_w / fb->format->cpp[0];
75 - tile = vc4_state->src_x / pix_per_tile;
76 - x_off = vc4_state->src_x % pix_per_tile;
77 + if (fb->format->format == DRM_FORMAT_P030) {
78 + hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
79 + tiling = SCALER_CTL0_TILING_128B;
80 + } else {
81 + hvs_format = HVS_PIXEL_FORMAT_H264;
82 +
83 + switch (base_format_mod) {
84 + case DRM_FORMAT_MOD_BROADCOM_SAND64:
85 + tiling = SCALER_CTL0_TILING_64B;
86 + break;
87 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
88 + tiling = SCALER_CTL0_TILING_128B;
89 + break;
90 + case DRM_FORMAT_MOD_BROADCOM_SAND256:
91 + tiling = SCALER_CTL0_TILING_256B_OR_T;
92 + break;
93 + default:
94 + return -EINVAL;
95 + }
96 + }
97
98 /* Adjust the base pointer to the first pixel to be scanned
99 * out.
100 + *
101 + * For P030, y_ptr [31:4] is the 128bit word for the start pixel
102 + * y_ptr [3:0] is the pixel (0-11) contained within that 128bit
103 + * word that should be taken as the first pixel.
104 + * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the
105 + * element within the 128bit word, eg for pixel 3 the value
106 + * should be 6.
107 */
108 for (i = 0; i < num_planes; i++) {
109 + u32 tile_w, tile, x_off, pix_per_tile;
110 +
111 + if (fb->format->format == DRM_FORMAT_P030) {
112 + /*
113 + * Spec says: bits [31:4] of the given address
114 + * should point to the 128-bit word containing
115 + * the desired starting pixel, and bits[3:0]
116 + * should be between 0 and 11, indicating which
117 + * of the 12-pixels in that 128-bit word is the
118 + * first pixel to be used
119 + */
120 + u32 remaining_pixels = vc4_state->src_x % 96;
121 + u32 aligned = remaining_pixels / 12;
122 + u32 last_bits = remaining_pixels % 12;
123 +
124 + x_off = aligned * 16 + last_bits;
125 + tile_w = 128;
126 + pix_per_tile = 96;
127 + } else {
128 + switch (base_format_mod) {
129 + case DRM_FORMAT_MOD_BROADCOM_SAND64:
130 + tile_w = 64;
131 + break;
132 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
133 + tile_w = 128;
134 + break;
135 + case DRM_FORMAT_MOD_BROADCOM_SAND256:
136 + tile_w = 256;
137 + break;
138 + default:
139 + return -EINVAL;
140 + }
141 + pix_per_tile = tile_w / fb->format->cpp[0];
142 + x_off = (vc4_state->src_x % pix_per_tile) /
143 + (i ? h_subsample : 1) *
144 + fb->format->cpp[i];
145 + }
146 +
147 + tile = vc4_state->src_x / pix_per_tile;
148 +
149 vc4_state->offsets[i] += param * tile_w * tile;
150 vc4_state->offsets[i] += src_y /
151 (i ? v_subsample : 1) *
152 tile_w;
153 - vc4_state->offsets[i] += x_off /
154 - (i ? h_subsample : 1) *
155 - fb->format->cpp[i];
156 + vc4_state->offsets[i] += x_off & ~(i ? 1 : 0);
157 }
158
159 pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
160 @@ -953,7 +1003,8 @@ static int vc4_plane_mode_set(struct drm
161
162 /* Pitch word 1/2 */
163 for (i = 1; i < num_planes; i++) {
164 - if (hvs_format != HVS_PIXEL_FORMAT_H264) {
165 + if (hvs_format != HVS_PIXEL_FORMAT_H264 &&
166 + hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT) {
167 vc4_dlist_write(vc4_state,
168 VC4_SET_FIELD(fb->pitches[i],
169 SCALER_SRC_PITCH));
170 @@ -1313,6 +1364,13 @@ static bool vc4_format_mod_supported(str
171 default:
172 return false;
173 }
174 + case DRM_FORMAT_P030:
175 + switch (fourcc_mod_broadcom_mod(modifier)) {
176 + case DRM_FORMAT_MOD_BROADCOM_SAND128:
177 + return true;
178 + default:
179 + return false;
180 + }
181 case DRM_FORMAT_RGBX1010102:
182 case DRM_FORMAT_BGRX1010102:
183 case DRM_FORMAT_RGBA1010102:
184 @@ -1345,8 +1403,11 @@ struct drm_plane *vc4_plane_init(struct
185 struct drm_plane *plane = NULL;
186 struct vc4_plane *vc4_plane;
187 u32 formats[ARRAY_SIZE(hvs_formats)];
188 + int num_formats = 0;
189 int ret = 0;
190 unsigned i;
191 + bool hvs5 = of_device_is_compatible(dev->dev->of_node,
192 + "brcm,bcm2711-vc5");
193 static const uint64_t modifiers[] = {
194 DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
195 DRM_FORMAT_MOD_BROADCOM_SAND128,
196 @@ -1361,13 +1422,17 @@ struct drm_plane *vc4_plane_init(struct
197 if (!vc4_plane)
198 return ERR_PTR(-ENOMEM);
199
200 - for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
201 - formats[i] = hvs_formats[i].drm;
202 + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
203 + if (!hvs_formats[i].hvs5_only || hvs5) {
204 + formats[num_formats] = hvs_formats[i].drm;
205 + num_formats++;
206 + }
207 + }
208
209 plane = &vc4_plane->base;
210 ret = drm_universal_plane_init(dev, plane, 0,
211 &vc4_plane_funcs,
212 - formats, ARRAY_SIZE(formats),
213 + formats, num_formats,
214 modifiers, type, NULL);
215 if (ret)
216 return ERR_PTR(ret);