xref: /third_party/libdrm/tests/tegra/vic40.c (revision d722e3fb)
1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright © 2018 NVIDIA Corporation
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci */
22d722e3fbSopenharmony_ci
23d722e3fbSopenharmony_ci#include <errno.h>
24d722e3fbSopenharmony_ci#include <string.h>
25d722e3fbSopenharmony_ci
26d722e3fbSopenharmony_ci#include "private.h"
27d722e3fbSopenharmony_ci#include "tegra.h"
28d722e3fbSopenharmony_ci#include "vic.h"
29d722e3fbSopenharmony_ci#include "vic40.h"
30d722e3fbSopenharmony_ci
31d722e3fbSopenharmony_cistruct vic40 {
32d722e3fbSopenharmony_ci    struct vic base;
33d722e3fbSopenharmony_ci
34d722e3fbSopenharmony_ci    struct {
35d722e3fbSopenharmony_ci        struct drm_tegra_mapping *map;
36d722e3fbSopenharmony_ci        struct drm_tegra_bo *bo;
37d722e3fbSopenharmony_ci    } config;
38d722e3fbSopenharmony_ci
39d722e3fbSopenharmony_ci    struct {
40d722e3fbSopenharmony_ci        struct drm_tegra_mapping *map;
41d722e3fbSopenharmony_ci        struct drm_tegra_bo *bo;
42d722e3fbSopenharmony_ci    } filter;
43d722e3fbSopenharmony_ci};
44d722e3fbSopenharmony_ci
45d722e3fbSopenharmony_cistatic int vic40_fill(struct vic *v, struct vic_image *output,
46d722e3fbSopenharmony_ci                      unsigned int left, unsigned int top,
47d722e3fbSopenharmony_ci                      unsigned int right, unsigned int bottom,
48d722e3fbSopenharmony_ci                      unsigned int alpha, unsigned int red,
49d722e3fbSopenharmony_ci                      unsigned int green, unsigned int blue)
50d722e3fbSopenharmony_ci{
51d722e3fbSopenharmony_ci    struct vic40 *vic = container_of(v, struct vic40, base);
52d722e3fbSopenharmony_ci    ConfigStruct *c;
53d722e3fbSopenharmony_ci    int err;
54d722e3fbSopenharmony_ci
55d722e3fbSopenharmony_ci    err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
56d722e3fbSopenharmony_ci    if (err < 0) {
57d722e3fbSopenharmony_ci        fprintf(stderr, "failed to map configuration structure: %s\n",
58d722e3fbSopenharmony_ci                strerror(-err));
59d722e3fbSopenharmony_ci        return err;
60d722e3fbSopenharmony_ci    }
61d722e3fbSopenharmony_ci
62d722e3fbSopenharmony_ci    memset(c, 0, sizeof(*c));
63d722e3fbSopenharmony_ci
64d722e3fbSopenharmony_ci    c->outputConfig.TargetRectTop = top;
65d722e3fbSopenharmony_ci    c->outputConfig.TargetRectLeft = left;
66d722e3fbSopenharmony_ci    c->outputConfig.TargetRectRight = right;
67d722e3fbSopenharmony_ci    c->outputConfig.TargetRectBottom = bottom;
68d722e3fbSopenharmony_ci    c->outputConfig.BackgroundAlpha = alpha;
69d722e3fbSopenharmony_ci    c->outputConfig.BackgroundR = red;
70d722e3fbSopenharmony_ci    c->outputConfig.BackgroundG = green;
71d722e3fbSopenharmony_ci    c->outputConfig.BackgroundB = blue;
72d722e3fbSopenharmony_ci
73d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutPixelFormat = output->format;
74d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutBlkKind = output->kind;
75d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutBlkHeight = 0;
76d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
77d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
78d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
79d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
80d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutChromaWidth = 16383;
81d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutChromaHeight = 16383;
82d722e3fbSopenharmony_ci
83d722e3fbSopenharmony_ci    drm_tegra_bo_unmap(vic->config.bo);
84d722e3fbSopenharmony_ci
85d722e3fbSopenharmony_ci    return 0;
86d722e3fbSopenharmony_ci}
87d722e3fbSopenharmony_ci
88d722e3fbSopenharmony_cistatic int vic40_blit(struct vic *v, struct vic_image *output,
89d722e3fbSopenharmony_ci                      struct vic_image *input)
90d722e3fbSopenharmony_ci{
91d722e3fbSopenharmony_ci    struct vic40 *vic = container_of(v, struct vic40, base);
92d722e3fbSopenharmony_ci    SlotSurfaceConfig *surface;
93d722e3fbSopenharmony_ci    SlotConfig *slot;
94d722e3fbSopenharmony_ci    ConfigStruct *c;
95d722e3fbSopenharmony_ci    int err;
96d722e3fbSopenharmony_ci
97d722e3fbSopenharmony_ci    err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
98d722e3fbSopenharmony_ci    if (err < 0) {
99d722e3fbSopenharmony_ci        fprintf(stderr, "failed to map configuration structure: %s\n",
100d722e3fbSopenharmony_ci                strerror(-err));
101d722e3fbSopenharmony_ci        return err;
102d722e3fbSopenharmony_ci    }
103d722e3fbSopenharmony_ci
104d722e3fbSopenharmony_ci    memset(c, 0, sizeof(*c));
105d722e3fbSopenharmony_ci
106d722e3fbSopenharmony_ci    c->outputConfig.TargetRectTop = 0;
107d722e3fbSopenharmony_ci    c->outputConfig.TargetRectLeft = 0;
108d722e3fbSopenharmony_ci    c->outputConfig.TargetRectRight = output->width - 1;
109d722e3fbSopenharmony_ci    c->outputConfig.TargetRectBottom = output->height - 1;
110d722e3fbSopenharmony_ci    c->outputConfig.BackgroundAlpha = 1023;
111d722e3fbSopenharmony_ci    c->outputConfig.BackgroundR = 1023;
112d722e3fbSopenharmony_ci    c->outputConfig.BackgroundG = 1023;
113d722e3fbSopenharmony_ci    c->outputConfig.BackgroundB = 1023;
114d722e3fbSopenharmony_ci
115d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutPixelFormat = output->format;
116d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutBlkKind = output->kind;
117d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutBlkHeight = 0;
118d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
119d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
120d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
121d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
122d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutChromaWidth = 16383;
123d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutChromaHeight = 16383;
124d722e3fbSopenharmony_ci
125d722e3fbSopenharmony_ci    slot = &c->slotStruct[0].slotConfig;
126d722e3fbSopenharmony_ci    slot->SlotEnable = 1;
127d722e3fbSopenharmony_ci    slot->CurrentFieldEnable = 1;
128d722e3fbSopenharmony_ci    slot->PlanarAlpha = 1023;
129d722e3fbSopenharmony_ci    slot->ConstantAlpha = 1;
130d722e3fbSopenharmony_ci    slot->SourceRectLeft = 0 << 16;
131d722e3fbSopenharmony_ci    slot->SourceRectRight = (input->width - 1) << 16;
132d722e3fbSopenharmony_ci    slot->SourceRectTop = 0 << 16;
133d722e3fbSopenharmony_ci    slot->SourceRectBottom = (input->height - 1) << 16;
134d722e3fbSopenharmony_ci    slot->DestRectLeft = 0;
135d722e3fbSopenharmony_ci    slot->DestRectRight = output->width - 1;
136d722e3fbSopenharmony_ci    slot->DestRectTop = 0;
137d722e3fbSopenharmony_ci    slot->DestRectBottom = output->height - 1;
138d722e3fbSopenharmony_ci    slot->SoftClampHigh = 1023;
139d722e3fbSopenharmony_ci
140d722e3fbSopenharmony_ci    surface = &c->slotStruct[0].slotSurfaceConfig;
141d722e3fbSopenharmony_ci    surface->SlotPixelFormat = input->format;
142d722e3fbSopenharmony_ci    surface->SlotBlkKind = input->kind;
143d722e3fbSopenharmony_ci    surface->SlotBlkHeight = 0; /* XXX */
144d722e3fbSopenharmony_ci    surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
145d722e3fbSopenharmony_ci    surface->SlotSurfaceWidth = input->width - 1;
146d722e3fbSopenharmony_ci    surface->SlotSurfaceHeight = input->height - 1;
147d722e3fbSopenharmony_ci    surface->SlotLumaWidth = input->stride - 1;
148d722e3fbSopenharmony_ci    surface->SlotLumaHeight = input->height - 1;
149d722e3fbSopenharmony_ci    surface->SlotChromaWidth = 16383;
150d722e3fbSopenharmony_ci    surface->SlotChromaHeight = 16383;
151d722e3fbSopenharmony_ci
152d722e3fbSopenharmony_ci    drm_tegra_bo_unmap(vic->config.bo);
153d722e3fbSopenharmony_ci
154d722e3fbSopenharmony_ci    return 0;
155d722e3fbSopenharmony_ci}
156d722e3fbSopenharmony_ci
157d722e3fbSopenharmony_cistatic int vic40_flip(struct vic *v, struct vic_image *output,
158d722e3fbSopenharmony_ci                      struct vic_image *input)
159d722e3fbSopenharmony_ci{
160d722e3fbSopenharmony_ci    struct vic40 *vic = container_of(v, struct vic40, base);
161d722e3fbSopenharmony_ci    SlotSurfaceConfig *surface;
162d722e3fbSopenharmony_ci    SlotConfig *slot;
163d722e3fbSopenharmony_ci    ConfigStruct *c;
164d722e3fbSopenharmony_ci    int err;
165d722e3fbSopenharmony_ci
166d722e3fbSopenharmony_ci    err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
167d722e3fbSopenharmony_ci    if (err < 0) {
168d722e3fbSopenharmony_ci        fprintf(stderr, "failed to map configuration structure: %s\n",
169d722e3fbSopenharmony_ci                strerror(-err));
170d722e3fbSopenharmony_ci        return err;
171d722e3fbSopenharmony_ci    }
172d722e3fbSopenharmony_ci
173d722e3fbSopenharmony_ci    memset(c, 0, sizeof(*c));
174d722e3fbSopenharmony_ci
175d722e3fbSopenharmony_ci    c->outputConfig.TargetRectTop = 0;
176d722e3fbSopenharmony_ci    c->outputConfig.TargetRectLeft = 0;
177d722e3fbSopenharmony_ci    c->outputConfig.TargetRectRight = output->width - 1;
178d722e3fbSopenharmony_ci    c->outputConfig.TargetRectBottom = output->height - 1;
179d722e3fbSopenharmony_ci    c->outputConfig.BackgroundAlpha = 1023;
180d722e3fbSopenharmony_ci    c->outputConfig.BackgroundR = 1023;
181d722e3fbSopenharmony_ci    c->outputConfig.BackgroundG = 1023;
182d722e3fbSopenharmony_ci    c->outputConfig.BackgroundB = 1023;
183d722e3fbSopenharmony_ci    c->outputConfig.OutputFlipY = 1;
184d722e3fbSopenharmony_ci
185d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutPixelFormat = output->format;
186d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutBlkKind = output->kind;
187d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutBlkHeight = 0;
188d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
189d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
190d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
191d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
192d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutChromaWidth = 16383;
193d722e3fbSopenharmony_ci    c->outputSurfaceConfig.OutChromaHeight = 16383;
194d722e3fbSopenharmony_ci
195d722e3fbSopenharmony_ci    slot = &c->slotStruct[0].slotConfig;
196d722e3fbSopenharmony_ci    slot->SlotEnable = 1;
197d722e3fbSopenharmony_ci    slot->CurrentFieldEnable = 1;
198d722e3fbSopenharmony_ci    slot->PlanarAlpha = 1023;
199d722e3fbSopenharmony_ci    slot->ConstantAlpha = 1;
200d722e3fbSopenharmony_ci    slot->SourceRectLeft = 0 << 16;
201d722e3fbSopenharmony_ci    slot->SourceRectRight = (input->width - 1) << 16;
202d722e3fbSopenharmony_ci    slot->SourceRectTop = 0 << 16;
203d722e3fbSopenharmony_ci    slot->SourceRectBottom = (input->height - 1) << 16;
204d722e3fbSopenharmony_ci    slot->DestRectLeft = 0;
205d722e3fbSopenharmony_ci    slot->DestRectRight = output->width - 1;
206d722e3fbSopenharmony_ci    slot->DestRectTop = 0;
207d722e3fbSopenharmony_ci    slot->DestRectBottom = output->height - 1;
208d722e3fbSopenharmony_ci    slot->SoftClampHigh = 1023;
209d722e3fbSopenharmony_ci
210d722e3fbSopenharmony_ci    surface = &c->slotStruct[0].slotSurfaceConfig;
211d722e3fbSopenharmony_ci    surface->SlotPixelFormat = input->format;
212d722e3fbSopenharmony_ci    surface->SlotBlkKind = input->kind;
213d722e3fbSopenharmony_ci    surface->SlotBlkHeight = 0; /* XXX */
214d722e3fbSopenharmony_ci    surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
215d722e3fbSopenharmony_ci    surface->SlotSurfaceWidth = input->width - 1;
216d722e3fbSopenharmony_ci    surface->SlotSurfaceHeight = input->height - 1;
217d722e3fbSopenharmony_ci    surface->SlotLumaWidth = input->stride - 1;
218d722e3fbSopenharmony_ci    surface->SlotLumaHeight = input->height - 1;
219d722e3fbSopenharmony_ci    surface->SlotChromaWidth = 16383;
220d722e3fbSopenharmony_ci    surface->SlotChromaHeight = 16383;
221d722e3fbSopenharmony_ci
222d722e3fbSopenharmony_ci    drm_tegra_bo_unmap(vic->config.bo);
223d722e3fbSopenharmony_ci
224d722e3fbSopenharmony_ci    return 0;
225d722e3fbSopenharmony_ci}
226d722e3fbSopenharmony_ci
227d722e3fbSopenharmony_cistatic int vic40_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
228d722e3fbSopenharmony_ci                         uint32_t **ptrp, struct vic_image *output,
229d722e3fbSopenharmony_ci                         struct vic_image **inputs, unsigned int num_inputs)
230d722e3fbSopenharmony_ci{
231d722e3fbSopenharmony_ci    struct vic40 *vic = container_of(v, struct vic40, base);
232d722e3fbSopenharmony_ci    unsigned int i;
233d722e3fbSopenharmony_ci
234d722e3fbSopenharmony_ci    if (num_inputs > 1)
235d722e3fbSopenharmony_ci        return -EINVAL;
236d722e3fbSopenharmony_ci
237d722e3fbSopenharmony_ci    VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
238d722e3fbSopenharmony_ci    VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
239d722e3fbSopenharmony_ci    VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
240d722e3fbSopenharmony_ci    VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
241d722e3fbSopenharmony_ci
242d722e3fbSopenharmony_ci    for (i = 0; i < num_inputs; i++)
243d722e3fbSopenharmony_ci        VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0);
244d722e3fbSopenharmony_ci
245d722e3fbSopenharmony_ci    VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
246d722e3fbSopenharmony_ci
247d722e3fbSopenharmony_ci    return 0;
248d722e3fbSopenharmony_ci}
249d722e3fbSopenharmony_ci
250d722e3fbSopenharmony_cistatic void vic40_free(struct vic *v)
251d722e3fbSopenharmony_ci{
252d722e3fbSopenharmony_ci    struct vic40 *vic = container_of(v, struct vic40, base);
253d722e3fbSopenharmony_ci
254d722e3fbSopenharmony_ci    drm_tegra_channel_unmap(vic->filter.map);
255d722e3fbSopenharmony_ci    drm_tegra_bo_unref(vic->filter.bo);
256d722e3fbSopenharmony_ci
257d722e3fbSopenharmony_ci    drm_tegra_channel_unmap(vic->config.map);
258d722e3fbSopenharmony_ci    drm_tegra_bo_unref(vic->config.bo);
259d722e3fbSopenharmony_ci
260d722e3fbSopenharmony_ci    drm_tegra_syncpoint_free(v->syncpt);
261d722e3fbSopenharmony_ci
262d722e3fbSopenharmony_ci    free(vic);
263d722e3fbSopenharmony_ci}
264d722e3fbSopenharmony_ci
265d722e3fbSopenharmony_cistatic const struct vic_ops vic40_ops = {
266d722e3fbSopenharmony_ci    .fill = vic40_fill,
267d722e3fbSopenharmony_ci    .blit = vic40_blit,
268d722e3fbSopenharmony_ci    .flip = vic40_flip,
269d722e3fbSopenharmony_ci    .execute = vic40_execute,
270d722e3fbSopenharmony_ci    .free = vic40_free,
271d722e3fbSopenharmony_ci};
272d722e3fbSopenharmony_ci
273d722e3fbSopenharmony_ciint vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
274d722e3fbSopenharmony_ci              struct vic **vicp)
275d722e3fbSopenharmony_ci{
276d722e3fbSopenharmony_ci    struct vic40 *vic;
277d722e3fbSopenharmony_ci    void *ptr;
278d722e3fbSopenharmony_ci    int err;
279d722e3fbSopenharmony_ci
280d722e3fbSopenharmony_ci    vic = calloc(1, sizeof(*vic));
281d722e3fbSopenharmony_ci    if (!vic)
282d722e3fbSopenharmony_ci        return -ENOMEM;
283d722e3fbSopenharmony_ci
284d722e3fbSopenharmony_ci    vic->base.drm = drm;
285d722e3fbSopenharmony_ci    vic->base.channel = channel;
286d722e3fbSopenharmony_ci    vic->base.ops = &vic40_ops;
287d722e3fbSopenharmony_ci    vic->base.version = 0x21;
288d722e3fbSopenharmony_ci
289d722e3fbSopenharmony_ci    err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
290d722e3fbSopenharmony_ci    if (err < 0) {
291d722e3fbSopenharmony_ci        fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
292d722e3fbSopenharmony_ci        return err;
293d722e3fbSopenharmony_ci    }
294d722e3fbSopenharmony_ci
295d722e3fbSopenharmony_ci    err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
296d722e3fbSopenharmony_ci    if (err < 0) {
297d722e3fbSopenharmony_ci        fprintf(stderr, "failed to allocate configuration structurer: %s\n",
298d722e3fbSopenharmony_ci                strerror(-err));
299d722e3fbSopenharmony_ci        return err;
300d722e3fbSopenharmony_ci    }
301d722e3fbSopenharmony_ci
302d722e3fbSopenharmony_ci    err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
303d722e3fbSopenharmony_ci                                &vic->config.map);
304d722e3fbSopenharmony_ci    if (err < 0) {
305d722e3fbSopenharmony_ci        fprintf(stderr, "failed to map configuration structure: %s\n",
306d722e3fbSopenharmony_ci                strerror(-err));
307d722e3fbSopenharmony_ci        return err;
308d722e3fbSopenharmony_ci    }
309d722e3fbSopenharmony_ci
310d722e3fbSopenharmony_ci    err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
311d722e3fbSopenharmony_ci    if (err < 0) {
312d722e3fbSopenharmony_ci        fprintf(stderr, "failed to allocate filter buffer: %s\n",
313d722e3fbSopenharmony_ci                strerror(-err));
314d722e3fbSopenharmony_ci        return err;
315d722e3fbSopenharmony_ci    }
316d722e3fbSopenharmony_ci
317d722e3fbSopenharmony_ci    err = drm_tegra_bo_map(vic->filter.bo, &ptr);
318d722e3fbSopenharmony_ci    if (err < 0) {
319d722e3fbSopenharmony_ci        fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
320d722e3fbSopenharmony_ci        return err;
321d722e3fbSopenharmony_ci    }
322d722e3fbSopenharmony_ci
323d722e3fbSopenharmony_ci    memset(ptr, 0, 16384);
324d722e3fbSopenharmony_ci    drm_tegra_bo_unmap(vic->filter.bo);
325d722e3fbSopenharmony_ci
326d722e3fbSopenharmony_ci    err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
327d722e3fbSopenharmony_ci                                &vic->filter.map);
328d722e3fbSopenharmony_ci    if (err < 0) {
329d722e3fbSopenharmony_ci        fprintf(stderr, "failed to map filter buffer: %s\n",
330d722e3fbSopenharmony_ci                strerror(-err));
331d722e3fbSopenharmony_ci        return err;
332d722e3fbSopenharmony_ci    }
333d722e3fbSopenharmony_ci
334d722e3fbSopenharmony_ci    if (vicp)
335d722e3fbSopenharmony_ci        *vicp = &vic->base;
336d722e3fbSopenharmony_ci
337d722e3fbSopenharmony_ci    return 0;
338d722e3fbSopenharmony_ci}
339