1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Samsung S5P G2D - 2D Graphics Accelerator Driver 4 * 5 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 6 * Kamil Debski, <k.debski@samsung.com> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/fs.h> 11 #include <linux/timer.h> 12 #include <linux/sched.h> 13 #include <linux/slab.h> 14 #include <linux/clk.h> 15 #include <linux/interrupt.h> 16 #include <linux/of.h> 17 18 #include <linux/platform_device.h> 19 #include <media/v4l2-mem2mem.h> 20 #include <media/v4l2-device.h> 21 #include <media/v4l2-ioctl.h> 22 #include <media/videobuf2-v4l2.h> 23 #include <media/videobuf2-dma-contig.h> 24 25 #include "g2d.h" 26 #include "g2d-regs.h" 27 28 #define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh) 29 30 static struct g2d_fmt formats[] = { 31 { 32 .fourcc = V4L2_PIX_FMT_RGB32, 33 .depth = 32, 34 .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888), 35 }, 36 { 37 .fourcc = V4L2_PIX_FMT_RGB565X, 38 .depth = 16, 39 .hw = COLOR_MODE(ORDER_XRGB, MODE_RGB_565), 40 }, 41 { 42 .fourcc = V4L2_PIX_FMT_RGB555X, 43 .depth = 16, 44 .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555), 45 }, 46 { 47 .fourcc = V4L2_PIX_FMT_RGB444, 48 .depth = 16, 49 .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444), 50 }, 51 { 52 .fourcc = V4L2_PIX_FMT_RGB24, 53 .depth = 24, 54 .hw = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888), 55 }, 56 }; 57 #define NUM_FORMATS ARRAY_SIZE(formats) 58 59 static struct g2d_frame def_frame = { 60 .width = DEFAULT_WIDTH, 61 .height = DEFAULT_HEIGHT, 62 .c_width = DEFAULT_WIDTH, 63 .c_height = DEFAULT_HEIGHT, 64 .o_width = 0, 65 .o_height = 0, 66 .fmt = &formats[0], 67 .right = DEFAULT_WIDTH, 68 .bottom = DEFAULT_HEIGHT, 69 }; 70 71 static struct g2d_fmt *find_fmt(struct v4l2_format *f) 72 { 73 unsigned int i; 74 for (i = 0; i < NUM_FORMATS; i++) { 75 if (formats[i].fourcc == f->fmt.pix.pixelformat) 76 return &formats[i]; 77 } 78 return NULL; 79 } 80 81 82 static struct g2d_frame *get_frame(struct g2d_ctx *ctx, 83 enum v4l2_buf_type type) 84 { 85 switch (type) { 86 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 87 return &ctx->in; 88 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 89 return &ctx->out; 90 default: 91 return ERR_PTR(-EINVAL); 92 } 93 } 94 95 static int g2d_queue_setup(struct vb2_queue *vq, 96 unsigned int *nbuffers, unsigned int *nplanes, 97 unsigned int sizes[], struct device *alloc_devs[]) 98 { 99 struct g2d_ctx *ctx = vb2_get_drv_priv(vq); 100 struct g2d_frame *f = get_frame(ctx, vq->type); 101 102 if (IS_ERR(f)) 103 return PTR_ERR(f); 104 105 sizes[0] = f->size; 106 *nplanes = 1; 107 108 if (*nbuffers == 0) 109 *nbuffers = 1; 110 111 return 0; 112 } 113 114 static int g2d_buf_prepare(struct vb2_buffer *vb) 115 { 116 struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 117 struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type); 118 119 if (IS_ERR(f)) 120 return PTR_ERR(f); 121 vb2_set_plane_payload(vb, 0, f->size); 122 return 0; 123 } 124 125 static void g2d_buf_queue(struct vb2_buffer *vb) 126 { 127 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 128 struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 129 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); 130 } 131 132 static const struct vb2_ops g2d_qops = { 133 .queue_setup = g2d_queue_setup, 134 .buf_prepare = g2d_buf_prepare, 135 .buf_queue = g2d_buf_queue, 136 }; 137 138 static int queue_init(void *priv, struct vb2_queue *src_vq, 139 struct vb2_queue *dst_vq) 140 { 141 struct g2d_ctx *ctx = priv; 142 int ret; 143 144 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 145 src_vq->io_modes = VB2_MMAP | VB2_USERPTR; 146 src_vq->drv_priv = ctx; 147 src_vq->ops = &g2d_qops; 148 src_vq->mem_ops = &vb2_dma_contig_memops; 149 src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 150 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 151 src_vq->lock = &ctx->dev->mutex; 152 src_vq->dev = ctx->dev->v4l2_dev.dev; 153 154 ret = vb2_queue_init(src_vq); 155 if (ret) 156 return ret; 157 158 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 159 dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; 160 dst_vq->drv_priv = ctx; 161 dst_vq->ops = &g2d_qops; 162 dst_vq->mem_ops = &vb2_dma_contig_memops; 163 dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); 164 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 165 dst_vq->lock = &ctx->dev->mutex; 166 dst_vq->dev = ctx->dev->v4l2_dev.dev; 167 168 return vb2_queue_init(dst_vq); 169 } 170 171 static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) 172 { 173 struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, 174 ctrl_handler); 175 unsigned long flags; 176 177 spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); 178 switch (ctrl->id) { 179 case V4L2_CID_COLORFX: 180 if (ctrl->val == V4L2_COLORFX_NEGATIVE) 181 ctx->rop = ROP4_INVERT; 182 else 183 ctx->rop = ROP4_COPY; 184 break; 185 186 case V4L2_CID_HFLIP: 187 ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1); 188 break; 189 190 } 191 spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); 192 return 0; 193 } 194 195 static const struct v4l2_ctrl_ops g2d_ctrl_ops = { 196 .s_ctrl = g2d_s_ctrl, 197 }; 198 199 static int g2d_setup_ctrls(struct g2d_ctx *ctx) 200 { 201 struct g2d_dev *dev = ctx->dev; 202 203 v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); 204 205 ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, 206 V4L2_CID_HFLIP, 0, 1, 1, 0); 207 208 ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, 209 V4L2_CID_VFLIP, 0, 1, 1, 0); 210 211 v4l2_ctrl_new_std_menu( 212 &ctx->ctrl_handler, 213 &g2d_ctrl_ops, 214 V4L2_CID_COLORFX, 215 V4L2_COLORFX_NEGATIVE, 216 ~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)), 217 V4L2_COLORFX_NONE); 218 219 if (ctx->ctrl_handler.error) { 220 int err = ctx->ctrl_handler.error; 221 v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n"); 222 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 223 return err; 224 } 225 226 v4l2_ctrl_cluster(2, &ctx->ctrl_hflip); 227 228 return 0; 229 } 230 231 static int g2d_open(struct file *file) 232 { 233 struct g2d_dev *dev = video_drvdata(file); 234 struct g2d_ctx *ctx = NULL; 235 int ret = 0; 236 237 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 238 if (!ctx) 239 return -ENOMEM; 240 ctx->dev = dev; 241 /* Set default formats */ 242 ctx->in = def_frame; 243 ctx->out = def_frame; 244 245 if (mutex_lock_interruptible(&dev->mutex)) { 246 kfree(ctx); 247 return -ERESTARTSYS; 248 } 249 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); 250 if (IS_ERR(ctx->fh.m2m_ctx)) { 251 ret = PTR_ERR(ctx->fh.m2m_ctx); 252 mutex_unlock(&dev->mutex); 253 kfree(ctx); 254 return ret; 255 } 256 v4l2_fh_init(&ctx->fh, video_devdata(file)); 257 file->private_data = &ctx->fh; 258 v4l2_fh_add(&ctx->fh); 259 260 g2d_setup_ctrls(ctx); 261 262 /* Write the default values to the ctx struct */ 263 v4l2_ctrl_handler_setup(&ctx->ctrl_handler); 264 265 ctx->fh.ctrl_handler = &ctx->ctrl_handler; 266 mutex_unlock(&dev->mutex); 267 268 v4l2_info(&dev->v4l2_dev, "instance opened\n"); 269 return 0; 270 } 271 272 static int g2d_release(struct file *file) 273 { 274 struct g2d_dev *dev = video_drvdata(file); 275 struct g2d_ctx *ctx = fh2ctx(file->private_data); 276 277 mutex_lock(&dev->mutex); 278 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); 279 mutex_unlock(&dev->mutex); 280 v4l2_ctrl_handler_free(&ctx->ctrl_handler); 281 v4l2_fh_del(&ctx->fh); 282 v4l2_fh_exit(&ctx->fh); 283 kfree(ctx); 284 v4l2_info(&dev->v4l2_dev, "instance closed\n"); 285 return 0; 286 } 287 288 289 static int vidioc_querycap(struct file *file, void *priv, 290 struct v4l2_capability *cap) 291 { 292 strscpy(cap->driver, G2D_NAME, sizeof(cap->driver)); 293 strscpy(cap->card, G2D_NAME, sizeof(cap->card)); 294 cap->bus_info[0] = 0; 295 return 0; 296 } 297 298 static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) 299 { 300 if (f->index >= NUM_FORMATS) 301 return -EINVAL; 302 f->pixelformat = formats[f->index].fourcc; 303 return 0; 304 } 305 306 static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) 307 { 308 struct g2d_ctx *ctx = prv; 309 struct vb2_queue *vq; 310 struct g2d_frame *frm; 311 312 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 313 if (!vq) 314 return -EINVAL; 315 frm = get_frame(ctx, f->type); 316 if (IS_ERR(frm)) 317 return PTR_ERR(frm); 318 319 f->fmt.pix.width = frm->width; 320 f->fmt.pix.height = frm->height; 321 f->fmt.pix.field = V4L2_FIELD_NONE; 322 f->fmt.pix.pixelformat = frm->fmt->fourcc; 323 f->fmt.pix.bytesperline = (frm->width * frm->fmt->depth) >> 3; 324 f->fmt.pix.sizeimage = frm->size; 325 return 0; 326 } 327 328 static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) 329 { 330 struct g2d_fmt *fmt; 331 enum v4l2_field *field; 332 333 fmt = find_fmt(f); 334 if (!fmt) 335 return -EINVAL; 336 337 field = &f->fmt.pix.field; 338 if (*field == V4L2_FIELD_ANY) 339 *field = V4L2_FIELD_NONE; 340 else if (*field != V4L2_FIELD_NONE) 341 return -EINVAL; 342 343 if (f->fmt.pix.width > MAX_WIDTH) 344 f->fmt.pix.width = MAX_WIDTH; 345 if (f->fmt.pix.height > MAX_HEIGHT) 346 f->fmt.pix.height = MAX_HEIGHT; 347 348 if (f->fmt.pix.width < 1) 349 f->fmt.pix.width = 1; 350 if (f->fmt.pix.height < 1) 351 f->fmt.pix.height = 1; 352 353 f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; 354 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; 355 return 0; 356 } 357 358 static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) 359 { 360 struct g2d_ctx *ctx = prv; 361 struct g2d_dev *dev = ctx->dev; 362 struct vb2_queue *vq; 363 struct g2d_frame *frm; 364 struct g2d_fmt *fmt; 365 int ret = 0; 366 367 /* Adjust all values accordingly to the hardware capabilities 368 * and chosen format. */ 369 ret = vidioc_try_fmt(file, prv, f); 370 if (ret) 371 return ret; 372 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); 373 if (vb2_is_busy(vq)) { 374 v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type); 375 return -EBUSY; 376 } 377 frm = get_frame(ctx, f->type); 378 if (IS_ERR(frm)) 379 return PTR_ERR(frm); 380 fmt = find_fmt(f); 381 if (!fmt) 382 return -EINVAL; 383 frm->width = f->fmt.pix.width; 384 frm->height = f->fmt.pix.height; 385 frm->size = f->fmt.pix.sizeimage; 386 /* Reset crop settings */ 387 frm->o_width = 0; 388 frm->o_height = 0; 389 frm->c_width = frm->width; 390 frm->c_height = frm->height; 391 frm->right = frm->width; 392 frm->bottom = frm->height; 393 frm->fmt = fmt; 394 frm->stride = f->fmt.pix.bytesperline; 395 return 0; 396 } 397 398 static int vidioc_g_selection(struct file *file, void *prv, 399 struct v4l2_selection *s) 400 { 401 struct g2d_ctx *ctx = prv; 402 struct g2d_frame *f; 403 404 f = get_frame(ctx, s->type); 405 if (IS_ERR(f)) 406 return PTR_ERR(f); 407 408 switch (s->target) { 409 case V4L2_SEL_TGT_CROP: 410 case V4L2_SEL_TGT_CROP_DEFAULT: 411 case V4L2_SEL_TGT_CROP_BOUNDS: 412 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 413 return -EINVAL; 414 break; 415 case V4L2_SEL_TGT_COMPOSE: 416 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 417 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 418 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 419 return -EINVAL; 420 break; 421 default: 422 return -EINVAL; 423 } 424 425 switch (s->target) { 426 case V4L2_SEL_TGT_CROP: 427 case V4L2_SEL_TGT_COMPOSE: 428 s->r.left = f->o_height; 429 s->r.top = f->o_width; 430 s->r.width = f->c_width; 431 s->r.height = f->c_height; 432 break; 433 case V4L2_SEL_TGT_CROP_DEFAULT: 434 case V4L2_SEL_TGT_CROP_BOUNDS: 435 case V4L2_SEL_TGT_COMPOSE_DEFAULT: 436 case V4L2_SEL_TGT_COMPOSE_BOUNDS: 437 s->r.left = 0; 438 s->r.top = 0; 439 s->r.width = f->width; 440 s->r.height = f->height; 441 break; 442 default: 443 return -EINVAL; 444 } 445 return 0; 446 } 447 448 static int vidioc_try_selection(struct file *file, void *prv, 449 const struct v4l2_selection *s) 450 { 451 struct g2d_ctx *ctx = prv; 452 struct g2d_dev *dev = ctx->dev; 453 struct g2d_frame *f; 454 455 f = get_frame(ctx, s->type); 456 if (IS_ERR(f)) 457 return PTR_ERR(f); 458 459 if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 460 if (s->target != V4L2_SEL_TGT_COMPOSE) 461 return -EINVAL; 462 } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 463 if (s->target != V4L2_SEL_TGT_CROP) 464 return -EINVAL; 465 } 466 467 if (s->r.top < 0 || s->r.left < 0) { 468 v4l2_err(&dev->v4l2_dev, 469 "doesn't support negative values for top & left\n"); 470 return -EINVAL; 471 } 472 473 return 0; 474 } 475 476 static int vidioc_s_selection(struct file *file, void *prv, 477 struct v4l2_selection *s) 478 { 479 struct g2d_ctx *ctx = prv; 480 struct g2d_frame *f; 481 int ret; 482 483 ret = vidioc_try_selection(file, prv, s); 484 if (ret) 485 return ret; 486 f = get_frame(ctx, s->type); 487 if (IS_ERR(f)) 488 return PTR_ERR(f); 489 490 f->c_width = s->r.width; 491 f->c_height = s->r.height; 492 f->o_width = s->r.left; 493 f->o_height = s->r.top; 494 f->bottom = f->o_height + f->c_height; 495 f->right = f->o_width + f->c_width; 496 return 0; 497 } 498 499 static void device_run(void *prv) 500 { 501 struct g2d_ctx *ctx = prv; 502 struct g2d_dev *dev = ctx->dev; 503 struct vb2_v4l2_buffer *src, *dst; 504 unsigned long flags; 505 u32 cmd = 0; 506 507 dev->curr = ctx; 508 509 src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); 510 dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); 511 512 clk_enable(dev->gate); 513 g2d_reset(dev); 514 515 spin_lock_irqsave(&dev->ctrl_lock, flags); 516 517 g2d_set_src_size(dev, &ctx->in); 518 g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0)); 519 520 g2d_set_dst_size(dev, &ctx->out); 521 g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0)); 522 523 g2d_set_rop4(dev, ctx->rop); 524 g2d_set_flip(dev, ctx->flip); 525 526 if (ctx->in.c_width != ctx->out.c_width || 527 ctx->in.c_height != ctx->out.c_height) { 528 if (dev->variant->hw_rev == TYPE_G2D_3X) 529 cmd |= CMD_V3_ENABLE_STRETCH; 530 else 531 g2d_set_v41_stretch(dev, &ctx->in, &ctx->out); 532 } 533 534 g2d_set_cmd(dev, cmd); 535 g2d_start(dev); 536 537 spin_unlock_irqrestore(&dev->ctrl_lock, flags); 538 } 539 540 static irqreturn_t g2d_isr(int irq, void *prv) 541 { 542 struct g2d_dev *dev = prv; 543 struct g2d_ctx *ctx = dev->curr; 544 struct vb2_v4l2_buffer *src, *dst; 545 546 g2d_clear_int(dev); 547 clk_disable(dev->gate); 548 549 BUG_ON(ctx == NULL); 550 551 src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); 552 dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 553 554 BUG_ON(src == NULL); 555 BUG_ON(dst == NULL); 556 557 dst->timecode = src->timecode; 558 dst->vb2_buf.timestamp = src->vb2_buf.timestamp; 559 dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 560 dst->flags |= 561 src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 562 563 v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); 564 v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); 565 v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx); 566 567 dev->curr = NULL; 568 return IRQ_HANDLED; 569 } 570 571 static const struct v4l2_file_operations g2d_fops = { 572 .owner = THIS_MODULE, 573 .open = g2d_open, 574 .release = g2d_release, 575 .poll = v4l2_m2m_fop_poll, 576 .unlocked_ioctl = video_ioctl2, 577 .mmap = v4l2_m2m_fop_mmap, 578 }; 579 580 static const struct v4l2_ioctl_ops g2d_ioctl_ops = { 581 .vidioc_querycap = vidioc_querycap, 582 583 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, 584 .vidioc_g_fmt_vid_cap = vidioc_g_fmt, 585 .vidioc_try_fmt_vid_cap = vidioc_try_fmt, 586 .vidioc_s_fmt_vid_cap = vidioc_s_fmt, 587 588 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt, 589 .vidioc_g_fmt_vid_out = vidioc_g_fmt, 590 .vidioc_try_fmt_vid_out = vidioc_try_fmt, 591 .vidioc_s_fmt_vid_out = vidioc_s_fmt, 592 593 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 594 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 595 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 596 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 597 598 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 599 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 600 601 .vidioc_g_selection = vidioc_g_selection, 602 .vidioc_s_selection = vidioc_s_selection, 603 }; 604 605 static const struct video_device g2d_videodev = { 606 .name = G2D_NAME, 607 .fops = &g2d_fops, 608 .ioctl_ops = &g2d_ioctl_ops, 609 .minor = -1, 610 .release = video_device_release, 611 .vfl_dir = VFL_DIR_M2M, 612 }; 613 614 static const struct v4l2_m2m_ops g2d_m2m_ops = { 615 .device_run = device_run, 616 }; 617 618 static const struct of_device_id exynos_g2d_match[]; 619 620 static int g2d_probe(struct platform_device *pdev) 621 { 622 struct g2d_dev *dev; 623 struct video_device *vfd; 624 const struct of_device_id *of_id; 625 int ret = 0; 626 627 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 628 if (!dev) 629 return -ENOMEM; 630 631 spin_lock_init(&dev->ctrl_lock); 632 mutex_init(&dev->mutex); 633 atomic_set(&dev->num_inst, 0); 634 635 dev->regs = devm_platform_ioremap_resource(pdev, 0); 636 if (IS_ERR(dev->regs)) 637 return PTR_ERR(dev->regs); 638 639 dev->clk = clk_get(&pdev->dev, "sclk_fimg2d"); 640 if (IS_ERR(dev->clk)) { 641 dev_err(&pdev->dev, "failed to get g2d clock\n"); 642 return -ENXIO; 643 } 644 645 ret = clk_prepare(dev->clk); 646 if (ret) { 647 dev_err(&pdev->dev, "failed to prepare g2d clock\n"); 648 goto put_clk; 649 } 650 651 dev->gate = clk_get(&pdev->dev, "fimg2d"); 652 if (IS_ERR(dev->gate)) { 653 dev_err(&pdev->dev, "failed to get g2d clock gate\n"); 654 ret = -ENXIO; 655 goto unprep_clk; 656 } 657 658 ret = clk_prepare(dev->gate); 659 if (ret) { 660 dev_err(&pdev->dev, "failed to prepare g2d clock gate\n"); 661 goto put_clk_gate; 662 } 663 664 ret = platform_get_irq(pdev, 0); 665 if (ret < 0) 666 goto unprep_clk_gate; 667 668 dev->irq = ret; 669 670 ret = devm_request_irq(&pdev->dev, dev->irq, g2d_isr, 671 0, pdev->name, dev); 672 if (ret) { 673 dev_err(&pdev->dev, "failed to install IRQ\n"); 674 goto unprep_clk_gate; 675 } 676 677 vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); 678 679 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); 680 if (ret) 681 goto unprep_clk_gate; 682 vfd = video_device_alloc(); 683 if (!vfd) { 684 v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); 685 ret = -ENOMEM; 686 goto unreg_v4l2_dev; 687 } 688 *vfd = g2d_videodev; 689 set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags); 690 vfd->lock = &dev->mutex; 691 vfd->v4l2_dev = &dev->v4l2_dev; 692 vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; 693 694 platform_set_drvdata(pdev, dev); 695 dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops); 696 if (IS_ERR(dev->m2m_dev)) { 697 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); 698 ret = PTR_ERR(dev->m2m_dev); 699 goto rel_vdev; 700 } 701 702 def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; 703 704 of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node); 705 if (!of_id) { 706 ret = -ENODEV; 707 goto free_m2m; 708 } 709 dev->variant = (struct g2d_variant *)of_id->data; 710 711 ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); 712 if (ret) { 713 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); 714 goto free_m2m; 715 } 716 video_set_drvdata(vfd, dev); 717 dev->vfd = vfd; 718 v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n", 719 vfd->num); 720 721 return 0; 722 723 free_m2m: 724 v4l2_m2m_release(dev->m2m_dev); 725 rel_vdev: 726 video_device_release(vfd); 727 unreg_v4l2_dev: 728 v4l2_device_unregister(&dev->v4l2_dev); 729 unprep_clk_gate: 730 clk_unprepare(dev->gate); 731 put_clk_gate: 732 clk_put(dev->gate); 733 unprep_clk: 734 clk_unprepare(dev->clk); 735 put_clk: 736 clk_put(dev->clk); 737 738 return ret; 739 } 740 741 static void g2d_remove(struct platform_device *pdev) 742 { 743 struct g2d_dev *dev = platform_get_drvdata(pdev); 744 745 v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME); 746 v4l2_m2m_release(dev->m2m_dev); 747 video_unregister_device(dev->vfd); 748 v4l2_device_unregister(&dev->v4l2_dev); 749 vb2_dma_contig_clear_max_seg_size(&pdev->dev); 750 clk_unprepare(dev->gate); 751 clk_put(dev->gate); 752 clk_unprepare(dev->clk); 753 clk_put(dev->clk); 754 } 755 756 static struct g2d_variant g2d_drvdata_v3x = { 757 .hw_rev = TYPE_G2D_3X, /* Revision 3.0 for S5PV210 and Exynos4210 */ 758 }; 759 760 static struct g2d_variant g2d_drvdata_v4x = { 761 .hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */ 762 }; 763 764 static const struct of_device_id exynos_g2d_match[] = { 765 { 766 .compatible = "samsung,s5pv210-g2d", 767 .data = &g2d_drvdata_v3x, 768 }, { 769 .compatible = "samsung,exynos4212-g2d", 770 .data = &g2d_drvdata_v4x, 771 }, 772 {}, 773 }; 774 MODULE_DEVICE_TABLE(of, exynos_g2d_match); 775 776 static struct platform_driver g2d_pdrv = { 777 .probe = g2d_probe, 778 .remove = g2d_remove, 779 .driver = { 780 .name = G2D_NAME, 781 .of_match_table = exynos_g2d_match, 782 }, 783 }; 784 785 module_platform_driver(g2d_pdrv); 786 787 MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>"); 788 MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver"); 789 MODULE_LICENSE("GPL"); 790