linux/drivers/media/platform/m2m-deinterlace.c
<<
>>
Prefs
   1/*
   2 * V4L2 deinterlacing support.
   3 *
   4 * Copyright (c) 2012 Vista Silicon S.L.
   5 * Javier Martin <javier.martin@vista-silicon.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by the
   9 * Free Software Foundation; either version 2 of the
  10 * License, or (at your option) any later version
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/slab.h>
  15#include <linux/interrupt.h>
  16#include <linux/dmaengine.h>
  17#include <linux/platform_device.h>
  18
  19#include <media/v4l2-mem2mem.h>
  20#include <media/v4l2-device.h>
  21#include <media/v4l2-ioctl.h>
  22#include <media/videobuf2-dma-contig.h>
  23
  24#define MEM2MEM_TEST_MODULE_NAME "mem2mem-deinterlace"
  25
  26MODULE_DESCRIPTION("mem2mem device which supports deinterlacing using dmaengine");
  27MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
  28MODULE_LICENSE("GPL");
  29MODULE_VERSION("0.0.1");
  30
  31static bool debug;
  32module_param(debug, bool, 0644);
  33
  34/* Flags that indicate a format can be used for capture/output */
  35#define MEM2MEM_CAPTURE (1 << 0)
  36#define MEM2MEM_OUTPUT  (1 << 1)
  37
  38#define MEM2MEM_NAME            "m2m-deinterlace"
  39
  40#define dprintk(dev, fmt, arg...) \
  41        v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
  42
  43struct deinterlace_fmt {
  44        char    *name;
  45        u32     fourcc;
  46        /* Types the format can be used for */
  47        u32     types;
  48};
  49
  50static struct deinterlace_fmt formats[] = {
  51        {
  52                .name   = "YUV 4:2:0 Planar",
  53                .fourcc = V4L2_PIX_FMT_YUV420,
  54                .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
  55        },
  56        {
  57                .name   = "YUYV 4:2:2",
  58                .fourcc = V4L2_PIX_FMT_YUYV,
  59                .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
  60        },
  61};
  62
  63#define NUM_FORMATS ARRAY_SIZE(formats)
  64
  65/* Per-queue, driver-specific private data */
  66struct deinterlace_q_data {
  67        unsigned int            width;
  68        unsigned int            height;
  69        unsigned int            sizeimage;
  70        struct deinterlace_fmt  *fmt;
  71        enum v4l2_field         field;
  72};
  73
  74enum {
  75        V4L2_M2M_SRC = 0,
  76        V4L2_M2M_DST = 1,
  77};
  78
  79enum {
  80        YUV420_DMA_Y_ODD,
  81        YUV420_DMA_Y_EVEN,
  82        YUV420_DMA_U_ODD,
  83        YUV420_DMA_U_EVEN,
  84        YUV420_DMA_V_ODD,
  85        YUV420_DMA_V_EVEN,
  86        YUV420_DMA_Y_ODD_DOUBLING,
  87        YUV420_DMA_U_ODD_DOUBLING,
  88        YUV420_DMA_V_ODD_DOUBLING,
  89        YUYV_DMA_ODD,
  90        YUYV_DMA_EVEN,
  91        YUYV_DMA_EVEN_DOUBLING,
  92};
  93
  94/* Source and destination queue data */
  95static struct deinterlace_q_data q_data[2];
  96
  97static struct deinterlace_q_data *get_q_data(enum v4l2_buf_type type)
  98{
  99        switch (type) {
 100        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 101                return &q_data[V4L2_M2M_SRC];
 102        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 103                return &q_data[V4L2_M2M_DST];
 104        default:
 105                BUG();
 106        }
 107        return NULL;
 108}
 109
 110static struct deinterlace_fmt *find_format(struct v4l2_format *f)
 111{
 112        struct deinterlace_fmt *fmt;
 113        unsigned int k;
 114
 115        for (k = 0; k < NUM_FORMATS; k++) {
 116                fmt = &formats[k];
 117                if ((fmt->types & f->type) &&
 118                        (fmt->fourcc == f->fmt.pix.pixelformat))
 119                        break;
 120        }
 121
 122        if (k == NUM_FORMATS)
 123                return NULL;
 124
 125        return &formats[k];
 126}
 127
 128struct deinterlace_dev {
 129        struct v4l2_device      v4l2_dev;
 130        struct video_device     *vfd;
 131
 132        atomic_t                busy;
 133        struct mutex            dev_mutex;
 134        spinlock_t              irqlock;
 135
 136        struct dma_chan         *dma_chan;
 137
 138        struct v4l2_m2m_dev     *m2m_dev;
 139        struct vb2_alloc_ctx    *alloc_ctx;
 140};
 141
 142struct deinterlace_ctx {
 143        struct deinterlace_dev  *dev;
 144
 145        /* Abort requested by m2m */
 146        int                     aborting;
 147        enum v4l2_colorspace    colorspace;
 148        dma_cookie_t            cookie;
 149        struct v4l2_m2m_ctx     *m2m_ctx;
 150        struct dma_interleaved_template *xt;
 151};
 152
 153/*
 154 * mem2mem callbacks
 155 */
 156static int deinterlace_job_ready(void *priv)
 157{
 158        struct deinterlace_ctx *ctx = priv;
 159        struct deinterlace_dev *pcdev = ctx->dev;
 160
 161        if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0)
 162            && (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0)
 163            && (atomic_read(&ctx->dev->busy) == 0)) {
 164                dprintk(pcdev, "Task ready\n");
 165                return 1;
 166        }
 167
 168        dprintk(pcdev, "Task not ready to run\n");
 169
 170        return 0;
 171}
 172
 173static void deinterlace_job_abort(void *priv)
 174{
 175        struct deinterlace_ctx *ctx = priv;
 176        struct deinterlace_dev *pcdev = ctx->dev;
 177
 178        ctx->aborting = 1;
 179
 180        dprintk(pcdev, "Aborting task\n");
 181
 182        v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx);
 183}
 184
 185static void deinterlace_lock(void *priv)
 186{
 187        struct deinterlace_ctx *ctx = priv;
 188        struct deinterlace_dev *pcdev = ctx->dev;
 189        mutex_lock(&pcdev->dev_mutex);
 190}
 191
 192static void deinterlace_unlock(void *priv)
 193{
 194        struct deinterlace_ctx *ctx = priv;
 195        struct deinterlace_dev *pcdev = ctx->dev;
 196        mutex_unlock(&pcdev->dev_mutex);
 197}
 198
 199static void dma_callback(void *data)
 200{
 201        struct deinterlace_ctx *curr_ctx = data;
 202        struct deinterlace_dev *pcdev = curr_ctx->dev;
 203        struct vb2_buffer *src_vb, *dst_vb;
 204
 205        atomic_set(&pcdev->busy, 0);
 206
 207        src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
 208        dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
 209
 210        src_vb->v4l2_buf.timestamp = dst_vb->v4l2_buf.timestamp;
 211        src_vb->v4l2_buf.timecode = dst_vb->v4l2_buf.timecode;
 212
 213        v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
 214        v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
 215
 216        v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
 217
 218        dprintk(pcdev, "dma transfers completed.\n");
 219}
 220
 221static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
 222                                  int do_callback)
 223{
 224        struct deinterlace_q_data *s_q_data;
 225        struct vb2_buffer *src_buf, *dst_buf;
 226        struct deinterlace_dev *pcdev = ctx->dev;
 227        struct dma_chan *chan = pcdev->dma_chan;
 228        struct dma_device *dmadev = chan->device;
 229        struct dma_async_tx_descriptor *tx;
 230        unsigned int s_width, s_height;
 231        unsigned int s_size;
 232        dma_addr_t p_in, p_out;
 233        enum dma_ctrl_flags flags;
 234
 235        src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 236        dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 237
 238        s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
 239        s_width = s_q_data->width;
 240        s_height = s_q_data->height;
 241        s_size = s_width * s_height;
 242
 243        p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
 244        p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 245        if (!p_in || !p_out) {
 246                v4l2_err(&pcdev->v4l2_dev,
 247                         "Acquiring kernel pointers to buffers failed\n");
 248                return;
 249        }
 250
 251        switch (op) {
 252        case YUV420_DMA_Y_ODD:
 253                ctx->xt->numf = s_height / 2;
 254                ctx->xt->sgl[0].size = s_width;
 255                ctx->xt->sgl[0].icg = s_width;
 256                ctx->xt->src_start = p_in;
 257                ctx->xt->dst_start = p_out;
 258                break;
 259        case YUV420_DMA_Y_EVEN:
 260                ctx->xt->numf = s_height / 2;
 261                ctx->xt->sgl[0].size = s_width;
 262                ctx->xt->sgl[0].icg = s_width;
 263                ctx->xt->src_start = p_in + s_size / 2;
 264                ctx->xt->dst_start = p_out + s_width;
 265                break;
 266        case YUV420_DMA_U_ODD:
 267                ctx->xt->numf = s_height / 4;
 268                ctx->xt->sgl[0].size = s_width / 2;
 269                ctx->xt->sgl[0].icg = s_width / 2;
 270                ctx->xt->src_start = p_in + s_size;
 271                ctx->xt->dst_start = p_out + s_size;
 272                break;
 273        case YUV420_DMA_U_EVEN:
 274                ctx->xt->numf = s_height / 4;
 275                ctx->xt->sgl[0].size = s_width / 2;
 276                ctx->xt->sgl[0].icg = s_width / 2;
 277                ctx->xt->src_start = p_in + (9 * s_size) / 8;
 278                ctx->xt->dst_start = p_out + s_size + s_width / 2;
 279                break;
 280        case YUV420_DMA_V_ODD:
 281                ctx->xt->numf = s_height / 4;
 282                ctx->xt->sgl[0].size = s_width / 2;
 283                ctx->xt->sgl[0].icg = s_width / 2;
 284                ctx->xt->src_start = p_in + (5 * s_size) / 4;
 285                ctx->xt->dst_start = p_out + (5 * s_size) / 4;
 286                break;
 287        case YUV420_DMA_V_EVEN:
 288                ctx->xt->numf = s_height / 4;
 289                ctx->xt->sgl[0].size = s_width / 2;
 290                ctx->xt->sgl[0].icg = s_width / 2;
 291                ctx->xt->src_start = p_in + (11 * s_size) / 8;
 292                ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2;
 293                break;
 294        case YUV420_DMA_Y_ODD_DOUBLING:
 295                ctx->xt->numf = s_height / 2;
 296                ctx->xt->sgl[0].size = s_width;
 297                ctx->xt->sgl[0].icg = s_width;
 298                ctx->xt->src_start = p_in;
 299                ctx->xt->dst_start = p_out + s_width;
 300                break;
 301        case YUV420_DMA_U_ODD_DOUBLING:
 302                ctx->xt->numf = s_height / 4;
 303                ctx->xt->sgl[0].size = s_width / 2;
 304                ctx->xt->sgl[0].icg = s_width / 2;
 305                ctx->xt->src_start = p_in + s_size;
 306                ctx->xt->dst_start = p_out + s_size + s_width / 2;
 307                break;
 308        case YUV420_DMA_V_ODD_DOUBLING:
 309                ctx->xt->numf = s_height / 4;
 310                ctx->xt->sgl[0].size = s_width / 2;
 311                ctx->xt->sgl[0].icg = s_width / 2;
 312                ctx->xt->src_start = p_in + (5 * s_size) / 4;
 313                ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2;
 314                break;
 315        case YUYV_DMA_ODD:
 316                ctx->xt->numf = s_height / 2;
 317                ctx->xt->sgl[0].size = s_width * 2;
 318                ctx->xt->sgl[0].icg = s_width * 2;
 319                ctx->xt->src_start = p_in;
 320                ctx->xt->dst_start = p_out;
 321                break;
 322        case YUYV_DMA_EVEN:
 323                ctx->xt->numf = s_height / 2;
 324                ctx->xt->sgl[0].size = s_width * 2;
 325                ctx->xt->sgl[0].icg = s_width * 2;
 326                ctx->xt->src_start = p_in + s_size;
 327                ctx->xt->dst_start = p_out + s_width * 2;
 328                break;
 329        case YUYV_DMA_EVEN_DOUBLING:
 330        default:
 331                ctx->xt->numf = s_height / 2;
 332                ctx->xt->sgl[0].size = s_width * 2;
 333                ctx->xt->sgl[0].icg = s_width * 2;
 334                ctx->xt->src_start = p_in;
 335                ctx->xt->dst_start = p_out + s_width * 2;
 336                break;
 337        }
 338
 339        /* Common parameters for al transfers */
 340        ctx->xt->frame_size = 1;
 341        ctx->xt->dir = DMA_MEM_TO_MEM;
 342        ctx->xt->src_sgl = false;
 343        ctx->xt->dst_sgl = true;
 344        flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT |
 345                DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SKIP_SRC_UNMAP;
 346
 347        tx = dmadev->device_prep_interleaved_dma(chan, ctx->xt, flags);
 348        if (tx == NULL) {
 349                v4l2_warn(&pcdev->v4l2_dev, "DMA interleaved prep error\n");
 350                return;
 351        }
 352
 353        if (do_callback) {
 354                tx->callback = dma_callback;
 355                tx->callback_param = ctx;
 356        }
 357
 358        ctx->cookie = dmaengine_submit(tx);
 359        if (dma_submit_error(ctx->cookie)) {
 360                v4l2_warn(&pcdev->v4l2_dev,
 361                          "DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n",
 362                          ctx->cookie, (unsigned)p_in, (unsigned)p_out,
 363                          s_size * 3/2);
 364                return;
 365        }
 366
 367        dma_async_issue_pending(chan);
 368}
 369
 370static void deinterlace_device_run(void *priv)
 371{
 372        struct deinterlace_ctx *ctx = priv;
 373        struct deinterlace_q_data *dst_q_data;
 374
 375        atomic_set(&ctx->dev->busy, 1);
 376
 377        dprintk(ctx->dev, "%s: DMA try issue.\n", __func__);
 378
 379        dst_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
 380
 381        /*
 382         * 4 possible field conversions are possible at the moment:
 383         *  V4L2_FIELD_SEQ_TB --> V4L2_FIELD_INTERLACED_TB:
 384         *      two separate fields in the same input buffer are interlaced
 385         *      in the output buffer using weaving. Top field comes first.
 386         *  V4L2_FIELD_SEQ_TB --> V4L2_FIELD_NONE:
 387         *      top field from the input buffer is copied to the output buffer
 388         *      using line doubling. Bottom field from the input buffer is discarded.
 389         * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_INTERLACED_BT:
 390         *      two separate fields in the same input buffer are interlaced
 391         *      in the output buffer using weaving. Bottom field comes first.
 392         * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_NONE:
 393         *      bottom field from the input buffer is copied to the output buffer
 394         *      using line doubling. Top field from the input buffer is discarded.
 395         */
 396        switch (dst_q_data->fmt->fourcc) {
 397        case V4L2_PIX_FMT_YUV420:
 398                switch (dst_q_data->field) {
 399                case V4L2_FIELD_INTERLACED_TB:
 400                case V4L2_FIELD_INTERLACED_BT:
 401                        dprintk(ctx->dev, "%s: yuv420 interlaced tb.\n",
 402                                __func__);
 403                        deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0);
 404                        deinterlace_issue_dma(ctx, YUV420_DMA_Y_EVEN, 0);
 405                        deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0);
 406                        deinterlace_issue_dma(ctx, YUV420_DMA_U_EVEN, 0);
 407                        deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0);
 408                        deinterlace_issue_dma(ctx, YUV420_DMA_V_EVEN, 1);
 409                        break;
 410                case V4L2_FIELD_NONE:
 411                default:
 412                        dprintk(ctx->dev, "%s: yuv420 interlaced line doubling.\n",
 413                                __func__);
 414                        deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0);
 415                        deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD_DOUBLING, 0);
 416                        deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0);
 417                        deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD_DOUBLING, 0);
 418                        deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0);
 419                        deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD_DOUBLING, 1);
 420                        break;
 421                }
 422                break;
 423        case V4L2_PIX_FMT_YUYV:
 424        default:
 425                switch (dst_q_data->field) {
 426                case V4L2_FIELD_INTERLACED_TB:
 427                case V4L2_FIELD_INTERLACED_BT:
 428                        dprintk(ctx->dev, "%s: yuyv interlaced_tb.\n",
 429                                __func__);
 430                        deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0);
 431                        deinterlace_issue_dma(ctx, YUYV_DMA_EVEN, 1);
 432                        break;
 433                case V4L2_FIELD_NONE:
 434                default:
 435                        dprintk(ctx->dev, "%s: yuyv interlaced line doubling.\n",
 436                                __func__);
 437                        deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0);
 438                        deinterlace_issue_dma(ctx, YUYV_DMA_EVEN_DOUBLING, 1);
 439                        break;
 440                }
 441                break;
 442        }
 443
 444        dprintk(ctx->dev, "%s: DMA issue done.\n", __func__);
 445}
 446
 447/*
 448 * video ioctls
 449 */
 450static int vidioc_querycap(struct file *file, void *priv,
 451                           struct v4l2_capability *cap)
 452{
 453        strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
 454        strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
 455        strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card));
 456        /*
 457         * This is only a mem-to-mem video device. The capture and output
 458         * device capability flags are left only for backward compatibility
 459         * and are scheduled for removal.
 460         */
 461        cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
 462                           V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
 463        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 464
 465        return 0;
 466}
 467
 468static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
 469{
 470        int i, num;
 471        struct deinterlace_fmt *fmt;
 472
 473        num = 0;
 474
 475        for (i = 0; i < NUM_FORMATS; ++i) {
 476                if (formats[i].types & type) {
 477                        /* index-th format of type type found ? */
 478                        if (num == f->index)
 479                                break;
 480                        /* Correct type but haven't reached our index yet,
 481                         * just increment per-type index */
 482                        ++num;
 483                }
 484        }
 485
 486        if (i < NUM_FORMATS) {
 487                /* Format found */
 488                fmt = &formats[i];
 489                strlcpy(f->description, fmt->name, sizeof(f->description));
 490                f->pixelformat = fmt->fourcc;
 491                return 0;
 492        }
 493
 494        /* Format not found */
 495        return -EINVAL;
 496}
 497
 498static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 499                                   struct v4l2_fmtdesc *f)
 500{
 501        return enum_fmt(f, MEM2MEM_CAPTURE);
 502}
 503
 504static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
 505                                   struct v4l2_fmtdesc *f)
 506{
 507        return enum_fmt(f, MEM2MEM_OUTPUT);
 508}
 509
 510static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
 511{
 512        struct vb2_queue *vq;
 513        struct deinterlace_q_data *q_data;
 514
 515        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 516        if (!vq)
 517                return -EINVAL;
 518
 519        q_data = get_q_data(f->type);
 520
 521        f->fmt.pix.width        = q_data->width;
 522        f->fmt.pix.height       = q_data->height;
 523        f->fmt.pix.field        = q_data->field;
 524        f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
 525
 526        switch (q_data->fmt->fourcc) {
 527        case V4L2_PIX_FMT_YUV420:
 528                f->fmt.pix.bytesperline = q_data->width * 3 / 2;
 529                break;
 530        case V4L2_PIX_FMT_YUYV:
 531        default:
 532                f->fmt.pix.bytesperline = q_data->width * 2;
 533        }
 534
 535        f->fmt.pix.sizeimage    = q_data->sizeimage;
 536        f->fmt.pix.colorspace   = ctx->colorspace;
 537
 538        return 0;
 539}
 540
 541static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
 542                                struct v4l2_format *f)
 543{
 544        return vidioc_g_fmt(priv, f);
 545}
 546
 547static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 548                                struct v4l2_format *f)
 549{
 550        return vidioc_g_fmt(priv, f);
 551}
 552
 553static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt)
 554{
 555        switch (f->fmt.pix.pixelformat) {
 556        case V4L2_PIX_FMT_YUV420:
 557                f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
 558                break;
 559        case V4L2_PIX_FMT_YUYV:
 560        default:
 561                f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 562        }
 563        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 564
 565        return 0;
 566}
 567
 568static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 569                                  struct v4l2_format *f)
 570{
 571        struct deinterlace_fmt *fmt;
 572        struct deinterlace_ctx *ctx = priv;
 573
 574        fmt = find_format(f);
 575        if (!fmt || !(fmt->types & MEM2MEM_CAPTURE))
 576                f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
 577
 578        f->fmt.pix.colorspace = ctx->colorspace;
 579
 580        if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB &&
 581            f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT &&
 582            f->fmt.pix.field != V4L2_FIELD_NONE)
 583                f->fmt.pix.field = V4L2_FIELD_INTERLACED_TB;
 584
 585        return vidioc_try_fmt(f, fmt);
 586}
 587
 588static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
 589                                  struct v4l2_format *f)
 590{
 591        struct deinterlace_fmt *fmt;
 592
 593        fmt = find_format(f);
 594        if (!fmt || !(fmt->types & MEM2MEM_OUTPUT))
 595                f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
 596
 597        if (!f->fmt.pix.colorspace)
 598                f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
 599
 600        if (f->fmt.pix.field != V4L2_FIELD_SEQ_TB &&
 601            f->fmt.pix.field != V4L2_FIELD_SEQ_BT)
 602                f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
 603
 604        return vidioc_try_fmt(f, fmt);
 605}
 606
 607static int vidioc_s_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
 608{
 609        struct deinterlace_q_data *q_data;
 610        struct vb2_queue *vq;
 611
 612        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 613        if (!vq)
 614                return -EINVAL;
 615
 616        q_data = get_q_data(f->type);
 617        if (!q_data)
 618                return -EINVAL;
 619
 620        if (vb2_is_busy(vq)) {
 621                v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
 622                return -EBUSY;
 623        }
 624
 625        q_data->fmt = find_format(f);
 626        if (!q_data->fmt) {
 627                v4l2_err(&ctx->dev->v4l2_dev,
 628                         "Couldn't set format type %d, wxh: %dx%d. fmt: %d, field: %d\n",
 629                        f->type, f->fmt.pix.width, f->fmt.pix.height,
 630                        f->fmt.pix.pixelformat, f->fmt.pix.field);
 631                return -EINVAL;
 632        }
 633
 634        q_data->width           = f->fmt.pix.width;
 635        q_data->height          = f->fmt.pix.height;
 636        q_data->field           = f->fmt.pix.field;
 637
 638        switch (f->fmt.pix.pixelformat) {
 639        case V4L2_PIX_FMT_YUV420:
 640                f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
 641                q_data->sizeimage = (q_data->width * q_data->height * 3) / 2;
 642                break;
 643        case V4L2_PIX_FMT_YUYV:
 644        default:
 645                f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 646                q_data->sizeimage = q_data->width * q_data->height * 2;
 647        }
 648
 649        dprintk(ctx->dev,
 650                "Setting format for type %d, wxh: %dx%d, fmt: %d, field: %d\n",
 651                f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
 652                q_data->field);
 653
 654        return 0;
 655}
 656
 657static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 658                                struct v4l2_format *f)
 659{
 660        int ret;
 661
 662        ret = vidioc_try_fmt_vid_cap(file, priv, f);
 663        if (ret)
 664                return ret;
 665        return vidioc_s_fmt(priv, f);
 666}
 667
 668static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 669                                struct v4l2_format *f)
 670{
 671        struct deinterlace_ctx *ctx = priv;
 672        int ret;
 673
 674        ret = vidioc_try_fmt_vid_out(file, priv, f);
 675        if (ret)
 676                return ret;
 677
 678        ret = vidioc_s_fmt(priv, f);
 679        if (!ret)
 680                ctx->colorspace = f->fmt.pix.colorspace;
 681
 682        return ret;
 683}
 684
 685static int vidioc_reqbufs(struct file *file, void *priv,
 686                          struct v4l2_requestbuffers *reqbufs)
 687{
 688        struct deinterlace_ctx *ctx = priv;
 689
 690        return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
 691}
 692
 693static int vidioc_querybuf(struct file *file, void *priv,
 694                           struct v4l2_buffer *buf)
 695{
 696        struct deinterlace_ctx *ctx = priv;
 697
 698        return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
 699}
 700
 701static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 702{
 703        struct deinterlace_ctx *ctx = priv;
 704
 705        return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
 706}
 707
 708static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 709{
 710        struct deinterlace_ctx *ctx = priv;
 711
 712        return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 713}
 714
 715static int vidioc_streamon(struct file *file, void *priv,
 716                           enum v4l2_buf_type type)
 717{
 718        struct deinterlace_q_data *s_q_data, *d_q_data;
 719        struct deinterlace_ctx *ctx = priv;
 720
 721        s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
 722        d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
 723
 724        /* Check that src and dst queues have the same pix format */
 725        if (s_q_data->fmt->fourcc != d_q_data->fmt->fourcc) {
 726                v4l2_err(&ctx->dev->v4l2_dev,
 727                         "src and dst formats don't match.\n");
 728                return -EINVAL;
 729        }
 730
 731        /* Check that input and output deinterlacing types are compatible */
 732        switch (s_q_data->field) {
 733        case V4L2_FIELD_SEQ_BT:
 734                if (d_q_data->field != V4L2_FIELD_NONE &&
 735                        d_q_data->field != V4L2_FIELD_INTERLACED_BT) {
 736                        v4l2_err(&ctx->dev->v4l2_dev,
 737                         "src and dst field conversion [(%d)->(%d)] not supported.\n",
 738                                s_q_data->field, d_q_data->field);
 739                        return -EINVAL;
 740                }
 741                break;
 742        case V4L2_FIELD_SEQ_TB:
 743                if (d_q_data->field != V4L2_FIELD_NONE &&
 744                        d_q_data->field != V4L2_FIELD_INTERLACED_TB) {
 745                        v4l2_err(&ctx->dev->v4l2_dev,
 746                         "src and dst field conversion [(%d)->(%d)] not supported.\n",
 747                                s_q_data->field, d_q_data->field);
 748                        return -EINVAL;
 749                }
 750                break;
 751        default:
 752                return -EINVAL;
 753        }
 754
 755        return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
 756}
 757
 758static int vidioc_streamoff(struct file *file, void *priv,
 759                            enum v4l2_buf_type type)
 760{
 761        struct deinterlace_ctx *ctx = priv;
 762
 763        return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
 764}
 765
 766static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
 767        .vidioc_querycap        = vidioc_querycap,
 768
 769        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
 770        .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
 771        .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
 772        .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
 773
 774        .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
 775        .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
 776        .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
 777        .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
 778
 779        .vidioc_reqbufs         = vidioc_reqbufs,
 780        .vidioc_querybuf        = vidioc_querybuf,
 781
 782        .vidioc_qbuf            = vidioc_qbuf,
 783        .vidioc_dqbuf           = vidioc_dqbuf,
 784
 785        .vidioc_streamon        = vidioc_streamon,
 786        .vidioc_streamoff       = vidioc_streamoff,
 787};
 788
 789
 790/*
 791 * Queue operations
 792 */
 793struct vb2_dc_conf {
 794        struct device           *dev;
 795};
 796
 797static int deinterlace_queue_setup(struct vb2_queue *vq,
 798                                const struct v4l2_format *fmt,
 799                                unsigned int *nbuffers, unsigned int *nplanes,
 800                                unsigned int sizes[], void *alloc_ctxs[])
 801{
 802        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
 803        struct deinterlace_q_data *q_data;
 804        unsigned int size, count = *nbuffers;
 805
 806        q_data = get_q_data(vq->type);
 807
 808        switch (q_data->fmt->fourcc) {
 809        case V4L2_PIX_FMT_YUV420:
 810                size = q_data->width * q_data->height * 3 / 2;
 811                break;
 812        case V4L2_PIX_FMT_YUYV:
 813        default:
 814                size = q_data->width * q_data->height * 2;
 815        }
 816
 817        *nplanes = 1;
 818        *nbuffers = count;
 819        sizes[0] = size;
 820
 821        alloc_ctxs[0] = ctx->dev->alloc_ctx;
 822
 823        dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
 824
 825        return 0;
 826}
 827
 828static int deinterlace_buf_prepare(struct vb2_buffer *vb)
 829{
 830        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 831        struct deinterlace_q_data *q_data;
 832
 833        dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 834
 835        q_data = get_q_data(vb->vb2_queue->type);
 836
 837        if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
 838                dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
 839                        __func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
 840                return -EINVAL;
 841        }
 842
 843        vb2_set_plane_payload(vb, 0, q_data->sizeimage);
 844
 845        return 0;
 846}
 847
 848static void deinterlace_buf_queue(struct vb2_buffer *vb)
 849{
 850        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 851        v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
 852}
 853
 854static struct vb2_ops deinterlace_qops = {
 855        .queue_setup     = deinterlace_queue_setup,
 856        .buf_prepare     = deinterlace_buf_prepare,
 857        .buf_queue       = deinterlace_buf_queue,
 858};
 859
 860static int queue_init(void *priv, struct vb2_queue *src_vq,
 861                      struct vb2_queue *dst_vq)
 862{
 863        struct deinterlace_ctx *ctx = priv;
 864        int ret;
 865
 866        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 867        src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
 868        src_vq->drv_priv = ctx;
 869        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 870        src_vq->ops = &deinterlace_qops;
 871        src_vq->mem_ops = &vb2_dma_contig_memops;
 872        src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 873        q_data[V4L2_M2M_SRC].fmt = &formats[0];
 874        q_data[V4L2_M2M_SRC].width = 640;
 875        q_data[V4L2_M2M_SRC].height = 480;
 876        q_data[V4L2_M2M_SRC].sizeimage = (640 * 480 * 3) / 2;
 877        q_data[V4L2_M2M_SRC].field = V4L2_FIELD_SEQ_TB;
 878
 879        ret = vb2_queue_init(src_vq);
 880        if (ret)
 881                return ret;
 882
 883        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 884        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
 885        dst_vq->drv_priv = ctx;
 886        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 887        dst_vq->ops = &deinterlace_qops;
 888        dst_vq->mem_ops = &vb2_dma_contig_memops;
 889        dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 890        q_data[V4L2_M2M_DST].fmt = &formats[0];
 891        q_data[V4L2_M2M_DST].width = 640;
 892        q_data[V4L2_M2M_DST].height = 480;
 893        q_data[V4L2_M2M_DST].sizeimage = (640 * 480 * 3) / 2;
 894        q_data[V4L2_M2M_SRC].field = V4L2_FIELD_INTERLACED_TB;
 895
 896        return vb2_queue_init(dst_vq);
 897}
 898
 899/*
 900 * File operations
 901 */
 902static int deinterlace_open(struct file *file)
 903{
 904        struct deinterlace_dev *pcdev = video_drvdata(file);
 905        struct deinterlace_ctx *ctx = NULL;
 906
 907        ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 908        if (!ctx)
 909                return -ENOMEM;
 910
 911        file->private_data = ctx;
 912        ctx->dev = pcdev;
 913
 914        ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
 915        if (IS_ERR(ctx->m2m_ctx)) {
 916                int ret = PTR_ERR(ctx->m2m_ctx);
 917
 918                kfree(ctx);
 919                return ret;
 920        }
 921
 922        ctx->xt = kzalloc(sizeof(struct dma_async_tx_descriptor) +
 923                                sizeof(struct data_chunk), GFP_KERNEL);
 924        if (!ctx->xt) {
 925                kfree(ctx);
 926                return -ENOMEM;
 927        }
 928
 929        ctx->colorspace = V4L2_COLORSPACE_REC709;
 930
 931        dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
 932
 933        return 0;
 934}
 935
 936static int deinterlace_release(struct file *file)
 937{
 938        struct deinterlace_dev *pcdev = video_drvdata(file);
 939        struct deinterlace_ctx *ctx = file->private_data;
 940
 941        dprintk(pcdev, "Releasing instance %p\n", ctx);
 942
 943        v4l2_m2m_ctx_release(ctx->m2m_ctx);
 944        kfree(ctx->xt);
 945        kfree(ctx);
 946
 947        return 0;
 948}
 949
 950static unsigned int deinterlace_poll(struct file *file,
 951                                 struct poll_table_struct *wait)
 952{
 953        struct deinterlace_ctx *ctx = file->private_data;
 954        int ret;
 955
 956        deinterlace_lock(ctx);
 957        ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
 958        deinterlace_unlock(ctx);
 959
 960        return ret;
 961}
 962
 963static int deinterlace_mmap(struct file *file, struct vm_area_struct *vma)
 964{
 965        struct deinterlace_ctx *ctx = file->private_data;
 966
 967        return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
 968}
 969
 970static const struct v4l2_file_operations deinterlace_fops = {
 971        .owner          = THIS_MODULE,
 972        .open           = deinterlace_open,
 973        .release        = deinterlace_release,
 974        .poll           = deinterlace_poll,
 975        .unlocked_ioctl = video_ioctl2,
 976        .mmap           = deinterlace_mmap,
 977};
 978
 979static struct video_device deinterlace_videodev = {
 980        .name           = MEM2MEM_NAME,
 981        .fops           = &deinterlace_fops,
 982        .ioctl_ops      = &deinterlace_ioctl_ops,
 983        .minor          = -1,
 984        .release        = video_device_release,
 985        .vfl_dir        = VFL_DIR_M2M,
 986};
 987
 988static struct v4l2_m2m_ops m2m_ops = {
 989        .device_run     = deinterlace_device_run,
 990        .job_ready      = deinterlace_job_ready,
 991        .job_abort      = deinterlace_job_abort,
 992        .lock           = deinterlace_lock,
 993        .unlock         = deinterlace_unlock,
 994};
 995
 996static int deinterlace_probe(struct platform_device *pdev)
 997{
 998        struct deinterlace_dev *pcdev;
 999        struct video_device *vfd;
1000        dma_cap_mask_t mask;
1001        int ret = 0;
1002
1003        pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
1004        if (!pcdev)
1005                return -ENOMEM;
1006
1007        spin_lock_init(&pcdev->irqlock);
1008
1009        dma_cap_zero(mask);
1010        dma_cap_set(DMA_INTERLEAVE, mask);
1011        pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
1012        if (!pcdev->dma_chan)
1013                goto free_dev;
1014
1015        if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
1016                v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n");
1017                goto rel_dma;
1018        }
1019
1020        ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
1021        if (ret)
1022                goto rel_dma;
1023
1024        atomic_set(&pcdev->busy, 0);
1025        mutex_init(&pcdev->dev_mutex);
1026
1027        vfd = video_device_alloc();
1028        if (!vfd) {
1029                v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
1030                ret = -ENOMEM;
1031                goto unreg_dev;
1032        }
1033
1034        *vfd = deinterlace_videodev;
1035        vfd->lock = &pcdev->dev_mutex;
1036        vfd->v4l2_dev = &pcdev->v4l2_dev;
1037
1038        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1039        if (ret) {
1040                v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
1041                goto rel_vdev;
1042        }
1043
1044        video_set_drvdata(vfd, pcdev);
1045        snprintf(vfd->name, sizeof(vfd->name), "%s", deinterlace_videodev.name);
1046        pcdev->vfd = vfd;
1047        v4l2_info(&pcdev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
1048                        " Device registered as /dev/video%d\n", vfd->num);
1049
1050        platform_set_drvdata(pdev, pcdev);
1051
1052        pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1053        if (IS_ERR(pcdev->alloc_ctx)) {
1054                v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
1055                ret = PTR_ERR(pcdev->alloc_ctx);
1056                goto err_ctx;
1057        }
1058
1059        pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
1060        if (IS_ERR(pcdev->m2m_dev)) {
1061                v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
1062                ret = PTR_ERR(pcdev->m2m_dev);
1063                goto err_m2m;
1064        }
1065
1066        return 0;
1067
1068        v4l2_m2m_release(pcdev->m2m_dev);
1069err_m2m:
1070        video_unregister_device(pcdev->vfd);
1071err_ctx:
1072        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
1073rel_vdev:
1074        video_device_release(vfd);
1075unreg_dev:
1076        v4l2_device_unregister(&pcdev->v4l2_dev);
1077rel_dma:
1078        dma_release_channel(pcdev->dma_chan);
1079free_dev:
1080        kfree(pcdev);
1081
1082        return ret;
1083}
1084
1085static int deinterlace_remove(struct platform_device *pdev)
1086{
1087        struct deinterlace_dev *pcdev =
1088                (struct deinterlace_dev *)platform_get_drvdata(pdev);
1089
1090        v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
1091        v4l2_m2m_release(pcdev->m2m_dev);
1092        video_unregister_device(pcdev->vfd);
1093        v4l2_device_unregister(&pcdev->v4l2_dev);
1094        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
1095        dma_release_channel(pcdev->dma_chan);
1096        kfree(pcdev);
1097
1098        return 0;
1099}
1100
1101static struct platform_driver deinterlace_pdrv = {
1102        .probe          = deinterlace_probe,
1103        .remove         = deinterlace_remove,
1104        .driver         = {
1105                .name   = MEM2MEM_NAME,
1106                .owner  = THIS_MODULE,
1107        },
1108};
1109module_platform_driver(deinterlace_pdrv);
1110
1111