Skip to content

Commit b8358b9

Browse files
mripardpopcornmix
authored andcommitted
drm/vc4: tests: Introduce a test for LBM buffer size
The BCM2712 comes with a different LBM size computation than the previous generations, so let's add the few examples provided as kunit tests to make sure we always satisfy those requirements. Signed-off-by: Maxime Ripard <maxime@cerno.tech>
1 parent 7d0c024 commit b8358b9

File tree

3 files changed

+310
-2
lines changed

3 files changed

+310
-2
lines changed

drivers/gpu/drm/vc4/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \
3131
tests/vc4_mock_crtc.o \
3232
tests/vc4_mock_output.o \
3333
tests/vc4_mock_plane.o \
34-
tests/vc4_test_pv_muxing.o
34+
tests/vc4_test_pv_muxing.o \
35+
tests/vc4_test_lbm_size.o
3536

3637
vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
3738

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <drm/drm_atomic_helper.h>
4+
#include <drm/drm_atomic_uapi.h>
5+
#include <drm/drm_drv.h>
6+
#include <drm/drm_fourcc.h>
7+
#include <drm/drm_framebuffer.h>
8+
#include <drm/drm_plane.h>
9+
#include <drm/drm_kunit_helpers.h>
10+
11+
#include "../../drm_crtc_internal.h"
12+
#include "../../drm_internal.h"
13+
14+
#include <kunit/test.h>
15+
16+
#include "../vc4_drv.h"
17+
18+
#include "vc4_mock.h"
19+
20+
u32 vc4_lbm_size(struct drm_plane_state *state);
21+
22+
struct vc4_lbm_size_priv {
23+
struct vc4_dev *vc4;
24+
struct drm_file *file;
25+
struct drm_modeset_acquire_ctx ctx;
26+
struct drm_atomic_state *state;
27+
};
28+
29+
struct vc4_lbm_size_param {
30+
unsigned int src_w, src_h;
31+
unsigned int crtc_w, crtc_h;
32+
bool forced_alpha;
33+
u32 fourcc;
34+
enum vc4_scaling_mode expected_x_scaling[2];
35+
enum vc4_scaling_mode expected_y_scaling[2];
36+
unsigned int expected_lbm_size;
37+
};
38+
39+
static const struct vc4_lbm_size_param vc4_test_lbm_size_params[] = {
40+
{
41+
.src_w = 256,
42+
.crtc_w = 256,
43+
.src_h = 256,
44+
.crtc_h = 512,
45+
.fourcc = DRM_FORMAT_ARGB8888,
46+
.expected_x_scaling = { VC4_SCALING_NONE, },
47+
.expected_y_scaling = { VC4_SCALING_PPF, },
48+
.expected_lbm_size = 32,
49+
},
50+
{
51+
.src_w = 256,
52+
.crtc_w = 179,
53+
.src_h = 256,
54+
.crtc_h = 512,
55+
.fourcc = DRM_FORMAT_ARGB8888,
56+
.expected_x_scaling = { VC4_SCALING_PPF, },
57+
.expected_y_scaling = { VC4_SCALING_PPF, },
58+
.expected_lbm_size = 23,
59+
},
60+
{
61+
.src_w = 256,
62+
.crtc_w = 256,
63+
.src_h = 256,
64+
.crtc_h = 512,
65+
.fourcc = DRM_FORMAT_XRGB8888,
66+
.expected_x_scaling = { VC4_SCALING_NONE, },
67+
.expected_y_scaling = { VC4_SCALING_PPF, },
68+
.expected_lbm_size = 24,
69+
},
70+
{
71+
.src_w = 100,
72+
.crtc_w = 73,
73+
.src_h = 100,
74+
.crtc_h = 73,
75+
.fourcc = DRM_FORMAT_XRGB8888,
76+
.expected_x_scaling = { VC4_SCALING_PPF, },
77+
.expected_y_scaling = { VC4_SCALING_PPF, },
78+
.expected_lbm_size = 8,
79+
},
80+
{
81+
.src_w = 256,
82+
.crtc_w = 256,
83+
.src_h = 256,
84+
.crtc_h = 512,
85+
.forced_alpha = true,
86+
.fourcc = DRM_FORMAT_ARGB8888,
87+
.expected_x_scaling = { VC4_SCALING_NONE, },
88+
.expected_y_scaling = { VC4_SCALING_PPF, },
89+
.expected_lbm_size = 24,
90+
},
91+
{
92+
.src_w = 100,
93+
.crtc_w = 73,
94+
.src_h = 100,
95+
.crtc_h = 73,
96+
.forced_alpha = true,
97+
.fourcc = DRM_FORMAT_ARGB8888,
98+
.expected_x_scaling = { VC4_SCALING_PPF, },
99+
.expected_y_scaling = { VC4_SCALING_PPF, },
100+
.expected_lbm_size = 8,
101+
},
102+
{
103+
.src_w = 256,
104+
.crtc_w = 94,
105+
.src_h = 256,
106+
.crtc_h = 94,
107+
.fourcc = DRM_FORMAT_ARGB8888,
108+
.expected_x_scaling = { VC4_SCALING_TPZ, },
109+
.expected_y_scaling = { VC4_SCALING_TPZ, },
110+
.expected_lbm_size = 6,
111+
},
112+
113+
/*
114+
* TODO: Those tests reflect the LBM size calculation examples, but the
115+
* driver ends up taking different scaler filters decisions, and thus
116+
* doesn't end up with the same sizes. It would be valuable to have
117+
* those tests, but the driver doesn't take a bad decision either, so
118+
* it's not clear what we should do at this point.
119+
*/
120+
#if 0
121+
{
122+
.src_w = 320,
123+
.crtc_w = 320,
124+
.src_h = 320,
125+
.crtc_h = 320,
126+
.fourcc = DRM_FORMAT_YUV420,
127+
.expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, },
128+
.expected_y_scaling = { VC4_SCALING_NONE, VC4_SCALING_PPF, },
129+
.expected_lbm_size = 10,
130+
},
131+
{
132+
.src_w = 512,
133+
.crtc_w = 512,
134+
.src_h = 512,
135+
.crtc_h = 256,
136+
.fourcc = DRM_FORMAT_YUV420,
137+
.expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, },
138+
.expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_NONE, },
139+
.expected_lbm_size = 5,
140+
},
141+
{
142+
.src_w = 486,
143+
.crtc_w = 157,
144+
.src_h = 404,
145+
.crtc_h = 929,
146+
.fourcc = DRM_FORMAT_YUV422,
147+
.expected_x_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, },
148+
.expected_y_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, },
149+
.expected_lbm_size = 20,
150+
},
151+
{
152+
.src_w = 320,
153+
.crtc_w = 128,
154+
.src_h = 176,
155+
.crtc_h = 70,
156+
.fourcc = DRM_FORMAT_YUV420,
157+
.expected_x_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, },
158+
.expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, },
159+
.expected_lbm_size = 8,
160+
},
161+
#endif
162+
};
163+
164+
static void vc4_test_lbm_size_desc(const struct vc4_lbm_size_param *t, char *desc)
165+
{
166+
snprintf(desc, KUNIT_PARAM_DESC_SIZE,
167+
"%ux%u to %ux%u %s(%p4cc)",
168+
t->src_w, t->src_h,
169+
t->crtc_w, t->crtc_h,
170+
t->forced_alpha ? "with forced alpha " : "",
171+
&t->fourcc);
172+
}
173+
174+
KUNIT_ARRAY_PARAM(vc4_test_lbm_size,
175+
vc4_test_lbm_size_params,
176+
vc4_test_lbm_size_desc);
177+
178+
static void drm_vc4_test_vc4_lbm_size(struct kunit *test)
179+
{
180+
const struct vc4_lbm_size_param *params = test->param_value;
181+
const struct vc4_lbm_size_priv *priv = test->priv;
182+
const struct drm_format_info *info;
183+
struct drm_mode_fb_cmd2 fb_req = { };
184+
struct drm_atomic_state *state = priv->state;
185+
struct vc4_plane_state *vc4_plane_state;
186+
struct drm_plane_state *plane_state;
187+
struct vc4_dummy_output *output;
188+
struct drm_framebuffer *fb;
189+
struct drm_plane *plane;
190+
struct drm_crtc *crtc;
191+
unsigned int i;
192+
int ret;
193+
194+
info = drm_format_info(params->fourcc);
195+
KUNIT_ASSERT_NOT_NULL(test, info);
196+
197+
output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
198+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
199+
200+
crtc = vc4_find_crtc_for_encoder(test, &output->encoder.base);
201+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
202+
203+
plane = vc4_mock_atomic_add_plane(test, state, crtc);
204+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
205+
206+
plane_state = drm_atomic_get_plane_state(state, plane);
207+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_state);
208+
209+
vc4_plane_state = to_vc4_plane_state(plane_state);
210+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4_plane_state);
211+
212+
fb_req.pixel_format = params->fourcc;
213+
fb_req.width = params->src_w;
214+
fb_req.height = params->src_h;
215+
216+
for (i = 0; i < info->num_planes; i++) {
217+
struct drm_mode_create_dumb dumb_args = { };
218+
219+
dumb_args.width = params->src_w;
220+
dumb_args.height = params->src_h;
221+
dumb_args.bpp = drm_format_info_bpp(info, i);
222+
223+
ret = drm_mode_create_dumb(state->dev, &dumb_args, priv->file);
224+
KUNIT_ASSERT_EQ(test, ret, 0);
225+
226+
fb_req.handles[i] = dumb_args.handle;
227+
fb_req.pitches[i] = dumb_args.pitch;
228+
}
229+
230+
fb = drm_internal_framebuffer_create(state->dev, &fb_req, priv->file);
231+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb);
232+
233+
drm_atomic_set_fb_for_plane(plane_state, fb);
234+
235+
plane_state->src_x = 0;
236+
plane_state->src_y = 0;
237+
plane_state->src_h = params->src_h << 16;
238+
plane_state->src_w = params->src_w << 16;
239+
240+
plane_state->crtc_x = 0;
241+
plane_state->crtc_y = 0;
242+
plane_state->crtc_h = params->crtc_h;
243+
plane_state->crtc_w = params->crtc_w;
244+
245+
if (params->forced_alpha)
246+
plane_state->alpha = 128;
247+
248+
ret = drm_atomic_check_only(state);
249+
KUNIT_ASSERT_EQ(test, ret, 0);
250+
251+
KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm.size, params->expected_lbm_size);
252+
253+
for (i = 0; i < 2; i++) {
254+
KUNIT_EXPECT_EQ(test,
255+
vc4_plane_state->x_scaling[i],
256+
params->expected_x_scaling[i]);
257+
KUNIT_EXPECT_EQ(test,
258+
vc4_plane_state->y_scaling[i],
259+
params->expected_y_scaling[i]);
260+
}
261+
262+
drm_framebuffer_put(fb);
263+
264+
for (i = 0; i < info->num_planes; i++)
265+
drm_mode_destroy_dumb(state->dev, fb_req.handles[i], priv->file);
266+
}
267+
268+
static struct kunit_case vc4_lbm_size_tests[] = {
269+
KUNIT_CASE_PARAM(drm_vc4_test_vc4_lbm_size,
270+
vc4_test_lbm_size_gen_params),
271+
{}
272+
};
273+
274+
static int vc4_lbm_size_test_init(struct kunit *test)
275+
{
276+
struct drm_modeset_acquire_ctx *ctx;
277+
struct vc4_lbm_size_priv *priv;
278+
struct drm_device *drm;
279+
struct vc4_dev *vc4;
280+
281+
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
282+
KUNIT_ASSERT_NOT_NULL(test, priv);
283+
test->priv = priv;
284+
285+
vc4 = vc6_mock_device(test);
286+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
287+
priv->vc4 = vc4;
288+
289+
priv->file = drm_file_alloc(priv->vc4->base.primary);
290+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->file);
291+
292+
ctx = drm_kunit_helper_acquire_ctx_alloc(test);
293+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
294+
295+
drm = &vc4->base;
296+
priv->state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
297+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->state);
298+
299+
return 0;
300+
}
301+
302+
static struct kunit_suite vc4_lbm_size_test_suite = {
303+
.name = "vc4-lbm-size",
304+
.init = vc4_lbm_size_test_init,
305+
.test_cases = vc4_lbm_size_tests,
306+
};
307+
308+
kunit_test_suite(vc4_lbm_size_test_suite);

drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,6 @@ static struct kunit_case vc6_pv_muxing_tests[] = {
853853
static struct kunit_suite vc6_pv_muxing_test_suite = {
854854
.name = "vc6-pv-muxing-combinations",
855855
.init = vc4_pv_muxing_test_init,
856-
.exit = vc4_pv_muxing_test_exit,
857856
.test_cases = vc6_pv_muxing_tests,
858857
};
859858

0 commit comments

Comments
 (0)