linux/drivers/media/platform/rockchip/rga/rga.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
   4 * Author: Jacob Chen <jacob-chen@iotwrt.com>
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/debugfs.h>
   9#include <linux/delay.h>
  10#include <linux/fs.h>
  11#include <linux/interrupt.h>
  12#include <linux/module.h>
  13#include <linux/of.h>
  14#include <linux/pm_runtime.h>
  15#include <linux/reset.h>
  16#include <linux/sched.h>
  17#include <linux/slab.h>
  18#include <linux/timer.h>
  19
  20#include <linux/platform_device.h>
  21#include <media/v4l2-device.h>
  22#include <media/v4l2-event.h>
  23#include <media/v4l2-ioctl.h>
  24#include <media/v4l2-mem2mem.h>
  25#include <media/videobuf2-dma-sg.h>
  26#include <media/videobuf2-v4l2.h>
  27
  28#include "rga-hw.h"
  29#include "rga.h"
  30
  31static int debug;
  32module_param(debug, int, 0644);
  33
  34static void device_run(void *prv)
  35{
  36        struct rga_ctx *ctx = prv;
  37        struct rockchip_rga *rga = ctx->rga;
  38        struct vb2_v4l2_buffer *src, *dst;
  39        unsigned long flags;
  40
  41        spin_lock_irqsave(&rga->ctrl_lock, flags);
  42
  43        rga->curr = ctx;
  44
  45        src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
  46        dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
  47
  48        rga_buf_map(&src->vb2_buf);
  49        rga_buf_map(&dst->vb2_buf);
  50
  51        rga_hw_start(rga);
  52
  53        spin_unlock_irqrestore(&rga->ctrl_lock, flags);
  54}
  55
  56static irqreturn_t rga_isr(int irq, void *prv)
  57{
  58        struct rockchip_rga *rga = prv;
  59        int intr;
  60
  61        intr = rga_read(rga, RGA_INT) & 0xf;
  62
  63        rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
  64
  65        if (intr & 0x04) {
  66                struct vb2_v4l2_buffer *src, *dst;
  67                struct rga_ctx *ctx = rga->curr;
  68
  69                WARN_ON(!ctx);
  70
  71                rga->curr = NULL;
  72
  73                src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
  74                dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
  75
  76                WARN_ON(!src);
  77                WARN_ON(!dst);
  78
  79                dst->timecode = src->timecode;
  80                dst->vb2_buf.timestamp = src->vb2_buf.timestamp;
  81                dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
  82                dst->flags |= src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
  83
  84                v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
  85                v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
  86                v4l2_m2m_job_finish(rga->m2m_dev, ctx->fh.m2m_ctx);
  87        }
  88
  89        return IRQ_HANDLED;
  90}
  91
  92static const struct v4l2_m2m_ops rga_m2m_ops = {
  93        .device_run = device_run,
  94};
  95
  96static int
  97queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
  98{
  99        struct rga_ctx *ctx = priv;
 100        int ret;
 101
 102        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 103        src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 104        src_vq->drv_priv = ctx;
 105        src_vq->ops = &rga_qops;
 106        src_vq->mem_ops = &vb2_dma_sg_memops;
 107        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 108        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 109        src_vq->lock = &ctx->rga->mutex;
 110        src_vq->dev = ctx->rga->v4l2_dev.dev;
 111
 112        ret = vb2_queue_init(src_vq);
 113        if (ret)
 114                return ret;
 115
 116        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 117        dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 118        dst_vq->drv_priv = ctx;
 119        dst_vq->ops = &rga_qops;
 120        dst_vq->mem_ops = &vb2_dma_sg_memops;
 121        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 122        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 123        dst_vq->lock = &ctx->rga->mutex;
 124        dst_vq->dev = ctx->rga->v4l2_dev.dev;
 125
 126        return vb2_queue_init(dst_vq);
 127}
 128
 129static int rga_s_ctrl(struct v4l2_ctrl *ctrl)
 130{
 131        struct rga_ctx *ctx = container_of(ctrl->handler, struct rga_ctx,
 132                                           ctrl_handler);
 133        unsigned long flags;
 134
 135        spin_lock_irqsave(&ctx->rga->ctrl_lock, flags);
 136        switch (ctrl->id) {
 137        case V4L2_CID_HFLIP:
 138                ctx->hflip = ctrl->val;
 139                break;
 140        case V4L2_CID_VFLIP:
 141                ctx->vflip = ctrl->val;
 142                break;
 143        case V4L2_CID_ROTATE:
 144                ctx->rotate = ctrl->val;
 145                break;
 146        case V4L2_CID_BG_COLOR:
 147                ctx->fill_color = ctrl->val;
 148                break;
 149        }
 150        spin_unlock_irqrestore(&ctx->rga->ctrl_lock, flags);
 151        return 0;
 152}
 153
 154static const struct v4l2_ctrl_ops rga_ctrl_ops = {
 155        .s_ctrl = rga_s_ctrl,
 156};
 157
 158static int rga_setup_ctrls(struct rga_ctx *ctx)
 159{
 160        struct rockchip_rga *rga = ctx->rga;
 161
 162        v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
 163
 164        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
 165                          V4L2_CID_HFLIP, 0, 1, 1, 0);
 166
 167        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
 168                          V4L2_CID_VFLIP, 0, 1, 1, 0);
 169
 170        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
 171                          V4L2_CID_ROTATE, 0, 270, 90, 0);
 172
 173        v4l2_ctrl_new_std(&ctx->ctrl_handler, &rga_ctrl_ops,
 174                          V4L2_CID_BG_COLOR, 0, 0xffffffff, 1, 0);
 175
 176        if (ctx->ctrl_handler.error) {
 177                int err = ctx->ctrl_handler.error;
 178
 179                v4l2_err(&rga->v4l2_dev, "%s failed\n", __func__);
 180                v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 181                return err;
 182        }
 183
 184        return 0;
 185}
 186
 187static struct rga_fmt formats[] = {
 188        {
 189                .fourcc = V4L2_PIX_FMT_ARGB32,
 190                .color_swap = RGA_COLOR_RB_SWAP,
 191                .hw_format = RGA_COLOR_FMT_ABGR8888,
 192                .depth = 32,
 193                .uv_factor = 1,
 194                .y_div = 1,
 195                .x_div = 1,
 196        },
 197        {
 198                .fourcc = V4L2_PIX_FMT_XRGB32,
 199                .color_swap = RGA_COLOR_RB_SWAP,
 200                .hw_format = RGA_COLOR_FMT_XBGR8888,
 201                .depth = 32,
 202                .uv_factor = 1,
 203                .y_div = 1,
 204                .x_div = 1,
 205        },
 206        {
 207                .fourcc = V4L2_PIX_FMT_ABGR32,
 208                .color_swap = RGA_COLOR_ALPHA_SWAP,
 209                .hw_format = RGA_COLOR_FMT_ABGR8888,
 210                .depth = 32,
 211                .uv_factor = 1,
 212                .y_div = 1,
 213                .x_div = 1,
 214        },
 215        {
 216                .fourcc = V4L2_PIX_FMT_XBGR32,
 217                .color_swap = RGA_COLOR_ALPHA_SWAP,
 218                .hw_format = RGA_COLOR_FMT_XBGR8888,
 219                .depth = 32,
 220                .uv_factor = 1,
 221                .y_div = 1,
 222                .x_div = 1,
 223        },
 224        {
 225                .fourcc = V4L2_PIX_FMT_RGB24,
 226                .color_swap = RGA_COLOR_NONE_SWAP,
 227                .hw_format = RGA_COLOR_FMT_RGB888,
 228                .depth = 24,
 229                .uv_factor = 1,
 230                .y_div = 1,
 231                .x_div = 1,
 232        },
 233        {
 234                .fourcc = V4L2_PIX_FMT_BGR24,
 235                .color_swap = RGA_COLOR_RB_SWAP,
 236                .hw_format = RGA_COLOR_FMT_RGB888,
 237                .depth = 24,
 238                .uv_factor = 1,
 239                .y_div = 1,
 240                .x_div = 1,
 241        },
 242        {
 243                .fourcc = V4L2_PIX_FMT_ARGB444,
 244                .color_swap = RGA_COLOR_RB_SWAP,
 245                .hw_format = RGA_COLOR_FMT_ABGR4444,
 246                .depth = 16,
 247                .uv_factor = 1,
 248                .y_div = 1,
 249                .x_div = 1,
 250        },
 251        {
 252                .fourcc = V4L2_PIX_FMT_ARGB555,
 253                .color_swap = RGA_COLOR_RB_SWAP,
 254                .hw_format = RGA_COLOR_FMT_ABGR1555,
 255                .depth = 16,
 256                .uv_factor = 1,
 257                .y_div = 1,
 258                .x_div = 1,
 259        },
 260        {
 261                .fourcc = V4L2_PIX_FMT_RGB565,
 262                .color_swap = RGA_COLOR_RB_SWAP,
 263                .hw_format = RGA_COLOR_FMT_BGR565,
 264                .depth = 16,
 265                .uv_factor = 1,
 266                .y_div = 1,
 267                .x_div = 1,
 268        },
 269        {
 270                .fourcc = V4L2_PIX_FMT_NV21,
 271                .color_swap = RGA_COLOR_UV_SWAP,
 272                .hw_format = RGA_COLOR_FMT_YUV420SP,
 273                .depth = 12,
 274                .uv_factor = 4,
 275                .y_div = 2,
 276                .x_div = 1,
 277        },
 278        {
 279                .fourcc = V4L2_PIX_FMT_NV61,
 280                .color_swap = RGA_COLOR_UV_SWAP,
 281                .hw_format = RGA_COLOR_FMT_YUV422SP,
 282                .depth = 16,
 283                .uv_factor = 2,
 284                .y_div = 1,
 285                .x_div = 1,
 286        },
 287        {
 288                .fourcc = V4L2_PIX_FMT_NV12,
 289                .color_swap = RGA_COLOR_NONE_SWAP,
 290                .hw_format = RGA_COLOR_FMT_YUV420SP,
 291                .depth = 12,
 292                .uv_factor = 4,
 293                .y_div = 2,
 294                .x_div = 1,
 295        },
 296        {
 297                .fourcc = V4L2_PIX_FMT_NV16,
 298                .color_swap = RGA_COLOR_NONE_SWAP,
 299                .hw_format = RGA_COLOR_FMT_YUV422SP,
 300                .depth = 16,
 301                .uv_factor = 2,
 302                .y_div = 1,
 303                .x_div = 1,
 304        },
 305        {
 306                .fourcc = V4L2_PIX_FMT_YUV420,
 307                .color_swap = RGA_COLOR_NONE_SWAP,
 308                .hw_format = RGA_COLOR_FMT_YUV420P,
 309                .depth = 12,
 310                .uv_factor = 4,
 311                .y_div = 2,
 312                .x_div = 2,
 313        },
 314        {
 315                .fourcc = V4L2_PIX_FMT_YUV422P,
 316                .color_swap = RGA_COLOR_NONE_SWAP,
 317                .hw_format = RGA_COLOR_FMT_YUV422P,
 318                .depth = 16,
 319                .uv_factor = 2,
 320                .y_div = 1,
 321                .x_div = 2,
 322        },
 323        {
 324                .fourcc = V4L2_PIX_FMT_YVU420,
 325                .color_swap = RGA_COLOR_UV_SWAP,
 326                .hw_format = RGA_COLOR_FMT_YUV420P,
 327                .depth = 12,
 328                .uv_factor = 4,
 329                .y_div = 2,
 330                .x_div = 2,
 331        },
 332};
 333
 334#define NUM_FORMATS ARRAY_SIZE(formats)
 335
 336static struct rga_fmt *rga_fmt_find(struct v4l2_format *f)
 337{
 338        unsigned int i;
 339
 340        for (i = 0; i < NUM_FORMATS; i++) {
 341                if (formats[i].fourcc == f->fmt.pix.pixelformat)
 342                        return &formats[i];
 343        }
 344        return NULL;
 345}
 346
 347static struct rga_frame def_frame = {
 348        .width = DEFAULT_WIDTH,
 349        .height = DEFAULT_HEIGHT,
 350        .colorspace = V4L2_COLORSPACE_DEFAULT,
 351        .crop.left = 0,
 352        .crop.top = 0,
 353        .crop.width = DEFAULT_WIDTH,
 354        .crop.height = DEFAULT_HEIGHT,
 355        .fmt = &formats[0],
 356};
 357
 358struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type)
 359{
 360        switch (type) {
 361        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 362                return &ctx->in;
 363        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 364                return &ctx->out;
 365        default:
 366                return ERR_PTR(-EINVAL);
 367        }
 368}
 369
 370static int rga_open(struct file *file)
 371{
 372        struct rockchip_rga *rga = video_drvdata(file);
 373        struct rga_ctx *ctx = NULL;
 374        int ret = 0;
 375
 376        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 377        if (!ctx)
 378                return -ENOMEM;
 379        ctx->rga = rga;
 380        /* Set default formats */
 381        ctx->in = def_frame;
 382        ctx->out = def_frame;
 383
 384        if (mutex_lock_interruptible(&rga->mutex)) {
 385                kfree(ctx);
 386                return -ERESTARTSYS;
 387        }
 388        ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(rga->m2m_dev, ctx, &queue_init);
 389        if (IS_ERR(ctx->fh.m2m_ctx)) {
 390                ret = PTR_ERR(ctx->fh.m2m_ctx);
 391                mutex_unlock(&rga->mutex);
 392                kfree(ctx);
 393                return ret;
 394        }
 395        v4l2_fh_init(&ctx->fh, video_devdata(file));
 396        file->private_data = &ctx->fh;
 397        v4l2_fh_add(&ctx->fh);
 398
 399        rga_setup_ctrls(ctx);
 400
 401        /* Write the default values to the ctx struct */
 402        v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
 403
 404        ctx->fh.ctrl_handler = &ctx->ctrl_handler;
 405        mutex_unlock(&rga->mutex);
 406
 407        return 0;
 408}
 409
 410static int rga_release(struct file *file)
 411{
 412        struct rga_ctx *ctx =
 413                container_of(file->private_data, struct rga_ctx, fh);
 414        struct rockchip_rga *rga = ctx->rga;
 415
 416        mutex_lock(&rga->mutex);
 417
 418        v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 419
 420        v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 421        v4l2_fh_del(&ctx->fh);
 422        v4l2_fh_exit(&ctx->fh);
 423        kfree(ctx);
 424
 425        mutex_unlock(&rga->mutex);
 426
 427        return 0;
 428}
 429
 430static const struct v4l2_file_operations rga_fops = {
 431        .owner = THIS_MODULE,
 432        .open = rga_open,
 433        .release = rga_release,
 434        .poll = v4l2_m2m_fop_poll,
 435        .unlocked_ioctl = video_ioctl2,
 436        .mmap = v4l2_m2m_fop_mmap,
 437};
 438
 439static int
 440vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
 441{
 442        strscpy(cap->driver, RGA_NAME, sizeof(cap->driver));
 443        strscpy(cap->card, "rockchip-rga", sizeof(cap->card));
 444        strscpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info));
 445
 446        return 0;
 447}
 448
 449static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f)
 450{
 451        struct rga_fmt *fmt;
 452
 453        if (f->index >= NUM_FORMATS)
 454                return -EINVAL;
 455
 456        fmt = &formats[f->index];
 457        f->pixelformat = fmt->fourcc;
 458
 459        return 0;
 460}
 461
 462static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f)
 463{
 464        struct rga_ctx *ctx = prv;
 465        struct vb2_queue *vq;
 466        struct rga_frame *frm;
 467
 468        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 469        if (!vq)
 470                return -EINVAL;
 471        frm = rga_get_frame(ctx, f->type);
 472        if (IS_ERR(frm))
 473                return PTR_ERR(frm);
 474
 475        f->fmt.pix.width = frm->width;
 476        f->fmt.pix.height = frm->height;
 477        f->fmt.pix.field = V4L2_FIELD_NONE;
 478        f->fmt.pix.pixelformat = frm->fmt->fourcc;
 479        f->fmt.pix.bytesperline = frm->stride;
 480        f->fmt.pix.sizeimage = frm->size;
 481        f->fmt.pix.colorspace = frm->colorspace;
 482
 483        return 0;
 484}
 485
 486static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f)
 487{
 488        struct rga_fmt *fmt;
 489
 490        fmt = rga_fmt_find(f);
 491        if (!fmt) {
 492                fmt = &formats[0];
 493                f->fmt.pix.pixelformat = fmt->fourcc;
 494        }
 495
 496        f->fmt.pix.field = V4L2_FIELD_NONE;
 497
 498        if (f->fmt.pix.width > MAX_WIDTH)
 499                f->fmt.pix.width = MAX_WIDTH;
 500        if (f->fmt.pix.height > MAX_HEIGHT)
 501                f->fmt.pix.height = MAX_HEIGHT;
 502
 503        if (f->fmt.pix.width < MIN_WIDTH)
 504                f->fmt.pix.width = MIN_WIDTH;
 505        if (f->fmt.pix.height < MIN_HEIGHT)
 506                f->fmt.pix.height = MIN_HEIGHT;
 507
 508        if (fmt->hw_format >= RGA_COLOR_FMT_YUV422SP)
 509                f->fmt.pix.bytesperline = f->fmt.pix.width;
 510        else
 511                f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
 512
 513        f->fmt.pix.sizeimage =
 514                f->fmt.pix.height * (f->fmt.pix.width * fmt->depth) >> 3;
 515
 516        return 0;
 517}
 518
 519static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
 520{
 521        struct rga_ctx *ctx = prv;
 522        struct rockchip_rga *rga = ctx->rga;
 523        struct vb2_queue *vq;
 524        struct rga_frame *frm;
 525        struct rga_fmt *fmt;
 526        int ret = 0;
 527
 528        /* Adjust all values accordingly to the hardware capabilities
 529         * and chosen format.
 530         */
 531        ret = vidioc_try_fmt(file, prv, f);
 532        if (ret)
 533                return ret;
 534        vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 535        if (vb2_is_busy(vq)) {
 536                v4l2_err(&rga->v4l2_dev, "queue (%d) bust\n", f->type);
 537                return -EBUSY;
 538        }
 539        frm = rga_get_frame(ctx, f->type);
 540        if (IS_ERR(frm))
 541                return PTR_ERR(frm);
 542        fmt = rga_fmt_find(f);
 543        if (!fmt)
 544                return -EINVAL;
 545        frm->width = f->fmt.pix.width;
 546        frm->height = f->fmt.pix.height;
 547        frm->size = f->fmt.pix.sizeimage;
 548        frm->fmt = fmt;
 549        frm->stride = f->fmt.pix.bytesperline;
 550        frm->colorspace = f->fmt.pix.colorspace;
 551
 552        /* Reset crop settings */
 553        frm->crop.left = 0;
 554        frm->crop.top = 0;
 555        frm->crop.width = frm->width;
 556        frm->crop.height = frm->height;
 557
 558        return 0;
 559}
 560
 561static int vidioc_g_selection(struct file *file, void *prv,
 562                              struct v4l2_selection *s)
 563{
 564        struct rga_ctx *ctx = prv;
 565        struct rga_frame *f;
 566        bool use_frame = false;
 567
 568        f = rga_get_frame(ctx, s->type);
 569        if (IS_ERR(f))
 570                return PTR_ERR(f);
 571
 572        switch (s->target) {
 573        case V4L2_SEL_TGT_COMPOSE_DEFAULT:
 574        case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 575                if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 576                        return -EINVAL;
 577                break;
 578        case V4L2_SEL_TGT_CROP_DEFAULT:
 579        case V4L2_SEL_TGT_CROP_BOUNDS:
 580                if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 581                        return -EINVAL;
 582                break;
 583        case V4L2_SEL_TGT_COMPOSE:
 584                if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 585                        return -EINVAL;
 586                use_frame = true;
 587                break;
 588        case V4L2_SEL_TGT_CROP:
 589                if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 590                        return -EINVAL;
 591                use_frame = true;
 592                break;
 593        default:
 594                return -EINVAL;
 595        }
 596
 597        if (use_frame) {
 598                s->r = f->crop;
 599        } else {
 600                s->r.left = 0;
 601                s->r.top = 0;
 602                s->r.width = f->width;
 603                s->r.height = f->height;
 604        }
 605
 606        return 0;
 607}
 608
 609static int vidioc_s_selection(struct file *file, void *prv,
 610                              struct v4l2_selection *s)
 611{
 612        struct rga_ctx *ctx = prv;
 613        struct rockchip_rga *rga = ctx->rga;
 614        struct rga_frame *f;
 615        int ret = 0;
 616
 617        f = rga_get_frame(ctx, s->type);
 618        if (IS_ERR(f))
 619                return PTR_ERR(f);
 620
 621        switch (s->target) {
 622        case V4L2_SEL_TGT_COMPOSE:
 623                /*
 624                 * COMPOSE target is only valid for capture buffer type, return
 625                 * error for output buffer type
 626                 */
 627                if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 628                        return -EINVAL;
 629                break;
 630        case V4L2_SEL_TGT_CROP:
 631                /*
 632                 * CROP target is only valid for output buffer type, return
 633                 * error for capture buffer type
 634                 */
 635                if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 636                        return -EINVAL;
 637                break;
 638        /*
 639         * bound and default crop/compose targets are invalid targets to
 640         * try/set
 641         */
 642        default:
 643                return -EINVAL;
 644        }
 645
 646        if (s->r.top < 0 || s->r.left < 0) {
 647                v4l2_dbg(debug, 1, &rga->v4l2_dev,
 648                         "doesn't support negative values for top & left.\n");
 649                return -EINVAL;
 650        }
 651
 652        if (s->r.left + s->r.width > f->width ||
 653            s->r.top + s->r.height > f->height ||
 654            s->r.width < MIN_WIDTH || s->r.height < MIN_HEIGHT) {
 655                v4l2_dbg(debug, 1, &rga->v4l2_dev, "unsupported crop value.\n");
 656                return -EINVAL;
 657        }
 658
 659        f->crop = s->r;
 660
 661        return ret;
 662}
 663
 664static const struct v4l2_ioctl_ops rga_ioctl_ops = {
 665        .vidioc_querycap = vidioc_querycap,
 666
 667        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
 668        .vidioc_g_fmt_vid_cap = vidioc_g_fmt,
 669        .vidioc_try_fmt_vid_cap = vidioc_try_fmt,
 670        .vidioc_s_fmt_vid_cap = vidioc_s_fmt,
 671
 672        .vidioc_enum_fmt_vid_out = vidioc_enum_fmt,
 673        .vidioc_g_fmt_vid_out = vidioc_g_fmt,
 674        .vidioc_try_fmt_vid_out = vidioc_try_fmt,
 675        .vidioc_s_fmt_vid_out = vidioc_s_fmt,
 676
 677        .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
 678        .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
 679        .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
 680        .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 681        .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 682        .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
 683        .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 684
 685        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 686        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 687
 688        .vidioc_streamon = v4l2_m2m_ioctl_streamon,
 689        .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
 690
 691        .vidioc_g_selection = vidioc_g_selection,
 692        .vidioc_s_selection = vidioc_s_selection,
 693};
 694
 695static const struct video_device rga_videodev = {
 696        .name = "rockchip-rga",
 697        .fops = &rga_fops,
 698        .ioctl_ops = &rga_ioctl_ops,
 699        .minor = -1,
 700        .release = video_device_release,
 701        .vfl_dir = VFL_DIR_M2M,
 702        .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
 703};
 704
 705static int rga_enable_clocks(struct rockchip_rga *rga)
 706{
 707        int ret;
 708
 709        ret = clk_prepare_enable(rga->sclk);
 710        if (ret) {
 711                dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
 712                return ret;
 713        }
 714
 715        ret = clk_prepare_enable(rga->aclk);
 716        if (ret) {
 717                dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
 718                goto err_disable_sclk;
 719        }
 720
 721        ret = clk_prepare_enable(rga->hclk);
 722        if (ret) {
 723                dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
 724                goto err_disable_aclk;
 725        }
 726
 727        return 0;
 728
 729err_disable_sclk:
 730        clk_disable_unprepare(rga->sclk);
 731err_disable_aclk:
 732        clk_disable_unprepare(rga->aclk);
 733
 734        return ret;
 735}
 736
 737static void rga_disable_clocks(struct rockchip_rga *rga)
 738{
 739        clk_disable_unprepare(rga->sclk);
 740        clk_disable_unprepare(rga->hclk);
 741        clk_disable_unprepare(rga->aclk);
 742}
 743
 744static int rga_parse_dt(struct rockchip_rga *rga)
 745{
 746        struct reset_control *core_rst, *axi_rst, *ahb_rst;
 747
 748        core_rst = devm_reset_control_get(rga->dev, "core");
 749        if (IS_ERR(core_rst)) {
 750                dev_err(rga->dev, "failed to get core reset controller\n");
 751                return PTR_ERR(core_rst);
 752        }
 753
 754        axi_rst = devm_reset_control_get(rga->dev, "axi");
 755        if (IS_ERR(axi_rst)) {
 756                dev_err(rga->dev, "failed to get axi reset controller\n");
 757                return PTR_ERR(axi_rst);
 758        }
 759
 760        ahb_rst = devm_reset_control_get(rga->dev, "ahb");
 761        if (IS_ERR(ahb_rst)) {
 762                dev_err(rga->dev, "failed to get ahb reset controller\n");
 763                return PTR_ERR(ahb_rst);
 764        }
 765
 766        reset_control_assert(core_rst);
 767        udelay(1);
 768        reset_control_deassert(core_rst);
 769
 770        reset_control_assert(axi_rst);
 771        udelay(1);
 772        reset_control_deassert(axi_rst);
 773
 774        reset_control_assert(ahb_rst);
 775        udelay(1);
 776        reset_control_deassert(ahb_rst);
 777
 778        rga->sclk = devm_clk_get(rga->dev, "sclk");
 779        if (IS_ERR(rga->sclk)) {
 780                dev_err(rga->dev, "failed to get sclk clock\n");
 781                return PTR_ERR(rga->sclk);
 782        }
 783
 784        rga->aclk = devm_clk_get(rga->dev, "aclk");
 785        if (IS_ERR(rga->aclk)) {
 786                dev_err(rga->dev, "failed to get aclk clock\n");
 787                return PTR_ERR(rga->aclk);
 788        }
 789
 790        rga->hclk = devm_clk_get(rga->dev, "hclk");
 791        if (IS_ERR(rga->hclk)) {
 792                dev_err(rga->dev, "failed to get hclk clock\n");
 793                return PTR_ERR(rga->hclk);
 794        }
 795
 796        return 0;
 797}
 798
 799static int rga_probe(struct platform_device *pdev)
 800{
 801        struct rockchip_rga *rga;
 802        struct video_device *vfd;
 803        struct resource *res;
 804        int ret = 0;
 805        int irq;
 806
 807        if (!pdev->dev.of_node)
 808                return -ENODEV;
 809
 810        rga = devm_kzalloc(&pdev->dev, sizeof(*rga), GFP_KERNEL);
 811        if (!rga)
 812                return -ENOMEM;
 813
 814        rga->dev = &pdev->dev;
 815        spin_lock_init(&rga->ctrl_lock);
 816        mutex_init(&rga->mutex);
 817
 818        ret = rga_parse_dt(rga);
 819        if (ret)
 820                dev_err(&pdev->dev, "Unable to parse OF data\n");
 821
 822        pm_runtime_enable(rga->dev);
 823
 824        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 825
 826        rga->regs = devm_ioremap_resource(rga->dev, res);
 827        if (IS_ERR(rga->regs)) {
 828                ret = PTR_ERR(rga->regs);
 829                goto err_put_clk;
 830        }
 831
 832        irq = platform_get_irq(pdev, 0);
 833        if (irq < 0) {
 834                ret = irq;
 835                goto err_put_clk;
 836        }
 837
 838        ret = devm_request_irq(rga->dev, irq, rga_isr, 0,
 839                               dev_name(rga->dev), rga);
 840        if (ret < 0) {
 841                dev_err(rga->dev, "failed to request irq\n");
 842                goto err_put_clk;
 843        }
 844
 845        ret = v4l2_device_register(&pdev->dev, &rga->v4l2_dev);
 846        if (ret)
 847                goto err_put_clk;
 848        vfd = video_device_alloc();
 849        if (!vfd) {
 850                v4l2_err(&rga->v4l2_dev, "Failed to allocate video device\n");
 851                ret = -ENOMEM;
 852                goto unreg_v4l2_dev;
 853        }
 854        *vfd = rga_videodev;
 855        vfd->lock = &rga->mutex;
 856        vfd->v4l2_dev = &rga->v4l2_dev;
 857
 858        video_set_drvdata(vfd, rga);
 859        rga->vfd = vfd;
 860
 861        platform_set_drvdata(pdev, rga);
 862        rga->m2m_dev = v4l2_m2m_init(&rga_m2m_ops);
 863        if (IS_ERR(rga->m2m_dev)) {
 864                v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
 865                ret = PTR_ERR(rga->m2m_dev);
 866                goto unreg_video_dev;
 867        }
 868
 869        pm_runtime_get_sync(rga->dev);
 870
 871        rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
 872        rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
 873
 874        v4l2_info(&rga->v4l2_dev, "HW Version: 0x%02x.%02x\n",
 875                  rga->version.major, rga->version.minor);
 876
 877        pm_runtime_put(rga->dev);
 878
 879        /* Create CMD buffer */
 880        rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
 881                                           &rga->cmdbuf_phy, GFP_KERNEL,
 882                                           DMA_ATTR_WRITE_COMBINE);
 883
 884        rga->src_mmu_pages =
 885                (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
 886        rga->dst_mmu_pages =
 887                (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
 888
 889        def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
 890        def_frame.size = def_frame.stride * def_frame.height;
 891
 892        ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
 893        if (ret) {
 894                v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
 895                goto rel_vdev;
 896        }
 897
 898        v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
 899                  vfd->name, video_device_node_name(vfd));
 900
 901        return 0;
 902
 903rel_vdev:
 904        video_device_release(vfd);
 905unreg_video_dev:
 906        video_unregister_device(rga->vfd);
 907unreg_v4l2_dev:
 908        v4l2_device_unregister(&rga->v4l2_dev);
 909err_put_clk:
 910        pm_runtime_disable(rga->dev);
 911
 912        return ret;
 913}
 914
 915static int rga_remove(struct platform_device *pdev)
 916{
 917        struct rockchip_rga *rga = platform_get_drvdata(pdev);
 918
 919        dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
 920                       rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
 921
 922        free_pages((unsigned long)rga->src_mmu_pages, 3);
 923        free_pages((unsigned long)rga->dst_mmu_pages, 3);
 924
 925        v4l2_info(&rga->v4l2_dev, "Removing\n");
 926
 927        v4l2_m2m_release(rga->m2m_dev);
 928        video_unregister_device(rga->vfd);
 929        v4l2_device_unregister(&rga->v4l2_dev);
 930
 931        pm_runtime_disable(rga->dev);
 932
 933        return 0;
 934}
 935
 936static int __maybe_unused rga_runtime_suspend(struct device *dev)
 937{
 938        struct rockchip_rga *rga = dev_get_drvdata(dev);
 939
 940        rga_disable_clocks(rga);
 941
 942        return 0;
 943}
 944
 945static int __maybe_unused rga_runtime_resume(struct device *dev)
 946{
 947        struct rockchip_rga *rga = dev_get_drvdata(dev);
 948
 949        return rga_enable_clocks(rga);
 950}
 951
 952static const struct dev_pm_ops rga_pm = {
 953        SET_RUNTIME_PM_OPS(rga_runtime_suspend,
 954                           rga_runtime_resume, NULL)
 955};
 956
 957static const struct of_device_id rockchip_rga_match[] = {
 958        {
 959                .compatible = "rockchip,rk3288-rga",
 960        },
 961        {
 962                .compatible = "rockchip,rk3399-rga",
 963        },
 964        {},
 965};
 966
 967MODULE_DEVICE_TABLE(of, rockchip_rga_match);
 968
 969static struct platform_driver rga_pdrv = {
 970        .probe = rga_probe,
 971        .remove = rga_remove,
 972        .driver = {
 973                .name = RGA_NAME,
 974                .pm = &rga_pm,
 975                .of_match_table = rockchip_rga_match,
 976        },
 977};
 978
 979module_platform_driver(rga_pdrv);
 980
 981MODULE_AUTHOR("Jacob Chen <jacob-chen@iotwrt.com>");
 982MODULE_DESCRIPTION("Rockchip Raster 2d Graphic Acceleration Unit");
 983MODULE_LICENSE("GPL");
 984