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