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 "vic30.h"
30
31 struct vic30 {
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 struct {
45 struct drm_tegra_mapping *map;
46 struct drm_tegra_bo *bo;
47 } hist;
48 };
49
vic30_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)50 static int vic30_fill(struct vic *v, struct vic_image *output,
51 unsigned int left, unsigned int top,
52 unsigned int right, unsigned int bottom,
53 unsigned int alpha, unsigned int red,
54 unsigned int green, unsigned int blue)
55 {
56 struct vic30 *vic = container_of(v, struct vic30, base);
57 ConfigStruct *c;
58 int err;
59
60 err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
61 if (err < 0) {
62 fprintf(stderr, "failed to map configuration structure: %s\n",
63 strerror(-err));
64 return err;
65 }
66
67 memset(c, 0, sizeof(*c));
68
69 c->surfaceList0Struct.TargetRectLeft = left;
70 c->surfaceList0Struct.TargetRectTop = top;
71 c->surfaceList0Struct.TargetRectRight = right;
72 c->surfaceList0Struct.TargetRectBottom = bottom;
73
74 c->blending0Struct.PixelFormat = output->format;
75 c->blending0Struct.BackgroundAlpha = alpha;
76 c->blending0Struct.BackgroundR = red;
77 c->blending0Struct.BackgroundG = green;
78 c->blending0Struct.BackgroundB = blue;
79 c->blending0Struct.LumaWidth = output->stride - 1;
80 c->blending0Struct.LumaHeight = output->height - 1;
81 c->blending0Struct.ChromaWidth = 16383;
82 c->blending0Struct.ChromaWidth = 16383;
83 c->blending0Struct.TargetRectLeft = left;
84 c->blending0Struct.TargetRectTop = top;
85 c->blending0Struct.TargetRectRight = right;
86 c->blending0Struct.TargetRectBottom = bottom;
87 c->blending0Struct.SurfaceWidth = output->width - 1;
88 c->blending0Struct.SurfaceHeight = output->height - 1;
89 c->blending0Struct.BlkKind = output->kind;
90 c->blending0Struct.BlkHeight = 0;
91
92 c->fetchControl0Struct.TargetRectLeft = left;
93 c->fetchControl0Struct.TargetRectTop = top;
94 c->fetchControl0Struct.TargetRectRight = right;
95 c->fetchControl0Struct.TargetRectBottom = bottom;
96
97 drm_tegra_bo_unmap(vic->config.bo);
98
99 return 0;
100 }
101
vic30_blit(struct vic * v,struct vic_image * output,struct vic_image * input)102 static int vic30_blit(struct vic *v, struct vic_image *output,
103 struct vic_image *input)
104 {
105 struct vic30 *vic = container_of(v, struct vic30, base);
106 ColorConversionLumaAlphaStruct *ccla;
107 ColorConversionMatrixStruct *ccm;
108 ColorConversionClampStruct *ccc;
109 SurfaceListSurfaceStruct *s;
110 BlendingSurfaceStruct *b;
111 SurfaceCache0Struct *sc;
112 ConfigStruct *c;
113 int err;
114
115 err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
116 if (err < 0) {
117 fprintf(stderr, "failed to map configuration structure: %s\n",
118 strerror(-err));
119 return err;
120 }
121
122 memset(c, 0, sizeof(*c));
123
124 c->surfaceList0Struct.TargetRectLeft = 0;
125 c->surfaceList0Struct.TargetRectTop = 0;
126 c->surfaceList0Struct.TargetRectRight = output->width - 1;
127 c->surfaceList0Struct.TargetRectBottom = output->height - 1;
128
129 c->blending0Struct.PixelFormat = output->format;
130 c->blending0Struct.BackgroundAlpha = 0;
131 c->blending0Struct.BackgroundR = 0;
132 c->blending0Struct.BackgroundG = 0;
133 c->blending0Struct.BackgroundB = 0;
134 c->blending0Struct.LumaWidth = output->stride - 1;
135 c->blending0Struct.LumaHeight = output->height - 1;
136 c->blending0Struct.ChromaWidth = 16383;
137 c->blending0Struct.ChromaWidth = 16383;
138 c->blending0Struct.TargetRectLeft = 0;
139 c->blending0Struct.TargetRectTop = 0;
140 c->blending0Struct.TargetRectRight = output->width - 1;
141 c->blending0Struct.TargetRectBottom = output->height - 1;
142 c->blending0Struct.SurfaceWidth = output->width - 1;
143 c->blending0Struct.SurfaceHeight = output->height - 1;
144 c->blending0Struct.BlkKind = output->kind;
145 c->blending0Struct.BlkHeight = 0;
146
147 c->fetchControl0Struct.TargetRectLeft = 0;
148 c->fetchControl0Struct.TargetRectTop = 0;
149 c->fetchControl0Struct.TargetRectRight = output->width - 1;
150 c->fetchControl0Struct.TargetRectBottom = output->height - 1;
151
152 /* setup fetch parameters for slot 0 */
153 c->fetchControl0Struct.Enable0 = 0x1;
154 c->fetchControl0Struct.Iir0 = 0x300;
155
156 /* setup cache parameters for slot 0 */
157 sc = &c->surfaceCache0Struct;
158 sc->PixelFormat0 = input->format;
159
160 /* setup surface configuration for slot 0 */
161 s = &c->surfaceListSurfaceStruct[0];
162 s->Enable = 1;
163 s->FrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
164 s->PixelFormat = input->format;
165 s->SurfaceWidth = input->width - 1;
166 s->SurfaceHeight = input->height - 1;
167 s->LumaWidth = input->stride - 1;
168 s->LumaHeight = input->height - 1;
169 s->ChromaWidth = 16383;
170 s->ChromaHeight = 16383;
171 s->CacheWidth = VIC_CACHE_WIDTH_256Bx1; //VIC_CACHE_WIDTH_16Bx16;
172 s->BlkKind = input->kind;
173 s->BlkHeight = 0;
174 s->DestRectLeft = 0;
175 s->DestRectTop = 0;
176 s->DestRectRight = output->width - 1;
177 s->DestRectBottom = output->height - 1;
178 s->SourceRectLeft = 0 << 16;
179 s->SourceRectTop = 0 << 16;
180 s->SourceRectRight = (input->width - 1) << 16;
181 s->SourceRectBottom = (input->height - 1) << 16;
182
183 /* setup color conversion for slot 0 */
184 ccla = &c->colorConversionLumaAlphaStruct[0];
185 ccla->PlanarAlpha = 1023;
186 ccla->ConstantAlpha = 0;
187
188 ccm = &c->colorConversionMatrixStruct[0];
189 ccm->c00 = 1023;
190 ccm->c11 = 1023;
191 ccm->c22 = 1023;
192
193 ccc = &c->colorConversionClampStruct[0];
194 ccc->low = 0;
195 ccc->high = 1023;
196
197 /* setup blending for slot 0 */
198 b = &c->blendingSurfaceStruct[0];
199 b->AlphaK1 = 1023;
200 b->SrcFactCMatchSelect = VIC_BLEND_SRCFACTC_K1;
201 b->SrcFactAMatchSelect = VIC_BLEND_SRCFACTA_K1;
202 b->DstFactCMatchSelect = VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC;
203 b->DstFactAMatchSelect = VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC;
204
205 drm_tegra_bo_unmap(vic->config.bo);
206
207 return 0;
208 }
209
vic30_flip(struct vic * v,struct vic_image * output,struct vic_image * input)210 static int vic30_flip(struct vic *v, struct vic_image *output,
211 struct vic_image *input)
212 {
213 struct vic30 *vic = container_of(v, struct vic30, base);
214 ColorConversionLumaAlphaStruct *ccla;
215 ColorConversionMatrixStruct *ccm;
216 ColorConversionClampStruct *ccc;
217 SurfaceListSurfaceStruct *s;
218 BlendingSurfaceStruct *b;
219 SurfaceCache0Struct *sc;
220 ConfigStruct *c;
221 int err;
222
223 err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
224 if (err < 0) {
225 fprintf(stderr, "failed to map configuration structure: %s\n",
226 strerror(-err));
227 return err;
228 }
229
230 memset(c, 0, sizeof(*c));
231
232 c->surfaceList0Struct.TargetRectLeft = 0;
233 c->surfaceList0Struct.TargetRectTop = 0;
234 c->surfaceList0Struct.TargetRectRight = output->width - 1;
235 c->surfaceList0Struct.TargetRectBottom = output->height - 1;
236
237 c->blending0Struct.PixelFormat = output->format;
238 c->blending0Struct.BackgroundAlpha = 0;
239 c->blending0Struct.BackgroundR = 0;
240 c->blending0Struct.BackgroundG = 0;
241 c->blending0Struct.BackgroundB = 0;
242 c->blending0Struct.LumaWidth = output->stride - 1;
243 c->blending0Struct.LumaHeight = output->height - 1;
244 c->blending0Struct.ChromaWidth = 16383;
245 c->blending0Struct.ChromaWidth = 16383;
246 c->blending0Struct.TargetRectLeft = 0;
247 c->blending0Struct.TargetRectTop = 0;
248 c->blending0Struct.TargetRectRight = output->width - 1;
249 c->blending0Struct.TargetRectBottom = output->height - 1;
250 c->blending0Struct.SurfaceWidth = output->width - 1;
251 c->blending0Struct.SurfaceHeight = output->height - 1;
252 c->blending0Struct.BlkKind = output->kind;
253 c->blending0Struct.BlkHeight = 0;
254 c->blending0Struct.OutputFlipY = 1;
255
256 c->fetchControl0Struct.TargetRectLeft = 0;
257 c->fetchControl0Struct.TargetRectTop = 0;
258 c->fetchControl0Struct.TargetRectRight = output->width - 1;
259 c->fetchControl0Struct.TargetRectBottom = output->height - 1;
260
261 /* setup fetch parameters for slot 0 */
262 c->fetchControl0Struct.Enable0 = 0x1;
263 c->fetchControl0Struct.Iir0 = 0x300;
264
265 /* setup cache parameters for slot 0 */
266 sc = &c->surfaceCache0Struct;
267 sc->PixelFormat0 = input->format;
268
269 /* setup surface configuration for slot 0 */
270 s = &c->surfaceListSurfaceStruct[0];
271 s->Enable = 1;
272 s->FrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
273 s->PixelFormat = input->format;
274 s->SurfaceWidth = input->width - 1;
275 s->SurfaceHeight = input->height - 1;
276 s->LumaWidth = input->stride - 1;
277 s->LumaHeight = input->height - 1;
278 s->ChromaWidth = 16383;
279 s->ChromaHeight = 16383;
280 s->CacheWidth = VIC_CACHE_WIDTH_256Bx1;
281 s->BlkKind = input->kind;
282 s->BlkHeight = 0;
283 s->DestRectLeft = 0;
284 s->DestRectTop = 0;
285 s->DestRectRight = output->width - 1;
286 s->DestRectBottom = output->height - 1;
287 s->SourceRectLeft = 0 << 16;
288 s->SourceRectTop = 0 << 16;
289 s->SourceRectRight = (input->width - 1) << 16;
290 s->SourceRectBottom = (input->height - 1) << 16;
291
292 /* setup color conversion for slot 0 */
293 ccla = &c->colorConversionLumaAlphaStruct[0];
294 ccla->PlanarAlpha = 1023;
295 ccla->ConstantAlpha = 0;
296
297 ccm = &c->colorConversionMatrixStruct[0];
298 ccm->c00 = 1023;
299 ccm->c11 = 1023;
300 ccm->c22 = 1023;
301
302 ccc = &c->colorConversionClampStruct[0];
303 ccc->low = 0;
304 ccc->high = 1023;
305
306 /* setup blending for slot 0 */
307 b = &c->blendingSurfaceStruct[0];
308 b->AlphaK1 = 1023;
309 b->SrcFactCMatchSelect = VIC_BLEND_SRCFACTC_K1;
310 b->SrcFactAMatchSelect = VIC_BLEND_SRCFACTA_K1;
311 b->DstFactCMatchSelect = VIC_BLEND_DSTFACTC_NEG_K1_TIMES_SRC;
312 b->DstFactAMatchSelect = VIC_BLEND_DSTFACTA_NEG_K1_TIMES_SRC;
313
314 drm_tegra_bo_unmap(vic->config.bo);
315
316 return 0;
317 }
318
vic30_execute(struct vic * v,struct drm_tegra_pushbuf * pushbuf,uint32_t ** ptrp,struct vic_image * output,struct vic_image ** inputs,unsigned int num_inputs)319 static int vic30_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
320 uint32_t **ptrp, struct vic_image *output,
321 struct vic_image **inputs, unsigned int num_inputs)
322 {
323 struct vic30 *vic = container_of(v, struct vic30, base);
324 unsigned int i;
325
326 if (num_inputs > 1)
327 return -EINVAL;
328
329 VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
330 VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
331 VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
332 VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_HIST_OFFSET, vic->hist.map, 0, 0);
333 VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
334
335 for (i = 0; i < num_inputs; i++)
336 VIC_PUSH_BUFFER(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0);
337
338 VIC_PUSH_METHOD(pushbuf, ptrp, NVA0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
339
340 return 0;
341 }
342
vic30_free(struct vic * v)343 static void vic30_free(struct vic *v)
344 {
345 struct vic30 *vic = container_of(v, struct vic30, base);
346
347 drm_tegra_channel_unmap(vic->hist.map);
348 drm_tegra_bo_unref(vic->hist.bo);
349
350 drm_tegra_channel_unmap(vic->filter.map);
351 drm_tegra_bo_unref(vic->filter.bo);
352
353 drm_tegra_channel_unmap(vic->config.map);
354 drm_tegra_bo_unref(vic->config.bo);
355
356 drm_tegra_syncpoint_free(v->syncpt);
357
358 free(vic);
359 }
360
361 static const struct vic_ops vic30_ops = {
362 .fill = vic30_fill,
363 .blit = vic30_blit,
364 .flip = vic30_flip,
365 .execute = vic30_execute,
366 .free = vic30_free,
367 };
368
vic30_new(struct drm_tegra * drm,struct drm_tegra_channel * channel,struct vic ** vicp)369 int vic30_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
370 struct vic **vicp)
371 {
372 struct vic30 *vic;
373 void *ptr;
374 int err;
375
376 vic = calloc(1, sizeof(*vic));
377 if (!vic)
378 return -ENOMEM;
379
380 vic->base.drm = drm;
381 vic->base.channel = channel;
382 vic->base.ops = &vic30_ops;
383 vic->base.version = 0x40;
384
385 err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
386 if (err < 0) {
387 fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
388 return err;
389 }
390
391 err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
392 if (err < 0) {
393 fprintf(stderr, "failed to allocate configuration structure: %s\n",
394 strerror(-err));
395 return err;
396 }
397
398 err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
399 &vic->config.map);
400 if (err < 0) {
401 fprintf(stderr, "failed to map configuration structure: %s\n",
402 strerror(-err));
403 return err;
404 }
405
406 err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
407 if (err < 0) {
408 fprintf(stderr, "failed to allocate filter buffer: %s\n",
409 strerror(-err));
410 return err;
411 }
412
413 err = drm_tegra_bo_map(vic->filter.bo, &ptr);
414 if (err < 0) {
415 fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
416 return err;
417 }
418
419 memset(ptr, 0, 16384);
420 drm_tegra_bo_unmap(vic->filter.bo);
421
422 err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
423 &vic->filter.map);
424 if (err < 0) {
425 fprintf(stderr, "failed to map filter buffer: %s\n",
426 strerror(-err));
427 return err;
428 }
429
430 err = drm_tegra_bo_new(drm, 0, 4096, &vic->hist.bo);
431 if (err < 0) {
432 fprintf(stderr, "failed to allocate history buffer: %s\n",
433 strerror(-err));
434 return err;
435 }
436
437 err = drm_tegra_bo_map(vic->hist.bo, &ptr);
438 if (err < 0) {
439 fprintf(stderr, "failed to map history buffer: %s\n", strerror(-err));
440 return err;
441 }
442
443 memset(ptr, 0, 4096);
444 drm_tegra_bo_unmap(vic->hist.bo);
445
446 err = drm_tegra_channel_map(channel, vic->hist.bo, DRM_TEGRA_CHANNEL_MAP_READ_WRITE,
447 &vic->hist.map);
448 if (err < 0) {
449 fprintf(stderr, "failed to map histogram buffer: %s\n",
450 strerror(-err));
451 return err;
452 }
453
454 if (vicp)
455 *vicp = &vic->base;
456
457 return 0;
458 }
459