linux/drivers/media/platform/sh_veu.c
<<
>>
Prefs
   1/*
   2 * sh-mobile VEU mem2mem driver
   3 *
   4 * Copyright (C) 2012 Renesas Electronics Corporation
   5 * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
   6 * Copyright (C) 2008 Magnus Damm
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the version 2 of the GNU General Public License as
  10 * published by the Free Software Foundation
  11 */
  12
  13#include <linux/err.h>
  14#include <linux/fs.h>
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/interrupt.h>
  18#include <linux/io.h>
  19#include <linux/platform_device.h>
  20#include <linux/pm_runtime.h>
  21#include <linux/slab.h>
  22#include <linux/types.h>
  23#include <linux/videodev2.h>
  24
  25#include <media/v4l2-dev.h>
  26#include <media/v4l2-device.h>
  27#include <media/v4l2-ioctl.h>
  28#include <media/v4l2-mem2mem.h>
  29#include <media/videobuf2-dma-contig.h>
  30
  31#define VEU_STR 0x00 /* start register */
  32#define VEU_SWR 0x10 /* src: line length */
  33#define VEU_SSR 0x14 /* src: image size */
  34#define VEU_SAYR 0x18 /* src: y/rgb plane address */
  35#define VEU_SACR 0x1c /* src: c plane address */
  36#define VEU_BSSR 0x20 /* bundle mode register */
  37#define VEU_EDWR 0x30 /* dst: line length */
  38#define VEU_DAYR 0x34 /* dst: y/rgb plane address */
  39#define VEU_DACR 0x38 /* dst: c plane address */
  40#define VEU_TRCR 0x50 /* transform control */
  41#define VEU_RFCR 0x54 /* resize scale */
  42#define VEU_RFSR 0x58 /* resize clip */
  43#define VEU_ENHR 0x5c /* enhance */
  44#define VEU_FMCR 0x70 /* filter mode */
  45#define VEU_VTCR 0x74 /* lowpass vertical */
  46#define VEU_HTCR 0x78 /* lowpass horizontal */
  47#define VEU_APCR 0x80 /* color match */
  48#define VEU_ECCR 0x84 /* color replace */
  49#define VEU_AFXR 0x90 /* fixed mode */
  50#define VEU_SWPR 0x94 /* swap */
  51#define VEU_EIER 0xa0 /* interrupt mask */
  52#define VEU_EVTR 0xa4 /* interrupt event */
  53#define VEU_STAR 0xb0 /* status */
  54#define VEU_BSRR 0xb4 /* reset */
  55
  56#define VEU_MCR00 0x200 /* color conversion matrix coefficient 00 */
  57#define VEU_MCR01 0x204 /* color conversion matrix coefficient 01 */
  58#define VEU_MCR02 0x208 /* color conversion matrix coefficient 02 */
  59#define VEU_MCR10 0x20c /* color conversion matrix coefficient 10 */
  60#define VEU_MCR11 0x210 /* color conversion matrix coefficient 11 */
  61#define VEU_MCR12 0x214 /* color conversion matrix coefficient 12 */
  62#define VEU_MCR20 0x218 /* color conversion matrix coefficient 20 */
  63#define VEU_MCR21 0x21c /* color conversion matrix coefficient 21 */
  64#define VEU_MCR22 0x220 /* color conversion matrix coefficient 22 */
  65#define VEU_COFFR 0x224 /* color conversion offset */
  66#define VEU_CBR   0x228 /* color conversion clip */
  67
  68/*
  69 * 4092x4092 max size is the normal case. In some cases it can be reduced to
  70 * 2048x2048, in other cases it can be 4092x8188 or even 8188x8188.
  71 */
  72#define MAX_W 4092
  73#define MAX_H 4092
  74#define MIN_W 8
  75#define MIN_H 8
  76#define ALIGN_W 4
  77
  78/* 3 buffers of 2048 x 1536 - 3 megapixels @ 16bpp */
  79#define VIDEO_MEM_LIMIT ALIGN(2048 * 1536 * 2 * 3, 1024 * 1024)
  80
  81#define MEM2MEM_DEF_TRANSLEN 1
  82
  83struct sh_veu_dev;
  84
  85struct sh_veu_file {
  86        struct sh_veu_dev *veu_dev;
  87        bool cfg_needed;
  88};
  89
  90struct sh_veu_format {
  91        char *name;
  92        u32 fourcc;
  93        unsigned int depth;
  94        unsigned int ydepth;
  95};
  96
  97/* video data format */
  98struct sh_veu_vfmt {
  99        /* Replace with v4l2_rect */
 100        struct v4l2_rect                frame;
 101        unsigned int                    bytesperline;
 102        unsigned int                    offset_y;
 103        unsigned int                    offset_c;
 104        const struct sh_veu_format      *fmt;
 105};
 106
 107struct sh_veu_dev {
 108        struct v4l2_device v4l2_dev;
 109        struct video_device vdev;
 110        struct v4l2_m2m_dev *m2m_dev;
 111        struct device *dev;
 112        struct v4l2_m2m_ctx *m2m_ctx;
 113        struct sh_veu_vfmt vfmt_out;
 114        struct sh_veu_vfmt vfmt_in;
 115        /* Only single user per direction so far */
 116        struct sh_veu_file *capture;
 117        struct sh_veu_file *output;
 118        struct mutex fop_lock;
 119        void __iomem *base;
 120        struct vb2_alloc_ctx *alloc_ctx;
 121        spinlock_t lock;
 122        bool is_2h;
 123        unsigned int xaction;
 124        bool aborting;
 125};
 126
 127enum sh_veu_fmt_idx {
 128        SH_VEU_FMT_NV12,
 129        SH_VEU_FMT_NV16,
 130        SH_VEU_FMT_NV24,
 131        SH_VEU_FMT_RGB332,
 132        SH_VEU_FMT_RGB444,
 133        SH_VEU_FMT_RGB565,
 134        SH_VEU_FMT_RGB666,
 135        SH_VEU_FMT_RGB24,
 136};
 137
 138#define VGA_WIDTH       640
 139#define VGA_HEIGHT      480
 140
 141#define DEFAULT_IN_WIDTH        VGA_WIDTH
 142#define DEFAULT_IN_HEIGHT       VGA_HEIGHT
 143#define DEFAULT_IN_FMTIDX       SH_VEU_FMT_NV12
 144#define DEFAULT_OUT_WIDTH       VGA_WIDTH
 145#define DEFAULT_OUT_HEIGHT      VGA_HEIGHT
 146#define DEFAULT_OUT_FMTIDX      SH_VEU_FMT_RGB565
 147
 148/*
 149 * Alignment: Y-plane should be 4-byte aligned for NV12 and NV16, and 8-byte
 150 * aligned for NV24.
 151 */
 152static const struct sh_veu_format sh_veu_fmt[] = {
 153        [SH_VEU_FMT_NV12]   = { .ydepth = 8, .depth = 12, .name = "NV12", .fourcc = V4L2_PIX_FMT_NV12 },
 154        [SH_VEU_FMT_NV16]   = { .ydepth = 8, .depth = 16, .name = "NV16", .fourcc = V4L2_PIX_FMT_NV16 },
 155        [SH_VEU_FMT_NV24]   = { .ydepth = 8, .depth = 24, .name = "NV24", .fourcc = V4L2_PIX_FMT_NV24 },
 156        [SH_VEU_FMT_RGB332] = { .ydepth = 8, .depth = 8, .name = "RGB332", .fourcc = V4L2_PIX_FMT_RGB332 },
 157        [SH_VEU_FMT_RGB444] = { .ydepth = 16, .depth = 16, .name = "RGB444", .fourcc = V4L2_PIX_FMT_RGB444 },
 158        [SH_VEU_FMT_RGB565] = { .ydepth = 16, .depth = 16, .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565 },
 159        [SH_VEU_FMT_RGB666] = { .ydepth = 32, .depth = 32, .name = "BGR666", .fourcc = V4L2_PIX_FMT_BGR666 },
 160        [SH_VEU_FMT_RGB24]  = { .ydepth = 24, .depth = 24, .name = "RGB24", .fourcc = V4L2_PIX_FMT_RGB24 },
 161};
 162
 163#define DEFAULT_IN_VFMT (struct sh_veu_vfmt){                                           \
 164        .frame = {                                                                      \
 165                .width = VGA_WIDTH,                                                     \
 166                .height = VGA_HEIGHT,                                                   \
 167        },                                                                              \
 168        .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_IN_FMTIDX].ydepth) >> 3,        \
 169        .fmt = &sh_veu_fmt[DEFAULT_IN_FMTIDX],                                          \
 170}
 171
 172#define DEFAULT_OUT_VFMT (struct sh_veu_vfmt){                                          \
 173        .frame = {                                                                      \
 174                .width = VGA_WIDTH,                                                     \
 175                .height = VGA_HEIGHT,                                                   \
 176        },                                                                              \
 177        .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_OUT_FMTIDX].ydepth) >> 3,       \
 178        .fmt = &sh_veu_fmt[DEFAULT_OUT_FMTIDX],                                         \
 179}
 180
 181/*
 182 * TODO: add support for further output formats:
 183 *      SH_VEU_FMT_NV12,
 184 *      SH_VEU_FMT_NV16,
 185 *      SH_VEU_FMT_NV24,
 186 *      SH_VEU_FMT_RGB332,
 187 *      SH_VEU_FMT_RGB444,
 188 *      SH_VEU_FMT_RGB666,
 189 *      SH_VEU_FMT_RGB24,
 190 */
 191
 192static const int sh_veu_fmt_out[] = {
 193        SH_VEU_FMT_RGB565,
 194};
 195
 196/*
 197 * TODO: add support for further input formats:
 198 *      SH_VEU_FMT_NV16,
 199 *      SH_VEU_FMT_NV24,
 200 *      SH_VEU_FMT_RGB565,
 201 *      SH_VEU_FMT_RGB666,
 202 *      SH_VEU_FMT_RGB24,
 203 */
 204static const int sh_veu_fmt_in[] = {
 205        SH_VEU_FMT_NV12,
 206};
 207
 208static enum v4l2_colorspace sh_veu_4cc2cspace(u32 fourcc)
 209{
 210        switch (fourcc) {
 211        default:
 212                BUG();
 213        case V4L2_PIX_FMT_NV12:
 214        case V4L2_PIX_FMT_NV16:
 215        case V4L2_PIX_FMT_NV24:
 216                return V4L2_COLORSPACE_JPEG;
 217        case V4L2_PIX_FMT_RGB332:
 218        case V4L2_PIX_FMT_RGB444:
 219        case V4L2_PIX_FMT_RGB565:
 220        case V4L2_PIX_FMT_BGR666:
 221        case V4L2_PIX_FMT_RGB24:
 222                return V4L2_COLORSPACE_SRGB;
 223        }
 224}
 225
 226static u32 sh_veu_reg_read(struct sh_veu_dev *veu, unsigned int reg)
 227{
 228        return ioread32(veu->base + reg);
 229}
 230
 231static void sh_veu_reg_write(struct sh_veu_dev *veu, unsigned int reg,
 232                             u32 value)
 233{
 234        iowrite32(value, veu->base + reg);
 235}
 236
 237                /* ========== mem2mem callbacks ========== */
 238
 239static void sh_veu_job_abort(void *priv)
 240{
 241        struct sh_veu_dev *veu = priv;
 242
 243        /* Will cancel the transaction in the next interrupt handler */
 244        veu->aborting = true;
 245}
 246
 247static void sh_veu_lock(void *priv)
 248{
 249        struct sh_veu_dev *veu = priv;
 250
 251        mutex_lock(&veu->fop_lock);
 252}
 253
 254static void sh_veu_unlock(void *priv)
 255{
 256        struct sh_veu_dev *veu = priv;
 257
 258        mutex_unlock(&veu->fop_lock);
 259}
 260
 261static void sh_veu_process(struct sh_veu_dev *veu,
 262                           struct vb2_buffer *src_buf,
 263                           struct vb2_buffer *dst_buf)
 264{
 265        dma_addr_t addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 266
 267        sh_veu_reg_write(veu, VEU_DAYR, addr + veu->vfmt_out.offset_y);
 268        sh_veu_reg_write(veu, VEU_DACR, veu->vfmt_out.offset_c ?
 269                         addr + veu->vfmt_out.offset_c : 0);
 270        dev_dbg(veu->dev, "%s(): dst base %lx, y: %x, c: %x\n", __func__,
 271                (unsigned long)addr,
 272                veu->vfmt_out.offset_y, veu->vfmt_out.offset_c);
 273
 274        addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
 275        sh_veu_reg_write(veu, VEU_SAYR, addr + veu->vfmt_in.offset_y);
 276        sh_veu_reg_write(veu, VEU_SACR, veu->vfmt_in.offset_c ?
 277                         addr + veu->vfmt_in.offset_c : 0);
 278        dev_dbg(veu->dev, "%s(): src base %lx, y: %x, c: %x\n", __func__,
 279                (unsigned long)addr,
 280                veu->vfmt_in.offset_y, veu->vfmt_in.offset_c);
 281
 282        sh_veu_reg_write(veu, VEU_STR, 1);
 283
 284        sh_veu_reg_write(veu, VEU_EIER, 1); /* enable interrupt in VEU */
 285}
 286
 287/**
 288 * sh_veu_device_run() - prepares and starts the device
 289 *
 290 * This will be called by the framework when it decides to schedule a particular
 291 * instance.
 292 */
 293static void sh_veu_device_run(void *priv)
 294{
 295        struct sh_veu_dev *veu = priv;
 296        struct vb2_buffer *src_buf, *dst_buf;
 297
 298        src_buf = v4l2_m2m_next_src_buf(veu->m2m_ctx);
 299        dst_buf = v4l2_m2m_next_dst_buf(veu->m2m_ctx);
 300
 301        if (src_buf && dst_buf)
 302                sh_veu_process(veu, src_buf, dst_buf);
 303}
 304
 305                /* ========== video ioctls ========== */
 306
 307static bool sh_veu_is_streamer(struct sh_veu_dev *veu, struct sh_veu_file *veu_file,
 308                               enum v4l2_buf_type type)
 309{
 310        return (type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
 311                veu_file == veu->capture) ||
 312                (type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
 313                 veu_file == veu->output);
 314}
 315
 316static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
 317                             struct vb2_queue *dst_vq);
 318
 319/*
 320 * It is not unusual to have video nodes open()ed multiple times. While some
 321 * V4L2 operations are non-intrusive, like querying formats and various
 322 * parameters, others, like setting formats, starting and stopping streaming,
 323 * queuing and dequeuing buffers, directly affect hardware configuration and /
 324 * or execution. This function verifies availability of the requested interface
 325 * and, if available, reserves it for the requesting user.
 326 */
 327static int sh_veu_stream_init(struct sh_veu_dev *veu, struct sh_veu_file *veu_file,
 328                              enum v4l2_buf_type type)
 329{
 330        struct sh_veu_file **stream;
 331
 332        switch (type) {
 333        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 334                stream = &veu->capture;
 335                break;
 336        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 337                stream = &veu->output;
 338                break;
 339        default:
 340                return -EINVAL;
 341        }
 342
 343        if (*stream == veu_file)
 344                return 0;
 345
 346        if (*stream)
 347                return -EBUSY;
 348
 349        *stream = veu_file;
 350
 351        return 0;
 352}
 353
 354static int sh_veu_context_init(struct sh_veu_dev *veu)
 355{
 356        if (veu->m2m_ctx)
 357                return 0;
 358
 359        veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu,
 360                                         sh_veu_queue_init);
 361
 362        return PTR_ERR_OR_ZERO(veu->m2m_ctx);
 363}
 364
 365static int sh_veu_querycap(struct file *file, void *priv,
 366                           struct v4l2_capability *cap)
 367{
 368        strlcpy(cap->driver, "sh-veu", sizeof(cap->driver));
 369        strlcpy(cap->card, "sh-mobile VEU", sizeof(cap->card));
 370        strlcpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info));
 371        cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
 372        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 373
 374        return 0;
 375}
 376
 377static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num)
 378{
 379        if (f->index >= fmt_num)
 380                return -EINVAL;
 381
 382        strlcpy(f->description, sh_veu_fmt[fmt[f->index]].name, sizeof(f->description));
 383        f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc;
 384        return 0;
 385}
 386
 387static int sh_veu_enum_fmt_vid_cap(struct file *file, void *priv,
 388                                   struct v4l2_fmtdesc *f)
 389{
 390        return sh_veu_enum_fmt(f, sh_veu_fmt_out, ARRAY_SIZE(sh_veu_fmt_out));
 391}
 392
 393static int sh_veu_enum_fmt_vid_out(struct file *file, void *priv,
 394                                   struct v4l2_fmtdesc *f)
 395{
 396        return sh_veu_enum_fmt(f, sh_veu_fmt_in, ARRAY_SIZE(sh_veu_fmt_in));
 397}
 398
 399static struct sh_veu_vfmt *sh_veu_get_vfmt(struct sh_veu_dev *veu,
 400                                           enum v4l2_buf_type type)
 401{
 402        switch (type) {
 403        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 404                return &veu->vfmt_out;
 405        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 406                return &veu->vfmt_in;
 407        default:
 408                return NULL;
 409        }
 410}
 411
 412static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
 413{
 414        struct v4l2_pix_format *pix = &f->fmt.pix;
 415        struct sh_veu_dev *veu = veu_file->veu_dev;
 416        struct sh_veu_vfmt *vfmt;
 417
 418        vfmt = sh_veu_get_vfmt(veu, f->type);
 419
 420        pix->width              = vfmt->frame.width;
 421        pix->height             = vfmt->frame.height;
 422        pix->field              = V4L2_FIELD_NONE;
 423        pix->pixelformat        = vfmt->fmt->fourcc;
 424        pix->colorspace         = sh_veu_4cc2cspace(pix->pixelformat);
 425        pix->bytesperline       = vfmt->bytesperline;
 426        pix->sizeimage          = vfmt->bytesperline * pix->height *
 427                vfmt->fmt->depth / vfmt->fmt->ydepth;
 428        pix->priv               = 0;
 429        dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
 430                f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
 431
 432        return 0;
 433}
 434
 435static int sh_veu_g_fmt_vid_out(struct file *file, void *priv,
 436                                struct v4l2_format *f)
 437{
 438        return sh_veu_g_fmt(priv, f);
 439}
 440
 441static int sh_veu_g_fmt_vid_cap(struct file *file, void *priv,
 442                                struct v4l2_format *f)
 443{
 444        return sh_veu_g_fmt(priv, f);
 445}
 446
 447static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt)
 448{
 449        struct v4l2_pix_format *pix = &f->fmt.pix;
 450        unsigned int y_bytes_used;
 451
 452        /*
 453         * V4L2 specification suggests, that the driver should correct the
 454         * format struct if any of the dimensions is unsupported
 455         */
 456        switch (pix->field) {
 457        default:
 458        case V4L2_FIELD_ANY:
 459                pix->field = V4L2_FIELD_NONE;
 460                /* fall through: continue handling V4L2_FIELD_NONE */
 461        case V4L2_FIELD_NONE:
 462                break;
 463        }
 464
 465        v4l_bound_align_image(&pix->width, MIN_W, MAX_W, ALIGN_W,
 466                              &pix->height, MIN_H, MAX_H, 0, 0);
 467
 468        y_bytes_used = (pix->width * fmt->ydepth) >> 3;
 469
 470        if (pix->bytesperline < y_bytes_used)
 471                pix->bytesperline = y_bytes_used;
 472        pix->sizeimage = pix->height * pix->bytesperline * fmt->depth / fmt->ydepth;
 473
 474        pix->pixelformat        = fmt->fourcc;
 475        pix->colorspace         = sh_veu_4cc2cspace(pix->pixelformat);
 476        pix->priv               = 0;
 477
 478        pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
 479
 480        return 0;
 481}
 482
 483static const struct sh_veu_format *sh_veu_find_fmt(const struct v4l2_format *f)
 484{
 485        const int *fmt;
 486        int i, n, dflt;
 487
 488        pr_debug("%s(%d;%d)\n", __func__, f->type, f->fmt.pix.field);
 489
 490        switch (f->type) {
 491        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 492                fmt = sh_veu_fmt_out;
 493                n = ARRAY_SIZE(sh_veu_fmt_out);
 494                dflt = DEFAULT_OUT_FMTIDX;
 495                break;
 496        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 497        default:
 498                fmt = sh_veu_fmt_in;
 499                n = ARRAY_SIZE(sh_veu_fmt_in);
 500                dflt = DEFAULT_IN_FMTIDX;
 501                break;
 502        }
 503
 504        for (i = 0; i < n; i++)
 505                if (sh_veu_fmt[fmt[i]].fourcc == f->fmt.pix.pixelformat)
 506                        return &sh_veu_fmt[fmt[i]];
 507
 508        return &sh_veu_fmt[dflt];
 509}
 510
 511static int sh_veu_try_fmt_vid_cap(struct file *file, void *priv,
 512                                  struct v4l2_format *f)
 513{
 514        const struct sh_veu_format *fmt;
 515
 516        fmt = sh_veu_find_fmt(f);
 517        if (!fmt)
 518                /* wrong buffer type */
 519                return -EINVAL;
 520
 521        return sh_veu_try_fmt(f, fmt);
 522}
 523
 524static int sh_veu_try_fmt_vid_out(struct file *file, void *priv,
 525                                  struct v4l2_format *f)
 526{
 527        const struct sh_veu_format *fmt;
 528
 529        fmt = sh_veu_find_fmt(f);
 530        if (!fmt)
 531                /* wrong buffer type */
 532                return -EINVAL;
 533
 534        return sh_veu_try_fmt(f, fmt);
 535}
 536
 537static void sh_veu_colour_offset(struct sh_veu_dev *veu, struct sh_veu_vfmt *vfmt)
 538{
 539        /* dst_left and dst_top validity will be verified in CROP / COMPOSE */
 540        unsigned int left = vfmt->frame.left & ~0x03;
 541        unsigned int top = vfmt->frame.top;
 542        dma_addr_t offset = ((left * veu->vfmt_out.fmt->depth) >> 3) +
 543                top * veu->vfmt_out.bytesperline;
 544        unsigned int y_line;
 545
 546        vfmt->offset_y = offset;
 547
 548        switch (vfmt->fmt->fourcc) {
 549        case V4L2_PIX_FMT_NV12:
 550        case V4L2_PIX_FMT_NV16:
 551        case V4L2_PIX_FMT_NV24:
 552                y_line = ALIGN(vfmt->frame.width, 16);
 553                vfmt->offset_c = offset + y_line * vfmt->frame.height;
 554                break;
 555        case V4L2_PIX_FMT_RGB332:
 556        case V4L2_PIX_FMT_RGB444:
 557        case V4L2_PIX_FMT_RGB565:
 558        case V4L2_PIX_FMT_BGR666:
 559        case V4L2_PIX_FMT_RGB24:
 560                vfmt->offset_c = 0;
 561                break;
 562        default:
 563                BUG();
 564        }
 565}
 566
 567static int sh_veu_s_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
 568{
 569        struct v4l2_pix_format *pix = &f->fmt.pix;
 570        struct sh_veu_dev *veu = veu_file->veu_dev;
 571        struct sh_veu_vfmt *vfmt;
 572        struct vb2_queue *vq;
 573        int ret = sh_veu_context_init(veu);
 574        if (ret < 0)
 575                return ret;
 576
 577        vq = v4l2_m2m_get_vq(veu->m2m_ctx, f->type);
 578        if (!vq)
 579                return -EINVAL;
 580
 581        if (vb2_is_busy(vq)) {
 582                v4l2_err(&veu_file->veu_dev->v4l2_dev, "%s queue busy\n", __func__);
 583                return -EBUSY;
 584        }
 585
 586        vfmt = sh_veu_get_vfmt(veu, f->type);
 587        /* called after try_fmt(), hence vfmt != NULL. Implicit BUG_ON() below */
 588
 589        vfmt->fmt               = sh_veu_find_fmt(f);
 590        /* vfmt->fmt != NULL following the same argument as above */
 591        vfmt->frame.width       = pix->width;
 592        vfmt->frame.height      = pix->height;
 593        vfmt->bytesperline      = pix->bytesperline;
 594
 595        sh_veu_colour_offset(veu, vfmt);
 596
 597        /*
 598         * We could also verify and require configuration only if any parameters
 599         * actually have changed, but it is unlikely, that the user requests the
 600         * same configuration several times without closing the device.
 601         */
 602        veu_file->cfg_needed = true;
 603
 604        dev_dbg(veu->dev,
 605                "Setting format for type %d, wxh: %dx%d, fmt: %x\n",
 606                f->type, pix->width, pix->height, vfmt->fmt->fourcc);
 607
 608        return 0;
 609}
 610
 611static int sh_veu_s_fmt_vid_cap(struct file *file, void *priv,
 612                                struct v4l2_format *f)
 613{
 614        int ret = sh_veu_try_fmt_vid_cap(file, priv, f);
 615        if (ret)
 616                return ret;
 617
 618        return sh_veu_s_fmt(priv, f);
 619}
 620
 621static int sh_veu_s_fmt_vid_out(struct file *file, void *priv,
 622                                struct v4l2_format *f)
 623{
 624        int ret = sh_veu_try_fmt_vid_out(file, priv, f);
 625        if (ret)
 626                return ret;
 627
 628        return sh_veu_s_fmt(priv, f);
 629}
 630
 631static int sh_veu_reqbufs(struct file *file, void *priv,
 632                          struct v4l2_requestbuffers *reqbufs)
 633{
 634        struct sh_veu_file *veu_file = priv;
 635        struct sh_veu_dev *veu = veu_file->veu_dev;
 636        int ret = sh_veu_context_init(veu);
 637        if (ret < 0)
 638                return ret;
 639
 640        ret = sh_veu_stream_init(veu, veu_file, reqbufs->type);
 641        if (ret < 0)
 642                return ret;
 643
 644        return v4l2_m2m_reqbufs(file, veu->m2m_ctx, reqbufs);
 645}
 646
 647static int sh_veu_querybuf(struct file *file, void *priv,
 648                           struct v4l2_buffer *buf)
 649{
 650        struct sh_veu_file *veu_file = priv;
 651
 652        if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
 653                return -EBUSY;
 654
 655        return v4l2_m2m_querybuf(file, veu_file->veu_dev->m2m_ctx, buf);
 656}
 657
 658static int sh_veu_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 659{
 660        struct sh_veu_file *veu_file = priv;
 661
 662        dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type);
 663        if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
 664                return -EBUSY;
 665
 666        return v4l2_m2m_qbuf(file, veu_file->veu_dev->m2m_ctx, buf);
 667}
 668
 669static int sh_veu_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 670{
 671        struct sh_veu_file *veu_file = priv;
 672
 673        dev_dbg(veu_file->veu_dev->dev, "%s(%d)\n", __func__, buf->type);
 674        if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, buf->type))
 675                return -EBUSY;
 676
 677        return v4l2_m2m_dqbuf(file, veu_file->veu_dev->m2m_ctx, buf);
 678}
 679
 680static void sh_veu_calc_scale(struct sh_veu_dev *veu,
 681                              int size_in, int size_out, int crop_out,
 682                              u32 *mant, u32 *frac, u32 *rep)
 683{
 684        u32 fixpoint;
 685
 686        /* calculate FRAC and MANT */
 687        *rep = *mant = *frac = 0;
 688
 689        if (size_in == size_out) {
 690                if (crop_out != size_out)
 691                        *mant = 1; /* needed for cropping */
 692                return;
 693        }
 694
 695        /* VEU2H special upscale */
 696        if (veu->is_2h && size_out > size_in) {
 697                u32 fixpoint = (4096 * size_in) / size_out;
 698                *mant = fixpoint / 4096;
 699                *frac = (fixpoint - (*mant * 4096)) & ~0x07;
 700
 701                switch (*frac) {
 702                case 0x800:
 703                        *rep = 1;
 704                        break;
 705                case 0x400:
 706                        *rep = 3;
 707                        break;
 708                case 0x200:
 709                        *rep = 7;
 710                        break;
 711                }
 712                if (*rep)
 713                        return;
 714        }
 715
 716        fixpoint = (4096 * (size_in - 1)) / (size_out + 1);
 717        *mant = fixpoint / 4096;
 718        *frac = fixpoint - (*mant * 4096);
 719
 720        if (*frac & 0x07) {
 721                /*
 722                 * FIXME: do we really have to round down twice in the
 723                 * up-scaling case?
 724                 */
 725                *frac &= ~0x07;
 726                if (size_out > size_in)
 727                        *frac -= 8; /* round down if scaling up */
 728                else
 729                        *frac += 8; /* round up if scaling down */
 730        }
 731}
 732
 733static unsigned long sh_veu_scale_v(struct sh_veu_dev *veu,
 734                                    int size_in, int size_out, int crop_out)
 735{
 736        u32 mant, frac, value, rep;
 737
 738        sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep);
 739
 740        /* set scale */
 741        value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff0000) |
 742                (((mant << 12) | frac) << 16);
 743
 744        sh_veu_reg_write(veu, VEU_RFCR, value);
 745
 746        /* set clip */
 747        value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff0000) |
 748                (((rep << 12) | crop_out) << 16);
 749
 750        sh_veu_reg_write(veu, VEU_RFSR, value);
 751
 752        return ALIGN((size_in * crop_out) / size_out, 4);
 753}
 754
 755static unsigned long sh_veu_scale_h(struct sh_veu_dev *veu,
 756                                    int size_in, int size_out, int crop_out)
 757{
 758        u32 mant, frac, value, rep;
 759
 760        sh_veu_calc_scale(veu, size_in, size_out, crop_out, &mant, &frac, &rep);
 761
 762        /* set scale */
 763        value = (sh_veu_reg_read(veu, VEU_RFCR) & ~0xffff) |
 764                (mant << 12) | frac;
 765
 766        sh_veu_reg_write(veu, VEU_RFCR, value);
 767
 768        /* set clip */
 769        value = (sh_veu_reg_read(veu, VEU_RFSR) & ~0xffff) |
 770                (rep << 12) | crop_out;
 771
 772        sh_veu_reg_write(veu, VEU_RFSR, value);
 773
 774        return ALIGN((size_in * crop_out) / size_out, 4);
 775}
 776
 777static void sh_veu_configure(struct sh_veu_dev *veu)
 778{
 779        u32 src_width, src_stride, src_height;
 780        u32 dst_width, dst_stride, dst_height;
 781        u32 real_w, real_h;
 782
 783        /* reset VEU */
 784        sh_veu_reg_write(veu, VEU_BSRR, 0x100);
 785
 786        src_width = veu->vfmt_in.frame.width;
 787        src_height = veu->vfmt_in.frame.height;
 788        src_stride = ALIGN(veu->vfmt_in.frame.width, 16);
 789
 790        dst_width = real_w = veu->vfmt_out.frame.width;
 791        dst_height = real_h = veu->vfmt_out.frame.height;
 792        /* Datasheet is unclear - whether it's always number of bytes or not */
 793        dst_stride = veu->vfmt_out.bytesperline;
 794
 795        /*
 796         * So far real_w == dst_width && real_h == dst_height, but it wasn't
 797         * necessarily the case in the original vidix driver, so, it may change
 798         * here in the future too.
 799         */
 800        src_width = sh_veu_scale_h(veu, src_width, real_w, dst_width);
 801        src_height = sh_veu_scale_v(veu, src_height, real_h, dst_height);
 802
 803        sh_veu_reg_write(veu, VEU_SWR, src_stride);
 804        sh_veu_reg_write(veu, VEU_SSR, src_width | (src_height << 16));
 805        sh_veu_reg_write(veu, VEU_BSSR, 0); /* not using bundle mode */
 806
 807        sh_veu_reg_write(veu, VEU_EDWR, dst_stride);
 808        sh_veu_reg_write(veu, VEU_DACR, 0); /* unused for RGB */
 809
 810        sh_veu_reg_write(veu, VEU_SWPR, 0x67);
 811        sh_veu_reg_write(veu, VEU_TRCR, (6 << 16) | (0 << 14) | 2 | 4);
 812
 813        if (veu->is_2h) {
 814                sh_veu_reg_write(veu, VEU_MCR00, 0x0cc5);
 815                sh_veu_reg_write(veu, VEU_MCR01, 0x0950);
 816                sh_veu_reg_write(veu, VEU_MCR02, 0x0000);
 817
 818                sh_veu_reg_write(veu, VEU_MCR10, 0x397f);
 819                sh_veu_reg_write(veu, VEU_MCR11, 0x0950);
 820                sh_veu_reg_write(veu, VEU_MCR12, 0x3ccd);
 821
 822                sh_veu_reg_write(veu, VEU_MCR20, 0x0000);
 823                sh_veu_reg_write(veu, VEU_MCR21, 0x0950);
 824                sh_veu_reg_write(veu, VEU_MCR22, 0x1023);
 825
 826                sh_veu_reg_write(veu, VEU_COFFR, 0x00800010);
 827        }
 828}
 829
 830static int sh_veu_streamon(struct file *file, void *priv,
 831                           enum v4l2_buf_type type)
 832{
 833        struct sh_veu_file *veu_file = priv;
 834
 835        if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type))
 836                return -EBUSY;
 837
 838        if (veu_file->cfg_needed) {
 839                struct sh_veu_dev *veu = veu_file->veu_dev;
 840                veu_file->cfg_needed = false;
 841                sh_veu_configure(veu_file->veu_dev);
 842                veu->xaction = 0;
 843                veu->aborting = false;
 844        }
 845
 846        return v4l2_m2m_streamon(file, veu_file->veu_dev->m2m_ctx, type);
 847}
 848
 849static int sh_veu_streamoff(struct file *file, void *priv,
 850                            enum v4l2_buf_type type)
 851{
 852        struct sh_veu_file *veu_file = priv;
 853
 854        if (!sh_veu_is_streamer(veu_file->veu_dev, veu_file, type))
 855                return -EBUSY;
 856
 857        return v4l2_m2m_streamoff(file, veu_file->veu_dev->m2m_ctx, type);
 858}
 859
 860static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
 861        .vidioc_querycap        = sh_veu_querycap,
 862
 863        .vidioc_enum_fmt_vid_cap = sh_veu_enum_fmt_vid_cap,
 864        .vidioc_g_fmt_vid_cap   = sh_veu_g_fmt_vid_cap,
 865        .vidioc_try_fmt_vid_cap = sh_veu_try_fmt_vid_cap,
 866        .vidioc_s_fmt_vid_cap   = sh_veu_s_fmt_vid_cap,
 867
 868        .vidioc_enum_fmt_vid_out = sh_veu_enum_fmt_vid_out,
 869        .vidioc_g_fmt_vid_out   = sh_veu_g_fmt_vid_out,
 870        .vidioc_try_fmt_vid_out = sh_veu_try_fmt_vid_out,
 871        .vidioc_s_fmt_vid_out   = sh_veu_s_fmt_vid_out,
 872
 873        .vidioc_reqbufs         = sh_veu_reqbufs,
 874        .vidioc_querybuf        = sh_veu_querybuf,
 875
 876        .vidioc_qbuf            = sh_veu_qbuf,
 877        .vidioc_dqbuf           = sh_veu_dqbuf,
 878
 879        .vidioc_streamon        = sh_veu_streamon,
 880        .vidioc_streamoff       = sh_veu_streamoff,
 881};
 882
 883                /* ========== Queue operations ========== */
 884
 885static int sh_veu_queue_setup(struct vb2_queue *vq,
 886                              const struct v4l2_format *f,
 887                              unsigned int *nbuffers, unsigned int *nplanes,
 888                              unsigned int sizes[], void *alloc_ctxs[])
 889{
 890        struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
 891        struct sh_veu_vfmt *vfmt;
 892        unsigned int size, count = *nbuffers;
 893
 894        if (f) {
 895                const struct v4l2_pix_format *pix = &f->fmt.pix;
 896                const struct sh_veu_format *fmt = sh_veu_find_fmt(f);
 897                struct v4l2_format ftmp = *f;
 898
 899                if (fmt->fourcc != pix->pixelformat)
 900                        return -EINVAL;
 901                sh_veu_try_fmt(&ftmp, fmt);
 902                if (ftmp.fmt.pix.width != pix->width ||
 903                    ftmp.fmt.pix.height != pix->height)
 904                        return -EINVAL;
 905                size = pix->bytesperline ? pix->bytesperline * pix->height * fmt->depth / fmt->ydepth :
 906                        pix->width * pix->height * fmt->depth / fmt->ydepth;
 907        } else {
 908                vfmt = sh_veu_get_vfmt(veu, vq->type);
 909                size = vfmt->bytesperline * vfmt->frame.height * vfmt->fmt->depth / vfmt->fmt->ydepth;
 910        }
 911
 912        if (count < 2)
 913                *nbuffers = count = 2;
 914
 915        if (size * count > VIDEO_MEM_LIMIT) {
 916                count = VIDEO_MEM_LIMIT / size;
 917                *nbuffers = count;
 918        }
 919
 920        *nplanes = 1;
 921        sizes[0] = size;
 922        alloc_ctxs[0] = veu->alloc_ctx;
 923
 924        dev_dbg(veu->dev, "get %d buffer(s) of size %d each.\n", count, size);
 925
 926        return 0;
 927}
 928
 929static int sh_veu_buf_prepare(struct vb2_buffer *vb)
 930{
 931        struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
 932        struct sh_veu_vfmt *vfmt;
 933        unsigned int sizeimage;
 934
 935        vfmt = sh_veu_get_vfmt(veu, vb->vb2_queue->type);
 936        sizeimage = vfmt->bytesperline * vfmt->frame.height *
 937                vfmt->fmt->depth / vfmt->fmt->ydepth;
 938
 939        if (vb2_plane_size(vb, 0) < sizeimage) {
 940                dev_dbg(veu->dev, "%s data will not fit into plane (%lu < %u)\n",
 941                        __func__, vb2_plane_size(vb, 0), sizeimage);
 942                return -EINVAL;
 943        }
 944
 945        vb2_set_plane_payload(vb, 0, sizeimage);
 946
 947        return 0;
 948}
 949
 950static void sh_veu_buf_queue(struct vb2_buffer *vb)
 951{
 952        struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
 953        dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->v4l2_buf.type);
 954        v4l2_m2m_buf_queue(veu->m2m_ctx, vb);
 955}
 956
 957static void sh_veu_wait_prepare(struct vb2_queue *q)
 958{
 959        sh_veu_unlock(vb2_get_drv_priv(q));
 960}
 961
 962static void sh_veu_wait_finish(struct vb2_queue *q)
 963{
 964        sh_veu_lock(vb2_get_drv_priv(q));
 965}
 966
 967static const struct vb2_ops sh_veu_qops = {
 968        .queue_setup     = sh_veu_queue_setup,
 969        .buf_prepare     = sh_veu_buf_prepare,
 970        .buf_queue       = sh_veu_buf_queue,
 971        .wait_prepare    = sh_veu_wait_prepare,
 972        .wait_finish     = sh_veu_wait_finish,
 973};
 974
 975static int sh_veu_queue_init(void *priv, struct vb2_queue *src_vq,
 976                             struct vb2_queue *dst_vq)
 977{
 978        int ret;
 979
 980        memset(src_vq, 0, sizeof(*src_vq));
 981        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 982        src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
 983        src_vq->drv_priv = priv;
 984        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 985        src_vq->ops = &sh_veu_qops;
 986        src_vq->mem_ops = &vb2_dma_contig_memops;
 987
 988        ret = vb2_queue_init(src_vq);
 989        if (ret < 0)
 990                return ret;
 991
 992        memset(dst_vq, 0, sizeof(*dst_vq));
 993        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 994        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
 995        dst_vq->drv_priv = priv;
 996        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 997        dst_vq->ops = &sh_veu_qops;
 998        dst_vq->mem_ops = &vb2_dma_contig_memops;
 999
1000        return vb2_queue_init(dst_vq);
1001}
1002
1003                /* ========== File operations ========== */
1004
1005static int sh_veu_open(struct file *file)
1006{
1007        struct sh_veu_dev *veu = video_drvdata(file);
1008        struct sh_veu_file *veu_file;
1009
1010        veu_file = kzalloc(sizeof(*veu_file), GFP_KERNEL);
1011        if (!veu_file)
1012                return -ENOMEM;
1013
1014        veu_file->veu_dev = veu;
1015        veu_file->cfg_needed = true;
1016
1017        file->private_data = veu_file;
1018
1019        pm_runtime_get_sync(veu->dev);
1020
1021        dev_dbg(veu->dev, "Created instance %p\n", veu_file);
1022
1023        return 0;
1024}
1025
1026static int sh_veu_release(struct file *file)
1027{
1028        struct sh_veu_dev *veu = video_drvdata(file);
1029        struct sh_veu_file *veu_file = file->private_data;
1030
1031        dev_dbg(veu->dev, "Releasing instance %p\n", veu_file);
1032
1033        if (veu_file == veu->capture) {
1034                veu->capture = NULL;
1035                vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE));
1036        }
1037
1038        if (veu_file == veu->output) {
1039                veu->output = NULL;
1040                vb2_queue_release(v4l2_m2m_get_vq(veu->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT));
1041        }
1042
1043        if (!veu->output && !veu->capture && veu->m2m_ctx) {
1044                v4l2_m2m_ctx_release(veu->m2m_ctx);
1045                veu->m2m_ctx = NULL;
1046        }
1047
1048        pm_runtime_put(veu->dev);
1049
1050        kfree(veu_file);
1051
1052        return 0;
1053}
1054
1055static unsigned int sh_veu_poll(struct file *file,
1056                                struct poll_table_struct *wait)
1057{
1058        struct sh_veu_file *veu_file = file->private_data;
1059
1060        return v4l2_m2m_poll(file, veu_file->veu_dev->m2m_ctx, wait);
1061}
1062
1063static int sh_veu_mmap(struct file *file, struct vm_area_struct *vma)
1064{
1065        struct sh_veu_file *veu_file = file->private_data;
1066
1067        return v4l2_m2m_mmap(file, veu_file->veu_dev->m2m_ctx, vma);
1068}
1069
1070static const struct v4l2_file_operations sh_veu_fops = {
1071        .owner          = THIS_MODULE,
1072        .open           = sh_veu_open,
1073        .release        = sh_veu_release,
1074        .poll           = sh_veu_poll,
1075        .unlocked_ioctl = video_ioctl2,
1076        .mmap           = sh_veu_mmap,
1077};
1078
1079static const struct video_device sh_veu_videodev = {
1080        .name           = "sh-veu",
1081        .fops           = &sh_veu_fops,
1082        .ioctl_ops      = &sh_veu_ioctl_ops,
1083        .minor          = -1,
1084        .release        = video_device_release_empty,
1085        .vfl_dir        = VFL_DIR_M2M,
1086};
1087
1088static const struct v4l2_m2m_ops sh_veu_m2m_ops = {
1089        .device_run     = sh_veu_device_run,
1090        .job_abort      = sh_veu_job_abort,
1091};
1092
1093static irqreturn_t sh_veu_bh(int irq, void *dev_id)
1094{
1095        struct sh_veu_dev *veu = dev_id;
1096
1097        if (veu->xaction == MEM2MEM_DEF_TRANSLEN || veu->aborting) {
1098                v4l2_m2m_job_finish(veu->m2m_dev, veu->m2m_ctx);
1099                veu->xaction = 0;
1100        } else {
1101                sh_veu_device_run(veu);
1102        }
1103
1104        return IRQ_HANDLED;
1105}
1106
1107static irqreturn_t sh_veu_isr(int irq, void *dev_id)
1108{
1109        struct sh_veu_dev *veu = dev_id;
1110        struct vb2_buffer *dst;
1111        struct vb2_buffer *src;
1112        u32 status = sh_veu_reg_read(veu, VEU_EVTR);
1113
1114        /* bundle read mode not used */
1115        if (!(status & 1))
1116                return IRQ_NONE;
1117
1118        /* disable interrupt in VEU */
1119        sh_veu_reg_write(veu, VEU_EIER, 0);
1120        /* halt operation */
1121        sh_veu_reg_write(veu, VEU_STR, 0);
1122        /* ack int, write 0 to clear bits */
1123        sh_veu_reg_write(veu, VEU_EVTR, status & ~1);
1124
1125        /* conversion completed */
1126        dst = v4l2_m2m_dst_buf_remove(veu->m2m_ctx);
1127        src = v4l2_m2m_src_buf_remove(veu->m2m_ctx);
1128        if (!src || !dst)
1129                return IRQ_NONE;
1130
1131        spin_lock(&veu->lock);
1132        v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
1133        v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
1134        spin_unlock(&veu->lock);
1135
1136        veu->xaction++;
1137
1138        return IRQ_WAKE_THREAD;
1139}
1140
1141static int sh_veu_probe(struct platform_device *pdev)
1142{
1143        struct sh_veu_dev *veu;
1144        struct resource *reg_res;
1145        struct video_device *vdev;
1146        int irq, ret;
1147
1148        reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1149        irq = platform_get_irq(pdev, 0);
1150
1151        if (!reg_res || irq <= 0) {
1152                dev_err(&pdev->dev, "Insufficient VEU platform information.\n");
1153                return -ENODEV;
1154        }
1155
1156        veu = devm_kzalloc(&pdev->dev, sizeof(*veu), GFP_KERNEL);
1157        if (!veu)
1158                return -ENOMEM;
1159
1160        veu->is_2h = resource_size(reg_res) == 0x22c;
1161
1162        veu->base = devm_ioremap_resource(&pdev->dev, reg_res);
1163        if (IS_ERR(veu->base))
1164                return PTR_ERR(veu->base);
1165
1166        ret = devm_request_threaded_irq(&pdev->dev, irq, sh_veu_isr, sh_veu_bh,
1167                                        0, "veu", veu);
1168        if (ret < 0)
1169                return ret;
1170
1171        ret = v4l2_device_register(&pdev->dev, &veu->v4l2_dev);
1172        if (ret < 0) {
1173                dev_err(&pdev->dev, "Error registering v4l2 device\n");
1174                return ret;
1175        }
1176
1177        vdev = &veu->vdev;
1178
1179        veu->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1180        if (IS_ERR(veu->alloc_ctx)) {
1181                ret = PTR_ERR(veu->alloc_ctx);
1182                goto einitctx;
1183        }
1184
1185        *vdev = sh_veu_videodev;
1186        spin_lock_init(&veu->lock);
1187        mutex_init(&veu->fop_lock);
1188        vdev->lock = &veu->fop_lock;
1189
1190        video_set_drvdata(vdev, veu);
1191
1192        veu->dev        = &pdev->dev;
1193        veu->vfmt_out   = DEFAULT_OUT_VFMT;
1194        veu->vfmt_in    = DEFAULT_IN_VFMT;
1195
1196        veu->m2m_dev = v4l2_m2m_init(&sh_veu_m2m_ops);
1197        if (IS_ERR(veu->m2m_dev)) {
1198                ret = PTR_ERR(veu->m2m_dev);
1199                v4l2_err(&veu->v4l2_dev, "Failed to init mem2mem device: %d\n", ret);
1200                goto em2minit;
1201        }
1202
1203        pm_runtime_enable(&pdev->dev);
1204        pm_runtime_resume(&pdev->dev);
1205
1206        ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1207        pm_runtime_suspend(&pdev->dev);
1208        if (ret < 0)
1209                goto evidreg;
1210
1211        return ret;
1212
1213evidreg:
1214        pm_runtime_disable(&pdev->dev);
1215        v4l2_m2m_release(veu->m2m_dev);
1216em2minit:
1217        vb2_dma_contig_cleanup_ctx(veu->alloc_ctx);
1218einitctx:
1219        v4l2_device_unregister(&veu->v4l2_dev);
1220        return ret;
1221}
1222
1223static int sh_veu_remove(struct platform_device *pdev)
1224{
1225        struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
1226        struct sh_veu_dev *veu = container_of(v4l2_dev,
1227                                              struct sh_veu_dev, v4l2_dev);
1228
1229        video_unregister_device(&veu->vdev);
1230        pm_runtime_disable(&pdev->dev);
1231        v4l2_m2m_release(veu->m2m_dev);
1232        vb2_dma_contig_cleanup_ctx(veu->alloc_ctx);
1233        v4l2_device_unregister(&veu->v4l2_dev);
1234
1235        return 0;
1236}
1237
1238static struct platform_driver __refdata sh_veu_pdrv = {
1239        .remove         = sh_veu_remove,
1240        .driver         = {
1241                .name   = "sh_veu",
1242                .owner  = THIS_MODULE,
1243        },
1244};
1245
1246module_platform_driver_probe(sh_veu_pdrv, sh_veu_probe);
1247
1248MODULE_DESCRIPTION("sh-mobile VEU mem2mem driver");
1249MODULE_AUTHOR("Guennadi Liakhovetski, <g.liakhovetski@gmx.de>");
1250MODULE_LICENSE("GPL v2");
1251