1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Cedrus VPU driver 4 * 5 * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com> 6 * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com> 7 * Copyright (C) 2018 Bootlin 8 * 9 * Based on the vim2m driver, that is: 10 * 11 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. 12 * Pawel Osciak, <pawel@osciak.com> 13 * Marek Szyprowski, <m.szyprowski@samsung.com> 14 */ 15 16 #include <linux/pm_runtime.h> 17 18 #include <media/videobuf2-dma-contig.h> 19 #include <media/v4l2-device.h> 20 #include <media/v4l2-ioctl.h> 21 #include <media/v4l2-event.h> 22 #include <media/v4l2-mem2mem.h> 23 24 #include "cedrus.h" 25 #include "cedrus_video.h" 26 #include "cedrus_dec.h" 27 #include "cedrus_hw.h" 28 29 #define CEDRUS_DECODE_SRC BIT(0) 30 #define CEDRUS_DECODE_DST BIT(1) 31 32 #define CEDRUS_MIN_WIDTH 16U 33 #define CEDRUS_MIN_HEIGHT 16U 34 #define CEDRUS_MAX_WIDTH 4096U 35 #define CEDRUS_MAX_HEIGHT 2304U 36 37 static struct cedrus_format cedrus_formats[] = { 38 { 39 .pixelformat = V4L2_PIX_FMT_MPEG2_SLICE, 40 .directions = CEDRUS_DECODE_SRC, 41 .capabilities = CEDRUS_CAPABILITY_MPEG2_DEC, 42 }, 43 { 44 .pixelformat = V4L2_PIX_FMT_H264_SLICE, 45 .directions = CEDRUS_DECODE_SRC, 46 .capabilities = CEDRUS_CAPABILITY_H264_DEC, 47 }, 48 { 49 .pixelformat = V4L2_PIX_FMT_HEVC_SLICE, 50 .directions = CEDRUS_DECODE_SRC, 51 .capabilities = CEDRUS_CAPABILITY_H265_DEC, 52 }, 53 { 54 .pixelformat = V4L2_PIX_FMT_VP8_FRAME, 55 .directions = CEDRUS_DECODE_SRC, 56 .capabilities = CEDRUS_CAPABILITY_VP8_DEC, 57 }, 58 { 59 .pixelformat = V4L2_PIX_FMT_NV12, 60 .directions = CEDRUS_DECODE_DST, 61 .capabilities = CEDRUS_CAPABILITY_UNTILED, 62 }, 63 { 64 .pixelformat = V4L2_PIX_FMT_NV12_32L32, 65 .directions = CEDRUS_DECODE_DST, 66 }, 67 }; 68 69 #define CEDRUS_FORMATS_COUNT ARRAY_SIZE(cedrus_formats) 70 71 static inline struct cedrus_ctx *cedrus_file2ctx(struct file *file) 72 { 73 return container_of(file->private_data, struct cedrus_ctx, fh); 74 } 75 76 static struct cedrus_format *cedrus_find_format(struct cedrus_ctx *ctx, 77 u32 pixelformat, u32 directions) 78 { 79 struct cedrus_format *first_valid_fmt = NULL; 80 struct cedrus_format *fmt; 81 unsigned int i; 82 83 for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) { 84 fmt = &cedrus_formats[i]; 85 86 if (!cedrus_is_capable(ctx, fmt->capabilities) || 87 !(fmt->directions & directions)) 88 continue; 89 90 if (fmt->pixelformat == pixelformat) 91 break; 92 93 if (!first_valid_fmt) 94 first_valid_fmt = fmt; 95 } 96 97 if (i == CEDRUS_FORMATS_COUNT) 98 return first_valid_fmt; 99 100 return &cedrus_formats[i]; 101 } 102 103 void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) 104 { 105 unsigned int width = pix_fmt->width; 106 unsigned int height = pix_fmt->height; 107 unsigned int sizeimage = pix_fmt->sizeimage; 108 unsigned int bytesperline = pix_fmt->bytesperline; 109 110 pix_fmt->field = V4L2_FIELD_NONE; 111 112 /* Limit to hardware min/max. */ 113 width = clamp(width, CEDRUS_MIN_WIDTH, CEDRUS_MAX_WIDTH); 114 height = clamp(height, CEDRUS_MIN_HEIGHT, CEDRUS_MAX_HEIGHT); 115 116 switch (pix_fmt->pixelformat) { 117 case V4L2_PIX_FMT_MPEG2_SLICE: 118 case V4L2_PIX_FMT_H264_SLICE: 119 case V4L2_PIX_FMT_HEVC_SLICE: 120 case V4L2_PIX_FMT_VP8_FRAME: 121 /* Zero bytes per line for encoded source. */ 122 bytesperline = 0; 123 /* Choose some minimum size since this can't be 0 */ 124 sizeimage = max_t(u32, SZ_1K, sizeimage); 125 break; 126 127 case V4L2_PIX_FMT_NV12_32L32: 128 /* 32-aligned stride. */ 129 bytesperline = ALIGN(width, 32); 130 131 /* 32-aligned height. */ 132 height = ALIGN(height, 32); 133 134 /* Luma plane size. */ 135 sizeimage = bytesperline * height; 136 137 /* Chroma plane size. */ 138 sizeimage += bytesperline * ALIGN(height, 64) / 2; 139 140 break; 141 142 case V4L2_PIX_FMT_NV12: 143 /* 16-aligned stride. */ 144 bytesperline = ALIGN(width, 16); 145 146 /* 16-aligned height. */ 147 height = ALIGN(height, 16); 148 149 /* Luma plane size. */ 150 sizeimage = bytesperline * height; 151 152 /* Chroma plane size. */ 153 sizeimage += bytesperline * height / 2; 154 155 break; 156 } 157 158 pix_fmt->width = width; 159 pix_fmt->height = height; 160 161 pix_fmt->bytesperline = bytesperline; 162 pix_fmt->sizeimage = sizeimage; 163 } 164 165 static int cedrus_querycap(struct file *file, void *priv, 166 struct v4l2_capability *cap) 167 { 168 strscpy(cap->driver, CEDRUS_NAME, sizeof(cap->driver)); 169 strscpy(cap->card, CEDRUS_NAME, sizeof(cap->card)); 170 snprintf(cap->bus_info, sizeof(cap->bus_info), 171 "platform:%s", CEDRUS_NAME); 172 173 return 0; 174 } 175 176 static int cedrus_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, 177 u32 direction) 178 { 179 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 180 unsigned int i, index; 181 182 /* Index among formats that match the requested direction. */ 183 index = 0; 184 185 for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) { 186 if (!cedrus_is_capable(ctx, cedrus_formats[i].capabilities)) 187 continue; 188 189 if (!(cedrus_formats[i].directions & direction)) 190 continue; 191 192 if (index == f->index) 193 break; 194 195 index++; 196 } 197 198 /* Matched format. */ 199 if (i < CEDRUS_FORMATS_COUNT) { 200 f->pixelformat = cedrus_formats[i].pixelformat; 201 202 return 0; 203 } 204 205 return -EINVAL; 206 } 207 208 static int cedrus_enum_fmt_vid_cap(struct file *file, void *priv, 209 struct v4l2_fmtdesc *f) 210 { 211 return cedrus_enum_fmt(file, f, CEDRUS_DECODE_DST); 212 } 213 214 static int cedrus_enum_fmt_vid_out(struct file *file, void *priv, 215 struct v4l2_fmtdesc *f) 216 { 217 return cedrus_enum_fmt(file, f, CEDRUS_DECODE_SRC); 218 } 219 220 static int cedrus_g_fmt_vid_cap(struct file *file, void *priv, 221 struct v4l2_format *f) 222 { 223 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 224 225 f->fmt.pix = ctx->dst_fmt; 226 return 0; 227 } 228 229 static int cedrus_g_fmt_vid_out(struct file *file, void *priv, 230 struct v4l2_format *f) 231 { 232 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 233 234 f->fmt.pix = ctx->src_fmt; 235 return 0; 236 } 237 238 static int cedrus_try_fmt_vid_cap_p(struct cedrus_ctx *ctx, 239 struct v4l2_pix_format *pix_fmt) 240 { 241 struct cedrus_format *fmt = 242 cedrus_find_format(ctx, pix_fmt->pixelformat, 243 CEDRUS_DECODE_DST); 244 245 if (!fmt) 246 return -EINVAL; 247 248 pix_fmt->pixelformat = fmt->pixelformat; 249 pix_fmt->width = ctx->src_fmt.width; 250 pix_fmt->height = ctx->src_fmt.height; 251 cedrus_prepare_format(pix_fmt); 252 253 if (ctx->current_codec->extra_cap_size) 254 pix_fmt->sizeimage += 255 ctx->current_codec->extra_cap_size(ctx, pix_fmt); 256 257 return 0; 258 } 259 260 static int cedrus_try_fmt_vid_cap(struct file *file, void *priv, 261 struct v4l2_format *f) 262 { 263 return cedrus_try_fmt_vid_cap_p(cedrus_file2ctx(file), &f->fmt.pix); 264 } 265 266 static int cedrus_try_fmt_vid_out_p(struct cedrus_ctx *ctx, 267 struct v4l2_pix_format *pix_fmt) 268 { 269 struct cedrus_format *fmt = 270 cedrus_find_format(ctx, pix_fmt->pixelformat, 271 CEDRUS_DECODE_SRC); 272 273 if (!fmt) 274 return -EINVAL; 275 276 pix_fmt->pixelformat = fmt->pixelformat; 277 cedrus_prepare_format(pix_fmt); 278 279 return 0; 280 } 281 282 static int cedrus_try_fmt_vid_out(struct file *file, void *priv, 283 struct v4l2_format *f) 284 { 285 return cedrus_try_fmt_vid_out_p(cedrus_file2ctx(file), &f->fmt.pix); 286 } 287 288 static int cedrus_s_fmt_vid_cap(struct file *file, void *priv, 289 struct v4l2_format *f) 290 { 291 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 292 struct vb2_queue *vq; 293 int ret; 294 295 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 296 if (vb2_is_busy(vq)) 297 return -EBUSY; 298 299 ret = cedrus_try_fmt_vid_cap(file, priv, f); 300 if (ret) 301 return ret; 302 303 ctx->dst_fmt = f->fmt.pix; 304 305 return 0; 306 } 307 308 void cedrus_reset_cap_format(struct cedrus_ctx *ctx) 309 { 310 ctx->dst_fmt.pixelformat = 0; 311 cedrus_try_fmt_vid_cap_p(ctx, &ctx->dst_fmt); 312 } 313 314 static int cedrus_s_fmt_vid_out_p(struct cedrus_ctx *ctx, 315 struct v4l2_pix_format *pix_fmt) 316 { 317 struct vb2_queue *vq; 318 int ret; 319 320 ret = cedrus_try_fmt_vid_out_p(ctx, pix_fmt); 321 if (ret) 322 return ret; 323 324 ctx->src_fmt = *pix_fmt; 325 326 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); 327 328 switch (ctx->src_fmt.pixelformat) { 329 case V4L2_PIX_FMT_H264_SLICE: 330 case V4L2_PIX_FMT_HEVC_SLICE: 331 vq->subsystem_flags |= 332 VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 333 break; 334 default: 335 vq->subsystem_flags &= 336 ~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 337 break; 338 } 339 340 switch (ctx->src_fmt.pixelformat) { 341 case V4L2_PIX_FMT_MPEG2_SLICE: 342 ctx->current_codec = &cedrus_dec_ops_mpeg2; 343 break; 344 case V4L2_PIX_FMT_H264_SLICE: 345 ctx->current_codec = &cedrus_dec_ops_h264; 346 break; 347 case V4L2_PIX_FMT_HEVC_SLICE: 348 ctx->current_codec = &cedrus_dec_ops_h265; 349 break; 350 case V4L2_PIX_FMT_VP8_FRAME: 351 ctx->current_codec = &cedrus_dec_ops_vp8; 352 break; 353 } 354 355 /* Propagate format information to capture. */ 356 ctx->dst_fmt.colorspace = pix_fmt->colorspace; 357 ctx->dst_fmt.xfer_func = pix_fmt->xfer_func; 358 ctx->dst_fmt.ycbcr_enc = pix_fmt->ycbcr_enc; 359 ctx->dst_fmt.quantization = pix_fmt->quantization; 360 cedrus_reset_cap_format(ctx); 361 362 return 0; 363 } 364 365 void cedrus_reset_out_format(struct cedrus_ctx *ctx) 366 { 367 ctx->src_fmt.pixelformat = 0; 368 cedrus_s_fmt_vid_out_p(ctx, &ctx->src_fmt); 369 } 370 371 static int cedrus_s_fmt_vid_out(struct file *file, void *priv, 372 struct v4l2_format *f) 373 { 374 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 375 struct vb2_queue *vq; 376 struct vb2_queue *peer_vq; 377 378 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 379 /* 380 * In order to support dynamic resolution change, 381 * the decoder admits a resolution change, as long 382 * as the pixelformat remains. Can't be done if streaming. 383 */ 384 if (vb2_is_streaming(vq) || (vb2_is_busy(vq) && 385 f->fmt.pix.pixelformat != ctx->src_fmt.pixelformat)) 386 return -EBUSY; 387 /* 388 * Since format change on the OUTPUT queue will reset 389 * the CAPTURE queue, we can't allow doing so 390 * when the CAPTURE queue has buffers allocated. 391 */ 392 peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, 393 V4L2_BUF_TYPE_VIDEO_CAPTURE); 394 if (vb2_is_busy(peer_vq)) 395 return -EBUSY; 396 397 return cedrus_s_fmt_vid_out_p(cedrus_file2ctx(file), &f->fmt.pix); 398 } 399 400 const struct v4l2_ioctl_ops cedrus_ioctl_ops = { 401 .vidioc_querycap = cedrus_querycap, 402 403 .vidioc_enum_fmt_vid_cap = cedrus_enum_fmt_vid_cap, 404 .vidioc_g_fmt_vid_cap = cedrus_g_fmt_vid_cap, 405 .vidioc_try_fmt_vid_cap = cedrus_try_fmt_vid_cap, 406 .vidioc_s_fmt_vid_cap = cedrus_s_fmt_vid_cap, 407 408 .vidioc_enum_fmt_vid_out = cedrus_enum_fmt_vid_out, 409 .vidioc_g_fmt_vid_out = cedrus_g_fmt_vid_out, 410 .vidioc_try_fmt_vid_out = cedrus_try_fmt_vid_out, 411 .vidioc_s_fmt_vid_out = cedrus_s_fmt_vid_out, 412 413 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 414 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 415 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 416 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 417 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 418 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 419 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 420 421 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 422 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 423 424 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd, 425 .vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd, 426 427 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 428 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 429 }; 430 431 static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, 432 unsigned int *nplanes, unsigned int sizes[], 433 struct device *alloc_devs[]) 434 { 435 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 436 struct v4l2_pix_format *pix_fmt; 437 438 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 439 pix_fmt = &ctx->src_fmt; 440 else 441 pix_fmt = &ctx->dst_fmt; 442 443 if (*nplanes) { 444 if (sizes[0] < pix_fmt->sizeimage) 445 return -EINVAL; 446 } else { 447 sizes[0] = pix_fmt->sizeimage; 448 *nplanes = 1; 449 } 450 451 return 0; 452 } 453 454 static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state) 455 { 456 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 457 struct vb2_v4l2_buffer *vbuf; 458 459 for (;;) { 460 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 461 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 462 else 463 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 464 465 if (!vbuf) 466 return; 467 468 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, 469 &ctx->hdl); 470 v4l2_m2m_buf_done(vbuf, state); 471 } 472 } 473 474 static int cedrus_buf_out_validate(struct vb2_buffer *vb) 475 { 476 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 477 478 vbuf->field = V4L2_FIELD_NONE; 479 return 0; 480 } 481 482 static int cedrus_buf_prepare(struct vb2_buffer *vb) 483 { 484 struct vb2_queue *vq = vb->vb2_queue; 485 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 486 struct v4l2_pix_format *pix_fmt; 487 488 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 489 pix_fmt = &ctx->src_fmt; 490 else 491 pix_fmt = &ctx->dst_fmt; 492 493 if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) 494 return -EINVAL; 495 496 /* 497 * Buffer's bytesused must be written by driver for CAPTURE buffers. 498 * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets 499 * it to buffer length). 500 */ 501 if (V4L2_TYPE_IS_CAPTURE(vq->type)) 502 vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); 503 504 return 0; 505 } 506 507 static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) 508 { 509 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 510 struct cedrus_dev *dev = ctx->dev; 511 int ret = 0; 512 513 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 514 ret = pm_runtime_resume_and_get(dev->dev); 515 if (ret < 0) 516 goto err_cleanup; 517 518 if (ctx->current_codec->start) { 519 ret = ctx->current_codec->start(ctx); 520 if (ret) 521 goto err_pm; 522 } 523 } 524 525 return 0; 526 527 err_pm: 528 pm_runtime_put(dev->dev); 529 err_cleanup: 530 cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); 531 532 return ret; 533 } 534 535 static void cedrus_stop_streaming(struct vb2_queue *vq) 536 { 537 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 538 struct cedrus_dev *dev = ctx->dev; 539 540 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 541 if (ctx->current_codec->stop) 542 ctx->current_codec->stop(ctx); 543 544 pm_runtime_put(dev->dev); 545 } 546 547 cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR); 548 } 549 550 static void cedrus_buf_queue(struct vb2_buffer *vb) 551 { 552 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 553 struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 554 555 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 556 } 557 558 static void cedrus_buf_request_complete(struct vb2_buffer *vb) 559 { 560 struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 561 562 v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); 563 } 564 565 static const struct vb2_ops cedrus_qops = { 566 .queue_setup = cedrus_queue_setup, 567 .buf_prepare = cedrus_buf_prepare, 568 .buf_queue = cedrus_buf_queue, 569 .buf_out_validate = cedrus_buf_out_validate, 570 .buf_request_complete = cedrus_buf_request_complete, 571 .start_streaming = cedrus_start_streaming, 572 .stop_streaming = cedrus_stop_streaming, 573 .wait_prepare = vb2_ops_wait_prepare, 574 .wait_finish = vb2_ops_wait_finish, 575 }; 576 577 int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, 578 struct vb2_queue *dst_vq) 579 { 580 struct cedrus_ctx *ctx = priv; 581 int ret; 582 583 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 584 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 585 src_vq->drv_priv = ctx; 586 src_vq->buf_struct_size = sizeof(struct cedrus_buffer); 587 src_vq->ops = &cedrus_qops; 588 src_vq->mem_ops = &vb2_dma_contig_memops; 589 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 590 src_vq->lock = &ctx->dev->dev_mutex; 591 src_vq->dev = ctx->dev->dev; 592 src_vq->supports_requests = true; 593 src_vq->requires_requests = true; 594 595 ret = vb2_queue_init(src_vq); 596 if (ret) 597 return ret; 598 599 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 600 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 601 dst_vq->drv_priv = ctx; 602 dst_vq->buf_struct_size = sizeof(struct cedrus_buffer); 603 dst_vq->ops = &cedrus_qops; 604 dst_vq->mem_ops = &vb2_dma_contig_memops; 605 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 606 dst_vq->lock = &ctx->dev->dev_mutex; 607 dst_vq->dev = ctx->dev->dev; 608 609 return vb2_queue_init(dst_vq); 610 } 611