diff options
author | Ke Qinghua <qinghua.ke@freescale.com> | 2013-12-19 10:29:12 +0800 |
---|---|---|
committer | Ke Qinghua <qinghua.ke@freescale.com> | 2013-12-19 12:17:06 +0800 |
commit | 6702ef28b741ab2895f4220ac70f7949a55bb8ee (patch) | |
tree | ad771be3c7581889bbda0ea48c68d83472cb5225 /drivers | |
parent | 6aa195c6f430c25f671c00b88601cc7550f5a72c (diff) |
ENGR00292372 Add consumer IR support in android 4.4
Add IR char driver,mx6_ir driver,epit driver and update configuration
for support IR.
Signed-off-by: Ke Qinghua <qinghua.ke@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/Kconfig | 8 | ||||
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/ir.c | 174 |
3 files changed, 183 insertions, 0 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 00061c2e6f04..658e001072ad 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -79,6 +79,14 @@ config TTY_PRINTK If unsure, say N. +config DEVIR + bool "/dev/ir IR device support" + default y + help + Say Y here if you want to support the /dev/ir device. The + /dev/ir device is used for consumer IR. + When this device is not exist, say "N". + config BRIQ_PANEL tristate 'Total Impact briQ front panel driver' depends on PPC_CHRP diff --git a/drivers/char/Makefile b/drivers/char/Makefile index fc3e61b1875f..4db4cc2a13f0 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -67,4 +67,5 @@ obj-$(CONFIG_MXC_IIM) += mxc_iim.o obj-$(CONFIG_MXS_VIIM) += mxs_viim.o obj-$(CONFIG_JS_RTC) += js-rtc.o +obj-$(CONFIG_DEVIR) += ir.o js-rtc-y = rtc.o diff --git a/drivers/char/ir.c b/drivers/char/ir.c new file mode 100644 index 000000000000..5eefdc2dd721 --- /dev/null +++ b/drivers/char/ir.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. + */ +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/ctype.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/mutex.h> +#include <linux/uaccess.h> +#include <linux/slab.h> +#include <linux/ir.h> + +#define IR_MINOR 255 + +static DEFINE_MUTEX(ir_mutex); + +static int ir_open_cnt; /* #times opened */ + +static int ir_open(struct inode *inode, struct file *file) +{ + int ret; + mutex_lock(&ir_mutex); + if (0 == ir_open_cnt) { + ret = 0; + ir_open_cnt++; + } else { + ret = -1; + } + mutex_unlock(&ir_mutex); + return ret; +} + +static int ir_release(struct inode *inode, struct file *file) +{ + mutex_lock(&ir_mutex); + ir_open_cnt--; + mutex_unlock(&ir_mutex); + return 0; +} + + +static long ir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct miscdevice *c; + void *devdata; + int ret = 0; + + mutex_lock(&ir_mutex); + c = file->private_data; + if (!c) { + mutex_unlock(&ir_mutex); + return -EINVAL; + } + devdata = dev_get_drvdata(c->this_device); + if (!devdata) { + mutex_unlock(&ir_mutex); + return -EINVAL; + } + + switch (cmd) { + case IR_GET_CARRIER_FREQS: + { + struct ir_carrier_freq ir_carrier; + int id; + + if (copy_from_user(&ir_carrier, + arg, + sizeof(struct ir_carrier_freq))) { + ret = -EINVAL; + } else { + id = ir_carrier.id; + ret = ir_get_carrier_range(id, + &ir_carrier.min, + &ir_carrier.max); + if (0 == ret) { + if (copy_to_user(arg, &ir_carrier, sizeof(ir_carrier))) + ret = -EINVAL; + } + } + break; + } + case IR_GET_CARRIER_FREQS_NUM: + { + int num = ir_get_num_carrier_freqs(); + if (copy_to_user(arg, &num, 1)) + ret = -EINVAL; + break; + } + case IR_CFG_CARRIER: + { + int carrier = (int)(arg); + ir_config(devdata, carrier); + break; + } + case IR_DATA_TRANSMIT: + { + struct ir_data_pattern p; + int *pattern; + + if (!arg) { + mutex_unlock(&ir_mutex); + return -EINVAL; + } + + if (copy_from_user(&p, arg, sizeof(struct ir_data_pattern))) { + mutex_unlock(&ir_mutex); + return -EINVAL; + } + + pattern = kzalloc(p.len*sizeof(int), GFP_KERNEL); + if (!pattern) { + mutex_unlock(&ir_mutex); + printk(KERN_ERR "memory allocate for IR pattern error.\n"); + return -EINVAL; + } + + if (copy_from_user(pattern, p.pattern, p.len*sizeof(int))) { + printk(KERN_ERR "memory allocate for IR pattern error.\n"); + ret = -EINVAL; + } else { + ir_transmit(devdata, p.len, pattern, 1); + } + kfree(pattern); + break; + } + default: + break; + } + mutex_unlock(&ir_mutex); + return ret; +} + +static const struct file_operations ir_fops = { + .owner = THIS_MODULE, + .open = ir_open, + .release = ir_release, + .unlocked_ioctl = ir_ioctl, +}; + +static struct miscdevice ir_miscdev = { + .minor = IR_MINOR, + .name = "ir", + .fops = &ir_fops, +}; + +void ir_device_register(const char *name, struct device *parent, void *devdata) +{ + int ret; + ret = misc_register(&ir_miscdev); + dev_set_drvdata(ir_miscdev.this_device, devdata); + return ret; +} +EXPORT_SYMBOL(ir_device_register); + +void ir_device_unregister(void) +{ + misc_deregister(&ir_miscdev); +} +EXPORT_SYMBOL(ir_device_unregister); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("IR Low Abstract Layer"); +MODULE_LICENSE("GPL"); |