bcm27xx: update 6.1 patches to latest version
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-6.1 / 950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch
1 From 39ae36d19bf6e59e3091f8f0ec6f4eac59aaf6f2 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Fri, 14 Apr 2023 13:43:32 +0200
4 Subject: [PATCH] drm/vc4: tests: Introduce a test for LBM buffer size
5
6 The BCM2712 comes with a different LBM size computation than the
7 previous generations, so let's add the few examples provided as kunit
8 tests to make sure we always satisfy those requirements.
9
10 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
11 ---
12 drivers/gpu/drm/vc4/Makefile | 3 +-
13 drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c | 327 ++++++++++++++++++
14 2 files changed, 329 insertions(+), 1 deletion(-)
15 create mode 100644 drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c
16
17 --- a/drivers/gpu/drm/vc4/Makefile
18 +++ b/drivers/gpu/drm/vc4/Makefile
19 @@ -31,7 +31,8 @@ vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \
20 tests/vc4_mock_crtc.o \
21 tests/vc4_mock_output.o \
22 tests/vc4_mock_plane.o \
23 - tests/vc4_test_pv_muxing.o
24 + tests/vc4_test_pv_muxing.o \
25 + tests/vc4_test_lbm_size.o
26
27 vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
28
29 --- /dev/null
30 +++ b/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c
31 @@ -0,0 +1,327 @@
32 +// SPDX-License-Identifier: GPL-2.0
33 +
34 +#include <drm/drm_atomic_helper.h>
35 +#include <drm/drm_atomic_uapi.h>
36 +#include <drm/drm_drv.h>
37 +#include <drm/drm_fourcc.h>
38 +#include <drm/drm_framebuffer.h>
39 +#include <drm/drm_plane.h>
40 +#include <drm/drm_kunit_helpers.h>
41 +
42 +#include "../../drm_crtc_internal.h"
43 +#include "../../drm_internal.h"
44 +
45 +#include <kunit/test.h>
46 +
47 +#include "../vc4_drv.h"
48 +
49 +#include "vc4_mock.h"
50 +
51 +u32 vc4_lbm_size(struct drm_plane_state *state);
52 +
53 +struct vc4_lbm_size_priv {
54 + struct vc4_dev *vc4;
55 + struct drm_file *file;
56 + struct drm_modeset_acquire_ctx ctx;
57 + struct drm_atomic_state *state;
58 +};
59 +
60 +struct vc4_lbm_size_param {
61 + unsigned int src_w, src_h;
62 + unsigned int crtc_w, crtc_h;
63 + bool forced_alpha;
64 + u32 fourcc;
65 + enum vc4_scaling_mode expected_x_scaling[2];
66 + enum vc4_scaling_mode expected_y_scaling[2];
67 + unsigned int expected_lbm_size;
68 +};
69 +
70 +static const struct vc4_lbm_size_param vc4_test_lbm_size_params[] = {
71 + {
72 + .src_w = 256,
73 + .crtc_w = 256,
74 + .src_h = 256,
75 + .crtc_h = 512,
76 + .fourcc = DRM_FORMAT_ARGB8888,
77 + .expected_x_scaling = { VC4_SCALING_NONE, },
78 + .expected_y_scaling = { VC4_SCALING_PPF, },
79 + .expected_lbm_size = 32,
80 + },
81 + {
82 + .src_w = 256,
83 + .crtc_w = 179,
84 + .src_h = 256,
85 + .crtc_h = 512,
86 + .fourcc = DRM_FORMAT_ARGB8888,
87 + .expected_x_scaling = { VC4_SCALING_PPF, },
88 + .expected_y_scaling = { VC4_SCALING_PPF, },
89 + .expected_lbm_size = 23,
90 + },
91 + {
92 + .src_w = 256,
93 + .crtc_w = 256,
94 + .src_h = 256,
95 + .crtc_h = 512,
96 + .fourcc = DRM_FORMAT_XRGB8888,
97 + .expected_x_scaling = { VC4_SCALING_NONE, },
98 + .expected_y_scaling = { VC4_SCALING_PPF, },
99 + .expected_lbm_size = 24,
100 + },
101 + {
102 + .src_w = 100,
103 + .crtc_w = 73,
104 + .src_h = 100,
105 + .crtc_h = 73,
106 + .fourcc = DRM_FORMAT_XRGB8888,
107 + .expected_x_scaling = { VC4_SCALING_PPF, },
108 + .expected_y_scaling = { VC4_SCALING_PPF, },
109 + .expected_lbm_size = 8,
110 + },
111 + {
112 + .src_w = 256,
113 + .crtc_w = 256,
114 + .src_h = 256,
115 + .crtc_h = 512,
116 + .forced_alpha = true,
117 + .fourcc = DRM_FORMAT_ARGB8888,
118 + .expected_x_scaling = { VC4_SCALING_NONE, },
119 + .expected_y_scaling = { VC4_SCALING_PPF, },
120 + .expected_lbm_size = 24,
121 + },
122 + {
123 + .src_w = 100,
124 + .crtc_w = 73,
125 + .src_h = 100,
126 + .crtc_h = 73,
127 + .forced_alpha = true,
128 + .fourcc = DRM_FORMAT_ARGB8888,
129 + .expected_x_scaling = { VC4_SCALING_PPF, },
130 + .expected_y_scaling = { VC4_SCALING_PPF, },
131 + .expected_lbm_size = 8,
132 + },
133 + {
134 + .src_w = 256,
135 + .crtc_w = 94,
136 + .src_h = 256,
137 + .crtc_h = 94,
138 + .fourcc = DRM_FORMAT_ARGB8888,
139 + .expected_x_scaling = { VC4_SCALING_TPZ, },
140 + .expected_y_scaling = { VC4_SCALING_TPZ, },
141 + .expected_lbm_size = 6,
142 + },
143 +
144 +/*
145 + * TODO: Those tests reflect the LBM size calculation examples, but the
146 + * driver ends up taking different scaler filters decisions, and thus
147 + * doesn't end up with the same sizes. It would be valuable to have
148 + * those tests, but the driver doesn't take a bad decision either, so
149 + * it's not clear what we should do at this point.
150 + */
151 +#if 0
152 + {
153 + .src_w = 320,
154 + .crtc_w = 320,
155 + .src_h = 320,
156 + .crtc_h = 320,
157 + .fourcc = DRM_FORMAT_YUV420,
158 + .expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, },
159 + .expected_y_scaling = { VC4_SCALING_NONE, VC4_SCALING_PPF, },
160 + .expected_lbm_size = 10,
161 + },
162 + {
163 + .src_w = 512,
164 + .crtc_w = 512,
165 + .src_h = 512,
166 + .crtc_h = 256,
167 + .fourcc = DRM_FORMAT_YUV420,
168 + .expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, },
169 + .expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_NONE, },
170 + .expected_lbm_size = 5,
171 + },
172 + {
173 + .src_w = 486,
174 + .crtc_w = 157,
175 + .src_h = 404,
176 + .crtc_h = 929,
177 + .fourcc = DRM_FORMAT_YUV422,
178 + .expected_x_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, },
179 + .expected_y_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, },
180 + .expected_lbm_size = 20,
181 + },
182 + {
183 + .src_w = 320,
184 + .crtc_w = 128,
185 + .src_h = 176,
186 + .crtc_h = 70,
187 + .fourcc = DRM_FORMAT_YUV420,
188 + .expected_x_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, },
189 + .expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, },
190 + .expected_lbm_size = 8,
191 + },
192 +#endif
193 +};
194 +
195 +static void vc4_test_lbm_size_desc(const struct vc4_lbm_size_param *t, char *desc)
196 +{
197 + snprintf(desc, KUNIT_PARAM_DESC_SIZE,
198 + "%ux%u to %ux%u %s(%p4cc)",
199 + t->src_w, t->src_h,
200 + t->crtc_w, t->crtc_h,
201 + t->forced_alpha ? "with forced alpha " : "",
202 + &t->fourcc);
203 +}
204 +
205 +KUNIT_ARRAY_PARAM(vc4_test_lbm_size,
206 + vc4_test_lbm_size_params,
207 + vc4_test_lbm_size_desc);
208 +
209 +static void drm_vc4_test_vc4_lbm_size(struct kunit *test)
210 +{
211 + const struct vc4_lbm_size_param *params = test->param_value;
212 + const struct vc4_lbm_size_priv *priv = test->priv;
213 + const struct drm_format_info *info;
214 + struct drm_mode_fb_cmd2 fb_req = { };
215 + struct drm_atomic_state *state = priv->state;
216 + struct vc4_plane_state *vc4_plane_state;
217 + struct drm_plane_state *plane_state;
218 + struct vc4_dummy_output *output;
219 + struct drm_framebuffer *fb;
220 + struct drm_plane *plane;
221 + struct drm_crtc *crtc;
222 + unsigned int i;
223 + int ret;
224 +
225 + info = drm_format_info(params->fourcc);
226 + KUNIT_ASSERT_NOT_NULL(test, info);
227 +
228 + output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
229 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
230 +
231 + crtc = vc4_find_crtc_for_encoder(test, &output->encoder.base);
232 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
233 +
234 + plane = vc4_mock_atomic_add_plane(test, state, crtc);
235 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
236 +
237 + plane_state = drm_atomic_get_plane_state(state, plane);
238 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_state);
239 +
240 + vc4_plane_state = to_vc4_plane_state(plane_state);
241 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4_plane_state);
242 +
243 + fb_req.pixel_format = params->fourcc;
244 + fb_req.width = params->src_w;
245 + fb_req.height = params->src_h;
246 +
247 + for (i = 0; i < info->num_planes; i++) {
248 + struct drm_mode_create_dumb dumb_args = { };
249 +
250 + dumb_args.width = params->src_w;
251 + dumb_args.height = params->src_h;
252 + dumb_args.bpp = drm_format_info_bpp(info, i);
253 +
254 + ret = drm_mode_create_dumb(state->dev, &dumb_args, priv->file);
255 + KUNIT_ASSERT_EQ(test, ret, 0);
256 +
257 + fb_req.handles[i] = dumb_args.handle;
258 + fb_req.pitches[i] = dumb_args.pitch;
259 + }
260 +
261 + fb = drm_internal_framebuffer_create(state->dev, &fb_req, priv->file);
262 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb);
263 +
264 + drm_atomic_set_fb_for_plane(plane_state, fb);
265 +
266 + plane_state->src_x = 0;
267 + plane_state->src_y = 0;
268 + plane_state->src_h = params->src_h << 16;
269 + plane_state->src_w = params->src_w << 16;
270 +
271 + plane_state->crtc_x = 0;
272 + plane_state->crtc_y = 0;
273 + plane_state->crtc_h = params->crtc_h;
274 + plane_state->crtc_w = params->crtc_w;
275 +
276 + if (params->forced_alpha)
277 + plane_state->alpha = 128;
278 +
279 + ret = drm_atomic_check_only(state);
280 + KUNIT_ASSERT_EQ(test, ret, 0);
281 +
282 + KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm.size, params->expected_lbm_size);
283 +
284 + for (i = 0; i < 2; i++) {
285 + KUNIT_EXPECT_EQ(test,
286 + vc4_plane_state->x_scaling[i],
287 + params->expected_x_scaling[i]);
288 + KUNIT_EXPECT_EQ(test,
289 + vc4_plane_state->y_scaling[i],
290 + params->expected_y_scaling[i]);
291 + }
292 +
293 + drm_framebuffer_put(fb);
294 +
295 + for (i = 0; i < info->num_planes; i++)
296 + drm_mode_destroy_dumb(state->dev, fb_req.handles[i], priv->file);
297 +}
298 +
299 +static struct kunit_case vc4_lbm_size_tests[] = {
300 + KUNIT_CASE_PARAM(drm_vc4_test_vc4_lbm_size,
301 + vc4_test_lbm_size_gen_params),
302 + {}
303 +};
304 +
305 +static int vc4_lbm_size_test_init(struct kunit *test)
306 +{
307 + struct drm_atomic_state *state;
308 + struct vc4_lbm_size_priv *priv;
309 + struct drm_device *drm;
310 + struct vc4_dev *vc4;
311 +
312 + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
313 + KUNIT_ASSERT_NOT_NULL(test, priv);
314 + test->priv = priv;
315 +
316 + vc4 = vc6_mock_device(test);
317 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
318 + priv->vc4 = vc4;
319 +
320 + priv->file = drm_file_alloc(priv->vc4->base.primary);
321 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->file);
322 +
323 + drm_modeset_acquire_init(&priv->ctx, 0);
324 +
325 + drm = &vc4->base;
326 + state = drm_atomic_state_alloc(drm);
327 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
328 +
329 + state->acquire_ctx = &priv->ctx;
330 +
331 + priv->state = state;
332 +
333 + return 0;
334 +}
335 +
336 +static void vc4_lbm_size_test_exit(struct kunit *test)
337 +{
338 + struct vc4_lbm_size_priv *priv = test->priv;
339 + struct vc4_dev *vc4 = priv->vc4;
340 + struct drm_device *drm = &vc4->base;
341 + struct drm_atomic_state *state = priv->state;
342 +
343 + drm_atomic_state_put(state);
344 + drm_modeset_drop_locks(&priv->ctx);
345 + drm_modeset_acquire_fini(&priv->ctx);
346 + drm_file_free(priv->file);
347 + drm_dev_unregister(drm);
348 + drm_kunit_helper_free_device(test, vc4->dev);
349 +}
350 +
351 +static struct kunit_suite vc4_lbm_size_test_suite = {
352 + .name = "vc4-lbm-size",
353 + .init = vc4_lbm_size_test_init,
354 + .exit = vc4_lbm_size_test_exit,
355 + .test_cases = vc4_lbm_size_tests,
356 +};
357 +
358 +kunit_test_suite(vc4_lbm_size_test_suite);