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 "vic42.h" 30 31 struct vic42 { 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 vic42_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 vic42 *vic = container_of(v, struct vic42, 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 vic42_blit(struct vic *v, struct vic_image *output, 89 struct vic_image *input) 90 { 91 struct vic42 *vic = container_of(v, struct vic42, 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 vic42_flip(struct vic *v, struct vic_image *output, 158 struct vic_image *input) 159 { 160 struct vic42 *vic = container_of(v, struct vic42, 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 vic42_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 vic42 *vic = container_of(v, struct vic42, base); 232 unsigned int i; 233 234 if (num_inputs > 1) 235 return -EINVAL; 236 237 VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1); 238 VIC_PUSH_METHOD(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16); 239 VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0); 240 VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_FILTER_STRUCT_OFFSET, vic->filter.map, 0, 0); 241 VIC_PUSH_BUFFER(pushbuf, ptrp, NVC5B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0); 242 243 for (i = 0; i < num_inputs; i++) { 244 uint32_t method = NVC5B6_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, NVC5B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8); 250 251 return 0; 252 } 253 254 static void vic42_free(struct vic *v) 255 { 256 struct vic42 *vic = container_of(v, struct vic42, 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 vic42_ops = { 270 .fill = vic42_fill, 271 .blit = vic42_blit, 272 .flip = vic42_flip, 273 .execute = vic42_execute, 274 .free = vic42_free, 275 }; 276 277 int vic42_new(struct drm_tegra *drm, struct drm_tegra_channel *channel, 278 struct vic **vicp) 279 { 280 struct vic42 *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 = &vic42_ops; 291 vic->base.version = 0x19; 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