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