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
vic41_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 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
vic41_blit(struct vic * v,struct vic_image * output,struct vic_image * input)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
vic41_flip(struct vic * v,struct vic_image * output,struct vic_image * input)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
vic41_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 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
vic41_free(struct vic * v)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
vic41_new(struct drm_tegra * drm,struct drm_tegra_channel * channel,struct vic ** vicp)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 }
343