linux/drivers/media/video/mx2_emmaprp.c
<<
>>
Prefs
   1/*
   2 * Support eMMa-PrP through mem2mem framework.
   3 *
   4 * eMMa-PrP is a piece of HW that allows fetching buffers
   5 * from one memory location and do several operations on
   6 * them such as scaling or format conversion giving, as a result
   7 * a new processed buffer in another memory location.
   8 *
   9 * Based on mem2mem_testdev.c by Pawel Osciak.
  10 *
  11 * Copyright (c) 2011 Vista Silicon S.L.
  12 * Javier Martin <javier.martin@vista-silicon.com>
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License as published by the
  16 * Free Software Foundation; either version 2 of the
  17 * License, or (at your option) any later version
  18 */
  19#include <linux/module.h>
  20#include <linux/clk.h>
  21#include <linux/slab.h>
  22#include <linux/interrupt.h>
  23#include <linux/io.h>
  24
  25#include <linux/platform_device.h>
  26#include <media/v4l2-mem2mem.h>
  27#include <media/v4l2-device.h>
  28#include <media/v4l2-ioctl.h>
  29#include <media/videobuf2-dma-contig.h>
  30#include <asm/sizes.h>
  31
  32#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp"
  33
  34MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs");
  35MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
  36MODULE_LICENSE("GPL");
  37MODULE_VERSION("0.0.1");
  38
  39static bool debug;
  40module_param(debug, bool, 0644);
  41
  42#define MIN_W 32
  43#define MIN_H 32
  44#define MAX_W 2040
  45#define MAX_H 2046
  46
  47#define S_ALIGN         1 /* multiple of 2 */
  48#define W_ALIGN_YUV420  3 /* multiple of 8 */
  49#define W_ALIGN_OTHERS  2 /* multiple of 4 */
  50#define H_ALIGN         1 /* multiple of 2 */
  51
  52/* Flags that indicate a format can be used for capture/output */
  53#define MEM2MEM_CAPTURE (1 << 0)
  54#define MEM2MEM_OUTPUT  (1 << 1)
  55
  56#define MEM2MEM_NAME            "m2m-emmaprp"
  57
  58/* In bytes, per queue */
  59#define MEM2MEM_VID_MEM_LIMIT   SZ_16M
  60
  61#define dprintk(dev, fmt, arg...) \
  62        v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
  63
  64/* EMMA PrP */
  65#define PRP_CNTL                        0x00
  66#define PRP_INTR_CNTL                   0x04
  67#define PRP_INTRSTATUS                  0x08
  68#define PRP_SOURCE_Y_PTR                0x0c
  69#define PRP_SOURCE_CB_PTR               0x10
  70#define PRP_SOURCE_CR_PTR               0x14
  71#define PRP_DEST_RGB1_PTR               0x18
  72#define PRP_DEST_RGB2_PTR               0x1c
  73#define PRP_DEST_Y_PTR                  0x20
  74#define PRP_DEST_CB_PTR                 0x24
  75#define PRP_DEST_CR_PTR                 0x28
  76#define PRP_SRC_FRAME_SIZE              0x2c
  77#define PRP_DEST_CH1_LINE_STRIDE        0x30
  78#define PRP_SRC_PIXEL_FORMAT_CNTL       0x34
  79#define PRP_CH1_PIXEL_FORMAT_CNTL       0x38
  80#define PRP_CH1_OUT_IMAGE_SIZE          0x3c
  81#define PRP_CH2_OUT_IMAGE_SIZE          0x40
  82#define PRP_SRC_LINE_STRIDE             0x44
  83#define PRP_CSC_COEF_012                0x48
  84#define PRP_CSC_COEF_345                0x4c
  85#define PRP_CSC_COEF_678                0x50
  86#define PRP_CH1_RZ_HORI_COEF1           0x54
  87#define PRP_CH1_RZ_HORI_COEF2           0x58
  88#define PRP_CH1_RZ_HORI_VALID           0x5c
  89#define PRP_CH1_RZ_VERT_COEF1           0x60
  90#define PRP_CH1_RZ_VERT_COEF2           0x64
  91#define PRP_CH1_RZ_VERT_VALID           0x68
  92#define PRP_CH2_RZ_HORI_COEF1           0x6c
  93#define PRP_CH2_RZ_HORI_COEF2           0x70
  94#define PRP_CH2_RZ_HORI_VALID           0x74
  95#define PRP_CH2_RZ_VERT_COEF1           0x78
  96#define PRP_CH2_RZ_VERT_COEF2           0x7c
  97#define PRP_CH2_RZ_VERT_VALID           0x80
  98
  99#define PRP_CNTL_CH1EN          (1 << 0)
 100#define PRP_CNTL_CH2EN          (1 << 1)
 101#define PRP_CNTL_CSIEN          (1 << 2)
 102#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
 103#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
 104#define PRP_CNTL_DATA_IN_RGB16  (2 << 3)
 105#define PRP_CNTL_DATA_IN_RGB32  (3 << 3)
 106#define PRP_CNTL_CH1_OUT_RGB8   (0 << 5)
 107#define PRP_CNTL_CH1_OUT_RGB16  (1 << 5)
 108#define PRP_CNTL_CH1_OUT_RGB32  (2 << 5)
 109#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
 110#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
 111#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
 112#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
 113#define PRP_CNTL_CH1_LEN        (1 << 9)
 114#define PRP_CNTL_CH2_LEN        (1 << 10)
 115#define PRP_CNTL_SKIP_FRAME     (1 << 11)
 116#define PRP_CNTL_SWRST          (1 << 12)
 117#define PRP_CNTL_CLKEN          (1 << 13)
 118#define PRP_CNTL_WEN            (1 << 14)
 119#define PRP_CNTL_CH1BYP         (1 << 15)
 120#define PRP_CNTL_IN_TSKIP(x)    ((x) << 16)
 121#define PRP_CNTL_CH1_TSKIP(x)   ((x) << 19)
 122#define PRP_CNTL_CH2_TSKIP(x)   ((x) << 22)
 123#define PRP_CNTL_INPUT_FIFO_LEVEL(x)    ((x) << 25)
 124#define PRP_CNTL_RZ_FIFO_LEVEL(x)       ((x) << 27)
 125#define PRP_CNTL_CH2B1EN        (1 << 29)
 126#define PRP_CNTL_CH2B2EN        (1 << 30)
 127#define PRP_CNTL_CH2FEN         (1 << 31)
 128
 129#define PRP_SIZE_HEIGHT(x)      (x)
 130#define PRP_SIZE_WIDTH(x)       ((x) << 16)
 131
 132/* IRQ Enable and status register */
 133#define PRP_INTR_RDERR          (1 << 0)
 134#define PRP_INTR_CH1WERR        (1 << 1)
 135#define PRP_INTR_CH2WERR        (1 << 2)
 136#define PRP_INTR_CH1FC          (1 << 3)
 137#define PRP_INTR_CH2FC          (1 << 5)
 138#define PRP_INTR_LBOVF          (1 << 7)
 139#define PRP_INTR_CH2OVF         (1 << 8)
 140
 141#define PRP_INTR_ST_RDERR       (1 << 0)
 142#define PRP_INTR_ST_CH1WERR     (1 << 1)
 143#define PRP_INTR_ST_CH2WERR     (1 << 2)
 144#define PRP_INTR_ST_CH2B2CI     (1 << 3)
 145#define PRP_INTR_ST_CH2B1CI     (1 << 4)
 146#define PRP_INTR_ST_CH1B2CI     (1 << 5)
 147#define PRP_INTR_ST_CH1B1CI     (1 << 6)
 148#define PRP_INTR_ST_LBOVF       (1 << 7)
 149#define PRP_INTR_ST_CH2OVF      (1 << 8)
 150
 151struct emmaprp_fmt {
 152        char    *name;
 153        u32     fourcc;
 154        /* Types the format can be used for */
 155        u32     types;
 156};
 157
 158static struct emmaprp_fmt formats[] = {
 159        {
 160                .name   = "YUV 4:2:0 Planar",
 161                .fourcc = V4L2_PIX_FMT_YUV420,
 162                .types  = MEM2MEM_CAPTURE,
 163        },
 164        {
 165                .name   = "4:2:2, packed, YUYV",
 166                .fourcc = V4L2_PIX_FMT_YUYV,
 167                .types  = MEM2MEM_OUTPUT,
 168        },
 169};
 170
 171/* Per-queue, driver-specific private data */
 172struct emmaprp_q_data {
 173        unsigned int            width;
 174        unsigned int            height;
 175        unsigned int            sizeimage;
 176        struct emmaprp_fmt      *fmt;
 177};
 178
 179enum {
 180        V4L2_M2M_SRC = 0,
 181        V4L2_M2M_DST = 1,
 182};
 183
 184#define NUM_FORMATS ARRAY_SIZE(formats)
 185
 186static struct emmaprp_fmt *find_format(struct v4l2_format *f)
 187{
 188        struct emmaprp_fmt *fmt;
 189        unsigned int k;
 190
 191        for (k = 0; k < NUM_FORMATS; k++) {
 192                fmt = &formats[k];
 193                if (fmt->fourcc == f->fmt.pix.pixelformat)
 194                        break;
 195        }
 196
 197        if (k == NUM_FORMATS)
 198                return NULL;
 199
 200        return &formats[k];
 201}
 202
 203struct emmaprp_dev {
 204        struct v4l2_device      v4l2_dev;
 205        struct video_device     *vfd;
 206
 207        struct mutex            dev_mutex;
 208        spinlock_t              irqlock;
 209
 210        int                     irq_emma;
 211        void __iomem            *base_emma;
 212        struct clk              *clk_emma;
 213        struct resource         *res_emma;
 214
 215        struct v4l2_m2m_dev     *m2m_dev;
 216        struct vb2_alloc_ctx    *alloc_ctx;
 217};
 218
 219struct emmaprp_ctx {
 220        struct emmaprp_dev      *dev;
 221        /* Abort requested by m2m */
 222        int                     aborting;
 223        struct emmaprp_q_data   q_data[2];
 224        struct v4l2_m2m_ctx     *m2m_ctx;
 225};
 226
 227static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx,
 228                                         enum v4l2_buf_type type)
 229{
 230        switch (type) {
 231        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 232                return &(ctx->q_data[V4L2_M2M_SRC]);
 233        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 234                return &(ctx->q_data[V4L2_M2M_DST]);
 235        default:
 236                BUG();
 237        }
 238        return NULL;
 239}
 240
 241/*
 242 * mem2mem callbacks
 243 */
 244static void emmaprp_job_abort(void *priv)
 245{
 246        struct emmaprp_ctx *ctx = priv;
 247        struct emmaprp_dev *pcdev = ctx->dev;
 248
 249        ctx->aborting = 1;
 250
 251        dprintk(pcdev, "Aborting task\n");
 252
 253        v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx);
 254}
 255
 256static void emmaprp_lock(void *priv)
 257{
 258        struct emmaprp_ctx *ctx = priv;
 259        struct emmaprp_dev *pcdev = ctx->dev;
 260        mutex_lock(&pcdev->dev_mutex);
 261}
 262
 263static void emmaprp_unlock(void *priv)
 264{
 265        struct emmaprp_ctx *ctx = priv;
 266        struct emmaprp_dev *pcdev = ctx->dev;
 267        mutex_unlock(&pcdev->dev_mutex);
 268}
 269
 270static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev)
 271{
 272        dprintk(pcdev,
 273                "eMMa-PrP Registers:\n"
 274                "  SOURCE_Y_PTR = 0x%08X\n"
 275                "  SRC_FRAME_SIZE = 0x%08X\n"
 276                "  DEST_Y_PTR = 0x%08X\n"
 277                "  DEST_CR_PTR = 0x%08X\n"
 278                "  DEST_CB_PTR = 0x%08X\n"
 279                "  CH2_OUT_IMAGE_SIZE = 0x%08X\n"
 280                "  CNTL = 0x%08X\n",
 281                readl(pcdev->base_emma + PRP_SOURCE_Y_PTR),
 282                readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE),
 283                readl(pcdev->base_emma + PRP_DEST_Y_PTR),
 284                readl(pcdev->base_emma + PRP_DEST_CR_PTR),
 285                readl(pcdev->base_emma + PRP_DEST_CB_PTR),
 286                readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE),
 287                readl(pcdev->base_emma + PRP_CNTL));
 288}
 289
 290static void emmaprp_device_run(void *priv)
 291{
 292        struct emmaprp_ctx *ctx = priv;
 293        struct emmaprp_q_data *s_q_data, *d_q_data;
 294        struct vb2_buffer *src_buf, *dst_buf;
 295        struct emmaprp_dev *pcdev = ctx->dev;
 296        unsigned int s_width, s_height;
 297        unsigned int d_width, d_height;
 298        unsigned int d_size;
 299        dma_addr_t p_in, p_out;
 300        u32 tmp;
 301
 302        src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 303        dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 304
 305        s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 306        s_width = s_q_data->width;
 307        s_height = s_q_data->height;
 308
 309        d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 310        d_width = d_q_data->width;
 311        d_height = d_q_data->height;
 312        d_size = d_width * d_height;
 313
 314        p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0);
 315        p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 316        if (!p_in || !p_out) {
 317                v4l2_err(&pcdev->v4l2_dev,
 318                         "Acquiring kernel pointers to buffers failed\n");
 319                return;
 320        }
 321
 322        /* Input frame parameters */
 323        writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR);
 324        writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height),
 325               pcdev->base_emma + PRP_SRC_FRAME_SIZE);
 326
 327        /* Output frame parameters */
 328        writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR);
 329        writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR);
 330        writel(p_out + d_size + (d_size >> 2),
 331               pcdev->base_emma + PRP_DEST_CR_PTR);
 332        writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height),
 333               pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
 334
 335        /* IRQ configuration */
 336        tmp = readl(pcdev->base_emma + PRP_INTR_CNTL);
 337        writel(tmp | PRP_INTR_RDERR |
 338                PRP_INTR_CH2WERR |
 339                PRP_INTR_CH2FC,
 340                pcdev->base_emma + PRP_INTR_CNTL);
 341
 342        emmaprp_dump_regs(pcdev);
 343
 344        /* Enable transfer */
 345        tmp = readl(pcdev->base_emma + PRP_CNTL);
 346        writel(tmp | PRP_CNTL_CH2_OUT_YUV420 |
 347                PRP_CNTL_DATA_IN_YUV422 |
 348                PRP_CNTL_CH2EN,
 349                pcdev->base_emma + PRP_CNTL);
 350}
 351
 352static irqreturn_t emmaprp_irq(int irq_emma, void *data)
 353{
 354        struct emmaprp_dev *pcdev = data;
 355        struct emmaprp_ctx *curr_ctx;
 356        struct vb2_buffer *src_vb, *dst_vb;
 357        unsigned long flags;
 358        u32 irqst;
 359
 360        /* Check irq flags and clear irq */
 361        irqst = readl(pcdev->base_emma + PRP_INTRSTATUS);
 362        writel(irqst, pcdev->base_emma + PRP_INTRSTATUS);
 363        dprintk(pcdev, "irqst = 0x%08x\n", irqst);
 364
 365        curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
 366        if (curr_ctx == NULL) {
 367                pr_err("Instance released before the end of transaction\n");
 368                return IRQ_HANDLED;
 369        }
 370
 371        if (!curr_ctx->aborting) {
 372                if ((irqst & PRP_INTR_ST_RDERR) ||
 373                (irqst & PRP_INTR_ST_CH2WERR)) {
 374                        pr_err("PrP bus error ocurred, this transfer is probably corrupted\n");
 375                        writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
 376                } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
 377                        src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
 378                        dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
 379
 380                        spin_lock_irqsave(&pcdev->irqlock, flags);
 381                        v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
 382                        v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
 383                        spin_unlock_irqrestore(&pcdev->irqlock, flags);
 384                }
 385        }
 386
 387        v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
 388        return IRQ_HANDLED;
 389}
 390
 391/*
 392 * video ioctls
 393 */
 394static int vidioc_querycap(struct file *file, void *priv,
 395                           struct v4l2_capability *cap)
 396{
 397        strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
 398        strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
 399        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
 400                          | V4L2_CAP_STREAMING;
 401
 402        return 0;
 403}
 404
 405static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
 406{
 407        int i, num;
 408        struct emmaprp_fmt *fmt;
 409
 410        num = 0;
 411
 412        for (i = 0; i < NUM_FORMATS; ++i) {
 413                if (formats[i].types & type) {
 414                        /* index-th format of type type found ? */
 415                        if (num == f->index)
 416                                break;
 417                        /* Correct type but haven't reached our index yet,
 418                         * just increment per-type index */
 419                        ++num;
 420                }
 421        }
 422
 423        if (i < NUM_FORMATS) {
 424                /* Format found */
 425                fmt = &formats[i];
 426                strlcpy(f->description, fmt->name, sizeof(f->description) - 1);
 427                f->pixelformat = fmt->fourcc;
 428                return 0;
 429        }
 430
 431        /* Format not found */
 432        return -EINVAL;
 433}
 434
 435static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 436                                   struct v4l2_fmtdesc *f)
 437{
 438        return enum_fmt(f, MEM2MEM_CAPTURE);
 439}
 440
 441static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
 442                                   struct v4l2_fmtdesc *f)
 443{
 444        return enum_fmt(f, MEM2MEM_OUTPUT);
 445}
 446
 447static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
 448{
 449        struct vb2_queue *vq;
 450        struct emmaprp_q_data *q_data;
 451
 452        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 453        if (!vq)
 454                return -EINVAL;
 455
 456        q_data = get_q_data(ctx, f->type);
 457
 458        f->fmt.pix.width        = q_data->width;
 459        f->fmt.pix.height       = q_data->height;
 460        f->fmt.pix.field        = V4L2_FIELD_NONE;
 461        f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
 462        if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
 463                f->fmt.pix.bytesperline = q_data->width * 3 / 2;
 464        else /* YUYV */
 465                f->fmt.pix.bytesperline = q_data->width * 2;
 466        f->fmt.pix.sizeimage    = q_data->sizeimage;
 467
 468        return 0;
 469}
 470
 471static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
 472                                struct v4l2_format *f)
 473{
 474        return vidioc_g_fmt(priv, f);
 475}
 476
 477static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 478                                struct v4l2_format *f)
 479{
 480        return vidioc_g_fmt(priv, f);
 481}
 482
 483static int vidioc_try_fmt(struct v4l2_format *f)
 484{
 485        enum v4l2_field field;
 486
 487
 488        if (!find_format(f))
 489                return -EINVAL;
 490
 491        field = f->fmt.pix.field;
 492        if (field == V4L2_FIELD_ANY)
 493                field = V4L2_FIELD_NONE;
 494        else if (V4L2_FIELD_NONE != field)
 495                return -EINVAL;
 496
 497        /* V4L2 specification suggests the driver corrects the format struct
 498         * if any of the dimensions is unsupported */
 499        f->fmt.pix.field = field;
 500
 501        if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
 502                v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
 503                                      W_ALIGN_YUV420, &f->fmt.pix.height,
 504                                      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
 505                f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
 506        } else {
 507                v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
 508                                      W_ALIGN_OTHERS, &f->fmt.pix.height,
 509                                      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
 510                f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 511        }
 512        f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 513
 514        return 0;
 515}
 516
 517static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 518                                  struct v4l2_format *f)
 519{
 520        struct emmaprp_fmt *fmt;
 521        struct emmaprp_ctx *ctx = priv;
 522
 523        fmt = find_format(f);
 524        if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
 525                v4l2_err(&ctx->dev->v4l2_dev,
 526                         "Fourcc format (0x%08x) invalid.\n",
 527                         f->fmt.pix.pixelformat);
 528                return -EINVAL;
 529        }
 530
 531        return vidioc_try_fmt(f);
 532}
 533
 534static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
 535                                  struct v4l2_format *f)
 536{
 537        struct emmaprp_fmt *fmt;
 538        struct emmaprp_ctx *ctx = priv;
 539
 540        fmt = find_format(f);
 541        if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
 542                v4l2_err(&ctx->dev->v4l2_dev,
 543                         "Fourcc format (0x%08x) invalid.\n",
 544                         f->fmt.pix.pixelformat);
 545                return -EINVAL;
 546        }
 547
 548        return vidioc_try_fmt(f);
 549}
 550
 551static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
 552{
 553        struct emmaprp_q_data *q_data;
 554        struct vb2_queue *vq;
 555        int ret;
 556
 557        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 558        if (!vq)
 559                return -EINVAL;
 560
 561        q_data = get_q_data(ctx, f->type);
 562        if (!q_data)
 563                return -EINVAL;
 564
 565        if (vb2_is_busy(vq)) {
 566                v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
 567                return -EBUSY;
 568        }
 569
 570        ret = vidioc_try_fmt(f);
 571        if (ret)
 572                return ret;
 573
 574        q_data->fmt             = find_format(f);
 575        q_data->width           = f->fmt.pix.width;
 576        q_data->height          = f->fmt.pix.height;
 577        if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
 578                q_data->sizeimage = q_data->width * q_data->height * 3 / 2;
 579        else /* YUYV */
 580                q_data->sizeimage = q_data->width * q_data->height * 2;
 581
 582        dprintk(ctx->dev,
 583                "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
 584                f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
 585
 586        return 0;
 587}
 588
 589static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 590                                struct v4l2_format *f)
 591{
 592        int ret;
 593
 594        ret = vidioc_try_fmt_vid_cap(file, priv, f);
 595        if (ret)
 596                return ret;
 597
 598        return vidioc_s_fmt(priv, f);
 599}
 600
 601static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 602                                struct v4l2_format *f)
 603{
 604        int ret;
 605
 606        ret = vidioc_try_fmt_vid_out(file, priv, f);
 607        if (ret)
 608                return ret;
 609
 610        return vidioc_s_fmt(priv, f);
 611}
 612
 613static int vidioc_reqbufs(struct file *file, void *priv,
 614                          struct v4l2_requestbuffers *reqbufs)
 615{
 616        struct emmaprp_ctx *ctx = priv;
 617
 618        return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
 619}
 620
 621static int vidioc_querybuf(struct file *file, void *priv,
 622                           struct v4l2_buffer *buf)
 623{
 624        struct emmaprp_ctx *ctx = priv;
 625
 626        return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
 627}
 628
 629static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 630{
 631        struct emmaprp_ctx *ctx = priv;
 632
 633        return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
 634}
 635
 636static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 637{
 638        struct emmaprp_ctx *ctx = priv;
 639
 640        return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 641}
 642
 643static int vidioc_streamon(struct file *file, void *priv,
 644                           enum v4l2_buf_type type)
 645{
 646        struct emmaprp_ctx *ctx = priv;
 647
 648        return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
 649}
 650
 651static int vidioc_streamoff(struct file *file, void *priv,
 652                            enum v4l2_buf_type type)
 653{
 654        struct emmaprp_ctx *ctx = priv;
 655
 656        return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
 657}
 658
 659static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
 660        .vidioc_querycap        = vidioc_querycap,
 661
 662        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
 663        .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
 664        .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
 665        .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
 666
 667        .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
 668        .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
 669        .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
 670        .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
 671
 672        .vidioc_reqbufs         = vidioc_reqbufs,
 673        .vidioc_querybuf        = vidioc_querybuf,
 674
 675        .vidioc_qbuf            = vidioc_qbuf,
 676        .vidioc_dqbuf           = vidioc_dqbuf,
 677
 678        .vidioc_streamon        = vidioc_streamon,
 679        .vidioc_streamoff       = vidioc_streamoff,
 680};
 681
 682
 683/*
 684 * Queue operations
 685 */
 686static int emmaprp_queue_setup(struct vb2_queue *vq,
 687                                const struct v4l2_format *fmt,
 688                                unsigned int *nbuffers, unsigned int *nplanes,
 689                                unsigned int sizes[], void *alloc_ctxs[])
 690{
 691        struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq);
 692        struct emmaprp_q_data *q_data;
 693        unsigned int size, count = *nbuffers;
 694
 695        q_data = get_q_data(ctx, vq->type);
 696
 697        if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
 698                size = q_data->width * q_data->height * 3 / 2;
 699        else
 700                size = q_data->width * q_data->height * 2;
 701
 702        while (size * count > MEM2MEM_VID_MEM_LIMIT)
 703                (count)--;
 704
 705        *nplanes = 1;
 706        *nbuffers = count;
 707        sizes[0] = size;
 708
 709        alloc_ctxs[0] = ctx->dev->alloc_ctx;
 710
 711        dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
 712
 713        return 0;
 714}
 715
 716static int emmaprp_buf_prepare(struct vb2_buffer *vb)
 717{
 718        struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 719        struct emmaprp_q_data *q_data;
 720
 721        dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 722
 723        q_data = get_q_data(ctx, vb->vb2_queue->type);
 724
 725        if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
 726                dprintk(ctx->dev, "%s data will not fit into plane"
 727                                  "(%lu < %lu)\n", __func__,
 728                                  vb2_plane_size(vb, 0),
 729                                  (long)q_data->sizeimage);
 730                return -EINVAL;
 731        }
 732
 733        vb2_set_plane_payload(vb, 0, q_data->sizeimage);
 734
 735        return 0;
 736}
 737
 738static void emmaprp_buf_queue(struct vb2_buffer *vb)
 739{
 740        struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 741        v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
 742}
 743
 744static struct vb2_ops emmaprp_qops = {
 745        .queue_setup     = emmaprp_queue_setup,
 746        .buf_prepare     = emmaprp_buf_prepare,
 747        .buf_queue       = emmaprp_buf_queue,
 748};
 749
 750static int queue_init(void *priv, struct vb2_queue *src_vq,
 751                      struct vb2_queue *dst_vq)
 752{
 753        struct emmaprp_ctx *ctx = priv;
 754        int ret;
 755
 756        memset(src_vq, 0, sizeof(*src_vq));
 757        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 758        src_vq->io_modes = VB2_MMAP;
 759        src_vq->drv_priv = ctx;
 760        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 761        src_vq->ops = &emmaprp_qops;
 762        src_vq->mem_ops = &vb2_dma_contig_memops;
 763
 764        ret = vb2_queue_init(src_vq);
 765        if (ret)
 766                return ret;
 767
 768        memset(dst_vq, 0, sizeof(*dst_vq));
 769        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 770        dst_vq->io_modes = VB2_MMAP;
 771        dst_vq->drv_priv = ctx;
 772        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 773        dst_vq->ops = &emmaprp_qops;
 774        dst_vq->mem_ops = &vb2_dma_contig_memops;
 775
 776        return vb2_queue_init(dst_vq);
 777}
 778
 779/*
 780 * File operations
 781 */
 782static int emmaprp_open(struct file *file)
 783{
 784        struct emmaprp_dev *pcdev = video_drvdata(file);
 785        struct emmaprp_ctx *ctx;
 786
 787        ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 788        if (!ctx)
 789                return -ENOMEM;
 790
 791        file->private_data = ctx;
 792        ctx->dev = pcdev;
 793
 794        ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
 795
 796        if (IS_ERR(ctx->m2m_ctx)) {
 797                int ret = PTR_ERR(ctx->m2m_ctx);
 798
 799                kfree(ctx);
 800                return ret;
 801        }
 802
 803        clk_enable(pcdev->clk_emma);
 804        ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
 805        ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
 806
 807        dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
 808
 809        return 0;
 810}
 811
 812static int emmaprp_release(struct file *file)
 813{
 814        struct emmaprp_dev *pcdev = video_drvdata(file);
 815        struct emmaprp_ctx *ctx = file->private_data;
 816
 817        dprintk(pcdev, "Releasing instance %p\n", ctx);
 818
 819        clk_disable(pcdev->clk_emma);
 820        v4l2_m2m_ctx_release(ctx->m2m_ctx);
 821        kfree(ctx);
 822
 823        return 0;
 824}
 825
 826static unsigned int emmaprp_poll(struct file *file,
 827                                 struct poll_table_struct *wait)
 828{
 829        struct emmaprp_ctx *ctx = file->private_data;
 830
 831        return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
 832}
 833
 834static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma)
 835{
 836        struct emmaprp_ctx *ctx = file->private_data;
 837
 838        return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
 839}
 840
 841static const struct v4l2_file_operations emmaprp_fops = {
 842        .owner          = THIS_MODULE,
 843        .open           = emmaprp_open,
 844        .release        = emmaprp_release,
 845        .poll           = emmaprp_poll,
 846        .unlocked_ioctl = video_ioctl2,
 847        .mmap           = emmaprp_mmap,
 848};
 849
 850static struct video_device emmaprp_videodev = {
 851        .name           = MEM2MEM_NAME,
 852        .fops           = &emmaprp_fops,
 853        .ioctl_ops      = &emmaprp_ioctl_ops,
 854        .minor          = -1,
 855        .release        = video_device_release,
 856};
 857
 858static struct v4l2_m2m_ops m2m_ops = {
 859        .device_run     = emmaprp_device_run,
 860        .job_abort      = emmaprp_job_abort,
 861        .lock           = emmaprp_lock,
 862        .unlock         = emmaprp_unlock,
 863};
 864
 865static int emmaprp_probe(struct platform_device *pdev)
 866{
 867        struct emmaprp_dev *pcdev;
 868        struct video_device *vfd;
 869        struct resource *res_emma;
 870        int irq_emma;
 871        int ret;
 872
 873        pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
 874        if (!pcdev)
 875                return -ENOMEM;
 876
 877        spin_lock_init(&pcdev->irqlock);
 878
 879        pcdev->clk_emma = clk_get(&pdev->dev, NULL);
 880        if (IS_ERR(pcdev->clk_emma)) {
 881                ret = PTR_ERR(pcdev->clk_emma);
 882                goto free_dev;
 883        }
 884
 885        irq_emma = platform_get_irq(pdev, 0);
 886        res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 887        if (irq_emma < 0 || res_emma == NULL) {
 888                dev_err(&pdev->dev, "Missing platform resources data\n");
 889                ret = -ENODEV;
 890                goto free_clk;
 891        }
 892
 893        ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
 894        if (ret)
 895                goto free_clk;
 896
 897        mutex_init(&pcdev->dev_mutex);
 898
 899        vfd = video_device_alloc();
 900        if (!vfd) {
 901                v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
 902                ret = -ENOMEM;
 903                goto unreg_dev;
 904        }
 905
 906        *vfd = emmaprp_videodev;
 907        vfd->lock = &pcdev->dev_mutex;
 908
 909        video_set_drvdata(vfd, pcdev);
 910        snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name);
 911        pcdev->vfd = vfd;
 912        v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME
 913                        " Device registered as /dev/video%d\n", vfd->num);
 914
 915        platform_set_drvdata(pdev, pcdev);
 916
 917        if (devm_request_mem_region(&pdev->dev, res_emma->start,
 918            resource_size(res_emma), MEM2MEM_NAME) == NULL)
 919                goto rel_vdev;
 920
 921        pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start,
 922                                        resource_size(res_emma));
 923        if (!pcdev->base_emma)
 924                goto rel_vdev;
 925
 926        pcdev->irq_emma = irq_emma;
 927        pcdev->res_emma = res_emma;
 928
 929        if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq,
 930                             0, MEM2MEM_NAME, pcdev) < 0)
 931                goto rel_vdev;
 932
 933        pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
 934        if (IS_ERR(pcdev->alloc_ctx)) {
 935                v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
 936                ret = PTR_ERR(pcdev->alloc_ctx);
 937                goto rel_vdev;
 938        }
 939
 940        pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
 941        if (IS_ERR(pcdev->m2m_dev)) {
 942                v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
 943                ret = PTR_ERR(pcdev->m2m_dev);
 944                goto rel_ctx;
 945        }
 946
 947        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
 948        if (ret) {
 949                v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
 950                goto rel_m2m;
 951        }
 952
 953        return 0;
 954
 955
 956rel_m2m:
 957        v4l2_m2m_release(pcdev->m2m_dev);
 958rel_ctx:
 959        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 960rel_vdev:
 961        video_device_release(vfd);
 962unreg_dev:
 963        v4l2_device_unregister(&pcdev->v4l2_dev);
 964free_clk:
 965        clk_put(pcdev->clk_emma);
 966free_dev:
 967        kfree(pcdev);
 968
 969        return ret;
 970}
 971
 972static int emmaprp_remove(struct platform_device *pdev)
 973{
 974        struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
 975
 976        v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME);
 977
 978        video_unregister_device(pcdev->vfd);
 979        v4l2_m2m_release(pcdev->m2m_dev);
 980        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 981        v4l2_device_unregister(&pcdev->v4l2_dev);
 982        clk_put(pcdev->clk_emma);
 983        kfree(pcdev);
 984
 985        return 0;
 986}
 987
 988static struct platform_driver emmaprp_pdrv = {
 989        .probe          = emmaprp_probe,
 990        .remove         = emmaprp_remove,
 991        .driver         = {
 992                .name   = MEM2MEM_NAME,
 993                .owner  = THIS_MODULE,
 994        },
 995};
 996
 997static void __exit emmaprp_exit(void)
 998{
 999        platform_driver_unregister(&emmaprp_pdrv);
1000}
1001
1002static int __init emmaprp_init(void)
1003{
1004        return platform_driver_register(&emmaprp_pdrv);
1005}
1006
1007module_init(emmaprp_init);
1008module_exit(emmaprp_exit);
1009