linux/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Allwinner sun8i deinterlacer with scaler driver
   4 *
   5 * Copyright (C) 2019 Jernej Skrabec <jernej.skrabec@siol.net>
   6 *
   7 * Based on vim2m driver.
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/interrupt.h>
  12#include <linux/io.h>
  13#include <linux/iopoll.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/of_device.h>
  17#include <linux/pm_runtime.h>
  18#include <linux/reset.h>
  19
  20#include <media/v4l2-device.h>
  21#include <media/v4l2-ioctl.h>
  22#include <media/v4l2-mem2mem.h>
  23
  24#include "sun8i-di.h"
  25
  26#define FLAG_SIZE (DEINTERLACE_MAX_WIDTH * DEINTERLACE_MAX_HEIGHT / 4)
  27
  28static u32 deinterlace_formats[] = {
  29        V4L2_PIX_FMT_NV12,
  30        V4L2_PIX_FMT_NV21,
  31};
  32
  33static inline u32 deinterlace_read(struct deinterlace_dev *dev, u32 reg)
  34{
  35        return readl(dev->base + reg);
  36}
  37
  38static inline void deinterlace_write(struct deinterlace_dev *dev,
  39                                     u32 reg, u32 value)
  40{
  41        writel(value, dev->base + reg);
  42}
  43
  44static inline void deinterlace_set_bits(struct deinterlace_dev *dev,
  45                                        u32 reg, u32 bits)
  46{
  47        writel(readl(dev->base + reg) | bits, dev->base + reg);
  48}
  49
  50static inline void deinterlace_clr_set_bits(struct deinterlace_dev *dev,
  51                                            u32 reg, u32 clr, u32 set)
  52{
  53        u32 val = readl(dev->base + reg);
  54
  55        val &= ~clr;
  56        val |= set;
  57
  58        writel(val, dev->base + reg);
  59}
  60
  61static void deinterlace_device_run(void *priv)
  62{
  63        struct deinterlace_ctx *ctx = priv;
  64        struct deinterlace_dev *dev = ctx->dev;
  65        u32 size, stride, width, height, val;
  66        struct vb2_v4l2_buffer *src, *dst;
  67        unsigned int hstep, vstep;
  68        dma_addr_t addr;
  69
  70        src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
  71        dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
  72
  73        v4l2_m2m_buf_copy_metadata(src, dst, true);
  74
  75        deinterlace_write(dev, DEINTERLACE_MOD_ENABLE,
  76                          DEINTERLACE_MOD_ENABLE_EN);
  77
  78        if (ctx->field) {
  79                deinterlace_write(dev, DEINTERLACE_TILE_FLAG0,
  80                                  ctx->flag1_buf_dma);
  81                deinterlace_write(dev, DEINTERLACE_TILE_FLAG1,
  82                                  ctx->flag2_buf_dma);
  83        } else {
  84                deinterlace_write(dev, DEINTERLACE_TILE_FLAG0,
  85                                  ctx->flag2_buf_dma);
  86                deinterlace_write(dev, DEINTERLACE_TILE_FLAG1,
  87                                  ctx->flag1_buf_dma);
  88        }
  89        deinterlace_write(dev, DEINTERLACE_FLAG_LINE_STRIDE, 0x200);
  90
  91        width = ctx->src_fmt.width;
  92        height = ctx->src_fmt.height;
  93        stride = ctx->src_fmt.bytesperline;
  94        size = stride * height;
  95
  96        addr = vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0);
  97        deinterlace_write(dev, DEINTERLACE_BUF_ADDR0, addr);
  98        deinterlace_write(dev, DEINTERLACE_BUF_ADDR1, addr + size);
  99        deinterlace_write(dev, DEINTERLACE_BUF_ADDR2, 0);
 100
 101        deinterlace_write(dev, DEINTERLACE_LINE_STRIDE0, stride);
 102        deinterlace_write(dev, DEINTERLACE_LINE_STRIDE1, stride);
 103
 104        deinterlace_write(dev, DEINTERLACE_CH0_IN_SIZE,
 105                          DEINTERLACE_SIZE(width, height));
 106        deinterlace_write(dev, DEINTERLACE_CH1_IN_SIZE,
 107                          DEINTERLACE_SIZE(width / 2, height / 2));
 108
 109        val = DEINTERLACE_IN_FMT_FMT(DEINTERLACE_IN_FMT_YUV420) |
 110              DEINTERLACE_IN_FMT_MOD(DEINTERLACE_MODE_UV_COMBINED);
 111        switch (ctx->src_fmt.pixelformat) {
 112        case V4L2_PIX_FMT_NV12:
 113                val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_UVUV);
 114                break;
 115        case V4L2_PIX_FMT_NV21:
 116                val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_VUVU);
 117                break;
 118        }
 119        deinterlace_write(dev, DEINTERLACE_IN_FMT, val);
 120
 121        if (ctx->prev)
 122                addr = vb2_dma_contig_plane_dma_addr(&ctx->prev->vb2_buf, 0);
 123
 124        deinterlace_write(dev, DEINTERLACE_PRELUMA, addr);
 125        deinterlace_write(dev, DEINTERLACE_PRECHROMA, addr + size);
 126
 127        val = DEINTERLACE_OUT_FMT_FMT(DEINTERLACE_OUT_FMT_YUV420SP);
 128        switch (ctx->src_fmt.pixelformat) {
 129        case V4L2_PIX_FMT_NV12:
 130                val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_UVUV);
 131                break;
 132        case V4L2_PIX_FMT_NV21:
 133                val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_VUVU);
 134                break;
 135        }
 136        deinterlace_write(dev, DEINTERLACE_OUT_FMT, val);
 137
 138        width = ctx->dst_fmt.width;
 139        height = ctx->dst_fmt.height;
 140        stride = ctx->dst_fmt.bytesperline;
 141        size = stride * height;
 142
 143        deinterlace_write(dev, DEINTERLACE_CH0_OUT_SIZE,
 144                          DEINTERLACE_SIZE(width, height));
 145        deinterlace_write(dev, DEINTERLACE_CH1_OUT_SIZE,
 146                          DEINTERLACE_SIZE(width / 2, height / 2));
 147
 148        deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE0, stride);
 149        deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE1, stride);
 150
 151        addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0);
 152        deinterlace_write(dev, DEINTERLACE_WB_ADDR0, addr);
 153        deinterlace_write(dev, DEINTERLACE_WB_ADDR1, addr + size);
 154        deinterlace_write(dev, DEINTERLACE_WB_ADDR2, 0);
 155
 156        hstep = (ctx->src_fmt.width << 16) / ctx->dst_fmt.width;
 157        vstep = (ctx->src_fmt.height << 16) / ctx->dst_fmt.height;
 158        deinterlace_write(dev, DEINTERLACE_CH0_HORZ_FACT, hstep);
 159        deinterlace_write(dev, DEINTERLACE_CH0_VERT_FACT, vstep);
 160        deinterlace_write(dev, DEINTERLACE_CH1_HORZ_FACT, hstep);
 161        deinterlace_write(dev, DEINTERLACE_CH1_VERT_FACT, vstep);
 162
 163        deinterlace_clr_set_bits(dev, DEINTERLACE_FIELD_CTRL,
 164                                 DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK,
 165                                 DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field));
 166
 167        deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 168                             DEINTERLACE_FRM_CTRL_START);
 169
 170        deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 171                             DEINTERLACE_FRM_CTRL_REG_READY);
 172
 173        deinterlace_set_bits(dev, DEINTERLACE_INT_ENABLE,
 174                             DEINTERLACE_INT_ENABLE_WB_EN);
 175
 176        deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 177                             DEINTERLACE_FRM_CTRL_WB_EN);
 178}
 179
 180static int deinterlace_job_ready(void *priv)
 181{
 182        struct deinterlace_ctx *ctx = priv;
 183
 184        return v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) >= 1 &&
 185               v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) >= 2;
 186}
 187
 188static void deinterlace_job_abort(void *priv)
 189{
 190        struct deinterlace_ctx *ctx = priv;
 191
 192        /* Will cancel the transaction in the next interrupt handler */
 193        ctx->aborting = 1;
 194}
 195
 196static irqreturn_t deinterlace_irq(int irq, void *data)
 197{
 198        struct deinterlace_dev *dev = data;
 199        struct vb2_v4l2_buffer *src, *dst;
 200        enum vb2_buffer_state state;
 201        struct deinterlace_ctx *ctx;
 202        unsigned int val;
 203
 204        ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
 205        if (!ctx) {
 206                v4l2_err(&dev->v4l2_dev,
 207                         "Instance released before the end of transaction\n");
 208                return IRQ_NONE;
 209        }
 210
 211        val = deinterlace_read(dev, DEINTERLACE_INT_STATUS);
 212        if (!(val & DEINTERLACE_INT_STATUS_WRITEBACK))
 213                return IRQ_NONE;
 214
 215        deinterlace_write(dev, DEINTERLACE_INT_ENABLE, 0);
 216        deinterlace_set_bits(dev, DEINTERLACE_INT_STATUS,
 217                             DEINTERLACE_INT_STATUS_WRITEBACK);
 218        deinterlace_write(dev, DEINTERLACE_MOD_ENABLE, 0);
 219        deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
 220                                 DEINTERLACE_FRM_CTRL_START, 0);
 221
 222        val = deinterlace_read(dev, DEINTERLACE_STATUS);
 223        if (val & DEINTERLACE_STATUS_WB_ERROR)
 224                state = VB2_BUF_STATE_ERROR;
 225        else
 226                state = VB2_BUF_STATE_DONE;
 227
 228        dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 229        v4l2_m2m_buf_done(dst, state);
 230
 231        if (ctx->field != ctx->first_field || ctx->aborting) {
 232                ctx->field = ctx->first_field;
 233
 234                src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 235                if (ctx->prev)
 236                        v4l2_m2m_buf_done(ctx->prev, state);
 237                ctx->prev = src;
 238
 239                v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 240        } else {
 241                ctx->field = !ctx->first_field;
 242                deinterlace_device_run(ctx);
 243        }
 244
 245        return IRQ_HANDLED;
 246}
 247
 248static void deinterlace_init(struct deinterlace_dev *dev)
 249{
 250        u32 val;
 251        int i;
 252
 253        deinterlace_write(dev, DEINTERLACE_BYPASS,
 254                          DEINTERLACE_BYPASS_CSC);
 255        deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE_CTRL,
 256                          DEINTERLACE_WB_LINE_STRIDE_CTRL_EN);
 257        deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 258                             DEINTERLACE_FRM_CTRL_OUT_CTRL);
 259        deinterlace_write(dev, DEINTERLACE_AGTH_SEL,
 260                          DEINTERLACE_AGTH_SEL_LINEBUF);
 261
 262        val = DEINTERLACE_CTRL_EN |
 263              DEINTERLACE_CTRL_MODE_MIXED |
 264              DEINTERLACE_CTRL_DIAG_INTP_EN |
 265              DEINTERLACE_CTRL_TEMP_DIFF_EN;
 266        deinterlace_write(dev, DEINTERLACE_CTRL, val);
 267
 268        deinterlace_clr_set_bits(dev, DEINTERLACE_LUMA_TH,
 269                                 DEINTERLACE_LUMA_TH_MIN_LUMA_MSK,
 270                                 DEINTERLACE_LUMA_TH_MIN_LUMA(4));
 271
 272        deinterlace_clr_set_bits(dev, DEINTERLACE_SPAT_COMP,
 273                                 DEINTERLACE_SPAT_COMP_TH2_MSK,
 274                                 DEINTERLACE_SPAT_COMP_TH2(5));
 275
 276        deinterlace_clr_set_bits(dev, DEINTERLACE_TEMP_DIFF,
 277                                 DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH_MSK,
 278                                 DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH(5));
 279
 280        val = DEINTERLACE_DIAG_INTP_TH0(60) |
 281              DEINTERLACE_DIAG_INTP_TH1(0) |
 282              DEINTERLACE_DIAG_INTP_TH3(30);
 283        deinterlace_write(dev, DEINTERLACE_DIAG_INTP, val);
 284
 285        deinterlace_clr_set_bits(dev, DEINTERLACE_CHROMA_DIFF,
 286                                 DEINTERLACE_CHROMA_DIFF_TH_MSK,
 287                                 DEINTERLACE_CHROMA_DIFF_TH(5));
 288
 289        /* neutral filter coefficients */
 290        deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 291                             DEINTERLACE_FRM_CTRL_COEF_ACCESS);
 292        readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val,
 293                           val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40);
 294
 295        for (i = 0; i < 32; i++) {
 296                deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4,
 297                                  DEINTERLACE_IDENTITY_COEF);
 298                deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4,
 299                                  DEINTERLACE_IDENTITY_COEF);
 300                deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4,
 301                                  DEINTERLACE_IDENTITY_COEF);
 302                deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4,
 303                                  DEINTERLACE_IDENTITY_COEF);
 304        }
 305
 306        deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
 307                                 DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0);
 308}
 309
 310static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file)
 311{
 312        return container_of(file->private_data, struct deinterlace_ctx, fh);
 313}
 314
 315static bool deinterlace_check_format(u32 pixelformat)
 316{
 317        unsigned int i;
 318
 319        for (i = 0; i < ARRAY_SIZE(deinterlace_formats); i++)
 320                if (deinterlace_formats[i] == pixelformat)
 321                        return true;
 322
 323        return false;
 324}
 325
 326static void deinterlace_prepare_format(struct v4l2_pix_format *pix_fmt)
 327{
 328        unsigned int height = pix_fmt->height;
 329        unsigned int width = pix_fmt->width;
 330        unsigned int bytesperline;
 331        unsigned int sizeimage;
 332
 333        width = clamp(width, DEINTERLACE_MIN_WIDTH,
 334                      DEINTERLACE_MAX_WIDTH);
 335        height = clamp(height, DEINTERLACE_MIN_HEIGHT,
 336                       DEINTERLACE_MAX_HEIGHT);
 337
 338        bytesperline = ALIGN(width, 2);
 339        /* luma */
 340        sizeimage = bytesperline * height;
 341        /* chroma */
 342        sizeimage += bytesperline * height / 2;
 343
 344        pix_fmt->width = width;
 345        pix_fmt->height = height;
 346        pix_fmt->bytesperline = bytesperline;
 347        pix_fmt->sizeimage = sizeimage;
 348}
 349
 350static int deinterlace_querycap(struct file *file, void *priv,
 351                                struct v4l2_capability *cap)
 352{
 353        strscpy(cap->driver, DEINTERLACE_NAME, sizeof(cap->driver));
 354        strscpy(cap->card, DEINTERLACE_NAME, sizeof(cap->card));
 355        snprintf(cap->bus_info, sizeof(cap->bus_info),
 356                 "platform:%s", DEINTERLACE_NAME);
 357
 358        return 0;
 359}
 360
 361static int deinterlace_enum_fmt(struct file *file, void *priv,
 362                                struct v4l2_fmtdesc *f)
 363{
 364        if (f->index < ARRAY_SIZE(deinterlace_formats)) {
 365                f->pixelformat = deinterlace_formats[f->index];
 366
 367                return 0;
 368        }
 369
 370        return -EINVAL;
 371}
 372
 373static int deinterlace_enum_framesizes(struct file *file, void *priv,
 374                                       struct v4l2_frmsizeenum *fsize)
 375{
 376        if (fsize->index != 0)
 377                return -EINVAL;
 378
 379        if (!deinterlace_check_format(fsize->pixel_format))
 380                return -EINVAL;
 381
 382        fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 383        fsize->stepwise.min_width = DEINTERLACE_MIN_WIDTH;
 384        fsize->stepwise.min_height = DEINTERLACE_MIN_HEIGHT;
 385        fsize->stepwise.max_width = DEINTERLACE_MAX_WIDTH;
 386        fsize->stepwise.max_height = DEINTERLACE_MAX_HEIGHT;
 387        fsize->stepwise.step_width = 2;
 388        fsize->stepwise.step_height = 1;
 389
 390        return 0;
 391}
 392
 393static int deinterlace_g_fmt_vid_cap(struct file *file, void *priv,
 394                                     struct v4l2_format *f)
 395{
 396        struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
 397
 398        f->fmt.pix = ctx->dst_fmt;
 399
 400        return 0;
 401}
 402
 403static int deinterlace_g_fmt_vid_out(struct file *file, void *priv,
 404                                     struct v4l2_format *f)
 405{
 406        struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
 407
 408        f->fmt.pix = ctx->src_fmt;
 409
 410        return 0;
 411}
 412
 413static int deinterlace_try_fmt_vid_cap(struct file *file, void *priv,
 414                                       struct v4l2_format *f)
 415{
 416        if (!deinterlace_check_format(f->fmt.pix.pixelformat))
 417                f->fmt.pix.pixelformat = deinterlace_formats[0];
 418
 419        if (f->fmt.pix.field != V4L2_FIELD_NONE)
 420                f->fmt.pix.field = V4L2_FIELD_NONE;
 421
 422        deinterlace_prepare_format(&f->fmt.pix);
 423
 424        return 0;
 425}
 426
 427static int deinterlace_try_fmt_vid_out(struct file *file, void *priv,
 428                                       struct v4l2_format *f)
 429{
 430        if (!deinterlace_check_format(f->fmt.pix.pixelformat))
 431                f->fmt.pix.pixelformat = deinterlace_formats[0];
 432
 433        if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB &&
 434            f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT &&
 435            f->fmt.pix.field != V4L2_FIELD_INTERLACED)
 436                f->fmt.pix.field = V4L2_FIELD_INTERLACED;
 437
 438        deinterlace_prepare_format(&f->fmt.pix);
 439
 440        return 0;
 441}
 442
 443static int deinterlace_s_fmt_vid_cap(struct file *file, void *priv,
 444                                     struct v4l2_format *f)
 445{
 446        struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
 447        struct vb2_queue *vq;
 448        int ret;
 449
 450        ret = deinterlace_try_fmt_vid_cap(file, priv, f);
 451        if (ret)
 452                return ret;
 453
 454        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 455        if (vb2_is_busy(vq))
 456                return -EBUSY;
 457
 458        ctx->dst_fmt = f->fmt.pix;
 459
 460        return 0;
 461}
 462
 463static int deinterlace_s_fmt_vid_out(struct file *file, void *priv,
 464                                     struct v4l2_format *f)
 465{
 466        struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
 467        struct vb2_queue *vq;
 468        int ret;
 469
 470        ret = deinterlace_try_fmt_vid_out(file, priv, f);
 471        if (ret)
 472                return ret;
 473
 474        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 475        if (vb2_is_busy(vq))
 476                return -EBUSY;
 477
 478        ctx->src_fmt = f->fmt.pix;
 479
 480        /* Propagate colorspace information to capture. */
 481        ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
 482        ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
 483        ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
 484        ctx->dst_fmt.quantization = f->fmt.pix.quantization;
 485
 486        return 0;
 487}
 488
 489static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
 490        .vidioc_querycap                = deinterlace_querycap,
 491
 492        .vidioc_enum_framesizes         = deinterlace_enum_framesizes,
 493
 494        .vidioc_enum_fmt_vid_cap        = deinterlace_enum_fmt,
 495        .vidioc_g_fmt_vid_cap           = deinterlace_g_fmt_vid_cap,
 496        .vidioc_try_fmt_vid_cap         = deinterlace_try_fmt_vid_cap,
 497        .vidioc_s_fmt_vid_cap           = deinterlace_s_fmt_vid_cap,
 498
 499        .vidioc_enum_fmt_vid_out        = deinterlace_enum_fmt,
 500        .vidioc_g_fmt_vid_out           = deinterlace_g_fmt_vid_out,
 501        .vidioc_try_fmt_vid_out         = deinterlace_try_fmt_vid_out,
 502        .vidioc_s_fmt_vid_out           = deinterlace_s_fmt_vid_out,
 503
 504        .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
 505        .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
 506        .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
 507        .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
 508        .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
 509        .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
 510        .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
 511
 512        .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
 513        .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
 514};
 515
 516static int deinterlace_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
 517                                   unsigned int *nplanes, unsigned int sizes[],
 518                                   struct device *alloc_devs[])
 519{
 520        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
 521        struct v4l2_pix_format *pix_fmt;
 522
 523        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 524                pix_fmt = &ctx->src_fmt;
 525        else
 526                pix_fmt = &ctx->dst_fmt;
 527
 528        if (*nplanes) {
 529                if (sizes[0] < pix_fmt->sizeimage)
 530                        return -EINVAL;
 531        } else {
 532                sizes[0] = pix_fmt->sizeimage;
 533                *nplanes = 1;
 534        }
 535
 536        return 0;
 537}
 538
 539static int deinterlace_buf_prepare(struct vb2_buffer *vb)
 540{
 541        struct vb2_queue *vq = vb->vb2_queue;
 542        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
 543        struct v4l2_pix_format *pix_fmt;
 544
 545        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 546                pix_fmt = &ctx->src_fmt;
 547        else
 548                pix_fmt = &ctx->dst_fmt;
 549
 550        if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
 551                return -EINVAL;
 552
 553        vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
 554
 555        return 0;
 556}
 557
 558static void deinterlace_buf_queue(struct vb2_buffer *vb)
 559{
 560        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 561        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 562
 563        v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
 564}
 565
 566static void deinterlace_queue_cleanup(struct vb2_queue *vq, u32 state)
 567{
 568        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
 569        struct vb2_v4l2_buffer *vbuf;
 570
 571        do {
 572                if (V4L2_TYPE_IS_OUTPUT(vq->type))
 573                        vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 574                else
 575                        vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 576
 577                if (vbuf)
 578                        v4l2_m2m_buf_done(vbuf, state);
 579        } while (vbuf);
 580
 581        if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->prev)
 582                v4l2_m2m_buf_done(ctx->prev, state);
 583}
 584
 585static int deinterlace_start_streaming(struct vb2_queue *vq, unsigned int count)
 586{
 587        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
 588        struct device *dev = ctx->dev->dev;
 589        int ret;
 590
 591        if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
 592                ret = pm_runtime_get_sync(dev);
 593                if (ret < 0) {
 594                        dev_err(dev, "Failed to enable module\n");
 595
 596                        goto err_runtime_get;
 597                }
 598
 599                ctx->first_field =
 600                        ctx->src_fmt.field == V4L2_FIELD_INTERLACED_BT;
 601                ctx->field = ctx->first_field;
 602
 603                ctx->prev = NULL;
 604                ctx->aborting = 0;
 605
 606                ctx->flag1_buf = dma_alloc_coherent(dev, FLAG_SIZE,
 607                                                    &ctx->flag1_buf_dma,
 608                                                    GFP_KERNEL);
 609                if (!ctx->flag1_buf) {
 610                        ret = -ENOMEM;
 611
 612                        goto err_no_mem1;
 613                }
 614
 615                ctx->flag2_buf = dma_alloc_coherent(dev, FLAG_SIZE,
 616                                                    &ctx->flag2_buf_dma,
 617                                                    GFP_KERNEL);
 618                if (!ctx->flag2_buf) {
 619                        ret = -ENOMEM;
 620
 621                        goto err_no_mem2;
 622                }
 623        }
 624
 625        return 0;
 626
 627err_no_mem2:
 628        dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf,
 629                          ctx->flag1_buf_dma);
 630err_no_mem1:
 631        pm_runtime_put(dev);
 632err_runtime_get:
 633        deinterlace_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
 634
 635        return ret;
 636}
 637
 638static void deinterlace_stop_streaming(struct vb2_queue *vq)
 639{
 640        struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
 641
 642        if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
 643                struct device *dev = ctx->dev->dev;
 644
 645                dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf,
 646                                  ctx->flag1_buf_dma);
 647                dma_free_coherent(dev, FLAG_SIZE, ctx->flag2_buf,
 648                                  ctx->flag2_buf_dma);
 649
 650                pm_runtime_put(dev);
 651        }
 652
 653        deinterlace_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
 654}
 655
 656static const struct vb2_ops deinterlace_qops = {
 657        .queue_setup            = deinterlace_queue_setup,
 658        .buf_prepare            = deinterlace_buf_prepare,
 659        .buf_queue              = deinterlace_buf_queue,
 660        .start_streaming        = deinterlace_start_streaming,
 661        .stop_streaming         = deinterlace_stop_streaming,
 662        .wait_prepare           = vb2_ops_wait_prepare,
 663        .wait_finish            = vb2_ops_wait_finish,
 664};
 665
 666static int deinterlace_queue_init(void *priv, struct vb2_queue *src_vq,
 667                                  struct vb2_queue *dst_vq)
 668{
 669        struct deinterlace_ctx *ctx = priv;
 670        int ret;
 671
 672        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 673        src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 674        src_vq->drv_priv = ctx;
 675        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 676        src_vq->min_buffers_needed = 1;
 677        src_vq->ops = &deinterlace_qops;
 678        src_vq->mem_ops = &vb2_dma_contig_memops;
 679        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 680        src_vq->lock = &ctx->dev->dev_mutex;
 681        src_vq->dev = ctx->dev->dev;
 682
 683        ret = vb2_queue_init(src_vq);
 684        if (ret)
 685                return ret;
 686
 687        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 688        dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 689        dst_vq->drv_priv = ctx;
 690        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 691        dst_vq->min_buffers_needed = 2;
 692        dst_vq->ops = &deinterlace_qops;
 693        dst_vq->mem_ops = &vb2_dma_contig_memops;
 694        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 695        dst_vq->lock = &ctx->dev->dev_mutex;
 696        dst_vq->dev = ctx->dev->dev;
 697
 698        ret = vb2_queue_init(dst_vq);
 699        if (ret)
 700                return ret;
 701
 702        return 0;
 703}
 704
 705static int deinterlace_open(struct file *file)
 706{
 707        struct deinterlace_dev *dev = video_drvdata(file);
 708        struct deinterlace_ctx *ctx = NULL;
 709        int ret;
 710
 711        if (mutex_lock_interruptible(&dev->dev_mutex))
 712                return -ERESTARTSYS;
 713
 714        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 715        if (!ctx) {
 716                mutex_unlock(&dev->dev_mutex);
 717                return -ENOMEM;
 718        }
 719
 720        /* default output format */
 721        ctx->src_fmt.pixelformat = deinterlace_formats[0];
 722        ctx->src_fmt.field = V4L2_FIELD_INTERLACED;
 723        ctx->src_fmt.width = 640;
 724        ctx->src_fmt.height = 480;
 725        deinterlace_prepare_format(&ctx->src_fmt);
 726
 727        /* default capture format */
 728        ctx->dst_fmt.pixelformat = deinterlace_formats[0];
 729        ctx->dst_fmt.field = V4L2_FIELD_NONE;
 730        ctx->dst_fmt.width = 640;
 731        ctx->dst_fmt.height = 480;
 732        deinterlace_prepare_format(&ctx->dst_fmt);
 733
 734        v4l2_fh_init(&ctx->fh, video_devdata(file));
 735        file->private_data = &ctx->fh;
 736        ctx->dev = dev;
 737
 738        ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
 739                                            &deinterlace_queue_init);
 740        if (IS_ERR(ctx->fh.m2m_ctx)) {
 741                ret = PTR_ERR(ctx->fh.m2m_ctx);
 742                goto err_free;
 743        }
 744
 745        v4l2_fh_add(&ctx->fh);
 746
 747        mutex_unlock(&dev->dev_mutex);
 748
 749        return 0;
 750
 751err_free:
 752        kfree(ctx);
 753        mutex_unlock(&dev->dev_mutex);
 754
 755        return ret;
 756}
 757
 758static int deinterlace_release(struct file *file)
 759{
 760        struct deinterlace_dev *dev = video_drvdata(file);
 761        struct deinterlace_ctx *ctx = container_of(file->private_data,
 762                                                   struct deinterlace_ctx, fh);
 763
 764        mutex_lock(&dev->dev_mutex);
 765
 766        v4l2_fh_del(&ctx->fh);
 767        v4l2_fh_exit(&ctx->fh);
 768        v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 769
 770        kfree(ctx);
 771
 772        mutex_unlock(&dev->dev_mutex);
 773
 774        return 0;
 775}
 776
 777static const struct v4l2_file_operations deinterlace_fops = {
 778        .owner          = THIS_MODULE,
 779        .open           = deinterlace_open,
 780        .release        = deinterlace_release,
 781        .poll           = v4l2_m2m_fop_poll,
 782        .unlocked_ioctl = video_ioctl2,
 783        .mmap           = v4l2_m2m_fop_mmap,
 784};
 785
 786static const struct video_device deinterlace_video_device = {
 787        .name           = DEINTERLACE_NAME,
 788        .vfl_dir        = VFL_DIR_M2M,
 789        .fops           = &deinterlace_fops,
 790        .ioctl_ops      = &deinterlace_ioctl_ops,
 791        .minor          = -1,
 792        .release        = video_device_release_empty,
 793        .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
 794};
 795
 796static const struct v4l2_m2m_ops deinterlace_m2m_ops = {
 797        .device_run     = deinterlace_device_run,
 798        .job_ready      = deinterlace_job_ready,
 799        .job_abort      = deinterlace_job_abort,
 800};
 801
 802static int deinterlace_probe(struct platform_device *pdev)
 803{
 804        struct deinterlace_dev *dev;
 805        struct video_device *vfd;
 806        struct resource *res;
 807        int irq, ret;
 808
 809        dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 810        if (!dev)
 811                return -ENOMEM;
 812
 813        dev->vfd = deinterlace_video_device;
 814        dev->dev = &pdev->dev;
 815
 816        irq = platform_get_irq(pdev, 0);
 817        if (irq <= 0)
 818                return irq;
 819
 820        ret = devm_request_irq(dev->dev, irq, deinterlace_irq,
 821                               0, dev_name(dev->dev), dev);
 822        if (ret) {
 823                dev_err(dev->dev, "Failed to request IRQ\n");
 824
 825                return ret;
 826        }
 827
 828        ret = of_dma_configure(dev->dev, dev->dev->of_node, true);
 829        if (ret)
 830                return ret;
 831
 832        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 833        dev->base = devm_ioremap_resource(&pdev->dev, res);
 834        if (IS_ERR(dev->base))
 835                return PTR_ERR(dev->base);
 836
 837        dev->bus_clk = devm_clk_get(dev->dev, "bus");
 838        if (IS_ERR(dev->bus_clk)) {
 839                dev_err(dev->dev, "Failed to get bus clock\n");
 840
 841                return PTR_ERR(dev->bus_clk);
 842        }
 843
 844        dev->mod_clk = devm_clk_get(dev->dev, "mod");
 845        if (IS_ERR(dev->mod_clk)) {
 846                dev_err(dev->dev, "Failed to get mod clock\n");
 847
 848                return PTR_ERR(dev->mod_clk);
 849        }
 850
 851        dev->ram_clk = devm_clk_get(dev->dev, "ram");
 852        if (IS_ERR(dev->ram_clk)) {
 853                dev_err(dev->dev, "Failed to get ram clock\n");
 854
 855                return PTR_ERR(dev->ram_clk);
 856        }
 857
 858        dev->rstc = devm_reset_control_get(dev->dev, NULL);
 859        if (IS_ERR(dev->rstc)) {
 860                dev_err(dev->dev, "Failed to get reset control\n");
 861
 862                return PTR_ERR(dev->rstc);
 863        }
 864
 865        mutex_init(&dev->dev_mutex);
 866
 867        ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 868        if (ret) {
 869                dev_err(dev->dev, "Failed to register V4L2 device\n");
 870
 871                return ret;
 872        }
 873
 874        vfd = &dev->vfd;
 875        vfd->lock = &dev->dev_mutex;
 876        vfd->v4l2_dev = &dev->v4l2_dev;
 877
 878        snprintf(vfd->name, sizeof(vfd->name), "%s",
 879                 deinterlace_video_device.name);
 880        video_set_drvdata(vfd, dev);
 881
 882        ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
 883        if (ret) {
 884                v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
 885
 886                goto err_v4l2;
 887        }
 888
 889        v4l2_info(&dev->v4l2_dev,
 890                  "Device registered as /dev/video%d\n", vfd->num);
 891
 892        dev->m2m_dev = v4l2_m2m_init(&deinterlace_m2m_ops);
 893        if (IS_ERR(dev->m2m_dev)) {
 894                v4l2_err(&dev->v4l2_dev,
 895                         "Failed to initialize V4L2 M2M device\n");
 896                ret = PTR_ERR(dev->m2m_dev);
 897
 898                goto err_video;
 899        }
 900
 901        platform_set_drvdata(pdev, dev);
 902
 903        pm_runtime_enable(dev->dev);
 904
 905        return 0;
 906
 907err_video:
 908        video_unregister_device(&dev->vfd);
 909err_v4l2:
 910        v4l2_device_unregister(&dev->v4l2_dev);
 911
 912        return ret;
 913}
 914
 915static int deinterlace_remove(struct platform_device *pdev)
 916{
 917        struct deinterlace_dev *dev = platform_get_drvdata(pdev);
 918
 919        v4l2_m2m_release(dev->m2m_dev);
 920        video_unregister_device(&dev->vfd);
 921        v4l2_device_unregister(&dev->v4l2_dev);
 922
 923        pm_runtime_force_suspend(&pdev->dev);
 924
 925        return 0;
 926}
 927
 928static int deinterlace_runtime_resume(struct device *device)
 929{
 930        struct deinterlace_dev *dev = dev_get_drvdata(device);
 931        int ret;
 932
 933        ret = clk_set_rate_exclusive(dev->mod_clk, 300000000);
 934        if (ret) {
 935                dev_err(dev->dev, "Failed to set exclusive mod clock rate\n");
 936
 937                return ret;
 938        }
 939
 940        ret = clk_prepare_enable(dev->bus_clk);
 941        if (ret) {
 942                dev_err(dev->dev, "Failed to enable bus clock\n");
 943
 944                goto err_exclusive_rate;
 945        }
 946
 947        ret = clk_prepare_enable(dev->mod_clk);
 948        if (ret) {
 949                dev_err(dev->dev, "Failed to enable mod clock\n");
 950
 951                goto err_bus_clk;
 952        }
 953
 954        ret = clk_prepare_enable(dev->ram_clk);
 955        if (ret) {
 956                dev_err(dev->dev, "Failed to enable ram clock\n");
 957
 958                goto err_mod_clk;
 959        }
 960
 961        ret = reset_control_deassert(dev->rstc);
 962        if (ret) {
 963                dev_err(dev->dev, "Failed to apply reset\n");
 964
 965                goto err_ram_clk;
 966        }
 967
 968        deinterlace_init(dev);
 969
 970        return 0;
 971
 972err_ram_clk:
 973        clk_disable_unprepare(dev->ram_clk);
 974err_mod_clk:
 975        clk_disable_unprepare(dev->mod_clk);
 976err_bus_clk:
 977        clk_disable_unprepare(dev->bus_clk);
 978err_exclusive_rate:
 979        clk_rate_exclusive_put(dev->mod_clk);
 980
 981        return ret;
 982}
 983
 984static int deinterlace_runtime_suspend(struct device *device)
 985{
 986        struct deinterlace_dev *dev = dev_get_drvdata(device);
 987
 988        reset_control_assert(dev->rstc);
 989
 990        clk_disable_unprepare(dev->ram_clk);
 991        clk_disable_unprepare(dev->mod_clk);
 992        clk_disable_unprepare(dev->bus_clk);
 993        clk_rate_exclusive_put(dev->mod_clk);
 994
 995        return 0;
 996}
 997
 998static const struct of_device_id deinterlace_dt_match[] = {
 999        { .compatible = "allwinner,sun8i-h3-deinterlace" },
1000        { /* sentinel */ }
1001};
1002MODULE_DEVICE_TABLE(of, deinterlace_dt_match);
1003
1004static const struct dev_pm_ops deinterlace_pm_ops = {
1005        .runtime_resume         = deinterlace_runtime_resume,
1006        .runtime_suspend        = deinterlace_runtime_suspend,
1007};
1008
1009static struct platform_driver deinterlace_driver = {
1010        .probe          = deinterlace_probe,
1011        .remove         = deinterlace_remove,
1012        .driver         = {
1013                .name           = DEINTERLACE_NAME,
1014                .of_match_table = deinterlace_dt_match,
1015                .pm             = &deinterlace_pm_ops,
1016        },
1017};
1018module_platform_driver(deinterlace_driver);
1019
1020MODULE_LICENSE("GPL v2");
1021MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
1022MODULE_DESCRIPTION("Allwinner Deinterlace driver");
1023