Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
g2d.c
Go to the documentation of this file.
1 /*
2  * Samsung S5P G2D - 2D Graphics Accelerator Driver
3  *
4  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5  * Kamil Debski, <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version
11  */
12 
13 #include <linux/module.h>
14 #include <linux/fs.h>
15 #include <linux/version.h>
16 #include <linux/timer.h>
17 #include <linux/sched.h>
18 #include <linux/slab.h>
19 #include <linux/clk.h>
20 #include <linux/interrupt.h>
21 
22 #include <linux/platform_device.h>
23 #include <media/v4l2-mem2mem.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-ioctl.h>
26 #include <media/videobuf2-core.h>
28 
29 #include "g2d.h"
30 #include "g2d-regs.h"
31 
32 #define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh)
33 
34 static struct g2d_fmt formats[] = {
35  {
36  .name = "XRGB_8888",
37  .fourcc = V4L2_PIX_FMT_RGB32,
38  .depth = 32,
40  },
41  {
42  .name = "RGB_565",
43  .fourcc = V4L2_PIX_FMT_RGB565X,
44  .depth = 16,
46  },
47  {
48  .name = "XRGB_1555",
49  .fourcc = V4L2_PIX_FMT_RGB555X,
50  .depth = 16,
52  },
53  {
54  .name = "XRGB_4444",
55  .fourcc = V4L2_PIX_FMT_RGB444,
56  .depth = 16,
58  },
59  {
60  .name = "PACKED_RGB_888",
61  .fourcc = V4L2_PIX_FMT_RGB24,
62  .depth = 24,
64  },
65 };
66 #define NUM_FORMATS ARRAY_SIZE(formats)
67 
68 static struct g2d_frame def_frame = {
69  .width = DEFAULT_WIDTH,
70  .height = DEFAULT_HEIGHT,
71  .c_width = DEFAULT_WIDTH,
72  .c_height = DEFAULT_HEIGHT,
73  .o_width = 0,
74  .o_height = 0,
75  .fmt = &formats[0],
76  .right = DEFAULT_WIDTH,
77  .bottom = DEFAULT_HEIGHT,
78 };
79 
80 static struct g2d_fmt *find_fmt(struct v4l2_format *f)
81 {
82  unsigned int i;
83  for (i = 0; i < NUM_FORMATS; i++) {
84  if (formats[i].fourcc == f->fmt.pix.pixelformat)
85  return &formats[i];
86  }
87  return NULL;
88 }
89 
90 
91 static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
92  enum v4l2_buf_type type)
93 {
94  switch (type) {
96  return &ctx->in;
98  return &ctx->out;
99  default:
100  return ERR_PTR(-EINVAL);
101  }
102 }
103 
104 static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
105  unsigned int *nbuffers, unsigned int *nplanes,
106  unsigned int sizes[], void *alloc_ctxs[])
107 {
108  struct g2d_ctx *ctx = vb2_get_drv_priv(vq);
109  struct g2d_frame *f = get_frame(ctx, vq->type);
110 
111  if (IS_ERR(f))
112  return PTR_ERR(f);
113 
114  sizes[0] = f->size;
115  *nplanes = 1;
116  alloc_ctxs[0] = ctx->dev->alloc_ctx;
117 
118  if (*nbuffers == 0)
119  *nbuffers = 1;
120 
121  return 0;
122 }
123 
124 static int g2d_buf_prepare(struct vb2_buffer *vb)
125 {
126  struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
127  struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type);
128 
129  if (IS_ERR(f))
130  return PTR_ERR(f);
131  vb2_set_plane_payload(vb, 0, f->size);
132  return 0;
133 }
134 
135 static void g2d_buf_queue(struct vb2_buffer *vb)
136 {
137  struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
138  v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
139 }
140 
141 
142 static struct vb2_ops g2d_qops = {
143  .queue_setup = g2d_queue_setup,
144  .buf_prepare = g2d_buf_prepare,
145  .buf_queue = g2d_buf_queue,
146 };
147 
148 static int queue_init(void *priv, struct vb2_queue *src_vq,
149  struct vb2_queue *dst_vq)
150 {
151  struct g2d_ctx *ctx = priv;
152  int ret;
153 
155  src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
156  src_vq->drv_priv = ctx;
157  src_vq->ops = &g2d_qops;
158  src_vq->mem_ops = &vb2_dma_contig_memops;
159  src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
160 
161  ret = vb2_queue_init(src_vq);
162  if (ret)
163  return ret;
164 
166  dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
167  dst_vq->drv_priv = ctx;
168  dst_vq->ops = &g2d_qops;
169  dst_vq->mem_ops = &vb2_dma_contig_memops;
170  dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
171 
172  return vb2_queue_init(dst_vq);
173 }
174 
175 static int g2d_s_ctrl(struct v4l2_ctrl *ctrl)
176 {
177  struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx,
178  ctrl_handler);
179  unsigned long flags;
180 
181  spin_lock_irqsave(&ctx->dev->ctrl_lock, flags);
182  switch (ctrl->id) {
183  case V4L2_CID_COLORFX:
184  if (ctrl->val == V4L2_COLORFX_NEGATIVE)
185  ctx->rop = ROP4_INVERT;
186  else
187  ctx->rop = ROP4_COPY;
188  break;
189 
190  case V4L2_CID_HFLIP:
191  ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1);
192  break;
193 
194  }
195  spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags);
196  return 0;
197 }
198 
199 static const struct v4l2_ctrl_ops g2d_ctrl_ops = {
200  .s_ctrl = g2d_s_ctrl,
201 };
202 
203 static int g2d_setup_ctrls(struct g2d_ctx *ctx)
204 {
205  struct g2d_dev *dev = ctx->dev;
206 
208 
209  ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops,
210  V4L2_CID_HFLIP, 0, 1, 1, 0);
211 
212  ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops,
213  V4L2_CID_VFLIP, 0, 1, 1, 0);
214 
216  &ctx->ctrl_handler,
217  &g2d_ctrl_ops,
220  ~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)),
222 
223  if (ctx->ctrl_handler.error) {
224  int err = ctx->ctrl_handler.error;
225  v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n");
227  return err;
228  }
229 
230  v4l2_ctrl_cluster(2, &ctx->ctrl_hflip);
231 
232  return 0;
233 }
234 
235 static int g2d_open(struct file *file)
236 {
237  struct g2d_dev *dev = video_drvdata(file);
238  struct g2d_ctx *ctx = NULL;
239  int ret = 0;
240 
241  ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
242  if (!ctx)
243  return -ENOMEM;
244  ctx->dev = dev;
245  /* Set default formats */
246  ctx->in = def_frame;
247  ctx->out = def_frame;
248 
249  if (mutex_lock_interruptible(&dev->mutex)) {
250  kfree(ctx);
251  return -ERESTARTSYS;
252  }
253  ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
254  if (IS_ERR(ctx->m2m_ctx)) {
255  ret = PTR_ERR(ctx->m2m_ctx);
256  mutex_unlock(&dev->mutex);
257  kfree(ctx);
258  return ret;
259  }
260  v4l2_fh_init(&ctx->fh, video_devdata(file));
261  file->private_data = &ctx->fh;
262  v4l2_fh_add(&ctx->fh);
263 
264  g2d_setup_ctrls(ctx);
265 
266  /* Write the default values to the ctx struct */
268 
269  ctx->fh.ctrl_handler = &ctx->ctrl_handler;
270  mutex_unlock(&dev->mutex);
271 
272  v4l2_info(&dev->v4l2_dev, "instance opened\n");
273  return 0;
274 }
275 
276 static int g2d_release(struct file *file)
277 {
278  struct g2d_dev *dev = video_drvdata(file);
279  struct g2d_ctx *ctx = fh2ctx(file->private_data);
280 
282  v4l2_fh_del(&ctx->fh);
283  v4l2_fh_exit(&ctx->fh);
284  kfree(ctx);
285  v4l2_info(&dev->v4l2_dev, "instance closed\n");
286  return 0;
287 }
288 
289 
290 static int vidioc_querycap(struct file *file, void *priv,
291  struct v4l2_capability *cap)
292 {
293  strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
294  strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
295  cap->bus_info[0] = 0;
296  cap->version = KERNEL_VERSION(1, 0, 0);
297  /*
298  * This is only a mem-to-mem video device. The capture and output
299  * device capability flags are left only for backward compatibility
300  * and are scheduled for removal.
301  */
304  return 0;
305 }
306 
307 static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f)
308 {
309  struct g2d_fmt *fmt;
310  if (f->index >= NUM_FORMATS)
311  return -EINVAL;
312  fmt = &formats[f->index];
313  f->pixelformat = fmt->fourcc;
314  strncpy(f->description, fmt->name, sizeof(f->description) - 1);
315  return 0;
316 }
317 
318 static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f)
319 {
320  struct g2d_ctx *ctx = prv;
321  struct vb2_queue *vq;
322  struct g2d_frame *frm;
323 
324  vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
325  if (!vq)
326  return -EINVAL;
327  frm = get_frame(ctx, f->type);
328  if (IS_ERR(frm))
329  return PTR_ERR(frm);
330 
331  f->fmt.pix.width = frm->width;
332  f->fmt.pix.height = frm->height;
333  f->fmt.pix.field = V4L2_FIELD_NONE;
334  f->fmt.pix.pixelformat = frm->fmt->fourcc;
335  f->fmt.pix.bytesperline = (frm->width * frm->fmt->depth) >> 3;
336  f->fmt.pix.sizeimage = frm->size;
337  return 0;
338 }
339 
340 static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f)
341 {
342  struct g2d_fmt *fmt;
343  enum v4l2_field *field;
344 
345  fmt = find_fmt(f);
346  if (!fmt)
347  return -EINVAL;
348 
349  field = &f->fmt.pix.field;
350  if (*field == V4L2_FIELD_ANY)
351  *field = V4L2_FIELD_NONE;
352  else if (*field != V4L2_FIELD_NONE)
353  return -EINVAL;
354 
355  if (f->fmt.pix.width > MAX_WIDTH)
356  f->fmt.pix.width = MAX_WIDTH;
357  if (f->fmt.pix.height > MAX_HEIGHT)
358  f->fmt.pix.height = MAX_HEIGHT;
359 
360  if (f->fmt.pix.width < 1)
361  f->fmt.pix.width = 1;
362  if (f->fmt.pix.height < 1)
363  f->fmt.pix.height = 1;
364 
365  f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
366  f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
367  return 0;
368 }
369 
370 static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
371 {
372  struct g2d_ctx *ctx = prv;
373  struct g2d_dev *dev = ctx->dev;
374  struct vb2_queue *vq;
375  struct g2d_frame *frm;
376  struct g2d_fmt *fmt;
377  int ret = 0;
378 
379  /* Adjust all values accordingly to the hardware capabilities
380  * and chosen format. */
381  ret = vidioc_try_fmt(file, prv, f);
382  if (ret)
383  return ret;
384  vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
385  if (vb2_is_busy(vq)) {
386  v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type);
387  return -EBUSY;
388  }
389  frm = get_frame(ctx, f->type);
390  if (IS_ERR(frm))
391  return PTR_ERR(frm);
392  fmt = find_fmt(f);
393  if (!fmt)
394  return -EINVAL;
395  frm->width = f->fmt.pix.width;
396  frm->height = f->fmt.pix.height;
397  frm->size = f->fmt.pix.sizeimage;
398  /* Reset crop settings */
399  frm->o_width = 0;
400  frm->o_height = 0;
401  frm->c_width = frm->width;
402  frm->c_height = frm->height;
403  frm->right = frm->width;
404  frm->bottom = frm->height;
405  frm->fmt = fmt;
406  frm->stride = f->fmt.pix.bytesperline;
407  return 0;
408 }
409 
410 static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait)
411 {
412  struct g2d_ctx *ctx = fh2ctx(file->private_data);
413  struct g2d_dev *dev = ctx->dev;
414  unsigned int res;
415 
416  mutex_lock(&dev->mutex);
417  res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
418  mutex_unlock(&dev->mutex);
419  return res;
420 }
421 
422 static int g2d_mmap(struct file *file, struct vm_area_struct *vma)
423 {
424  struct g2d_ctx *ctx = fh2ctx(file->private_data);
425  struct g2d_dev *dev = ctx->dev;
426  int ret;
427 
428  if (mutex_lock_interruptible(&dev->mutex))
429  return -ERESTARTSYS;
430  ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
431  mutex_unlock(&dev->mutex);
432  return ret;
433 }
434 
435 static int vidioc_reqbufs(struct file *file, void *priv,
436  struct v4l2_requestbuffers *reqbufs)
437 {
438  struct g2d_ctx *ctx = priv;
439  return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
440 }
441 
442 static int vidioc_querybuf(struct file *file, void *priv,
443  struct v4l2_buffer *buf)
444 {
445  struct g2d_ctx *ctx = priv;
446  return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
447 }
448 
449 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
450 {
451  struct g2d_ctx *ctx = priv;
452  return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
453 }
454 
455 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
456 {
457  struct g2d_ctx *ctx = priv;
458  return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
459 }
460 
461 
462 static int vidioc_streamon(struct file *file, void *priv,
463  enum v4l2_buf_type type)
464 {
465  struct g2d_ctx *ctx = priv;
466  return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
467 }
468 
469 static int vidioc_streamoff(struct file *file, void *priv,
470  enum v4l2_buf_type type)
471 {
472  struct g2d_ctx *ctx = priv;
473  return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
474 }
475 
476 static int vidioc_cropcap(struct file *file, void *priv,
477  struct v4l2_cropcap *cr)
478 {
479  struct g2d_ctx *ctx = priv;
480  struct g2d_frame *f;
481 
482  f = get_frame(ctx, cr->type);
483  if (IS_ERR(f))
484  return PTR_ERR(f);
485 
486  cr->bounds.left = 0;
487  cr->bounds.top = 0;
488  cr->bounds.width = f->width;
489  cr->bounds.height = f->height;
490  cr->defrect = cr->bounds;
491  return 0;
492 }
493 
494 static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
495 {
496  struct g2d_ctx *ctx = prv;
497  struct g2d_frame *f;
498 
499  f = get_frame(ctx, cr->type);
500  if (IS_ERR(f))
501  return PTR_ERR(f);
502 
503  cr->c.left = f->o_height;
504  cr->c.top = f->o_width;
505  cr->c.width = f->c_width;
506  cr->c.height = f->c_height;
507  return 0;
508 }
509 
510 static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
511 {
512  struct g2d_ctx *ctx = prv;
513  struct g2d_dev *dev = ctx->dev;
514  struct g2d_frame *f;
515 
516  f = get_frame(ctx, cr->type);
517  if (IS_ERR(f))
518  return PTR_ERR(f);
519 
520  if (cr->c.top < 0 || cr->c.left < 0) {
521  v4l2_err(&dev->v4l2_dev,
522  "doesn't support negative values for top & left\n");
523  return -EINVAL;
524  }
525 
526  return 0;
527 }
528 
529 static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
530 {
531  struct g2d_ctx *ctx = prv;
532  struct g2d_frame *f;
533  int ret;
534 
535  ret = vidioc_try_crop(file, prv, cr);
536  if (ret)
537  return ret;
538  f = get_frame(ctx, cr->type);
539  if (IS_ERR(f))
540  return PTR_ERR(f);
541 
542  f->c_width = cr->c.width;
543  f->c_height = cr->c.height;
544  f->o_width = cr->c.left;
545  f->o_height = cr->c.top;
546  f->bottom = f->o_height + f->c_height;
547  f->right = f->o_width + f->c_width;
548  return 0;
549 }
550 
551 static void g2d_lock(void *prv)
552 {
553  struct g2d_ctx *ctx = prv;
554  struct g2d_dev *dev = ctx->dev;
555  mutex_lock(&dev->mutex);
556 }
557 
558 static void g2d_unlock(void *prv)
559 {
560  struct g2d_ctx *ctx = prv;
561  struct g2d_dev *dev = ctx->dev;
562  mutex_unlock(&dev->mutex);
563 }
564 
565 static void job_abort(void *prv)
566 {
567  struct g2d_ctx *ctx = prv;
568  struct g2d_dev *dev = ctx->dev;
569  int ret;
570 
571  if (dev->curr == NULL) /* No job currently running */
572  return;
573 
574  ret = wait_event_timeout(dev->irq_queue,
575  dev->curr == NULL,
577 }
578 
579 static void device_run(void *prv)
580 {
581  struct g2d_ctx *ctx = prv;
582  struct g2d_dev *dev = ctx->dev;
583  struct vb2_buffer *src, *dst;
584  unsigned long flags;
585  u32 cmd = 0;
586 
587  dev->curr = ctx;
588 
589  src = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
590  dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
591 
592  clk_enable(dev->gate);
593  g2d_reset(dev);
594 
595  spin_lock_irqsave(&dev->ctrl_lock, flags);
596 
597  g2d_set_src_size(dev, &ctx->in);
598  g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0));
599 
600  g2d_set_dst_size(dev, &ctx->out);
601  g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0));
602 
603  g2d_set_rop4(dev, ctx->rop);
604  g2d_set_flip(dev, ctx->flip);
605 
606  if (ctx->in.c_width != ctx->out.c_width ||
607  ctx->in.c_height != ctx->out.c_height)
608  cmd |= g2d_cmd_stretch(1);
609  g2d_set_cmd(dev, cmd);
610  g2d_start(dev);
611 
612  spin_unlock_irqrestore(&dev->ctrl_lock, flags);
613 }
614 
615 static irqreturn_t g2d_isr(int irq, void *prv)
616 {
617  struct g2d_dev *dev = prv;
618  struct g2d_ctx *ctx = dev->curr;
619  struct vb2_buffer *src, *dst;
620 
621  g2d_clear_int(dev);
622  clk_disable(dev->gate);
623 
624  BUG_ON(ctx == NULL);
625 
626  src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
627  dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
628 
629  BUG_ON(src == NULL);
630  BUG_ON(dst == NULL);
631 
632  v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
633  v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
634  v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx);
635 
636  dev->curr = NULL;
637  wake_up(&dev->irq_queue);
638  return IRQ_HANDLED;
639 }
640 
641 static const struct v4l2_file_operations g2d_fops = {
642  .owner = THIS_MODULE,
643  .open = g2d_open,
644  .release = g2d_release,
645  .poll = g2d_poll,
646  .unlocked_ioctl = video_ioctl2,
647  .mmap = g2d_mmap,
648 };
649 
650 static const struct v4l2_ioctl_ops g2d_ioctl_ops = {
651  .vidioc_querycap = vidioc_querycap,
652 
653  .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
654  .vidioc_g_fmt_vid_cap = vidioc_g_fmt,
655  .vidioc_try_fmt_vid_cap = vidioc_try_fmt,
656  .vidioc_s_fmt_vid_cap = vidioc_s_fmt,
657 
658  .vidioc_enum_fmt_vid_out = vidioc_enum_fmt,
659  .vidioc_g_fmt_vid_out = vidioc_g_fmt,
660  .vidioc_try_fmt_vid_out = vidioc_try_fmt,
661  .vidioc_s_fmt_vid_out = vidioc_s_fmt,
662 
663  .vidioc_reqbufs = vidioc_reqbufs,
664  .vidioc_querybuf = vidioc_querybuf,
665 
666  .vidioc_qbuf = vidioc_qbuf,
667  .vidioc_dqbuf = vidioc_dqbuf,
668 
669  .vidioc_streamon = vidioc_streamon,
670  .vidioc_streamoff = vidioc_streamoff,
671 
672  .vidioc_g_crop = vidioc_g_crop,
673  .vidioc_s_crop = vidioc_s_crop,
674  .vidioc_cropcap = vidioc_cropcap,
675 };
676 
677 static struct video_device g2d_videodev = {
678  .name = G2D_NAME,
679  .fops = &g2d_fops,
680  .ioctl_ops = &g2d_ioctl_ops,
681  .minor = -1,
682  .release = video_device_release,
683  .vfl_dir = VFL_DIR_M2M,
684 };
685 
686 static struct v4l2_m2m_ops g2d_m2m_ops = {
687  .device_run = device_run,
688  .job_abort = job_abort,
689  .lock = g2d_lock,
690  .unlock = g2d_unlock,
691 };
692 
693 static int g2d_probe(struct platform_device *pdev)
694 {
695  struct g2d_dev *dev;
696  struct video_device *vfd;
697  struct resource *res;
698  int ret = 0;
699 
700  dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
701  if (!dev)
702  return -ENOMEM;
703 
704  spin_lock_init(&dev->ctrl_lock);
705  mutex_init(&dev->mutex);
706  atomic_set(&dev->num_inst, 0);
708 
709  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
710 
711  dev->regs = devm_request_and_ioremap(&pdev->dev, res);
712  if (dev->regs == NULL) {
713  dev_err(&pdev->dev, "Failed to obtain io memory\n");
714  return -ENOENT;
715  }
716 
717  dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
718  if (IS_ERR_OR_NULL(dev->clk)) {
719  dev_err(&pdev->dev, "failed to get g2d clock\n");
720  return -ENXIO;
721  }
722 
723  ret = clk_prepare(dev->clk);
724  if (ret) {
725  dev_err(&pdev->dev, "failed to prepare g2d clock\n");
726  goto put_clk;
727  }
728 
729  dev->gate = clk_get(&pdev->dev, "fimg2d");
730  if (IS_ERR_OR_NULL(dev->gate)) {
731  dev_err(&pdev->dev, "failed to get g2d clock gate\n");
732  ret = -ENXIO;
733  goto unprep_clk;
734  }
735 
736  ret = clk_prepare(dev->gate);
737  if (ret) {
738  dev_err(&pdev->dev, "failed to prepare g2d clock gate\n");
739  goto put_clk_gate;
740  }
741 
742  res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
743  if (!res) {
744  dev_err(&pdev->dev, "failed to find IRQ\n");
745  ret = -ENXIO;
746  goto unprep_clk_gate;
747  }
748 
749  dev->irq = res->start;
750 
751  ret = devm_request_irq(&pdev->dev, dev->irq, g2d_isr,
752  0, pdev->name, dev);
753  if (ret) {
754  dev_err(&pdev->dev, "failed to install IRQ\n");
755  goto put_clk_gate;
756  }
757 
758  dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
759  if (IS_ERR(dev->alloc_ctx)) {
760  ret = PTR_ERR(dev->alloc_ctx);
761  goto unprep_clk_gate;
762  }
763 
764  ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
765  if (ret)
766  goto alloc_ctx_cleanup;
767  vfd = video_device_alloc();
768  if (!vfd) {
769  v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
770  ret = -ENOMEM;
771  goto unreg_v4l2_dev;
772  }
773  *vfd = g2d_videodev;
774  vfd->lock = &dev->mutex;
775  ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
776  if (ret) {
777  v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
778  goto rel_vdev;
779  }
780  video_set_drvdata(vfd, dev);
781  snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name);
782  dev->vfd = vfd;
783  v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
784  vfd->num);
785  platform_set_drvdata(pdev, dev);
786  dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
787  if (IS_ERR(dev->m2m_dev)) {
788  v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
789  ret = PTR_ERR(dev->m2m_dev);
790  goto unreg_video_dev;
791  }
792 
793  def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
794 
795  return 0;
796 
797 unreg_video_dev:
799 rel_vdev:
801 unreg_v4l2_dev:
803 alloc_ctx_cleanup:
805 unprep_clk_gate:
806  clk_unprepare(dev->gate);
807 put_clk_gate:
808  clk_put(dev->gate);
809 unprep_clk:
810  clk_unprepare(dev->clk);
811 put_clk:
812  clk_put(dev->clk);
813 
814  return ret;
815 }
816 
817 static int g2d_remove(struct platform_device *pdev)
818 {
819  struct g2d_dev *dev = (struct g2d_dev *)platform_get_drvdata(pdev);
820 
821  v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME);
826  clk_unprepare(dev->gate);
827  clk_put(dev->gate);
828  clk_unprepare(dev->clk);
829  clk_put(dev->clk);
830  return 0;
831 }
832 
833 static struct platform_driver g2d_pdrv = {
834  .probe = g2d_probe,
835  .remove = g2d_remove,
836  .driver = {
837  .name = G2D_NAME,
838  .owner = THIS_MODULE,
839  },
840 };
841 
842 module_platform_driver(g2d_pdrv);
843 
844 MODULE_AUTHOR("Kamil Debski <[email protected]>");
845 MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver");
846 MODULE_LICENSE("GPL");