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_32L32, 60 .directions = CEDRUS_DECODE_DST, 61 }, 62 { 63 .pixelformat = V4L2_PIX_FMT_NV12, 64 .directions = CEDRUS_DECODE_DST, 65 .capabilities = CEDRUS_CAPABILITY_UNTILED, 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(u32 pixelformat, u32 directions, 77 unsigned int capabilities) 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 ((fmt->capabilities & capabilities) != 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 struct cedrus_dev *dev = ctx->dev; 181 unsigned int capabilities = dev->capabilities; 182 struct cedrus_format *fmt; 183 unsigned int i, index; 184 185 /* Index among formats that match the requested direction. */ 186 index = 0; 187 188 for (i = 0; i < CEDRUS_FORMATS_COUNT; i++) { 189 fmt = &cedrus_formats[i]; 190 191 if (fmt->capabilities && (fmt->capabilities & capabilities) != 192 fmt->capabilities) 193 continue; 194 195 if (!(cedrus_formats[i].directions & direction)) 196 continue; 197 198 if (index == f->index) 199 break; 200 201 index++; 202 } 203 204 /* Matched format. */ 205 if (i < CEDRUS_FORMATS_COUNT) { 206 f->pixelformat = cedrus_formats[i].pixelformat; 207 208 return 0; 209 } 210 211 return -EINVAL; 212 } 213 214 static int cedrus_enum_fmt_vid_cap(struct file *file, void *priv, 215 struct v4l2_fmtdesc *f) 216 { 217 return cedrus_enum_fmt(file, f, CEDRUS_DECODE_DST); 218 } 219 220 static int cedrus_enum_fmt_vid_out(struct file *file, void *priv, 221 struct v4l2_fmtdesc *f) 222 { 223 return cedrus_enum_fmt(file, f, CEDRUS_DECODE_SRC); 224 } 225 226 static int cedrus_g_fmt_vid_cap(struct file *file, void *priv, 227 struct v4l2_format *f) 228 { 229 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 230 231 f->fmt.pix = ctx->dst_fmt; 232 return 0; 233 } 234 235 static int cedrus_g_fmt_vid_out(struct file *file, void *priv, 236 struct v4l2_format *f) 237 { 238 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 239 240 f->fmt.pix = ctx->src_fmt; 241 return 0; 242 } 243 244 static int cedrus_try_fmt_vid_cap(struct file *file, void *priv, 245 struct v4l2_format *f) 246 { 247 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 248 struct cedrus_dev *dev = ctx->dev; 249 struct v4l2_pix_format *pix_fmt = &f->fmt.pix; 250 struct cedrus_format *fmt = 251 cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_DST, 252 dev->capabilities); 253 254 if (!fmt) 255 return -EINVAL; 256 257 pix_fmt->pixelformat = fmt->pixelformat; 258 pix_fmt->width = ctx->src_fmt.width; 259 pix_fmt->height = ctx->src_fmt.height; 260 cedrus_prepare_format(pix_fmt); 261 262 return 0; 263 } 264 265 static int cedrus_try_fmt_vid_out(struct file *file, void *priv, 266 struct v4l2_format *f) 267 { 268 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 269 struct cedrus_dev *dev = ctx->dev; 270 struct v4l2_pix_format *pix_fmt = &f->fmt.pix; 271 struct cedrus_format *fmt = 272 cedrus_find_format(pix_fmt->pixelformat, CEDRUS_DECODE_SRC, 273 dev->capabilities); 274 275 if (!fmt) 276 return -EINVAL; 277 278 pix_fmt->pixelformat = fmt->pixelformat; 279 cedrus_prepare_format(pix_fmt); 280 281 return 0; 282 } 283 284 static int cedrus_s_fmt_vid_cap(struct file *file, void *priv, 285 struct v4l2_format *f) 286 { 287 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 288 struct vb2_queue *vq; 289 int ret; 290 291 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 292 if (vb2_is_busy(vq)) 293 return -EBUSY; 294 295 ret = cedrus_try_fmt_vid_cap(file, priv, f); 296 if (ret) 297 return ret; 298 299 ctx->dst_fmt = f->fmt.pix; 300 301 return 0; 302 } 303 304 static int cedrus_s_fmt_vid_out(struct file *file, void *priv, 305 struct v4l2_format *f) 306 { 307 struct cedrus_ctx *ctx = cedrus_file2ctx(file); 308 struct vb2_queue *vq; 309 struct vb2_queue *peer_vq; 310 int ret; 311 312 ret = cedrus_try_fmt_vid_out(file, priv, f); 313 if (ret) 314 return ret; 315 316 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 317 /* 318 * In order to support dynamic resolution change, 319 * the decoder admits a resolution change, as long 320 * as the pixelformat remains. Can't be done if streaming. 321 */ 322 if (vb2_is_streaming(vq) || (vb2_is_busy(vq) && 323 f->fmt.pix.pixelformat != ctx->src_fmt.pixelformat)) 324 return -EBUSY; 325 /* 326 * Since format change on the OUTPUT queue will reset 327 * the CAPTURE queue, we can't allow doing so 328 * when the CAPTURE queue has buffers allocated. 329 */ 330 peer_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, 331 V4L2_BUF_TYPE_VIDEO_CAPTURE); 332 if (vb2_is_busy(peer_vq)) 333 return -EBUSY; 334 335 ret = cedrus_try_fmt_vid_out(file, priv, f); 336 if (ret) 337 return ret; 338 339 ctx->src_fmt = f->fmt.pix; 340 341 switch (ctx->src_fmt.pixelformat) { 342 case V4L2_PIX_FMT_H264_SLICE: 343 case V4L2_PIX_FMT_HEVC_SLICE: 344 vq->subsystem_flags |= 345 VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 346 break; 347 default: 348 vq->subsystem_flags &= 349 ~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 350 break; 351 } 352 353 /* Propagate format information to capture. */ 354 ctx->dst_fmt.colorspace = f->fmt.pix.colorspace; 355 ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func; 356 ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc; 357 ctx->dst_fmt.quantization = f->fmt.pix.quantization; 358 ctx->dst_fmt.width = ctx->src_fmt.width; 359 ctx->dst_fmt.height = ctx->src_fmt.height; 360 cedrus_prepare_format(&ctx->dst_fmt); 361 362 return 0; 363 } 364 365 const struct v4l2_ioctl_ops cedrus_ioctl_ops = { 366 .vidioc_querycap = cedrus_querycap, 367 368 .vidioc_enum_fmt_vid_cap = cedrus_enum_fmt_vid_cap, 369 .vidioc_g_fmt_vid_cap = cedrus_g_fmt_vid_cap, 370 .vidioc_try_fmt_vid_cap = cedrus_try_fmt_vid_cap, 371 .vidioc_s_fmt_vid_cap = cedrus_s_fmt_vid_cap, 372 373 .vidioc_enum_fmt_vid_out = cedrus_enum_fmt_vid_out, 374 .vidioc_g_fmt_vid_out = cedrus_g_fmt_vid_out, 375 .vidioc_try_fmt_vid_out = cedrus_try_fmt_vid_out, 376 .vidioc_s_fmt_vid_out = cedrus_s_fmt_vid_out, 377 378 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 379 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 380 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 381 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 382 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 383 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 384 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 385 386 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 387 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 388 389 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd, 390 .vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd, 391 392 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 393 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 394 }; 395 396 static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, 397 unsigned int *nplanes, unsigned int sizes[], 398 struct device *alloc_devs[]) 399 { 400 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 401 struct v4l2_pix_format *pix_fmt; 402 403 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 404 pix_fmt = &ctx->src_fmt; 405 else 406 pix_fmt = &ctx->dst_fmt; 407 408 if (*nplanes) { 409 if (sizes[0] < pix_fmt->sizeimage) 410 return -EINVAL; 411 } else { 412 sizes[0] = pix_fmt->sizeimage; 413 *nplanes = 1; 414 } 415 416 return 0; 417 } 418 419 static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state) 420 { 421 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 422 struct vb2_v4l2_buffer *vbuf; 423 424 for (;;) { 425 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 426 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 427 else 428 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 429 430 if (!vbuf) 431 return; 432 433 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, 434 &ctx->hdl); 435 v4l2_m2m_buf_done(vbuf, state); 436 } 437 } 438 439 static int cedrus_buf_out_validate(struct vb2_buffer *vb) 440 { 441 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 442 443 vbuf->field = V4L2_FIELD_NONE; 444 return 0; 445 } 446 447 static int cedrus_buf_prepare(struct vb2_buffer *vb) 448 { 449 struct vb2_queue *vq = vb->vb2_queue; 450 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 451 struct v4l2_pix_format *pix_fmt; 452 453 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 454 pix_fmt = &ctx->src_fmt; 455 else 456 pix_fmt = &ctx->dst_fmt; 457 458 if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) 459 return -EINVAL; 460 461 /* 462 * Buffer's bytesused must be written by driver for CAPTURE buffers. 463 * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets 464 * it to buffer length). 465 */ 466 if (V4L2_TYPE_IS_CAPTURE(vq->type)) 467 vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); 468 469 return 0; 470 } 471 472 static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) 473 { 474 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 475 struct cedrus_dev *dev = ctx->dev; 476 int ret = 0; 477 478 switch (ctx->src_fmt.pixelformat) { 479 case V4L2_PIX_FMT_MPEG2_SLICE: 480 ctx->current_codec = CEDRUS_CODEC_MPEG2; 481 break; 482 483 case V4L2_PIX_FMT_H264_SLICE: 484 ctx->current_codec = CEDRUS_CODEC_H264; 485 break; 486 487 case V4L2_PIX_FMT_HEVC_SLICE: 488 ctx->current_codec = CEDRUS_CODEC_H265; 489 break; 490 491 case V4L2_PIX_FMT_VP8_FRAME: 492 ctx->current_codec = CEDRUS_CODEC_VP8; 493 break; 494 495 default: 496 return -EINVAL; 497 } 498 499 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 500 ret = pm_runtime_resume_and_get(dev->dev); 501 if (ret < 0) 502 goto err_cleanup; 503 504 if (dev->dec_ops[ctx->current_codec]->start) { 505 ret = dev->dec_ops[ctx->current_codec]->start(ctx); 506 if (ret) 507 goto err_pm; 508 } 509 } 510 511 return 0; 512 513 err_pm: 514 pm_runtime_put(dev->dev); 515 err_cleanup: 516 cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); 517 518 return ret; 519 } 520 521 static void cedrus_stop_streaming(struct vb2_queue *vq) 522 { 523 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 524 struct cedrus_dev *dev = ctx->dev; 525 526 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 527 if (dev->dec_ops[ctx->current_codec]->stop) 528 dev->dec_ops[ctx->current_codec]->stop(ctx); 529 530 pm_runtime_put(dev->dev); 531 } 532 533 cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR); 534 } 535 536 static void cedrus_buf_queue(struct vb2_buffer *vb) 537 { 538 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 539 struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 540 541 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 542 } 543 544 static void cedrus_buf_request_complete(struct vb2_buffer *vb) 545 { 546 struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 547 548 v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); 549 } 550 551 static struct vb2_ops cedrus_qops = { 552 .queue_setup = cedrus_queue_setup, 553 .buf_prepare = cedrus_buf_prepare, 554 .buf_queue = cedrus_buf_queue, 555 .buf_out_validate = cedrus_buf_out_validate, 556 .buf_request_complete = cedrus_buf_request_complete, 557 .start_streaming = cedrus_start_streaming, 558 .stop_streaming = cedrus_stop_streaming, 559 .wait_prepare = vb2_ops_wait_prepare, 560 .wait_finish = vb2_ops_wait_finish, 561 }; 562 563 int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, 564 struct vb2_queue *dst_vq) 565 { 566 struct cedrus_ctx *ctx = priv; 567 int ret; 568 569 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 570 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 571 src_vq->drv_priv = ctx; 572 src_vq->buf_struct_size = sizeof(struct cedrus_buffer); 573 src_vq->ops = &cedrus_qops; 574 src_vq->mem_ops = &vb2_dma_contig_memops; 575 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 576 src_vq->lock = &ctx->dev->dev_mutex; 577 src_vq->dev = ctx->dev->dev; 578 src_vq->supports_requests = true; 579 src_vq->requires_requests = true; 580 581 ret = vb2_queue_init(src_vq); 582 if (ret) 583 return ret; 584 585 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 586 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 587 dst_vq->drv_priv = ctx; 588 dst_vq->buf_struct_size = sizeof(struct cedrus_buffer); 589 dst_vq->ops = &cedrus_qops; 590 dst_vq->mem_ops = &vb2_dma_contig_memops; 591 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 592 dst_vq->lock = &ctx->dev->dev_mutex; 593 dst_vq->dev = ctx->dev->dev; 594 595 return vb2_queue_init(dst_vq); 596 } 597