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 31struct 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 50static 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 102static 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 210static 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 319static 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 343static 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 361static 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 369int 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