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