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 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 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 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 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 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 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