2 * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
17 * @brief This file contains the IPUv3 driver device interface and fops functions.
22 #include <linux/types.h>
23 #include <linux/init.h>
24 #include <linux/platform_device.h>
25 #include <linux/err.h>
26 #include <linux/spinlock.h>
27 #include <linux/delay.h>
28 #include <linux/clk.h>
29 #include <linux/poll.h>
30 #include <linux/sched.h>
31 #include <linux/time.h>
32 #include <linux/wait.h>
33 #include <linux/dma-mapping.h>
35 #include <linux/ipu.h>
36 #include <asm/cacheflush.h>
40 #include "ipu_param_mem.h"
42 /* Strucutures and variables for exporting MXC IPU as device*/
44 static int mxc_ipu_major;
45 static struct class *mxc_ipu_class;
47 DEFINE_SPINLOCK(event_lock);
49 struct ipu_dev_irq_info {
50 wait_queue_head_t waitq;
54 int register_ipu_device(void);
56 /* Static functions */
58 int get_events(ipu_event_info *p)
63 spin_lock_irqsave(&event_lock, flags);
64 if (irq_info[p->irq].irq_pending > 0)
65 irq_info[p->irq].irq_pending--;
68 spin_unlock_irqrestore(&event_lock, flags);
73 static irqreturn_t mxc_ipu_generic_handler(int irq, void *dev_id)
75 irq_info[irq].irq_pending++;
77 /* Wakeup any blocking user context */
78 wake_up_interruptible(&(irq_info[irq].waitq));
82 static int mxc_ipu_open(struct inode *inode, struct file *file)
88 static long mxc_ipu_ioctl(struct file *file,
89 unsigned int cmd, unsigned long arg)
94 case IPU_INIT_CHANNEL:
96 ipu_channel_parm parm;
99 (&parm, (ipu_channel_parm *) arg,
100 sizeof(ipu_channel_parm)))
105 ipu_init_channel(parm.channel,
108 ret = ipu_init_channel(parm.channel, NULL);
112 case IPU_UNINIT_CHANNEL:
115 int __user *argp = (void __user *)arg;
116 if (get_user(ch, argp))
118 ipu_uninit_channel(ch);
121 case IPU_INIT_CHANNEL_BUFFER:
123 ipu_channel_buf_parm parm;
125 (&parm, (ipu_channel_buf_parm *) arg,
126 sizeof(ipu_channel_buf_parm)))
130 ipu_init_channel_buffer(
131 parm.channel, parm.type,
133 parm.width, parm.height,
144 case IPU_UPDATE_CHANNEL_BUFFER:
146 ipu_channel_buf_parm parm;
148 (&parm, (ipu_channel_buf_parm *) arg,
149 sizeof(ipu_channel_buf_parm)))
152 if ((parm.phyaddr_0 != (dma_addr_t) NULL)
153 && (parm.phyaddr_1 == (dma_addr_t) NULL)) {
155 ipu_update_channel_buffer(
160 } else if ((parm.phyaddr_0 == (dma_addr_t) NULL)
161 && (parm.phyaddr_1 != (dma_addr_t) NULL)) {
163 ipu_update_channel_buffer(
174 case IPU_SELECT_CHANNEL_BUFFER:
176 ipu_channel_buf_parm parm;
178 (&parm, (ipu_channel_buf_parm *) arg,
179 sizeof(ipu_channel_buf_parm)))
183 ipu_select_buffer(parm.channel,
184 parm.type, parm.bufNum);
188 case IPU_SELECT_MULTI_VDI_BUFFER:
192 (&parm, (uint32_t *) arg,
196 ret = ipu_select_multi_vdi_buffer(parm);
199 case IPU_LINK_CHANNELS:
201 ipu_channel_link link;
203 (&link, (ipu_channel_link *) arg,
204 sizeof(ipu_channel_link)))
207 ret = ipu_link_channels(link.src_ch,
212 case IPU_UNLINK_CHANNELS:
214 ipu_channel_link link;
216 (&link, (ipu_channel_link *) arg,
217 sizeof(ipu_channel_link)))
220 ret = ipu_unlink_channels(link.src_ch,
225 case IPU_ENABLE_CHANNEL:
228 int __user *argp = (void __user *)arg;
229 if (get_user(ch, argp))
231 ipu_enable_channel(ch);
234 case IPU_DISABLE_CHANNEL:
236 ipu_channel_info info;
238 (&info, (ipu_channel_info *) arg,
239 sizeof(ipu_channel_info)))
242 ret = ipu_disable_channel(info.channel,
249 int __user *argp = (void __user *)arg;
250 if (get_user(irq, argp))
255 case IPU_DISABLE_IRQ:
258 int __user *argp = (void __user *)arg;
259 if (get_user(irq, argp))
261 ipu_disable_irq(irq);
267 int __user *argp = (void __user *)arg;
268 if (get_user(irq, argp))
278 (&info, (ipu_irq_info *) arg,
279 sizeof(ipu_irq_info)))
282 ipu_free_irq(info.irq, info.dev_id);
283 irq_info[info.irq].irq_pending = 0;
286 case IPU_REQUEST_IRQ_STATUS:
289 int __user *argp = (void __user *)arg;
290 if (get_user(irq, argp))
292 ret = ipu_get_irq_status(irq);
295 case IPU_REGISTER_GENERIC_ISR:
299 (&info, (ipu_event_info *) arg,
300 sizeof(ipu_event_info)))
304 ipu_request_irq(info.irq,
305 mxc_ipu_generic_handler,
306 0, "video_sink", info.dev);
308 init_waitqueue_head(&(irq_info[info.irq].waitq));
312 /* User will have to allocate event_type
313 structure and pass the pointer in arg */
319 (&info, (ipu_event_info *) arg,
320 sizeof(ipu_event_info)))
323 r = get_events(&info);
325 if ((file->f_flags & O_NONBLOCK) &&
326 (irq_info[info.irq].irq_pending == 0))
328 wait_event_interruptible_timeout(irq_info[info.irq].waitq,
329 (irq_info[info.irq].irq_pending != 0), 2 * HZ);
330 r = get_events(&info);
334 if (!copy_to_user((ipu_event_info *) arg,
335 &info, sizeof(ipu_event_info)))
344 (&info, (ipu_mem_info *) arg,
345 sizeof(ipu_mem_info)))
348 info.vaddr = dma_alloc_coherent(0,
349 PAGE_ALIGN(info.size),
351 GFP_DMA | GFP_KERNEL);
352 if (info.vaddr == 0) {
353 printk(KERN_ERR "dma alloc failed!\n");
356 if (copy_to_user((ipu_mem_info *) arg, &info,
357 sizeof(ipu_mem_info)) > 0)
365 (&info, (ipu_mem_info *) arg,
366 sizeof(ipu_mem_info)))
370 dma_free_coherent(0, PAGE_ALIGN(info.size),
371 info.vaddr, info.paddr);
376 case IPU_IS_CHAN_BUSY:
380 (&chan, (ipu_channel_t *)arg,
381 sizeof(ipu_channel_t)))
384 if (ipu_is_channel_busy(chan))
390 case IPU_CALC_STRIPES_SIZE:
392 ipu_stripe_parm stripe_parm;
394 if (copy_from_user (&stripe_parm, (ipu_stripe_parm *)arg,
395 sizeof(ipu_stripe_parm)))
397 ipu_calc_stripes_sizes(stripe_parm.input_width,
398 stripe_parm.output_width,
399 stripe_parm.maximal_stripe_width,
401 stripe_parm.equal_stripes,
402 stripe_parm.input_pixelformat,
403 stripe_parm.output_pixelformat,
406 if (copy_to_user((ipu_stripe_parm *) arg, &stripe_parm,
407 sizeof(ipu_stripe_parm)) > 0)
411 case IPU_UPDATE_BUF_OFFSET:
413 ipu_buf_offset_parm offset_parm;
415 if (copy_from_user (&offset_parm, (ipu_buf_offset_parm *)arg,
416 sizeof(ipu_buf_offset_parm)))
418 ret = ipu_update_channel_offset(offset_parm.channel,
420 offset_parm.pixel_fmt,
424 offset_parm.u_offset,
425 offset_parm.v_offset,
426 offset_parm.vertical_offset,
427 offset_parm.horizontal_offset);
434 if (copy_from_user(&csc, (void *) arg,
435 sizeof(ipu_csc_update)))
437 if (copy_from_user(¶m[0][0], (void *) csc.param,
440 ipu_set_csc_coefficients(csc.channel, param);
449 static int mxc_ipu_mmap(struct file *file, struct vm_area_struct *vma)
451 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
453 if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
454 vma->vm_end - vma->vm_start,
455 vma->vm_page_prot)) {
463 static int mxc_ipu_release(struct inode *inode, struct file *file)
468 static struct file_operations mxc_ipu_fops = {
469 .owner = THIS_MODULE,
470 .open = mxc_ipu_open,
471 .mmap = mxc_ipu_mmap,
472 .release = mxc_ipu_release,
473 .unlocked_ioctl = mxc_ipu_ioctl,
476 int register_ipu_device()
480 mxc_ipu_major = register_chrdev(0, "mxc_ipu", &mxc_ipu_fops);
481 if (mxc_ipu_major < 0) {
483 "Unable to register Mxc Ipu as a char device\n");
484 return mxc_ipu_major;
487 mxc_ipu_class = class_create(THIS_MODULE, "mxc_ipu");
488 if (IS_ERR(mxc_ipu_class)) {
489 printk(KERN_ERR "Unable to create class for Mxc Ipu\n");
490 ret = PTR_ERR(mxc_ipu_class);
494 temp = device_create(mxc_ipu_class, NULL, MKDEV(mxc_ipu_major, 0),
498 printk(KERN_ERR "Unable to create class device for Mxc Ipu\n");
502 spin_lock_init(&event_lock);
507 class_destroy(mxc_ipu_class);
509 unregister_chrdev(mxc_ipu_major, "mxc_ipu");