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_SUNXI_TILED_NV12, 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_SUNXI_TILED_NV12: 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 * height / 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 vq->subsystem_flags |= 344 VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 345 break; 346 default: 347 vq->subsystem_flags &= 348 ~VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 349 break; 350 } 351 352 /* Propagate format information to capture. */ 353 ctx->dst_fmt.colorspace = f->fmt.pix.colorspace; 354 ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func; 355 ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc; 356 ctx->dst_fmt.quantization = f->fmt.pix.quantization; 357 ctx->dst_fmt.width = ctx->src_fmt.width; 358 ctx->dst_fmt.height = ctx->src_fmt.height; 359 cedrus_prepare_format(&ctx->dst_fmt); 360 361 return 0; 362 } 363 364 const struct v4l2_ioctl_ops cedrus_ioctl_ops = { 365 .vidioc_querycap = cedrus_querycap, 366 367 .vidioc_enum_fmt_vid_cap = cedrus_enum_fmt_vid_cap, 368 .vidioc_g_fmt_vid_cap = cedrus_g_fmt_vid_cap, 369 .vidioc_try_fmt_vid_cap = cedrus_try_fmt_vid_cap, 370 .vidioc_s_fmt_vid_cap = cedrus_s_fmt_vid_cap, 371 372 .vidioc_enum_fmt_vid_out = cedrus_enum_fmt_vid_out, 373 .vidioc_g_fmt_vid_out = cedrus_g_fmt_vid_out, 374 .vidioc_try_fmt_vid_out = cedrus_try_fmt_vid_out, 375 .vidioc_s_fmt_vid_out = cedrus_s_fmt_vid_out, 376 377 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 378 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 379 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 380 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 381 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 382 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 383 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 384 385 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 386 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 387 388 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd, 389 .vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd, 390 391 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 392 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 393 }; 394 395 static int cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, 396 unsigned int *nplanes, unsigned int sizes[], 397 struct device *alloc_devs[]) 398 { 399 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 400 struct v4l2_pix_format *pix_fmt; 401 402 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 403 pix_fmt = &ctx->src_fmt; 404 else 405 pix_fmt = &ctx->dst_fmt; 406 407 if (*nplanes) { 408 if (sizes[0] < pix_fmt->sizeimage) 409 return -EINVAL; 410 } else { 411 sizes[0] = pix_fmt->sizeimage; 412 *nplanes = 1; 413 } 414 415 return 0; 416 } 417 418 static void cedrus_queue_cleanup(struct vb2_queue *vq, u32 state) 419 { 420 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 421 struct vb2_v4l2_buffer *vbuf; 422 423 for (;;) { 424 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 425 vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 426 else 427 vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 428 429 if (!vbuf) 430 return; 431 432 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, 433 &ctx->hdl); 434 v4l2_m2m_buf_done(vbuf, state); 435 } 436 } 437 438 static int cedrus_buf_out_validate(struct vb2_buffer *vb) 439 { 440 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 441 442 vbuf->field = V4L2_FIELD_NONE; 443 return 0; 444 } 445 446 static int cedrus_buf_prepare(struct vb2_buffer *vb) 447 { 448 struct vb2_queue *vq = vb->vb2_queue; 449 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 450 struct v4l2_pix_format *pix_fmt; 451 452 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 453 pix_fmt = &ctx->src_fmt; 454 else 455 pix_fmt = &ctx->dst_fmt; 456 457 if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) 458 return -EINVAL; 459 460 vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); 461 462 return 0; 463 } 464 465 static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count) 466 { 467 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 468 struct cedrus_dev *dev = ctx->dev; 469 int ret = 0; 470 471 switch (ctx->src_fmt.pixelformat) { 472 case V4L2_PIX_FMT_MPEG2_SLICE: 473 ctx->current_codec = CEDRUS_CODEC_MPEG2; 474 break; 475 476 case V4L2_PIX_FMT_H264_SLICE: 477 ctx->current_codec = CEDRUS_CODEC_H264; 478 break; 479 480 case V4L2_PIX_FMT_HEVC_SLICE: 481 ctx->current_codec = CEDRUS_CODEC_H265; 482 break; 483 484 case V4L2_PIX_FMT_VP8_FRAME: 485 ctx->current_codec = CEDRUS_CODEC_VP8; 486 break; 487 488 default: 489 return -EINVAL; 490 } 491 492 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 493 ret = pm_runtime_get_sync(dev->dev); 494 if (ret < 0) { 495 pm_runtime_put_noidle(dev->dev); 496 goto err_cleanup; 497 } 498 499 if (dev->dec_ops[ctx->current_codec]->start) { 500 ret = dev->dec_ops[ctx->current_codec]->start(ctx); 501 if (ret) 502 goto err_pm; 503 } 504 } 505 506 return 0; 507 508 err_pm: 509 pm_runtime_put(dev->dev); 510 err_cleanup: 511 cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED); 512 513 return ret; 514 } 515 516 static void cedrus_stop_streaming(struct vb2_queue *vq) 517 { 518 struct cedrus_ctx *ctx = vb2_get_drv_priv(vq); 519 struct cedrus_dev *dev = ctx->dev; 520 521 if (V4L2_TYPE_IS_OUTPUT(vq->type)) { 522 if (dev->dec_ops[ctx->current_codec]->stop) 523 dev->dec_ops[ctx->current_codec]->stop(ctx); 524 525 pm_runtime_put(dev->dev); 526 } 527 528 cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR); 529 } 530 531 static void cedrus_buf_queue(struct vb2_buffer *vb) 532 { 533 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 534 struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 535 536 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 537 } 538 539 static void cedrus_buf_request_complete(struct vb2_buffer *vb) 540 { 541 struct cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 542 543 v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); 544 } 545 546 static struct vb2_ops cedrus_qops = { 547 .queue_setup = cedrus_queue_setup, 548 .buf_prepare = cedrus_buf_prepare, 549 .buf_queue = cedrus_buf_queue, 550 .buf_out_validate = cedrus_buf_out_validate, 551 .buf_request_complete = cedrus_buf_request_complete, 552 .start_streaming = cedrus_start_streaming, 553 .stop_streaming = cedrus_stop_streaming, 554 .wait_prepare = vb2_ops_wait_prepare, 555 .wait_finish = vb2_ops_wait_finish, 556 }; 557 558 int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, 559 struct vb2_queue *dst_vq) 560 { 561 struct cedrus_ctx *ctx = priv; 562 int ret; 563 564 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 565 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 566 src_vq->drv_priv = ctx; 567 src_vq->buf_struct_size = sizeof(struct cedrus_buffer); 568 src_vq->min_buffers_needed = 1; 569 src_vq->ops = &cedrus_qops; 570 src_vq->mem_ops = &vb2_dma_contig_memops; 571 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 572 src_vq->lock = &ctx->dev->dev_mutex; 573 src_vq->dev = ctx->dev->dev; 574 src_vq->supports_requests = true; 575 src_vq->requires_requests = true; 576 577 ret = vb2_queue_init(src_vq); 578 if (ret) 579 return ret; 580 581 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 582 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 583 dst_vq->drv_priv = ctx; 584 dst_vq->buf_struct_size = sizeof(struct cedrus_buffer); 585 dst_vq->min_buffers_needed = 1; 586 dst_vq->ops = &cedrus_qops; 587 dst_vq->mem_ops = &vb2_dma_contig_memops; 588 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 589 dst_vq->lock = &ctx->dev->dev_mutex; 590 dst_vq->dev = ctx->dev->dev; 591 592 return vb2_queue_init(dst_vq); 593 } 594