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 "vic40.h"
30
31 struct vic40 {
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
vic40_fill(struct vic * v,struct vic_image * output,unsigned int left,unsigned int top,unsigned int right,unsigned int bottom,unsigned int alpha,unsigned int red,unsigned int green,unsigned int blue)45 static int vic40_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 vic40 *vic = container_of(v, struct vic40, 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
vic40_blit(struct vic * v,struct vic_image * output,struct vic_image * input)88 static int vic40_blit(struct vic *v, struct vic_image *output,
89 struct vic_image *input)
90 {
91 struct vic40 *vic = container_of(v, struct vic40, 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 = 1023;
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 = 1023;
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
vic40_flip(struct vic * v,struct vic_image * output,struct vic_image * input)157 static int vic40_flip(struct vic *v, struct vic_image *output,
158 struct vic_image *input)
159 {
160 struct vic40 *vic = container_of(v, struct vic40, 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 = 1023;
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 = 1023;
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
vic40_execute(struct vic * v,struct drm_tegra_pushbuf * pushbuf,uint32_t ** ptrp,struct vic_image * output,struct vic_image ** inputs,unsigned int num_inputs)227 static int vic40_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 vic40 *vic = container_of(v, struct vic40, base);
232 unsigned int i;
233
234 if (num_inputs > 1)
235 return -EINVAL;
236
237 VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
238 VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
239 VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
240 VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
241
242 for (i = 0; i < num_inputs; i++)
243 VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0);
244
245 VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
246
247 return 0;
248 }
249
vic40_free(struct vic * v)250 static void vic40_free(struct vic *v)
251 {
252 struct vic40 *vic = container_of(v, struct vic40, base);
253
254 drm_tegra_channel_unmap(vic->filter.map);
255 drm_tegra_bo_unref(vic->filter.bo);
256
257 drm_tegra_channel_unmap(vic->config.map);
258 drm_tegra_bo_unref(vic->config.bo);
259
260 drm_tegra_syncpoint_free(v->syncpt);
261
262 free(vic);
263 }
264
265 static const struct vic_ops vic40_ops = {
266 .fill = vic40_fill,
267 .blit = vic40_blit,
268 .flip = vic40_flip,
269 .execute = vic40_execute,
270 .free = vic40_free,
271 };
272
vic40_new(struct drm_tegra * drm,struct drm_tegra_channel * channel,struct vic ** vicp)273 int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
274 struct vic **vicp)
275 {
276 struct vic40 *vic;
277 void *ptr;
278 int err;
279
280 vic = calloc(1, sizeof(*vic));
281 if (!vic)
282 return -ENOMEM;
283
284 vic->base.drm = drm;
285 vic->base.channel = channel;
286 vic->base.ops = &vic40_ops;
287 vic->base.version = 0x21;
288
289 err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
290 if (err < 0) {
291 fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
292 return err;
293 }
294
295 err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
296 if (err < 0) {
297 fprintf(stderr, "failed to allocate configuration structurer: %s\n",
298 strerror(-err));
299 return err;
300 }
301
302 err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
303 &vic->config.map);
304 if (err < 0) {
305 fprintf(stderr, "failed to map configuration structure: %s\n",
306 strerror(-err));
307 return err;
308 }
309
310 err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
311 if (err < 0) {
312 fprintf(stderr, "failed to allocate filter buffer: %s\n",
313 strerror(-err));
314 return err;
315 }
316
317 err = drm_tegra_bo_map(vic->filter.bo, &ptr);
318 if (err < 0) {
319 fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
320 return err;
321 }
322
323 memset(ptr, 0, 16384);
324 drm_tegra_bo_unmap(vic->filter.bo);
325
326 err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
327 &vic->filter.map);
328 if (err < 0) {
329 fprintf(stderr, "failed to map filter buffer: %s\n",
330 strerror(-err));
331 return err;
332 }
333
334 if (vicp)
335 *vicp = &vic->base;
336
337 return 0;
338 }
339