1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2018 BayLibre, SAS 4 * Author: Maxime Jourdan <mjourdan@baylibre.com> 5 */ 6 7#include <linux/of.h> 8#include <linux/clk.h> 9#include <linux/io.h> 10#include <linux/module.h> 11#include <linux/platform_device.h> 12#include <linux/mfd/syscon.h> 13#include <linux/slab.h> 14#include <linux/interrupt.h> 15#include <linux/kthread.h> 16#include <media/v4l2-ioctl.h> 17#include <media/v4l2-event.h> 18#include <media/v4l2-ctrls.h> 19#include <media/v4l2-mem2mem.h> 20#include <media/v4l2-dev.h> 21#include <media/videobuf2-dma-contig.h> 22 23#include "vdec.h" 24#include "esparser.h" 25#include "vdec_helpers.h" 26 27struct dummy_buf { 28 struct vb2_v4l2_buffer vb; 29 struct list_head list; 30}; 31 32/* 16 MiB for parsed bitstream swap exchange */ 33#define SIZE_VIFIFO SZ_16M 34 35static u32 get_output_size(u32 width, u32 height) 36{ 37 return ALIGN(width * height, SZ_64K); 38} 39 40u32 amvdec_get_output_size(struct amvdec_session *sess) 41{ 42 return get_output_size(sess->width, sess->height); 43} 44EXPORT_SYMBOL_GPL(amvdec_get_output_size); 45 46static int vdec_codec_needs_recycle(struct amvdec_session *sess) 47{ 48 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 49 50 return codec_ops->can_recycle && codec_ops->recycle; 51} 52 53static int vdec_recycle_thread(void *data) 54{ 55 struct amvdec_session *sess = data; 56 struct amvdec_core *core = sess->core; 57 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 58 struct amvdec_buffer *tmp, *n; 59 60 while (!kthread_should_stop()) { 61 mutex_lock(&sess->bufs_recycle_lock); 62 list_for_each_entry_safe(tmp, n, &sess->bufs_recycle, list) { 63 if (!codec_ops->can_recycle(core)) 64 break; 65 66 codec_ops->recycle(core, tmp->vb->index); 67 list_del(&tmp->list); 68 kfree(tmp); 69 } 70 mutex_unlock(&sess->bufs_recycle_lock); 71 72 usleep_range(5000, 10000); 73 } 74 75 return 0; 76} 77 78static int vdec_poweron(struct amvdec_session *sess) 79{ 80 int ret; 81 struct amvdec_ops *vdec_ops = sess->fmt_out->vdec_ops; 82 83 ret = clk_prepare_enable(sess->core->dos_parser_clk); 84 if (ret) 85 return ret; 86 87 ret = clk_prepare_enable(sess->core->dos_clk); 88 if (ret) 89 goto disable_dos_parser; 90 91 ret = vdec_ops->start(sess); 92 if (ret) 93 goto disable_dos; 94 95 esparser_power_up(sess); 96 97 return 0; 98 99disable_dos: 100 clk_disable_unprepare(sess->core->dos_clk); 101disable_dos_parser: 102 clk_disable_unprepare(sess->core->dos_parser_clk); 103 104 return ret; 105} 106 107static void vdec_wait_inactive(struct amvdec_session *sess) 108{ 109 /* We consider 50ms with no IRQ to be inactive. */ 110 while (time_is_after_jiffies64(sess->last_irq_jiffies + 111 msecs_to_jiffies(50))) 112 msleep(25); 113} 114 115static void vdec_poweroff(struct amvdec_session *sess) 116{ 117 struct amvdec_ops *vdec_ops = sess->fmt_out->vdec_ops; 118 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 119 120 sess->should_stop = 1; 121 vdec_wait_inactive(sess); 122 if (codec_ops->drain) 123 codec_ops->drain(sess); 124 125 vdec_ops->stop(sess); 126 clk_disable_unprepare(sess->core->dos_clk); 127 clk_disable_unprepare(sess->core->dos_parser_clk); 128} 129 130static void 131vdec_queue_recycle(struct amvdec_session *sess, struct vb2_buffer *vb) 132{ 133 struct amvdec_buffer *new_buf; 134 135 new_buf = kmalloc(sizeof(*new_buf), GFP_KERNEL); 136 if (!new_buf) 137 return; 138 new_buf->vb = vb; 139 140 mutex_lock(&sess->bufs_recycle_lock); 141 list_add_tail(&new_buf->list, &sess->bufs_recycle); 142 mutex_unlock(&sess->bufs_recycle_lock); 143} 144 145static void vdec_m2m_device_run(void *priv) 146{ 147 struct amvdec_session *sess = priv; 148 149 schedule_work(&sess->esparser_queue_work); 150} 151 152static void vdec_m2m_job_abort(void *priv) 153{ 154 struct amvdec_session *sess = priv; 155 156 v4l2_m2m_job_finish(sess->m2m_dev, sess->m2m_ctx); 157} 158 159static const struct v4l2_m2m_ops vdec_m2m_ops = { 160 .device_run = vdec_m2m_device_run, 161 .job_abort = vdec_m2m_job_abort, 162}; 163 164static void process_num_buffers(struct vb2_queue *q, 165 struct amvdec_session *sess, 166 unsigned int *num_buffers, 167 bool is_reqbufs) 168{ 169 const struct amvdec_format *fmt_out = sess->fmt_out; 170 unsigned int q_num_bufs = vb2_get_num_buffers(q); 171 unsigned int buffers_total = q_num_bufs + *num_buffers; 172 u32 min_buf_capture = v4l2_ctrl_g_ctrl(sess->ctrl_min_buf_capture); 173 174 if (q_num_bufs + *num_buffers < min_buf_capture) 175 *num_buffers = min_buf_capture - q_num_bufs; 176 if (is_reqbufs && buffers_total < fmt_out->min_buffers) 177 *num_buffers = fmt_out->min_buffers - q_num_bufs; 178 if (buffers_total > fmt_out->max_buffers) 179 *num_buffers = fmt_out->max_buffers - q_num_bufs; 180 181 /* We need to program the complete CAPTURE buffer list 182 * in registers during start_streaming, and the firmwares 183 * are free to choose any of them to write frames to. As such, 184 * we need all of them to be queued into the driver 185 */ 186 sess->num_dst_bufs = q_num_bufs + *num_buffers; 187 q->min_queued_buffers = max(fmt_out->min_buffers, sess->num_dst_bufs); 188} 189 190static int vdec_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, 191 unsigned int *num_planes, unsigned int sizes[], 192 struct device *alloc_devs[]) 193{ 194 struct amvdec_session *sess = vb2_get_drv_priv(q); 195 u32 output_size = amvdec_get_output_size(sess); 196 197 if (*num_planes) { 198 switch (q->type) { 199 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 200 if (*num_planes != 1 || 201 sizes[0] < sess->src_buffer_size) 202 return -EINVAL; 203 break; 204 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 205 switch (sess->pixfmt_cap) { 206 case V4L2_PIX_FMT_NV12M: 207 if (*num_planes != 2 || 208 sizes[0] < output_size || 209 sizes[1] < output_size / 2) 210 return -EINVAL; 211 break; 212 case V4L2_PIX_FMT_YUV420M: 213 if (*num_planes != 3 || 214 sizes[0] < output_size || 215 sizes[1] < output_size / 4 || 216 sizes[2] < output_size / 4) 217 return -EINVAL; 218 break; 219 default: 220 return -EINVAL; 221 } 222 223 process_num_buffers(q, sess, num_buffers, false); 224 break; 225 } 226 227 return 0; 228 } 229 230 switch (q->type) { 231 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 232 sizes[0] = sess->src_buffer_size; 233 *num_planes = 1; 234 break; 235 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 236 switch (sess->pixfmt_cap) { 237 case V4L2_PIX_FMT_NV12M: 238 sizes[0] = output_size; 239 sizes[1] = output_size / 2; 240 *num_planes = 2; 241 break; 242 case V4L2_PIX_FMT_YUV420M: 243 sizes[0] = output_size; 244 sizes[1] = output_size / 4; 245 sizes[2] = output_size / 4; 246 *num_planes = 3; 247 break; 248 default: 249 return -EINVAL; 250 } 251 252 process_num_buffers(q, sess, num_buffers, true); 253 break; 254 default: 255 return -EINVAL; 256 } 257 258 sess->changed_format = 1; 259 return 0; 260} 261 262static void vdec_vb2_buf_queue(struct vb2_buffer *vb) 263{ 264 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 265 struct amvdec_session *sess = vb2_get_drv_priv(vb->vb2_queue); 266 struct v4l2_m2m_ctx *m2m_ctx = sess->m2m_ctx; 267 268 v4l2_m2m_buf_queue(m2m_ctx, vbuf); 269 270 if (!sess->streamon_out) 271 return; 272 273 if (sess->streamon_cap && 274 vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 275 vdec_codec_needs_recycle(sess)) 276 vdec_queue_recycle(sess, vb); 277 278 schedule_work(&sess->esparser_queue_work); 279} 280 281static int vdec_start_streaming(struct vb2_queue *q, unsigned int count) 282{ 283 struct amvdec_session *sess = vb2_get_drv_priv(q); 284 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 285 struct amvdec_core *core = sess->core; 286 struct vb2_v4l2_buffer *buf; 287 int ret; 288 289 if (core->cur_sess && core->cur_sess != sess) { 290 ret = -EBUSY; 291 goto bufs_done; 292 } 293 294 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 295 sess->streamon_out = 1; 296 else 297 sess->streamon_cap = 1; 298 299 if (!sess->streamon_out) 300 return 0; 301 302 if (sess->status == STATUS_NEEDS_RESUME && 303 q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 304 sess->changed_format) { 305 codec_ops->resume(sess); 306 sess->status = STATUS_RUNNING; 307 return 0; 308 } 309 310 if (sess->status == STATUS_RUNNING || 311 sess->status == STATUS_NEEDS_RESUME || 312 sess->status == STATUS_INIT) 313 return 0; 314 315 sess->vififo_size = SIZE_VIFIFO; 316 sess->vififo_vaddr = 317 dma_alloc_coherent(sess->core->dev, sess->vififo_size, 318 &sess->vififo_paddr, GFP_KERNEL); 319 if (!sess->vififo_vaddr) { 320 dev_err(sess->core->dev, "Failed to request VIFIFO buffer\n"); 321 ret = -ENOMEM; 322 goto bufs_done; 323 } 324 325 sess->should_stop = 0; 326 sess->keyframe_found = 0; 327 sess->last_offset = 0; 328 sess->wrap_count = 0; 329 sess->pixelaspect.numerator = 1; 330 sess->pixelaspect.denominator = 1; 331 atomic_set(&sess->esparser_queued_bufs, 0); 332 v4l2_ctrl_s_ctrl(sess->ctrl_min_buf_capture, 1); 333 334 ret = vdec_poweron(sess); 335 if (ret) 336 goto vififo_free; 337 338 sess->sequence_cap = 0; 339 sess->sequence_out = 0; 340 if (vdec_codec_needs_recycle(sess)) 341 sess->recycle_thread = kthread_run(vdec_recycle_thread, sess, 342 "vdec_recycle"); 343 344 sess->status = STATUS_INIT; 345 core->cur_sess = sess; 346 schedule_work(&sess->esparser_queue_work); 347 return 0; 348 349vififo_free: 350 dma_free_coherent(sess->core->dev, sess->vififo_size, 351 sess->vififo_vaddr, sess->vififo_paddr); 352bufs_done: 353 while ((buf = v4l2_m2m_src_buf_remove(sess->m2m_ctx))) 354 v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED); 355 while ((buf = v4l2_m2m_dst_buf_remove(sess->m2m_ctx))) 356 v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED); 357 358 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 359 sess->streamon_out = 0; 360 else 361 sess->streamon_cap = 0; 362 363 return ret; 364} 365 366static void vdec_free_canvas(struct amvdec_session *sess) 367{ 368 int i; 369 370 for (i = 0; i < sess->canvas_num; ++i) 371 meson_canvas_free(sess->core->canvas, sess->canvas_alloc[i]); 372 373 sess->canvas_num = 0; 374} 375 376static void vdec_reset_timestamps(struct amvdec_session *sess) 377{ 378 struct amvdec_timestamp *tmp, *n; 379 380 list_for_each_entry_safe(tmp, n, &sess->timestamps, list) { 381 list_del(&tmp->list); 382 kfree(tmp); 383 } 384} 385 386static void vdec_reset_bufs_recycle(struct amvdec_session *sess) 387{ 388 struct amvdec_buffer *tmp, *n; 389 390 list_for_each_entry_safe(tmp, n, &sess->bufs_recycle, list) { 391 list_del(&tmp->list); 392 kfree(tmp); 393 } 394} 395 396static void vdec_stop_streaming(struct vb2_queue *q) 397{ 398 struct amvdec_session *sess = vb2_get_drv_priv(q); 399 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 400 struct amvdec_core *core = sess->core; 401 struct vb2_v4l2_buffer *buf; 402 403 if (sess->status == STATUS_RUNNING || 404 sess->status == STATUS_INIT || 405 (sess->status == STATUS_NEEDS_RESUME && 406 (!sess->streamon_out || !sess->streamon_cap))) { 407 if (vdec_codec_needs_recycle(sess)) 408 kthread_stop(sess->recycle_thread); 409 410 vdec_poweroff(sess); 411 vdec_free_canvas(sess); 412 dma_free_coherent(sess->core->dev, sess->vififo_size, 413 sess->vififo_vaddr, sess->vififo_paddr); 414 vdec_reset_timestamps(sess); 415 vdec_reset_bufs_recycle(sess); 416 kfree(sess->priv); 417 sess->priv = NULL; 418 core->cur_sess = NULL; 419 sess->status = STATUS_STOPPED; 420 } 421 422 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 423 while ((buf = v4l2_m2m_src_buf_remove(sess->m2m_ctx))) 424 v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); 425 426 sess->streamon_out = 0; 427 } else { 428 /* Drain remaining refs if was still running */ 429 if (sess->status >= STATUS_RUNNING && codec_ops->drain) 430 codec_ops->drain(sess); 431 432 while ((buf = v4l2_m2m_dst_buf_remove(sess->m2m_ctx))) 433 v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); 434 435 sess->streamon_cap = 0; 436 } 437} 438 439static int vdec_vb2_buf_prepare(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 447static const struct vb2_ops vdec_vb2_ops = { 448 .queue_setup = vdec_queue_setup, 449 .start_streaming = vdec_start_streaming, 450 .stop_streaming = vdec_stop_streaming, 451 .buf_queue = vdec_vb2_buf_queue, 452 .buf_prepare = vdec_vb2_buf_prepare, 453 .wait_prepare = vb2_ops_wait_prepare, 454 .wait_finish = vb2_ops_wait_finish, 455}; 456 457static int 458vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 459{ 460 strscpy(cap->driver, "meson-vdec", sizeof(cap->driver)); 461 strscpy(cap->card, "Amlogic Video Decoder", sizeof(cap->card)); 462 strscpy(cap->bus_info, "platform:meson-vdec", sizeof(cap->bus_info)); 463 464 return 0; 465} 466 467static const struct amvdec_format * 468find_format(const struct amvdec_format *fmts, u32 size, u32 pixfmt) 469{ 470 unsigned int i; 471 472 for (i = 0; i < size; i++) { 473 if (fmts[i].pixfmt == pixfmt) 474 return &fmts[i]; 475 } 476 477 return NULL; 478} 479 480static unsigned int 481vdec_supports_pixfmt_cap(const struct amvdec_format *fmt_out, u32 pixfmt_cap) 482{ 483 int i; 484 485 for (i = 0; fmt_out->pixfmts_cap[i]; i++) 486 if (fmt_out->pixfmts_cap[i] == pixfmt_cap) 487 return 1; 488 489 return 0; 490} 491 492static const struct amvdec_format * 493vdec_try_fmt_common(struct amvdec_session *sess, u32 size, 494 struct v4l2_format *f) 495{ 496 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 497 struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; 498 const struct amvdec_format *fmts = sess->core->platform->formats; 499 const struct amvdec_format *fmt_out = NULL; 500 u32 output_size = 0; 501 502 memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); 503 memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); 504 505 switch (f->type) { 506 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 507 fmt_out = find_format(fmts, size, pixmp->pixelformat); 508 if (!fmt_out) { 509 pixmp->pixelformat = V4L2_PIX_FMT_MPEG2; 510 fmt_out = find_format(fmts, size, pixmp->pixelformat); 511 } 512 break; 513 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 514 fmt_out = sess->fmt_out; 515 break; 516 default: 517 return NULL; 518 } 519 520 pixmp->width = clamp(pixmp->width, (u32)256, fmt_out->max_width); 521 pixmp->height = clamp(pixmp->height, (u32)144, fmt_out->max_height); 522 output_size = get_output_size(pixmp->width, pixmp->height); 523 524 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 525 if (!pfmt[0].sizeimage) 526 pfmt[0].sizeimage = sess->src_buffer_size; 527 pfmt[0].bytesperline = 0; 528 pixmp->num_planes = 1; 529 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 530 fmt_out = sess->fmt_out; 531 if (!vdec_supports_pixfmt_cap(fmt_out, pixmp->pixelformat)) 532 pixmp->pixelformat = fmt_out->pixfmts_cap[0]; 533 534 memset(pfmt[1].reserved, 0, sizeof(pfmt[1].reserved)); 535 if (pixmp->pixelformat == V4L2_PIX_FMT_NV12M) { 536 pfmt[0].sizeimage = output_size; 537 pfmt[0].bytesperline = ALIGN(pixmp->width, 32); 538 539 pfmt[1].sizeimage = output_size / 2; 540 pfmt[1].bytesperline = ALIGN(pixmp->width, 32); 541 pixmp->num_planes = 2; 542 } else if (pixmp->pixelformat == V4L2_PIX_FMT_YUV420M) { 543 pfmt[0].sizeimage = output_size; 544 pfmt[0].bytesperline = ALIGN(pixmp->width, 32); 545 546 pfmt[1].sizeimage = output_size / 4; 547 pfmt[1].bytesperline = ALIGN(pixmp->width, 32) / 2; 548 549 pfmt[2].sizeimage = output_size / 2; 550 pfmt[2].bytesperline = ALIGN(pixmp->width, 32) / 2; 551 pixmp->num_planes = 3; 552 } 553 } 554 555 if (pixmp->field == V4L2_FIELD_ANY) 556 pixmp->field = V4L2_FIELD_NONE; 557 558 return fmt_out; 559} 560 561static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f) 562{ 563 struct amvdec_session *sess = 564 container_of(file->private_data, struct amvdec_session, fh); 565 566 vdec_try_fmt_common(sess, sess->core->platform->num_formats, f); 567 568 return 0; 569} 570 571static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) 572{ 573 struct amvdec_session *sess = 574 container_of(file->private_data, struct amvdec_session, fh); 575 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 576 577 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 578 pixmp->pixelformat = sess->pixfmt_cap; 579 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 580 pixmp->pixelformat = sess->fmt_out->pixfmt; 581 582 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 583 pixmp->width = sess->width; 584 pixmp->height = sess->height; 585 pixmp->colorspace = sess->colorspace; 586 pixmp->ycbcr_enc = sess->ycbcr_enc; 587 pixmp->quantization = sess->quantization; 588 pixmp->xfer_func = sess->xfer_func; 589 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 590 pixmp->width = sess->width; 591 pixmp->height = sess->height; 592 } 593 594 vdec_try_fmt_common(sess, sess->core->platform->num_formats, f); 595 596 return 0; 597} 598 599static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) 600{ 601 struct amvdec_session *sess = 602 container_of(file->private_data, struct amvdec_session, fh); 603 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 604 u32 num_formats = sess->core->platform->num_formats; 605 const struct amvdec_format *fmt_out; 606 struct v4l2_pix_format_mplane orig_pixmp; 607 struct v4l2_format format; 608 u32 pixfmt_out = 0, pixfmt_cap = 0; 609 610 orig_pixmp = *pixmp; 611 612 fmt_out = vdec_try_fmt_common(sess, num_formats, f); 613 if (!fmt_out) 614 return -EINVAL; 615 616 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 617 pixfmt_out = pixmp->pixelformat; 618 pixfmt_cap = sess->pixfmt_cap; 619 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 620 pixfmt_cap = pixmp->pixelformat; 621 pixfmt_out = sess->fmt_out->pixfmt; 622 } 623 624 memset(&format, 0, sizeof(format)); 625 626 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 627 format.fmt.pix_mp.pixelformat = pixfmt_out; 628 format.fmt.pix_mp.width = orig_pixmp.width; 629 format.fmt.pix_mp.height = orig_pixmp.height; 630 vdec_try_fmt_common(sess, num_formats, &format); 631 632 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 633 sess->width = format.fmt.pix_mp.width; 634 sess->height = format.fmt.pix_mp.height; 635 sess->colorspace = pixmp->colorspace; 636 sess->ycbcr_enc = pixmp->ycbcr_enc; 637 sess->quantization = pixmp->quantization; 638 sess->xfer_func = pixmp->xfer_func; 639 sess->src_buffer_size = pixmp->plane_fmt[0].sizeimage; 640 } 641 642 memset(&format, 0, sizeof(format)); 643 644 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 645 format.fmt.pix_mp.pixelformat = pixfmt_cap; 646 format.fmt.pix_mp.width = orig_pixmp.width; 647 format.fmt.pix_mp.height = orig_pixmp.height; 648 vdec_try_fmt_common(sess, num_formats, &format); 649 650 sess->width = format.fmt.pix_mp.width; 651 sess->height = format.fmt.pix_mp.height; 652 653 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 654 sess->fmt_out = fmt_out; 655 else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 656 sess->pixfmt_cap = format.fmt.pix_mp.pixelformat; 657 658 return 0; 659} 660 661static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) 662{ 663 struct amvdec_session *sess = 664 container_of(file->private_data, struct amvdec_session, fh); 665 const struct vdec_platform *platform = sess->core->platform; 666 const struct amvdec_format *fmt_out; 667 668 memset(f->reserved, 0, sizeof(f->reserved)); 669 670 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 671 if (f->index >= platform->num_formats) 672 return -EINVAL; 673 674 fmt_out = &platform->formats[f->index]; 675 f->pixelformat = fmt_out->pixfmt; 676 f->flags = fmt_out->flags; 677 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 678 fmt_out = sess->fmt_out; 679 if (f->index >= 4 || !fmt_out->pixfmts_cap[f->index]) 680 return -EINVAL; 681 682 f->pixelformat = fmt_out->pixfmts_cap[f->index]; 683 } else { 684 return -EINVAL; 685 } 686 687 return 0; 688} 689 690static int vdec_enum_framesizes(struct file *file, void *fh, 691 struct v4l2_frmsizeenum *fsize) 692{ 693 struct amvdec_session *sess = 694 container_of(file->private_data, struct amvdec_session, fh); 695 const struct amvdec_format *formats = sess->core->platform->formats; 696 const struct amvdec_format *fmt; 697 u32 num_formats = sess->core->platform->num_formats; 698 699 fmt = find_format(formats, num_formats, fsize->pixel_format); 700 if (!fmt || fsize->index) 701 return -EINVAL; 702 703 fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; 704 705 fsize->stepwise.min_width = 256; 706 fsize->stepwise.max_width = fmt->max_width; 707 fsize->stepwise.step_width = 1; 708 fsize->stepwise.min_height = 144; 709 fsize->stepwise.max_height = fmt->max_height; 710 fsize->stepwise.step_height = 1; 711 712 return 0; 713} 714 715static int 716vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) 717{ 718 struct amvdec_session *sess = 719 container_of(file->private_data, struct amvdec_session, fh); 720 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 721 struct device *dev = sess->core->dev; 722 int ret; 723 724 ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd); 725 if (ret) 726 return ret; 727 728 if (!(sess->streamon_out & sess->streamon_cap)) 729 return 0; 730 731 if (cmd->cmd == V4L2_DEC_CMD_START) { 732 v4l2_m2m_clear_state(sess->m2m_ctx); 733 sess->should_stop = 0; 734 return 0; 735 } 736 737 /* Should not happen */ 738 if (cmd->cmd != V4L2_DEC_CMD_STOP) 739 return -EINVAL; 740 741 dev_dbg(dev, "Received V4L2_DEC_CMD_STOP\n"); 742 743 sess->should_stop = 1; 744 745 v4l2_m2m_mark_stopped(sess->m2m_ctx); 746 747 if (codec_ops->drain) { 748 vdec_wait_inactive(sess); 749 codec_ops->drain(sess); 750 } else if (codec_ops->eos_sequence) { 751 u32 len; 752 const u8 *data = codec_ops->eos_sequence(&len); 753 754 esparser_queue_eos(sess->core, data, len); 755 vdec_wait_inactive(sess); 756 } 757 758 return ret; 759} 760 761static int vdec_subscribe_event(struct v4l2_fh *fh, 762 const struct v4l2_event_subscription *sub) 763{ 764 switch (sub->type) { 765 case V4L2_EVENT_EOS: 766 case V4L2_EVENT_SOURCE_CHANGE: 767 return v4l2_event_subscribe(fh, sub, 0, NULL); 768 case V4L2_EVENT_CTRL: 769 return v4l2_ctrl_subscribe_event(fh, sub); 770 default: 771 return -EINVAL; 772 } 773} 774 775static int vdec_g_pixelaspect(struct file *file, void *fh, int type, 776 struct v4l2_fract *f) 777{ 778 struct amvdec_session *sess = 779 container_of(file->private_data, struct amvdec_session, fh); 780 781 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 782 return -EINVAL; 783 784 *f = sess->pixelaspect; 785 return 0; 786} 787 788static const struct v4l2_ioctl_ops vdec_ioctl_ops = { 789 .vidioc_querycap = vdec_querycap, 790 .vidioc_enum_fmt_vid_cap = vdec_enum_fmt, 791 .vidioc_enum_fmt_vid_out = vdec_enum_fmt, 792 .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt, 793 .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt, 794 .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt, 795 .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt, 796 .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt, 797 .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt, 798 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 799 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 800 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 801 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 802 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 803 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 804 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 805 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 806 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 807 .vidioc_enum_framesizes = vdec_enum_framesizes, 808 .vidioc_subscribe_event = vdec_subscribe_event, 809 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 810 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, 811 .vidioc_decoder_cmd = vdec_decoder_cmd, 812 .vidioc_g_pixelaspect = vdec_g_pixelaspect, 813}; 814 815static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, 816 struct vb2_queue *dst_vq) 817{ 818 struct amvdec_session *sess = priv; 819 int ret; 820 821 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 822 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 823 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 824 src_vq->ops = &vdec_vb2_ops; 825 src_vq->mem_ops = &vb2_dma_contig_memops; 826 src_vq->drv_priv = sess; 827 src_vq->buf_struct_size = sizeof(struct dummy_buf); 828 src_vq->min_queued_buffers = 1; 829 src_vq->dev = sess->core->dev; 830 src_vq->lock = &sess->lock; 831 ret = vb2_queue_init(src_vq); 832 if (ret) 833 return ret; 834 835 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 836 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 837 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 838 dst_vq->ops = &vdec_vb2_ops; 839 dst_vq->mem_ops = &vb2_dma_contig_memops; 840 dst_vq->drv_priv = sess; 841 dst_vq->buf_struct_size = sizeof(struct dummy_buf); 842 dst_vq->min_queued_buffers = 1; 843 dst_vq->dev = sess->core->dev; 844 dst_vq->lock = &sess->lock; 845 return vb2_queue_init(dst_vq); 846} 847 848static int vdec_init_ctrls(struct amvdec_session *sess) 849{ 850 struct v4l2_ctrl_handler *ctrl_handler = &sess->ctrl_handler; 851 int ret; 852 853 ret = v4l2_ctrl_handler_init(ctrl_handler, 1); 854 if (ret) 855 return ret; 856 857 sess->ctrl_min_buf_capture = 858 v4l2_ctrl_new_std(ctrl_handler, NULL, 859 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 860 1); 861 862 ret = ctrl_handler->error; 863 if (ret) { 864 v4l2_ctrl_handler_free(ctrl_handler); 865 return ret; 866 } 867 868 return 0; 869} 870 871static int vdec_open(struct file *file) 872{ 873 struct amvdec_core *core = video_drvdata(file); 874 struct device *dev = core->dev; 875 const struct amvdec_format *formats = core->platform->formats; 876 struct amvdec_session *sess; 877 int ret; 878 879 sess = kzalloc(sizeof(*sess), GFP_KERNEL); 880 if (!sess) 881 return -ENOMEM; 882 883 sess->core = core; 884 885 sess->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops); 886 if (IS_ERR(sess->m2m_dev)) { 887 dev_err(dev, "Fail to v4l2_m2m_init\n"); 888 ret = PTR_ERR(sess->m2m_dev); 889 goto err_free_sess; 890 } 891 892 sess->m2m_ctx = v4l2_m2m_ctx_init(sess->m2m_dev, sess, m2m_queue_init); 893 if (IS_ERR(sess->m2m_ctx)) { 894 dev_err(dev, "Fail to v4l2_m2m_ctx_init\n"); 895 ret = PTR_ERR(sess->m2m_ctx); 896 goto err_m2m_release; 897 } 898 899 ret = vdec_init_ctrls(sess); 900 if (ret) 901 goto err_m2m_release; 902 903 sess->pixfmt_cap = formats[0].pixfmts_cap[0]; 904 sess->fmt_out = &formats[0]; 905 sess->width = 1280; 906 sess->height = 720; 907 sess->pixelaspect.numerator = 1; 908 sess->pixelaspect.denominator = 1; 909 sess->src_buffer_size = SZ_1M; 910 911 INIT_LIST_HEAD(&sess->timestamps); 912 INIT_LIST_HEAD(&sess->bufs_recycle); 913 INIT_WORK(&sess->esparser_queue_work, esparser_queue_all_src); 914 mutex_init(&sess->lock); 915 mutex_init(&sess->bufs_recycle_lock); 916 spin_lock_init(&sess->ts_spinlock); 917 918 v4l2_fh_init(&sess->fh, core->vdev_dec); 919 sess->fh.ctrl_handler = &sess->ctrl_handler; 920 v4l2_fh_add(&sess->fh); 921 sess->fh.m2m_ctx = sess->m2m_ctx; 922 file->private_data = &sess->fh; 923 924 return 0; 925 926err_m2m_release: 927 v4l2_m2m_release(sess->m2m_dev); 928err_free_sess: 929 kfree(sess); 930 return ret; 931} 932 933static int vdec_close(struct file *file) 934{ 935 struct amvdec_session *sess = 936 container_of(file->private_data, struct amvdec_session, fh); 937 938 v4l2_m2m_ctx_release(sess->m2m_ctx); 939 v4l2_m2m_release(sess->m2m_dev); 940 v4l2_fh_del(&sess->fh); 941 v4l2_fh_exit(&sess->fh); 942 943 mutex_destroy(&sess->lock); 944 mutex_destroy(&sess->bufs_recycle_lock); 945 946 kfree(sess); 947 948 return 0; 949} 950 951static const struct v4l2_file_operations vdec_fops = { 952 .owner = THIS_MODULE, 953 .open = vdec_open, 954 .release = vdec_close, 955 .unlocked_ioctl = video_ioctl2, 956 .poll = v4l2_m2m_fop_poll, 957 .mmap = v4l2_m2m_fop_mmap, 958}; 959 960static irqreturn_t vdec_isr(int irq, void *data) 961{ 962 struct amvdec_core *core = data; 963 struct amvdec_session *sess = core->cur_sess; 964 965 sess->last_irq_jiffies = get_jiffies_64(); 966 967 return sess->fmt_out->codec_ops->isr(sess); 968} 969 970static irqreturn_t vdec_threaded_isr(int irq, void *data) 971{ 972 struct amvdec_core *core = data; 973 struct amvdec_session *sess = core->cur_sess; 974 975 return sess->fmt_out->codec_ops->threaded_isr(sess); 976} 977 978static const struct of_device_id vdec_dt_match[] = { 979 { .compatible = "amlogic,gxbb-vdec", 980 .data = &vdec_platform_gxbb }, 981 { .compatible = "amlogic,gxm-vdec", 982 .data = &vdec_platform_gxm }, 983 { .compatible = "amlogic,gxl-vdec", 984 .data = &vdec_platform_gxl }, 985 { .compatible = "amlogic,g12a-vdec", 986 .data = &vdec_platform_g12a }, 987 { .compatible = "amlogic,sm1-vdec", 988 .data = &vdec_platform_sm1 }, 989 {} 990}; 991MODULE_DEVICE_TABLE(of, vdec_dt_match); 992 993static int vdec_probe(struct platform_device *pdev) 994{ 995 struct device *dev = &pdev->dev; 996 struct video_device *vdev; 997 struct amvdec_core *core; 998 const struct of_device_id *of_id; 999 int irq; 1000 int ret; 1001 1002 core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); 1003 if (!core) 1004 return -ENOMEM; 1005 1006 core->dev = dev; 1007 platform_set_drvdata(pdev, core); 1008 1009 core->dos_base = devm_platform_ioremap_resource_byname(pdev, "dos"); 1010 if (IS_ERR(core->dos_base)) 1011 return PTR_ERR(core->dos_base); 1012 1013 core->esparser_base = devm_platform_ioremap_resource_byname(pdev, "esparser"); 1014 if (IS_ERR(core->esparser_base)) 1015 return PTR_ERR(core->esparser_base); 1016 1017 core->regmap_ao = 1018 syscon_regmap_lookup_by_phandle(dev->of_node, 1019 "amlogic,ao-sysctrl"); 1020 if (IS_ERR(core->regmap_ao)) { 1021 dev_err(dev, "Couldn't regmap AO sysctrl\n"); 1022 return PTR_ERR(core->regmap_ao); 1023 } 1024 1025 core->canvas = meson_canvas_get(dev); 1026 if (IS_ERR(core->canvas)) 1027 return PTR_ERR(core->canvas); 1028 1029 of_id = of_match_node(vdec_dt_match, dev->of_node); 1030 core->platform = of_id->data; 1031 1032 if (core->platform->revision == VDEC_REVISION_G12A || 1033 core->platform->revision == VDEC_REVISION_SM1) { 1034 core->vdec_hevcf_clk = devm_clk_get(dev, "vdec_hevcf"); 1035 if (IS_ERR(core->vdec_hevcf_clk)) 1036 return -EPROBE_DEFER; 1037 } 1038 1039 core->dos_parser_clk = devm_clk_get(dev, "dos_parser"); 1040 if (IS_ERR(core->dos_parser_clk)) 1041 return -EPROBE_DEFER; 1042 1043 core->dos_clk = devm_clk_get(dev, "dos"); 1044 if (IS_ERR(core->dos_clk)) 1045 return -EPROBE_DEFER; 1046 1047 core->vdec_1_clk = devm_clk_get(dev, "vdec_1"); 1048 if (IS_ERR(core->vdec_1_clk)) 1049 return -EPROBE_DEFER; 1050 1051 core->vdec_hevc_clk = devm_clk_get(dev, "vdec_hevc"); 1052 if (IS_ERR(core->vdec_hevc_clk)) 1053 return -EPROBE_DEFER; 1054 1055 irq = platform_get_irq_byname(pdev, "vdec"); 1056 if (irq < 0) 1057 return irq; 1058 1059 ret = devm_request_threaded_irq(core->dev, irq, vdec_isr, 1060 vdec_threaded_isr, IRQF_ONESHOT, 1061 "vdec", core); 1062 if (ret) 1063 return ret; 1064 1065 ret = esparser_init(pdev, core); 1066 if (ret) 1067 return ret; 1068 1069 ret = v4l2_device_register(dev, &core->v4l2_dev); 1070 if (ret) { 1071 dev_err(dev, "Couldn't register v4l2 device\n"); 1072 return -ENOMEM; 1073 } 1074 1075 vdev = video_device_alloc(); 1076 if (!vdev) { 1077 ret = -ENOMEM; 1078 goto err_vdev_release; 1079 } 1080 1081 core->vdev_dec = vdev; 1082 core->dev_dec = dev; 1083 mutex_init(&core->lock); 1084 1085 strscpy(vdev->name, "meson-video-decoder", sizeof(vdev->name)); 1086 vdev->release = video_device_release; 1087 vdev->fops = &vdec_fops; 1088 vdev->ioctl_ops = &vdec_ioctl_ops; 1089 vdev->vfl_dir = VFL_DIR_M2M; 1090 vdev->v4l2_dev = &core->v4l2_dev; 1091 vdev->lock = &core->lock; 1092 vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 1093 1094 video_set_drvdata(vdev, core); 1095 1096 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 1097 if (ret) { 1098 dev_err(dev, "Failed registering video device\n"); 1099 goto err_vdev_release; 1100 } 1101 1102 return 0; 1103 1104err_vdev_release: 1105 video_device_release(vdev); 1106 v4l2_device_unregister(&core->v4l2_dev); 1107 return ret; 1108} 1109 1110static void vdec_remove(struct platform_device *pdev) 1111{ 1112 struct amvdec_core *core = platform_get_drvdata(pdev); 1113 1114 video_unregister_device(core->vdev_dec); 1115 v4l2_device_unregister(&core->v4l2_dev); 1116} 1117 1118static struct platform_driver meson_vdec_driver = { 1119 .probe = vdec_probe, 1120 .remove_new = vdec_remove, 1121 .driver = { 1122 .name = "meson-vdec", 1123 .of_match_table = vdec_dt_match, 1124 }, 1125}; 1126module_platform_driver(meson_vdec_driver); 1127 1128MODULE_DESCRIPTION("Meson video decoder driver for GXBB/GXL/GXM/G12/SM1"); 1129MODULE_AUTHOR("Maxime Jourdan <mjourdan@baylibre.com>"); 1130MODULE_LICENSE("GPL"); 1131