linux/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Allwinner sun8i DE2 rotation driver
   4 *
   5 * Copyright (C) 2020 Jernej Skrabec <jernej.skrabec@siol.net>
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/interrupt.h>
  10#include <linux/io.h>
  11#include <linux/iopoll.h>
  12#include <linux/module.h>
  13#include <linux/of.h>
  14#include <linux/of_device.h>
  15#include <linux/pm_runtime.h>
  16#include <linux/reset.h>
  17
  18#include <media/v4l2-device.h>
  19#include <media/v4l2-event.h>
  20#include <media/v4l2-ioctl.h>
  21#include <media/v4l2-mem2mem.h>
  22
  23#include "sun8i-formats.h"
  24#include "sun8i-rotate.h"
  25
  26static inline u32 rotate_read(struct rotate_dev *dev, u32 reg)
  27{
  28        return readl(dev->base + reg);
  29}
  30
  31static inline void rotate_write(struct rotate_dev *dev, u32 reg, u32 value)
  32{
  33        writel(value, dev->base + reg);
  34}
  35
  36static inline void rotate_set_bits(struct rotate_dev *dev, u32 reg, u32 bits)
  37{
  38        writel(readl(dev->base + reg) | bits, dev->base + reg);
  39}
  40
  41static void rotate_calc_addr_pitch(dma_addr_t buffer,
  42                                   u32 bytesperline, u32 height,
  43                                   const struct rotate_format *fmt,
  44                                   dma_addr_t *addr, u32 *pitch)
  45{
  46        u32 size;
  47        int i;
  48
  49        for (i = 0; i < fmt->planes; i++) {
  50                pitch[i] = bytesperline;
  51                addr[i] = buffer;
  52                if (i > 0)
  53                        pitch[i] /= fmt->hsub / fmt->bpp[i];
  54                size = pitch[i] * height;
  55                if (i > 0)
  56                        size /= fmt->vsub;
  57                buffer += size;
  58        }
  59}
  60
  61static void rotate_device_run(void *priv)
  62{
  63        struct rotate_ctx *ctx = priv;
  64        struct rotate_dev *dev = ctx->dev;
  65        struct vb2_v4l2_buffer *src, *dst;
  66        const struct rotate_format *fmt;
  67        dma_addr_t addr[3];
  68        u32 val, pitch[3];
  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        val = ROTATE_GLB_CTL_MODE(ROTATE_MODE_COPY_ROTATE);
  76        if (ctx->hflip)
  77                val |= ROTATE_GLB_CTL_HFLIP;
  78        if (ctx->vflip)
  79                val |= ROTATE_GLB_CTL_VFLIP;
  80        val |= ROTATE_GLB_CTL_ROTATION(ctx->rotate / 90);
  81        if (ctx->rotate != 90 && ctx->rotate != 270)
  82                val |= ROTATE_GLB_CTL_BURST_LEN(ROTATE_BURST_64);
  83        else
  84                val |= ROTATE_GLB_CTL_BURST_LEN(ROTATE_BURST_8);
  85        rotate_write(dev, ROTATE_GLB_CTL, val);
  86
  87        fmt = rotate_find_format(ctx->src_fmt.pixelformat);
  88        if (!fmt)
  89                return;
  90
  91        rotate_write(dev, ROTATE_IN_FMT, ROTATE_IN_FMT_FORMAT(fmt->hw_format));
  92
  93        rotate_calc_addr_pitch(vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0),
  94                               ctx->src_fmt.bytesperline, ctx->src_fmt.height,
  95                               fmt, addr, pitch);
  96
  97        rotate_write(dev, ROTATE_IN_SIZE,
  98                     ROTATE_SIZE(ctx->src_fmt.width, ctx->src_fmt.height));
  99
 100        rotate_write(dev, ROTATE_IN_PITCH0, pitch[0]);
 101        rotate_write(dev, ROTATE_IN_PITCH1, pitch[1]);
 102        rotate_write(dev, ROTATE_IN_PITCH2, pitch[2]);
 103
 104        rotate_write(dev, ROTATE_IN_ADDRL0, addr[0]);
 105        rotate_write(dev, ROTATE_IN_ADDRL1, addr[1]);
 106        rotate_write(dev, ROTATE_IN_ADDRL2, addr[2]);
 107
 108        rotate_write(dev, ROTATE_IN_ADDRH0, 0);
 109        rotate_write(dev, ROTATE_IN_ADDRH1, 0);
 110        rotate_write(dev, ROTATE_IN_ADDRH2, 0);
 111
 112        fmt = rotate_find_format(ctx->dst_fmt.pixelformat);
 113        if (!fmt)
 114                return;
 115
 116        rotate_calc_addr_pitch(vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0),
 117                               ctx->dst_fmt.bytesperline, ctx->dst_fmt.height,
 118                               fmt, addr, pitch);
 119
 120        rotate_write(dev, ROTATE_OUT_SIZE,
 121                     ROTATE_SIZE(ctx->dst_fmt.width, ctx->dst_fmt.height));
 122
 123        rotate_write(dev, ROTATE_OUT_PITCH0, pitch[0]);
 124        rotate_write(dev, ROTATE_OUT_PITCH1, pitch[1]);
 125        rotate_write(dev, ROTATE_OUT_PITCH2, pitch[2]);
 126
 127        rotate_write(dev, ROTATE_OUT_ADDRL0, addr[0]);
 128        rotate_write(dev, ROTATE_OUT_ADDRL1, addr[1]);
 129        rotate_write(dev, ROTATE_OUT_ADDRL2, addr[2]);
 130
 131        rotate_write(dev, ROTATE_OUT_ADDRH0, 0);
 132        rotate_write(dev, ROTATE_OUT_ADDRH1, 0);
 133        rotate_write(dev, ROTATE_OUT_ADDRH2, 0);
 134
 135        rotate_set_bits(dev, ROTATE_INT, ROTATE_INT_FINISH_IRQ_EN);
 136        rotate_set_bits(dev, ROTATE_GLB_CTL, ROTATE_GLB_CTL_START);
 137}
 138
 139static irqreturn_t rotate_irq(int irq, void *data)
 140{
 141        struct vb2_v4l2_buffer *buffer;
 142        struct rotate_dev *dev = data;
 143        struct rotate_ctx *ctx;
 144        unsigned int val;
 145
 146        ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
 147        if (!ctx) {
 148                v4l2_err(&dev->v4l2_dev,
 149                         "Instance released before the end of transaction\n");
 150                return IRQ_NONE;
 151        }
 152
 153        val = rotate_read(dev, ROTATE_INT);
 154        if (!(val & ROTATE_INT_FINISH_IRQ))
 155                return IRQ_NONE;
 156
 157        /* clear flag and disable irq */
 158        rotate_write(dev, ROTATE_INT, ROTATE_INT_FINISH_IRQ);
 159
 160        buffer = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 161        v4l2_m2m_buf_done(buffer, VB2_BUF_STATE_DONE);
 162
 163        buffer = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 164        v4l2_m2m_buf_done(buffer, VB2_BUF_STATE_DONE);
 165
 166        v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 167
 168        return IRQ_HANDLED;
 169}
 170
 171static inline struct rotate_ctx *rotate_file2ctx(struct file *file)
 172{
 173        return container_of(file->private_data, struct rotate_ctx, fh);
 174}
 175
 176static void rotate_prepare_format(struct v4l2_pix_format *pix_fmt)
 177{
 178        unsigned int height, width, alignment, sizeimage, size, bpl;
 179        const struct rotate_format *fmt;
 180        int i;
 181
 182        fmt = rotate_find_format(pix_fmt->pixelformat);
 183        if (!fmt)
 184                return;
 185
 186        width = ALIGN(pix_fmt->width, fmt->hsub);
 187        height = ALIGN(pix_fmt->height, fmt->vsub);
 188
 189        /* all pitches have to be 16 byte aligned */
 190        alignment = 16;
 191        if (fmt->planes > 1)
 192                alignment *= fmt->hsub / fmt->bpp[1];
 193        bpl = ALIGN(width * fmt->bpp[0], alignment);
 194
 195        sizeimage = 0;
 196        for (i = 0; i < fmt->planes; i++) {
 197                size = bpl * height;
 198                if (i > 0) {
 199                        size *= fmt->bpp[i];
 200                        size /= fmt->hsub;
 201                        size /= fmt->vsub;
 202                }
 203                sizeimage += size;
 204        }
 205
 206        pix_fmt->width = width;
 207        pix_fmt->height = height;
 208        pix_fmt->bytesperline = bpl;
 209        pix_fmt->sizeimage = sizeimage;
 210}
 211
 212static int rotate_querycap(struct file *file, void *priv,
 213                           struct v4l2_capability *cap)
 214{
 215        strscpy(cap->driver, ROTATE_NAME, sizeof(cap->driver));
 216        strscpy(cap->card, ROTATE_NAME, sizeof(cap->card));
 217        snprintf(cap->bus_info, sizeof(cap->bus_info),
 218                 "platform:%s", ROTATE_NAME);
 219
 220        return 0;
 221}
 222
 223static int rotate_enum_fmt_vid_cap(struct file *file, void *priv,
 224                                   struct v4l2_fmtdesc *f)
 225{
 226        return rotate_enum_fmt(f, true);
 227}
 228
 229static int rotate_enum_fmt_vid_out(struct file *file, void *priv,
 230                                   struct v4l2_fmtdesc *f)
 231{
 232        return rotate_enum_fmt(f, false);
 233}
 234
 235static int rotate_enum_framesizes(struct file *file, void *priv,
 236                                  struct v4l2_frmsizeenum *fsize)
 237{
 238        const struct rotate_format *fmt;
 239
 240        if (fsize->index != 0)
 241                return -EINVAL;
 242
 243        fmt = rotate_find_format(fsize->pixel_format);
 244        if (!fmt)
 245                return -EINVAL;
 246
 247        fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 248        fsize->stepwise.min_width = ROTATE_MIN_WIDTH;
 249        fsize->stepwise.min_height = ROTATE_MIN_HEIGHT;
 250        fsize->stepwise.max_width = ROTATE_MAX_WIDTH;
 251        fsize->stepwise.max_height = ROTATE_MAX_HEIGHT;
 252        fsize->stepwise.step_width = fmt->hsub;
 253        fsize->stepwise.step_height = fmt->vsub;
 254
 255        return 0;
 256}
 257
 258static int rotate_set_cap_format(struct rotate_ctx *ctx,
 259                                 struct v4l2_pix_format *f,
 260                                 u32 rotate)
 261{
 262        const struct rotate_format *fmt;
 263
 264        fmt = rotate_find_format(ctx->src_fmt.pixelformat);
 265        if (!fmt)
 266                return -EINVAL;
 267
 268        if (fmt->flags & ROTATE_FLAG_YUV)
 269                f->pixelformat = V4L2_PIX_FMT_YUV420;
 270        else
 271                f->pixelformat = ctx->src_fmt.pixelformat;
 272
 273        f->field = V4L2_FIELD_NONE;
 274
 275        if (rotate == 90 || rotate == 270) {
 276                f->width = ctx->src_fmt.height;
 277                f->height = ctx->src_fmt.width;
 278        } else {
 279                f->width = ctx->src_fmt.width;
 280                f->height = ctx->src_fmt.height;
 281        }
 282
 283        rotate_prepare_format(f);
 284
 285        return 0;
 286}
 287
 288static int rotate_g_fmt_vid_cap(struct file *file, void *priv,
 289                                struct v4l2_format *f)
 290{
 291        struct rotate_ctx *ctx = rotate_file2ctx(file);
 292
 293        f->fmt.pix = ctx->dst_fmt;
 294
 295        return 0;
 296}
 297
 298static int rotate_g_fmt_vid_out(struct file *file, void *priv,
 299                                struct v4l2_format *f)
 300{
 301        struct rotate_ctx *ctx = rotate_file2ctx(file);
 302
 303        f->fmt.pix = ctx->src_fmt;
 304
 305        return 0;
 306}
 307
 308static int rotate_try_fmt_vid_cap(struct file *file, void *priv,
 309                                  struct v4l2_format *f)
 310{
 311        struct rotate_ctx *ctx = rotate_file2ctx(file);
 312
 313        return rotate_set_cap_format(ctx, &f->fmt.pix, ctx->rotate);
 314}
 315
 316static int rotate_try_fmt_vid_out(struct file *file, void *priv,
 317                                  struct v4l2_format *f)
 318{
 319        if (!rotate_find_format(f->fmt.pix.pixelformat))
 320                f->fmt.pix.pixelformat = V4L2_PIX_FMT_ARGB32;
 321
 322        if (f->fmt.pix.width < ROTATE_MIN_WIDTH)
 323                f->fmt.pix.width = ROTATE_MIN_WIDTH;
 324        if (f->fmt.pix.height < ROTATE_MIN_HEIGHT)
 325                f->fmt.pix.height = ROTATE_MIN_HEIGHT;
 326
 327        if (f->fmt.pix.width > ROTATE_MAX_WIDTH)
 328                f->fmt.pix.width = ROTATE_MAX_WIDTH;
 329        if (f->fmt.pix.height > ROTATE_MAX_HEIGHT)
 330                f->fmt.pix.height = ROTATE_MAX_HEIGHT;
 331
 332        f->fmt.pix.field = V4L2_FIELD_NONE;
 333
 334        rotate_prepare_format(&f->fmt.pix);
 335
 336        return 0;
 337}
 338
 339static int rotate_s_fmt_vid_cap(struct file *file, void *priv,
 340                                struct v4l2_format *f)
 341{
 342        struct rotate_ctx *ctx = rotate_file2ctx(file);
 343        struct vb2_queue *vq;
 344        int ret;
 345
 346        ret = rotate_try_fmt_vid_cap(file, priv, f);
 347        if (ret)
 348                return ret;
 349
 350        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 351        if (vb2_is_busy(vq))
 352                return -EBUSY;
 353
 354        ctx->dst_fmt = f->fmt.pix;
 355
 356        return 0;
 357}
 358
 359static int rotate_s_fmt_vid_out(struct file *file, void *priv,
 360                                struct v4l2_format *f)
 361{
 362        struct rotate_ctx *ctx = rotate_file2ctx(file);
 363        struct vb2_queue *vq;
 364        int ret;
 365
 366        ret = rotate_try_fmt_vid_out(file, priv, f);
 367        if (ret)
 368                return ret;
 369
 370        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 371        if (vb2_is_busy(vq))
 372                return -EBUSY;
 373
 374        /*
 375         * Capture queue has to be also checked, because format and size
 376         * depends on output format and size.
 377         */
 378        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 379        if (vb2_is_busy(vq))
 380                return -EBUSY;
 381
 382        ctx->src_fmt = f->fmt.pix;
 383
 384        /* Propagate colorspace information to capture. */
 385        ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
 386        ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
 387        ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
 388        ctx->dst_fmt.quantization = f->fmt.pix.quantization;
 389
 390        return rotate_set_cap_format(ctx, &ctx->dst_fmt, ctx->rotate);
 391}
 392
 393static const struct v4l2_ioctl_ops rotate_ioctl_ops = {
 394        .vidioc_querycap                = rotate_querycap,
 395
 396        .vidioc_enum_framesizes         = rotate_enum_framesizes,
 397
 398        .vidioc_enum_fmt_vid_cap        = rotate_enum_fmt_vid_cap,
 399        .vidioc_g_fmt_vid_cap           = rotate_g_fmt_vid_cap,
 400        .vidioc_try_fmt_vid_cap         = rotate_try_fmt_vid_cap,
 401        .vidioc_s_fmt_vid_cap           = rotate_s_fmt_vid_cap,
 402
 403        .vidioc_enum_fmt_vid_out        = rotate_enum_fmt_vid_out,
 404        .vidioc_g_fmt_vid_out           = rotate_g_fmt_vid_out,
 405        .vidioc_try_fmt_vid_out         = rotate_try_fmt_vid_out,
 406        .vidioc_s_fmt_vid_out           = rotate_s_fmt_vid_out,
 407
 408        .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
 409        .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
 410        .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
 411        .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
 412        .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
 413        .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
 414        .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
 415
 416        .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
 417        .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
 418
 419        .vidioc_log_status              = v4l2_ctrl_log_status,
 420        .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
 421        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 422};
 423
 424static int rotate_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
 425                              unsigned int *nplanes, unsigned int sizes[],
 426                              struct device *alloc_devs[])
 427{
 428        struct rotate_ctx *ctx = vb2_get_drv_priv(vq);
 429        struct v4l2_pix_format *pix_fmt;
 430
 431        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 432                pix_fmt = &ctx->src_fmt;
 433        else
 434                pix_fmt = &ctx->dst_fmt;
 435
 436        if (*nplanes) {
 437                if (sizes[0] < pix_fmt->sizeimage)
 438                        return -EINVAL;
 439        } else {
 440                sizes[0] = pix_fmt->sizeimage;
 441                *nplanes = 1;
 442        }
 443
 444        return 0;
 445}
 446
 447static int rotate_buf_prepare(struct vb2_buffer *vb)
 448{
 449        struct vb2_queue *vq = vb->vb2_queue;
 450        struct rotate_ctx *ctx = vb2_get_drv_priv(vq);
 451        struct v4l2_pix_format *pix_fmt;
 452
 453        if (V4L2_TYPE_IS_OUTPUT(vq->type))
 454                pix_fmt = &ctx->src_fmt;
 455        else
 456                pix_fmt = &ctx->dst_fmt;
 457
 458        if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
 459                return -EINVAL;
 460
 461        vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
 462
 463        return 0;
 464}
 465
 466static void rotate_buf_queue(struct vb2_buffer *vb)
 467{
 468        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 469        struct rotate_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 470
 471        v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
 472}
 473
 474static void rotate_queue_cleanup(struct vb2_queue *vq, u32 state)
 475{
 476        struct rotate_ctx *ctx = vb2_get_drv_priv(vq);
 477        struct vb2_v4l2_buffer *vbuf;
 478
 479        do {
 480                if (V4L2_TYPE_IS_OUTPUT(vq->type))
 481                        vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 482                else
 483                        vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 484
 485                if (vbuf)
 486                        v4l2_m2m_buf_done(vbuf, state);
 487        } while (vbuf);
 488}
 489
 490static int rotate_start_streaming(struct vb2_queue *vq, unsigned int count)
 491{
 492        if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
 493                struct rotate_ctx *ctx = vb2_get_drv_priv(vq);
 494                struct device *dev = ctx->dev->dev;
 495                int ret;
 496
 497                ret = pm_runtime_resume_and_get(dev);
 498                if (ret < 0) {
 499                        dev_err(dev, "Failed to enable module\n");
 500
 501                        return ret;
 502                }
 503        }
 504
 505        return 0;
 506}
 507
 508static void rotate_stop_streaming(struct vb2_queue *vq)
 509{
 510        if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
 511                struct rotate_ctx *ctx = vb2_get_drv_priv(vq);
 512
 513                pm_runtime_put(ctx->dev->dev);
 514        }
 515
 516        rotate_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
 517}
 518
 519static const struct vb2_ops rotate_qops = {
 520        .queue_setup            = rotate_queue_setup,
 521        .buf_prepare            = rotate_buf_prepare,
 522        .buf_queue              = rotate_buf_queue,
 523        .start_streaming        = rotate_start_streaming,
 524        .stop_streaming         = rotate_stop_streaming,
 525        .wait_prepare           = vb2_ops_wait_prepare,
 526        .wait_finish            = vb2_ops_wait_finish,
 527};
 528
 529static int rotate_queue_init(void *priv, struct vb2_queue *src_vq,
 530                             struct vb2_queue *dst_vq)
 531{
 532        struct rotate_ctx *ctx = priv;
 533        int ret;
 534
 535        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 536        src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 537        src_vq->drv_priv = ctx;
 538        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 539        src_vq->min_buffers_needed = 1;
 540        src_vq->ops = &rotate_qops;
 541        src_vq->mem_ops = &vb2_dma_contig_memops;
 542        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 543        src_vq->lock = &ctx->dev->dev_mutex;
 544        src_vq->dev = ctx->dev->dev;
 545
 546        ret = vb2_queue_init(src_vq);
 547        if (ret)
 548                return ret;
 549
 550        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 551        dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 552        dst_vq->drv_priv = ctx;
 553        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 554        dst_vq->min_buffers_needed = 2;
 555        dst_vq->ops = &rotate_qops;
 556        dst_vq->mem_ops = &vb2_dma_contig_memops;
 557        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 558        dst_vq->lock = &ctx->dev->dev_mutex;
 559        dst_vq->dev = ctx->dev->dev;
 560
 561        ret = vb2_queue_init(dst_vq);
 562        if (ret)
 563                return ret;
 564
 565        return 0;
 566}
 567
 568static int rotate_s_ctrl(struct v4l2_ctrl *ctrl)
 569{
 570        struct rotate_ctx *ctx = container_of(ctrl->handler,
 571                                              struct rotate_ctx,
 572                                              ctrl_handler);
 573        struct v4l2_pix_format fmt;
 574
 575        switch (ctrl->id) {
 576        case V4L2_CID_HFLIP:
 577                ctx->hflip = ctrl->val;
 578                break;
 579        case V4L2_CID_VFLIP:
 580                ctx->vflip = ctrl->val;
 581                break;
 582        case V4L2_CID_ROTATE:
 583                rotate_set_cap_format(ctx, &fmt, ctrl->val);
 584
 585                /* Check if capture format needs to be changed */
 586                if (fmt.width != ctx->dst_fmt.width ||
 587                    fmt.height != ctx->dst_fmt.height ||
 588                    fmt.bytesperline != ctx->dst_fmt.bytesperline ||
 589                    fmt.sizeimage != ctx->dst_fmt.sizeimage) {
 590                        struct vb2_queue *vq;
 591
 592                        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 593                                             V4L2_BUF_TYPE_VIDEO_CAPTURE);
 594                        if (vb2_is_busy(vq))
 595                                return -EBUSY;
 596
 597                        rotate_set_cap_format(ctx, &ctx->dst_fmt, ctrl->val);
 598                }
 599
 600                ctx->rotate = ctrl->val;
 601                break;
 602        default:
 603                return -EINVAL;
 604        }
 605
 606        return 0;
 607}
 608
 609static const struct v4l2_ctrl_ops rotate_ctrl_ops = {
 610        .s_ctrl = rotate_s_ctrl,
 611};
 612
 613static int rotate_setup_ctrls(struct rotate_ctx *ctx)
 614{
 615        v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
 616
 617        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rotate_ctrl_ops,
 618                          V4L2_CID_HFLIP, 0, 1, 1, 0);
 619
 620        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rotate_ctrl_ops,
 621                          V4L2_CID_VFLIP, 0, 1, 1, 0);
 622
 623        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rotate_ctrl_ops,
 624                          V4L2_CID_ROTATE, 0, 270, 90, 0);
 625
 626        if (ctx->ctrl_handler.error) {
 627                int err = ctx->ctrl_handler.error;
 628
 629                v4l2_err(&ctx->dev->v4l2_dev, "control setup failed!\n");
 630                v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 631
 632                return err;
 633        }
 634
 635        return v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
 636}
 637
 638static int rotate_open(struct file *file)
 639{
 640        struct rotate_dev *dev = video_drvdata(file);
 641        struct rotate_ctx *ctx = NULL;
 642        int ret;
 643
 644        if (mutex_lock_interruptible(&dev->dev_mutex))
 645                return -ERESTARTSYS;
 646
 647        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 648        if (!ctx) {
 649                mutex_unlock(&dev->dev_mutex);
 650                return -ENOMEM;
 651        }
 652
 653        /* default output format */
 654        ctx->src_fmt.pixelformat = V4L2_PIX_FMT_ARGB32;
 655        ctx->src_fmt.field = V4L2_FIELD_NONE;
 656        ctx->src_fmt.width = 640;
 657        ctx->src_fmt.height = 480;
 658        rotate_prepare_format(&ctx->src_fmt);
 659
 660        /* default capture format */
 661        rotate_set_cap_format(ctx, &ctx->dst_fmt, ctx->rotate);
 662
 663        v4l2_fh_init(&ctx->fh, video_devdata(file));
 664        file->private_data = &ctx->fh;
 665        ctx->dev = dev;
 666
 667        ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
 668                                            &rotate_queue_init);
 669        if (IS_ERR(ctx->fh.m2m_ctx)) {
 670                ret = PTR_ERR(ctx->fh.m2m_ctx);
 671                goto err_free;
 672        }
 673
 674        v4l2_fh_add(&ctx->fh);
 675
 676        ret = rotate_setup_ctrls(ctx);
 677        if (ret)
 678                goto err_free;
 679
 680        ctx->fh.ctrl_handler = &ctx->ctrl_handler;
 681
 682        mutex_unlock(&dev->dev_mutex);
 683
 684        return 0;
 685
 686err_free:
 687        kfree(ctx);
 688        mutex_unlock(&dev->dev_mutex);
 689
 690        return ret;
 691}
 692
 693static int rotate_release(struct file *file)
 694{
 695        struct rotate_dev *dev = video_drvdata(file);
 696        struct rotate_ctx *ctx = container_of(file->private_data,
 697                                                   struct rotate_ctx, fh);
 698
 699        mutex_lock(&dev->dev_mutex);
 700
 701        v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 702        v4l2_fh_del(&ctx->fh);
 703        v4l2_fh_exit(&ctx->fh);
 704        v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 705
 706        kfree(ctx);
 707
 708        mutex_unlock(&dev->dev_mutex);
 709
 710        return 0;
 711}
 712
 713static const struct v4l2_file_operations rotate_fops = {
 714        .owner          = THIS_MODULE,
 715        .open           = rotate_open,
 716        .release        = rotate_release,
 717        .poll           = v4l2_m2m_fop_poll,
 718        .unlocked_ioctl = video_ioctl2,
 719        .mmap           = v4l2_m2m_fop_mmap,
 720};
 721
 722static const struct video_device rotate_video_device = {
 723        .name           = ROTATE_NAME,
 724        .vfl_dir        = VFL_DIR_M2M,
 725        .fops           = &rotate_fops,
 726        .ioctl_ops      = &rotate_ioctl_ops,
 727        .minor          = -1,
 728        .release        = video_device_release_empty,
 729        .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
 730};
 731
 732static const struct v4l2_m2m_ops rotate_m2m_ops = {
 733        .device_run     = rotate_device_run,
 734};
 735
 736static int rotate_probe(struct platform_device *pdev)
 737{
 738        struct rotate_dev *dev;
 739        struct video_device *vfd;
 740        int irq, ret;
 741
 742        dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 743        if (!dev)
 744                return -ENOMEM;
 745
 746        dev->vfd = rotate_video_device;
 747        dev->dev = &pdev->dev;
 748
 749        irq = platform_get_irq(pdev, 0);
 750        if (irq <= 0)
 751                return irq;
 752
 753        ret = devm_request_irq(dev->dev, irq, rotate_irq,
 754                               0, dev_name(dev->dev), dev);
 755        if (ret) {
 756                dev_err(dev->dev, "Failed to request IRQ\n");
 757
 758                return ret;
 759        }
 760
 761        dev->base = devm_platform_ioremap_resource(pdev, 0);
 762        if (IS_ERR(dev->base))
 763                return PTR_ERR(dev->base);
 764
 765        dev->bus_clk = devm_clk_get(dev->dev, "bus");
 766        if (IS_ERR(dev->bus_clk)) {
 767                dev_err(dev->dev, "Failed to get bus clock\n");
 768
 769                return PTR_ERR(dev->bus_clk);
 770        }
 771
 772        dev->mod_clk = devm_clk_get(dev->dev, "mod");
 773        if (IS_ERR(dev->mod_clk)) {
 774                dev_err(dev->dev, "Failed to get mod clock\n");
 775
 776                return PTR_ERR(dev->mod_clk);
 777        }
 778
 779        dev->rstc = devm_reset_control_get(dev->dev, NULL);
 780        if (IS_ERR(dev->rstc)) {
 781                dev_err(dev->dev, "Failed to get reset control\n");
 782
 783                return PTR_ERR(dev->rstc);
 784        }
 785
 786        mutex_init(&dev->dev_mutex);
 787
 788        ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 789        if (ret) {
 790                dev_err(dev->dev, "Failed to register V4L2 device\n");
 791
 792                return ret;
 793        }
 794
 795        vfd = &dev->vfd;
 796        vfd->lock = &dev->dev_mutex;
 797        vfd->v4l2_dev = &dev->v4l2_dev;
 798
 799        snprintf(vfd->name, sizeof(vfd->name), "%s",
 800                 rotate_video_device.name);
 801        video_set_drvdata(vfd, dev);
 802
 803        ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
 804        if (ret) {
 805                v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
 806
 807                goto err_v4l2;
 808        }
 809
 810        v4l2_info(&dev->v4l2_dev,
 811                  "Device registered as /dev/video%d\n", vfd->num);
 812
 813        dev->m2m_dev = v4l2_m2m_init(&rotate_m2m_ops);
 814        if (IS_ERR(dev->m2m_dev)) {
 815                v4l2_err(&dev->v4l2_dev,
 816                         "Failed to initialize V4L2 M2M device\n");
 817                ret = PTR_ERR(dev->m2m_dev);
 818
 819                goto err_video;
 820        }
 821
 822        platform_set_drvdata(pdev, dev);
 823
 824        pm_runtime_enable(dev->dev);
 825
 826        return 0;
 827
 828err_video:
 829        video_unregister_device(&dev->vfd);
 830err_v4l2:
 831        v4l2_device_unregister(&dev->v4l2_dev);
 832
 833        return ret;
 834}
 835
 836static int rotate_remove(struct platform_device *pdev)
 837{
 838        struct rotate_dev *dev = platform_get_drvdata(pdev);
 839
 840        v4l2_m2m_release(dev->m2m_dev);
 841        video_unregister_device(&dev->vfd);
 842        v4l2_device_unregister(&dev->v4l2_dev);
 843
 844        pm_runtime_force_suspend(&pdev->dev);
 845
 846        return 0;
 847}
 848
 849static int rotate_runtime_resume(struct device *device)
 850{
 851        struct rotate_dev *dev = dev_get_drvdata(device);
 852        int ret;
 853
 854        ret = clk_prepare_enable(dev->bus_clk);
 855        if (ret) {
 856                dev_err(dev->dev, "Failed to enable bus clock\n");
 857
 858                return ret;
 859        }
 860
 861        ret = clk_prepare_enable(dev->mod_clk);
 862        if (ret) {
 863                dev_err(dev->dev, "Failed to enable mod clock\n");
 864
 865                goto err_bus_clk;
 866        }
 867
 868        ret = reset_control_deassert(dev->rstc);
 869        if (ret) {
 870                dev_err(dev->dev, "Failed to apply reset\n");
 871
 872                goto err_mod_clk;
 873        }
 874
 875        return 0;
 876
 877err_mod_clk:
 878        clk_disable_unprepare(dev->mod_clk);
 879err_bus_clk:
 880        clk_disable_unprepare(dev->bus_clk);
 881
 882        return ret;
 883}
 884
 885static int rotate_runtime_suspend(struct device *device)
 886{
 887        struct rotate_dev *dev = dev_get_drvdata(device);
 888
 889        reset_control_assert(dev->rstc);
 890
 891        clk_disable_unprepare(dev->mod_clk);
 892        clk_disable_unprepare(dev->bus_clk);
 893
 894        return 0;
 895}
 896
 897static const struct of_device_id rotate_dt_match[] = {
 898        { .compatible = "allwinner,sun8i-a83t-de2-rotate" },
 899        { /* sentinel */ }
 900};
 901MODULE_DEVICE_TABLE(of, rotate_dt_match);
 902
 903static const struct dev_pm_ops rotate_pm_ops = {
 904        .runtime_resume         = rotate_runtime_resume,
 905        .runtime_suspend        = rotate_runtime_suspend,
 906};
 907
 908static struct platform_driver rotate_driver = {
 909        .probe          = rotate_probe,
 910        .remove         = rotate_remove,
 911        .driver         = {
 912                .name           = ROTATE_NAME,
 913                .of_match_table = rotate_dt_match,
 914                .pm             = &rotate_pm_ops,
 915        },
 916};
 917module_platform_driver(rotate_driver);
 918
 919MODULE_LICENSE("GPL v2");
 920MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
 921MODULE_DESCRIPTION("Allwinner DE2 rotate driver");
 922