diff options
author | jt1134 <jt1134@gmail.com> | 2012-11-04 20:15:55 -0600 |
---|---|---|
committer | jt1134 <jt1134@gmail.com> | 2012-11-04 21:02:25 -0600 |
commit | 4645b5af63093e42c9aee645c6bf2de6cf8686c6 (patch) | |
tree | 1363cb501c2a0bcd2196d890701a730dcdb5ea89 /drivers/input | |
parent | dabec1aad7b62ded1831757e4096a2deba03f6a8 (diff) | |
download | kernel_samsung_aries-4645b5af63093e42c9aee645c6bf2de6cf8686c6.zip kernel_samsung_aries-4645b5af63093e42c9aee645c6bf2de6cf8686c6.tar.gz kernel_samsung_aries-4645b5af63093e42c9aee645c6bf2de6cf8686c6.tar.bz2 |
fascinatemtd: driver cleanup
- fascinatemtd has no FFC, remove s5ka3dx driver
- remove device-specific light and accel drivers
(fascinate is the only device using kr3dh anyways)
- also remove unneeded s5k4ecgx include
Change-Id: Ic0f6984b60146141e85aad0a2c16fcd5026d144b
Diffstat (limited to 'drivers/input')
-rwxr-xr-x | drivers/input/misc/Makefile | 7 | ||||
-rwxr-xr-x | drivers/input/misc/gp2a.c | 6 | ||||
-rwxr-xr-x | drivers/input/misc/gp2a_atlas.c | 736 | ||||
-rwxr-xr-x | drivers/input/misc/kr3dh.c | 13 | ||||
-rw-r--r-- | drivers/input/misc/kr3dh_cdma.c | 676 |
5 files changed, 11 insertions, 1427 deletions
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index e4aa0c7..2fcff8a 100755 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -20,15 +20,8 @@ obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o obj-$(CONFIG_INPUT_BMA023) += bma023.o obj-$(CONFIG_INPUT_YAS529) += yas529.o - -ifeq ($(CONFIG_SAMSUNG_FASCINATE),y) -obj-$(CONFIG_INPUT_KR3DH) += kr3dh_cdma.o -obj-$(CONFIG_OPTICAL_GP2A) += gp2a_atlas.o -else obj-$(CONFIG_INPUT_KR3DH) += kr3dh.o obj-$(CONFIG_OPTICAL_GP2A) += gp2a.o -endif - obj-$(CONFIG_INPUT_ORIENTATION) += orientation.o obj-$(CONFIG_INPUT_YAMAHA) += yamaha.o obj-$(CONFIG_INPUT_CM109) += cm109.o diff --git a/drivers/input/misc/gp2a.c b/drivers/input/misc/gp2a.c index 8bd70db..4ea7cde 100755 --- a/drivers/input/misc/gp2a.c +++ b/drivers/input/misc/gp2a.c @@ -382,7 +382,6 @@ static int gp2a_setup_irq(struct gp2a_data *gp2a) return rc; } -#ifndef CONFIG_SAMSUNG_FASCINATE rc = gpio_direction_input(pdata->p_out); if (rc < 0) { pr_err("%s: failed to set gpio %d as input (%d)\n", @@ -391,9 +390,6 @@ static int gp2a_setup_irq(struct gp2a_data *gp2a) } irq = gpio_to_irq(pdata->p_out); -#else - irq = pdata->p_irq; -#endif rc = request_threaded_irq(irq, NULL, gp2a_irq_handler, @@ -419,9 +415,7 @@ static int gp2a_setup_irq(struct gp2a_data *gp2a) goto done; err_request_irq: -#ifndef CONFIG_SAMSUNG_FASCINATE err_gpio_direction_input: -#endif gpio_free(pdata->p_out); done: return rc; diff --git a/drivers/input/misc/gp2a_atlas.c b/drivers/input/misc/gp2a_atlas.c deleted file mode 100755 index 1f65428..0000000 --- a/drivers/input/misc/gp2a_atlas.c +++ /dev/null @@ -1,736 +0,0 @@ -/* linux/driver/input/misc/gp2a.c - * Copyright (C) 2010 Samsung Electronics. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/i2c.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/miscdevice.h> -#include <linux/platform_device.h> -#include <linux/leds.h> -#include <linux/gpio.h> -#include <linux/wakelock.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/workqueue.h> -#include <linux/uaccess.h> -#include <linux/gp2a.h> - - -/* Note about power vs enable/disable: - * The chip has two functions, proximity and ambient light sensing. - * There is no separate power enablement to the two functions (unlike - * the Capella CM3602/3623). - * This module implements two drivers: /dev/proximity and /dev/light. - * When either driver is enabled (via sysfs attributes), we give power - * to the chip. When both are disabled, we remove power from the chip. - * In suspend, we remove power if light is disabled but not if proximity is - * enabled (proximity is allowed to wakeup from suspend). - * - * There are no ioctls for either driver interfaces. Output is via - * input device framework and control via sysfs attributes. - */ - - -#define gp2a_dbgmsg(str, args...) pr_debug("%s: " str, __func__, ##args) - - -#define ADC_BUFFER_NUM 6 - -/* ADDSEL is LOW */ -#define REGS_PROX 0x0 /* Read Only */ -#define REGS_GAIN 0x1 /* Write Only */ -#define REGS_HYS 0x2 /* Write Only */ -#define REGS_CYCLE 0x3 /* Write Only */ -#define REGS_OPMOD 0x4 /* Write Only */ - -/* sensor type */ -#define LIGHT 0 -#define PROXIMITY 1 -#define ALL 2 - -static u8 reg_defaults[5] = { - 0x00, /* PROX: read only register */ - 0x08, /* GAIN: large LED drive level */ - 0x40, /* HYS: receiver sensitivity */ - 0x04, /* CYCLE: */ - 0x01, /* OPMOD: normal operating mode */ -}; - -struct gp2a_data; - -enum { - LIGHT_ENABLED = BIT(0), - PROXIMITY_ENABLED = BIT(1), -}; - -/* driver data */ -struct gp2a_data { - struct input_dev *proximity_input_dev; - struct input_dev *light_input_dev; - struct gp2a_platform_data *pdata; - struct i2c_client *i2c_client; - struct class *lightsensor_class; - struct device *switch_cmd_dev; - int irq; - struct work_struct work_light; - struct hrtimer timer; - ktime_t light_poll_delay; - int adc_value_buf[ADC_BUFFER_NUM]; - int adc_index_count; - bool adc_buf_initialized; - bool on; - u8 power_state; - struct mutex power_lock; - struct wake_lock prx_wake_lock; - struct workqueue_struct *wq; - char val_state; -}; - -int gp2a_i2c_write(struct gp2a_data *gp2a, u8 reg, u8 *val) -{ - int err = 0; - struct i2c_msg msg[1]; - unsigned char data[2]; - int retry = 10; - struct i2c_client *client = gp2a->i2c_client; - - if ((client == NULL) || (!client->adapter)) - return -ENODEV; - - while (retry--) { - data[0] = reg; - data[1] = *val; - - msg->addr = client->addr; - msg->flags = 0; /* write */ - msg->len = 2; - msg->buf = data; - - err = i2c_transfer(client->adapter, msg, 1); - - if (err >= 0) - return 0; - } - return err; -} - -static void gp2a_light_enable(struct gp2a_data *gp2a) -{ - gp2a_dbgmsg("starting poll timer, delay %lldns\n", - ktime_to_ns(gp2a->light_poll_delay)); - hrtimer_start(&gp2a->timer, gp2a->light_poll_delay, HRTIMER_MODE_REL); -} - -static void gp2a_light_disable(struct gp2a_data *gp2a) -{ - gp2a_dbgmsg("cancelling poll timer\n"); - hrtimer_cancel(&gp2a->timer); - cancel_work_sync(&gp2a->work_light); -} - -static ssize_t poll_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - return sprintf(buf, "%lld\n", ktime_to_ns(gp2a->light_poll_delay)); -} - - -static ssize_t poll_delay_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - int64_t new_delay; - int err; - - err = strict_strtoll(buf, 10, &new_delay); - if (err < 0) - return err; - - gp2a_dbgmsg("new delay = %lldns, old delay = %lldns\n", - new_delay, ktime_to_ns(gp2a->light_poll_delay)); - mutex_lock(&gp2a->power_lock); - if (new_delay != ktime_to_ns(gp2a->light_poll_delay)) { - gp2a->light_poll_delay = ns_to_ktime(new_delay); - if (gp2a->power_state & LIGHT_ENABLED) { - gp2a_light_disable(gp2a); - gp2a_light_enable(gp2a); - } - } - mutex_unlock(&gp2a->power_lock); - - return size; -} - -static ssize_t light_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - (gp2a->power_state & LIGHT_ENABLED) ? 1 : 0); -} - -static ssize_t proximity_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0); -} - -static ssize_t light_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - bool new_value; - - if (sysfs_streq(buf, "1")) - new_value = true; - else if (sysfs_streq(buf, "0")) - new_value = false; - else { - pr_err("%s: invalid value %d\n", __func__, *buf); - return -EINVAL; - } - - mutex_lock(&gp2a->power_lock); - gp2a_dbgmsg("new_value = %d, old state = %d\n", - new_value, (gp2a->power_state & LIGHT_ENABLED) ? 1 : 0); - if (new_value && !(gp2a->power_state & LIGHT_ENABLED)) { - if (!gp2a->power_state) - gp2a->pdata->power(true); - gp2a->power_state |= LIGHT_ENABLED; - gp2a_light_enable(gp2a); - } else if (!new_value && (gp2a->power_state & LIGHT_ENABLED)) { - gp2a_light_disable(gp2a); - gp2a->power_state &= ~LIGHT_ENABLED; - if (!gp2a->power_state) - gp2a->pdata->power(false); - } - mutex_unlock(&gp2a->power_lock); - return size; -} - -static ssize_t proximity_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - bool new_value; - - if (sysfs_streq(buf, "1")) - new_value = true; - else if (sysfs_streq(buf, "0")) - new_value = false; - else { - pr_err("%s: invalid value %d\n", __func__, *buf); - return -EINVAL; - } - - mutex_lock(&gp2a->power_lock); - gp2a_dbgmsg("new_value = %d, old state = %d\n", - new_value, (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0); - if (new_value && !(gp2a->power_state & PROXIMITY_ENABLED)) { - if (!gp2a->power_state) - gp2a->pdata->power(true); - gp2a->power_state |= PROXIMITY_ENABLED; - enable_irq(gp2a->irq); - enable_irq_wake(gp2a->irq); - gp2a_i2c_write(gp2a, REGS_GAIN, ®_defaults[1]); - gp2a_i2c_write(gp2a, REGS_HYS, ®_defaults[2]); - gp2a_i2c_write(gp2a, REGS_CYCLE, ®_defaults[3]); - gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[4]); - } else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) { - disable_irq_wake(gp2a->irq); - disable_irq(gp2a->irq); - gp2a_i2c_write(gp2a, REGS_OPMOD, ®_defaults[0]); - gp2a->power_state &= ~PROXIMITY_ENABLED; - if (!gp2a->power_state) - gp2a->pdata->power(false); - } - mutex_unlock(&gp2a->power_lock); - return size; -} - -static DEVICE_ATTR(poll_delay, S_IRUGO | S_IWUSR | S_IWGRP, - poll_delay_show, poll_delay_store); - -static struct device_attribute dev_attr_light_enable = - __ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, - light_enable_show, light_enable_store); - -static struct device_attribute dev_attr_proximity_enable = - __ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, - proximity_enable_show, proximity_enable_store); - -static struct attribute *light_sysfs_attrs[] = { - &dev_attr_light_enable.attr, - &dev_attr_poll_delay.attr, - NULL -}; - -static struct attribute_group light_attribute_group = { - .attrs = light_sysfs_attrs, -}; - -static struct attribute *proximity_sysfs_attrs[] = { - &dev_attr_proximity_enable.attr, - NULL -}; - -static struct attribute_group proximity_attribute_group = { - .attrs = proximity_sysfs_attrs, -}; - -static int lightsensor_get_adcvalue(struct gp2a_data *gp2a) -{ - int i = 0; - int j = 0; - unsigned int adc_total = 0; - int adc_avr_value; - unsigned int adc_index = 0; - unsigned int adc_max = 0; - unsigned int adc_min = 0; - int value = 0; - - /* get ADC */ - value = gp2a->pdata->light_adc_value(); - - adc_index = (gp2a->adc_index_count++) % ADC_BUFFER_NUM; - - /*ADC buffer initialize (light sensor off ---> light sensor on) */ - if (!gp2a->adc_buf_initialized) { - gp2a->adc_buf_initialized = true; - for (j = 0; j < ADC_BUFFER_NUM; j++) - gp2a->adc_value_buf[j] = value; - } else - gp2a->adc_value_buf[adc_index] = value; - - adc_max = gp2a->adc_value_buf[0]; - adc_min = gp2a->adc_value_buf[0]; - - for (i = 0; i < ADC_BUFFER_NUM; i++) { - adc_total += gp2a->adc_value_buf[i]; - - if (adc_max < gp2a->adc_value_buf[i]) - adc_max = gp2a->adc_value_buf[i]; - - if (adc_min > gp2a->adc_value_buf[i]) - adc_min = gp2a->adc_value_buf[i]; - } - adc_avr_value = (adc_total-(adc_max+adc_min))/(ADC_BUFFER_NUM-2); - - if (gp2a->adc_index_count == ADC_BUFFER_NUM-1) - gp2a->adc_index_count = 0; - - return adc_avr_value; -} - -static void gp2a_work_func_light(struct work_struct *work) -{ - struct gp2a_data *gp2a = container_of(work, struct gp2a_data, - work_light); - int adc = lightsensor_get_adcvalue(gp2a); - input_report_abs(gp2a->light_input_dev, ABS_MISC, adc); - input_sync(gp2a->light_input_dev); -} - -/* This function is for light sensor. It operates every a few seconds. - * It asks for work to be done on a thread because i2c needs a thread - * context (slow and blocking) and then reschedules the timer to run again. - */ -static enum hrtimer_restart gp2a_timer_func(struct hrtimer *timer) -{ - struct gp2a_data *gp2a = container_of(timer, struct gp2a_data, timer); - queue_work(gp2a->wq, &gp2a->work_light); - hrtimer_forward_now(&gp2a->timer, gp2a->light_poll_delay); - return HRTIMER_RESTART; -} - -/* interrupt happened due to transition/change of near/far proximity state */ -irqreturn_t gp2a_irq_handler(int irq, void *data) -{ - struct gp2a_data *ip = data; - u8 setting; - int val = gpio_get_value(ip->pdata->p_out); - if (val < 0) { - pr_err("%s: gpio_get_value error %d\n", __func__, val); - return IRQ_HANDLED; - } - - if (val != ip->val_state) { - if (val) - setting = 0x40; - else - setting = 0x20; - gp2a_i2c_write(ip, REGS_HYS, &setting); - } - - ip->val_state = val; - pr_err("gp2a: proximity val = %d\n", val); - - /* 0 is close, 1 is far */ - input_report_abs(ip->proximity_input_dev, ABS_DISTANCE, val); - input_sync(ip->proximity_input_dev); - wake_lock_timeout(&ip->prx_wake_lock, 3*HZ); - - return IRQ_HANDLED; -} - -static int gp2a_setup_irq(struct gp2a_data *gp2a) -{ - int rc = -EIO; - struct gp2a_platform_data *pdata = gp2a->pdata; - int irq; - - gp2a_dbgmsg("start\n"); - - rc = gpio_request(pdata->p_out, "gpio_proximity_out"); - if (rc < 0) { - pr_err("%s: gpio %d request failed (%d)\n", - __func__, pdata->p_out, rc); - return rc; - } - -#ifndef CONFIG_SAMSUNG_FASCINATE - rc = gpio_direction_input(pdata->p_out); - if (rc < 0) { - pr_err("%s: failed to set gpio %d as input (%d)\n", - __func__, pdata->p_out, rc); - goto err_gpio_direction_input; - } - - irq = gpio_to_irq(pdata->p_out); -#else - irq = pdata->p_irq; -#endif - - rc = request_threaded_irq(irq, NULL, - gp2a_irq_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "proximity_int", - gp2a); - if (rc < 0) { - pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n", - __func__, irq, - pdata->p_out, rc); - goto err_request_irq; - } - - /* start with interrupts disabled */ - disable_irq(irq); - gp2a->irq = irq; - - gp2a_dbgmsg("success\n"); - - goto done; - -err_request_irq: -err_gpio_direction_input: - gpio_free(pdata->p_out); -done: - return rc; -} - -static ssize_t lightsensor_file_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gp2a_data *gp2a = dev_get_drvdata(dev); - int adc = 0; - - adc = lightsensor_get_adcvalue(gp2a); - return sprintf(buf, "%d\n", adc); -} - -static DEVICE_ATTR(lightsensor_file_state, 0644, lightsensor_file_state_show, - NULL); - -static const struct file_operations light_fops = { - .owner = THIS_MODULE, -}; - -static struct miscdevice light_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "light", - .fops = &light_fops, -}; - -static int gp2a_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret = -ENODEV; - struct input_dev *input_dev; - struct gp2a_data *gp2a; - struct gp2a_platform_data *pdata = client->dev.platform_data; - - if (!pdata) { - pr_err("%s: missing pdata!\n", __func__); - return ret; - } - if (!pdata->power || !pdata->light_adc_value) { - pr_err("%s: incomplete pdata!\n", __func__); - return ret; - } - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - pr_err("%s: i2c functionality check failed!\n", __func__); - return ret; - } - - gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); - if (!gp2a) { - pr_err("%s: failed to alloc memory for module data\n", - __func__); - return -ENOMEM; - } - - gp2a->pdata = pdata; - gp2a->i2c_client = client; - i2c_set_clientdata(client, gp2a); - - /* wake lock init */ - wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, - "prx_wake_lock"); - mutex_init(&gp2a->power_lock); - - ret = gp2a_setup_irq(gp2a); - if (ret) { - pr_err("%s: could not setup irq\n", __func__); - goto err_setup_irq; - } - - /* allocate proximity input_device */ - input_dev = input_allocate_device(); - if (!input_dev) { - pr_err("%s: could not allocate input device\n", __func__); - goto err_input_allocate_device_proximity; - } - gp2a->proximity_input_dev = input_dev; - input_set_drvdata(input_dev, gp2a); - input_dev->name = "proximity"; - input_set_capability(input_dev, EV_ABS, ABS_DISTANCE); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); - - gp2a_dbgmsg("registering proximity input device\n"); - ret = input_register_device(input_dev); - if (ret < 0) { - pr_err("%s: could not register input device\n", __func__); - input_free_device(input_dev); - goto err_input_register_device_proximity; - } - ret = sysfs_create_group(&input_dev->dev.kobj, - &proximity_attribute_group); - if (ret) { - pr_err("%s: could not create sysfs group\n", __func__); - goto err_sysfs_create_group_proximity; - } - - /* hrtimer settings. we poll for light values using a timer. */ - hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - gp2a->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC); - gp2a->timer.function = gp2a_timer_func; - - /* the timer just fires off a work queue request. we need a thread - to read the i2c (can be slow and blocking). */ - gp2a->wq = create_singlethread_workqueue("gp2a_wq"); - if (!gp2a->wq) { - ret = -ENOMEM; - pr_err("%s: could not create workqueue\n", __func__); - goto err_create_workqueue; - } - /* this is the thread function we run on the work queue */ - INIT_WORK(&gp2a->work_light, gp2a_work_func_light); - - /* allocate lightsensor-level input_device */ - input_dev = input_allocate_device(); - if (!input_dev) { - pr_err("%s: could not allocate input device\n", __func__); - ret = -ENOMEM; - goto err_input_allocate_device_light; - } - input_set_drvdata(input_dev, gp2a); - input_dev->name = "lightsensor-level"; - input_set_capability(input_dev, EV_ABS, ABS_MISC); - input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0); - - gp2a_dbgmsg("registering lightsensor-level input device\n"); - ret = input_register_device(input_dev); - if (ret < 0) { - pr_err("%s: could not register input device\n", __func__); - input_free_device(input_dev); - goto err_input_register_device_light; - } - gp2a->light_input_dev = input_dev; - ret = sysfs_create_group(&input_dev->dev.kobj, - &light_attribute_group); - if (ret) { - pr_err("%s: could not create sysfs group\n", __func__); - goto err_sysfs_create_group_light; - } - - /* set sysfs for light sensor */ - - ret = misc_register(&light_device); - if (ret) - pr_err(KERN_ERR "misc_register failed - light\n"); - - gp2a->lightsensor_class = class_create(THIS_MODULE, "lightsensor"); - if (IS_ERR(gp2a->lightsensor_class)) - pr_err("Failed to create class(lightsensor)!\n"); - - gp2a->switch_cmd_dev = device_create(gp2a->lightsensor_class, - NULL, 0, NULL, "switch_cmd"); - if (IS_ERR(gp2a->switch_cmd_dev)) - pr_err("Failed to create device(switch_cmd_dev)!\n"); - - if (device_create_file(gp2a->switch_cmd_dev, - &dev_attr_lightsensor_file_state) < 0) - pr_err("Failed to create device file(%s)!\n", - dev_attr_lightsensor_file_state.attr.name); - - dev_set_drvdata(gp2a->switch_cmd_dev, gp2a); - -#ifdef CONFIG_ARIES_NTT - /* set initial proximity value as 1 */ - input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); - input_sync(gp2a->proximity_input_dev); -#else - /* set initial proximity value as 1 */ - input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); - input_sync(gp2a->proximity_input_dev); -#endif - goto done; - - /* error, unwind it all */ -err_sysfs_create_group_light: - input_unregister_device(gp2a->light_input_dev); -err_input_register_device_light: -err_input_allocate_device_light: - destroy_workqueue(gp2a->wq); -err_create_workqueue: - sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, - &proximity_attribute_group); -err_sysfs_create_group_proximity: - input_unregister_device(gp2a->proximity_input_dev); -err_input_register_device_proximity: -err_input_allocate_device_proximity: - free_irq(gp2a->irq, 0); - gpio_free(gp2a->pdata->p_out); -err_setup_irq: - mutex_destroy(&gp2a->power_lock); - wake_lock_destroy(&gp2a->prx_wake_lock); - kfree(gp2a); -done: - return ret; -} - -static int gp2a_suspend(struct device *dev) -{ - /* We disable power only if proximity is disabled. If proximity - is enabled, we leave power on because proximity is allowed - to wake up device. We remove power without changing - gp2a->power_state because we use that state in resume. - */ - struct i2c_client *client = to_i2c_client(dev); - struct gp2a_data *gp2a = i2c_get_clientdata(client); - if (gp2a->power_state & LIGHT_ENABLED) - gp2a_light_disable(gp2a); - if (gp2a->power_state == LIGHT_ENABLED) - gp2a->pdata->power(false); - return 0; -} - -static int gp2a_resume(struct device *dev) -{ - /* Turn power back on if we were before suspend. */ - struct i2c_client *client = to_i2c_client(dev); - struct gp2a_data *gp2a = i2c_get_clientdata(client); - if (gp2a->power_state == LIGHT_ENABLED) - gp2a->pdata->power(true); - if (gp2a->power_state & LIGHT_ENABLED) - gp2a_light_enable(gp2a); - return 0; -} - -static int gp2a_i2c_remove(struct i2c_client *client) -{ - struct gp2a_data *gp2a = i2c_get_clientdata(client); - sysfs_remove_group(&gp2a->light_input_dev->dev.kobj, - &light_attribute_group); - input_unregister_device(gp2a->light_input_dev); - sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, - &proximity_attribute_group); - input_unregister_device(gp2a->proximity_input_dev); - free_irq(gp2a->irq, NULL); - gpio_free(gp2a->pdata->p_out); - if (gp2a->power_state) { - if (gp2a->power_state & LIGHT_ENABLED) - gp2a_light_disable(gp2a); - gp2a->pdata->power(false); - } - destroy_workqueue(gp2a->wq); - mutex_destroy(&gp2a->power_lock); - wake_lock_destroy(&gp2a->prx_wake_lock); - kfree(gp2a); - return 0; -} - -static const struct i2c_device_id gp2a_device_id[] = { - {"gp2a", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, gp2a_device_id); - -static const struct dev_pm_ops gp2a_pm_ops = { - .suspend = gp2a_suspend, - .resume = gp2a_resume -}; - -static struct i2c_driver gp2a_i2c_driver = { - .driver = { - .name = "gp2a", - .owner = THIS_MODULE, - .pm = &gp2a_pm_ops - }, - .probe = gp2a_i2c_probe, - .remove = gp2a_i2c_remove, - .id_table = gp2a_device_id, -}; - - -static int __init gp2a_init(void) -{ - return i2c_add_driver(&gp2a_i2c_driver); -} - -static void __exit gp2a_exit(void) -{ - i2c_del_driver(&gp2a_i2c_driver); -} - -module_init(gp2a_init); -module_exit(gp2a_exit); - -MODULE_AUTHOR("mjchen@sta.samsung.com"); -MODULE_DESCRIPTION("Optical Sensor driver for gp2ap002a00f"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/kr3dh.c b/drivers/input/misc/kr3dh.c index bb6555a..6299b4e 100755 --- a/drivers/input/misc/kr3dh.c +++ b/drivers/input/misc/kr3dh.c @@ -304,7 +304,12 @@ static int kr3dh_measure(struct kr3dh_data *kr3dh, struct acceleration *accel) value += kr3dh_position_map[pos][i][j] * (int)raw[j]; } /* normalisation*/ - g = (long long)value * GRAVITY_EARTH / KR3DH_RESOLUTION; + // here we want to report a range of -512 .. 512, corresponding to -2g .. 2g + // 'value' is between -32768 .. 32768, corresponding also to -2g .. 2g + // so .. trim off the 6 lower bits and we should be good. + g = value >> 6; + + //g = (long long)value * GRAVITY_EARTH / KR3DH_RESOLUTION; accel->axis[i] = g; } @@ -407,7 +412,8 @@ static ssize_t kr3dh_enable_store(struct device *dev, static ssize_t kr3dh_delay_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", kr3dh_get_delay(dev)); + /* delay is "displayed" here as ms, but we have stored it as ns */ + return sprintf(buf, "%d\n", kr3dh_get_delay(dev) / 1000000 ); } static ssize_t kr3dh_delay_store(struct device *dev, @@ -415,6 +421,9 @@ static ssize_t kr3dh_delay_store(struct device *dev, const char *buf, size_t count) { unsigned long delay = simple_strtoul(buf, NULL, 10); + + /* delay comes in here as miliseconds, but the system wants it as nanoseconds */ + delay *= 1000000; kr3dh_set_delay(dev, delay); diff --git a/drivers/input/misc/kr3dh_cdma.c b/drivers/input/misc/kr3dh_cdma.c deleted file mode 100644 index d96f9f8..0000000 --- a/drivers/input/misc/kr3dh_cdma.c +++ /dev/null @@ -1,676 +0,0 @@ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/input.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/mutex.h> -#include <linux/types.h> -#include <linux/workqueue.h> -#include <linux/uaccess.h> -#include <linux/delay.h> -#include <linux/completion.h> -#include "kr3dh_reg.h" - - - -#define TRACE_FUNC() pr_info(KR3DH_NAME ": <trace> %s()\n", __FUNCTION__) - -/* The default settings when sensor is on is for all 3 axis to be enabled - * and output data rate set to 400Hz. Output is via a ioctl read call. -*/ -#define DEFAULT_POWER_ON_SETTING (ODR400 | ENABLE_ALL_AXES) -#define READ_REPEAT_SHIFT 3 -#define READ_REPEAT (1 << READ_REPEAT_SHIFT) - -#define DEVICE_ID (0x32) -#define KR3DH_NAME "kr3dh" -#define KR3DH_RESOLUTION 16384 /* [count/G] */ -#define GRAVITY_EARTH 9806650 -#define ABSMIN_2G (-GRAVITY_EARTH * 2) -#define ABSMAX_2G (GRAVITY_EARTH * 2) - - - -static const struct odr_delay { - u8 odr; /* odr reg setting */ - s64 delay; /* odr in ns */ -}kr3dh_odr_table [] = { - { ODR400, 2500000LL }, /* 400Hz */ - { ODR100, 10000000LL }, /* 100Hz */ - { ODR50, 20000000LL }, /* 50Hz */ - { ODR10, 100000000LL }, /* 10Hz */ - { ODR5, 200000000LL }, /* 5Hz */ - { ODR2, 500000000LL }, /* 2Hz */ - { ODR1, 1000000000LL }, /* 1Hz */ - { ODRHALF, 2000000000LL }, /* 0.5Hz */ -}; - -#define event_delay(s) (delay_to_jiffies(((s) / (1000 * 1000)))) -#define delay_to_jiffies(d) ((d)?msecs_to_jiffies(d):1) -#define actual_delay(d) (jiffies_to_msecs(delay_to_jiffies(d))) - - -/* KR3DM acceleration data */ -struct acceleration { - int axis[3]; -}; - -/* - * driver private data - */ -struct kr3dh_data { - atomic_t enable; /* attribute value */ - atomic_t delay; /* attribute value */ - atomic_t position; /* attribute value */ - u8 ctrl_reg1_shadow; - struct acceleration last; /* last measured data */ - struct mutex enable_mutex; - struct mutex data_mutex; - struct i2c_client *client; - struct input_dev *input; - struct delayed_work work; -}; - - -/* - * Transformation matrix for chip mounting position - */ -static const int kr3dh_position_map[][3][3] = { - {{ 0, -1, 0}, { 1, 0, 0}, { 0, 0, 1}}, /* top/upper-left */ - {{ 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1}}, /* top/upper-right */ - {{ 0, 1, 0}, {-1, 0, 0}, { 0, 0, 1}}, /* top/lower-right */ - {{-1, 0, 0}, { 0, -1, 0}, { 0, 0, 1}}, /* top/lower-left */ - {{ 0, 1, 0}, { 1, 0, 0}, { 0, 0, -1}}, /* bottom/upper-right */ - {{-1, 0, 0}, { 0, 1, 0}, { 0, 0, -1}}, /* bottom/upper-left */ - {{ 0, -1, 0}, {-1, 0, 0}, { 0, 0, -1}}, /* bottom/lower-left */ - {{ 1, 0, 0}, { 0, -1, 0}, { 0, 0, -1}}, /* bottom/lower-right */ -}; - - - -static int kr3dh_power_down(struct kr3dh_data *kr3dh) -{ - int res = 0; - - res = i2c_smbus_write_byte_data(kr3dh->client, - CTRL_REG1, PM_OFF); - - res = i2c_smbus_write_byte_data(kr3dh->client, - CTRL_REG5, 0x00); - - return res; -} - -static int kr3dh_power_up(struct kr3dh_data *kr3dh) -{ - int res = 0; - - res = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG1, - kr3dh->ctrl_reg1_shadow); - - res = i2c_smbus_write_byte_data(kr3dh->client, - CTRL_REG5, 0x03); - - return res; - -} - -static int kr3dh_measure(struct kr3dh_data *kr3dh, struct acceleration *accel); - -static int kr3dh_hw_init(struct kr3dh_data *kr3dh) -{ - int err = 0; - - kr3dh->ctrl_reg1_shadow = DEFAULT_POWER_ON_SETTING; - err = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG1, - DEFAULT_POWER_ON_SETTING); - if (err) { - pr_err("kr3dh_hw_init() i2c write ctrl_reg1 failed\n"); - } - - /* Disables Filters */ - err = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG2,0x00); - if (err) { - pr_err("kr3dh_hw_init() i2c write ctrl_reg2 failed\n"); - } - - /* Disable Interrupts */ - err = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG3,0x00); - if (err) { - pr_err("kr3dh_hw_init() i2c write ctrl_reg3 failed\n"); - } - - /* Non Continous mode, Little Endian, 2G Range */ - err = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG4,0x80); - if (err) { - pr_err("kr3dh_hw_init() i2c write ctrl_reg4 failed\n"); - } - - /* Sleep to Wake: TurnON */ - err = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG5,0x03); - if (err) { - pr_err("kr3dh_hw_init() i2c write ctrl_reg5 failed\n"); - } - - return err; -} - -static int kr3dh_get_enable(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - - return atomic_read(&kr3dh->enable); - -} - -static void kr3dh_set_enable(struct device *dev, int enable) -{ - struct i2c_client *client = to_i2c_client(dev); - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - int delay = atomic_read(&kr3dh->delay); - - mutex_lock(&kr3dh->enable_mutex); - - if (enable) { /* enable if state will be changed */ - if (!atomic_cmpxchg(&kr3dh->enable, 0, 1)) { - kr3dh_power_up(kr3dh); - schedule_delayed_work(&kr3dh->work, - event_delay(delay) + 1); - } - } else { /* disable if state will be changed */ - if (atomic_cmpxchg(&kr3dh->enable, 1, 0)) { - cancel_delayed_work_sync(&kr3dh->work); - kr3dh_power_down(kr3dh); - } - } - atomic_set(&kr3dh->enable, enable); - - mutex_unlock(&kr3dh->enable_mutex); - -} - -static int kr3dh_get_delay(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - - return atomic_read(&kr3dh->delay); -} - -static void kr3dh_set_delay(struct device *dev, s64 delay) -{ - struct i2c_client *client = to_i2c_client(dev); - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - u8 odr_value; - int i, res = 0; - unsigned long delay_ms = 0; - - /* determine optimum ODR */ - for (i = 1; (i < ARRAY_SIZE(kr3dh_odr_table)) && - (delay >= kr3dh_odr_table[i].delay); i++) - ; - odr_value = kr3dh_odr_table[i-1].odr; - atomic_set(&kr3dh->delay, delay); - - mutex_lock(&kr3dh->enable_mutex); - - if (kr3dh_get_enable(dev)) { - cancel_delayed_work_sync(&kr3dh->work); - if (odr_value != (kr3dh->ctrl_reg1_shadow & ODR_MASK)) { - u8 ctrl = (kr3dh->ctrl_reg1_shadow & ~ODR_MASK); - ctrl |= odr_value; - kr3dh->ctrl_reg1_shadow = ctrl; - res = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG1, ctrl); - printk("writing odr value 0x%x\n", odr_value); - } - delay_ms = delay ; - delay_ms = delay_ms / 1000; - delay_ms = delay_ms / 1000; - - schedule_delayed_work(&kr3dh->work, - delay_to_jiffies(delay_ms) + 1); - } else { - kr3dh_power_up(kr3dh); - if (odr_value != (kr3dh->ctrl_reg1_shadow & ODR_MASK)) { - u8 ctrl = (kr3dh->ctrl_reg1_shadow & ~ODR_MASK); - ctrl |= odr_value; - kr3dh->ctrl_reg1_shadow = ctrl; - res = i2c_smbus_write_byte_data(kr3dh->client, CTRL_REG1, ctrl); - printk("writing odr value 0x%x\n", odr_value); - } - - kr3dh_power_down(kr3dh); - } - - mutex_unlock(&kr3dh->enable_mutex); -} - -static int kr3dh_set_position(struct device *dev, int position) -{ - struct i2c_client *client = to_i2c_client(dev); - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - - return atomic_set(&kr3dh->position, position); - -} - -static int kr3dh_get_position(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - - return atomic_read(&kr3dh->position); - -} -int kr3dh_i2c_byte_read(struct i2c_client *client, u8 command) -{ - union i2c_smbus_data data; - int status; - - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BYTE_DATA, &data); - if (status < 0) { - pr_err("I2C read error: acceleration not read\n"); - } - return (status < 0) ? status : data.byte; -} - -static int kr3dh_measure(struct kr3dh_data *kr3dh, struct acceleration *accel) -{ - int i =0; - int j = 0; - int value; - int pos = (int)atomic_read(&kr3dh->position); - unsigned char buf[6] = {0}; - short int raw[3] = {0}; - long long g; - - for (i = 0; i < 6; i++) { - buf[i] = kr3dh_i2c_byte_read(kr3dh->client, AXISDATA_REG + i); - } - for (i = 0; i < 3; i++) { - raw[i] = (unsigned short)(buf[i*2+1]<<8) + (unsigned short)buf[i*2]; - } - for (i = 0; i < 3; i++) { - value = 0; - for (j = 0; j < 3; j++) { - value += kr3dh_position_map[pos][i][j] * (int)raw[j]; - } - /* normalisation*/ - // here we want to report a range of -512 .. 512, corresponding to -2g .. 2g - // 'value' is between -32768 .. 32768, corresponding also to -2g .. 2g - // so .. trim off the 6 lower bits and we should be good. - g = value >> 6; - - //g = (long long)value * GRAVITY_EARTH / KR3DH_RESOLUTION; - accel->axis[i] = g; - } - - return 0; -} - -static void kr3dh_work_func(struct work_struct *work) -{ - struct kr3dh_data *kr3dh = container_of((struct delayed_work *)work, - struct kr3dh_data, work); - struct acceleration accel; - unsigned long delay = event_delay(atomic_read(&kr3dh->delay)); - - kr3dh_measure(kr3dh, &accel); - - input_report_rel(kr3dh->input, REL_X, accel.axis[0]); - input_report_rel(kr3dh->input, REL_Y, accel.axis[1]); - input_report_rel(kr3dh->input, REL_Z, accel.axis[2]); - input_sync(kr3dh->input); - - mutex_lock(&kr3dh->data_mutex); - kr3dh->last = accel; - mutex_unlock(&kr3dh->data_mutex); - - schedule_delayed_work(&kr3dh->work, delay); - -} - -/* - * Input device interface - */ -static int kr3dh_input_init(struct i2c_client *client, struct kr3dh_data *kr3dh) -{ - struct input_dev *dev; - int err; - - dev = input_allocate_device(); - if (!dev) { - return -ENOMEM; - } - dev->name = "accelerometer_sensor"; - dev->id.bustype = BUS_I2C; - - /* X */ - input_set_capability(dev, EV_REL, REL_X); - input_set_abs_params(dev, REL_X, ABSMIN_2G, ABSMAX_2G, 0, 0); - /* Y */ - input_set_capability(dev, EV_REL, REL_Y); - input_set_abs_params(dev, REL_Y, ABSMIN_2G, ABSMAX_2G, 0, 0); - /* Z */ - input_set_capability(dev, EV_REL, REL_Z); - input_set_abs_params(dev, REL_Z, ABSMIN_2G, ABSMAX_2G, 0, 0); - input_set_drvdata(dev, kr3dh); - dev->dev.parent = &client->dev; - - err = input_register_device(dev); - if (err < 0) { - input_free_device(dev); - return err; - } - kr3dh->input = dev; - - return 0; - -} - -static void kr3dh_input_fini(struct kr3dh_data *kr3dh) -{ - struct input_dev *dev = kr3dh->input; - - input_unregister_device(dev); - input_free_device(dev); - -} - -/* - * sysfs device attributes - */ - -static ssize_t kr3dh_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", kr3dh_get_enable(dev)); -} - -static ssize_t kr3dh_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long enable = simple_strtoul(buf, NULL, 10); - - if ((enable == 0) || (enable == 1)) { - kr3dh_set_enable(dev, enable); - } - - return count; - -} - -static ssize_t kr3dh_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - /* delay is "displayed" here as ms, but we have stored it as ns */ - return sprintf(buf, "%d\n", kr3dh_get_delay(dev) / 1000000 ); -} - -static ssize_t kr3dh_delay_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long delay = simple_strtoul(buf, NULL, 10); - - /* delay comes in here as miliseconds, but the system wants it as nanoseconds */ - delay *= 1000000; - - kr3dh_set_delay(dev, delay); - - return count; -} - -static ssize_t kr3dh_position_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", kr3dh_get_position(dev)); -} - -static ssize_t kr3dh_position_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long position; - - position = simple_strtoul(buf, NULL,10); - if ((position >= 0) && (position <= 7)) { - kr3dh_set_position(dev, position); - } - - return count; -} - -static ssize_t kr3dh_wake_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct input_dev *input = to_input_dev(dev); - static atomic_t serial = ATOMIC_INIT(0); - - input_report_abs(input, ABS_MISC, atomic_inc_return(&serial)); - - return count; - -} - -static ssize_t kr3dh_data_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct input_dev *input = to_input_dev(dev); - struct kr3dh_data *kr3dh = input_get_drvdata(input); - struct acceleration accel; - - mutex_lock(&kr3dh->data_mutex); - accel = kr3dh->last; - mutex_unlock(&kr3dh->data_mutex); - - return sprintf(buf, "%d %d %d\n", accel.axis[0], accel.axis[1], accel.axis[2]); -} - -static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP, - kr3dh_enable_show, kr3dh_enable_store); -static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR|S_IWGRP, - kr3dh_delay_show, kr3dh_delay_store); -static DEVICE_ATTR(position, S_IRUGO|S_IWUSR, - kr3dh_position_show, kr3dh_position_store); -static DEVICE_ATTR(wake, S_IWUSR|S_IWGRP, - NULL, kr3dh_wake_store); -static DEVICE_ATTR(data, S_IRUGO, - kr3dh_data_show, NULL); - -static struct attribute *kr3dh_attributes[] = { - &dev_attr_enable.attr, - &dev_attr_delay.attr, - &dev_attr_position.attr, - &dev_attr_wake.attr, - &dev_attr_data.attr, - NULL -}; - -static struct attribute_group kr3dh_attribute_group = { - .attrs = kr3dh_attributes -}; - - -static int kr3dh_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - int ret = 0; - int err = 0; - /* read chip id */ - ret = i2c_smbus_read_byte_data(client, WHO_AM_I); - - printk("KR3DH: DEVICE_ID -> %x\n", ret); - if (ret != DEVICE_ID) { - if (ret < 0) { - pr_err("%s: i2c for reading chip id failed\n", - __func__); - err = ret; - } else { - pr_err("%s : Device identification failed\n", - __func__); - err = -ENODEV; - } - } - return err; -} - -static int kr3dh_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct kr3dh_data *kr3dh; - int err; - - /* setup private data */ - kr3dh = kzalloc(sizeof(struct kr3dh_data), GFP_KERNEL); - if (!kr3dh) { - err = -ENOMEM; - goto error_0; - } - mutex_init(&kr3dh->enable_mutex); - mutex_init(&kr3dh->data_mutex); - - /* setup i2c client */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA | - I2C_FUNC_SMBUS_READ_BYTE_DATA)) - { - err = -ENODEV; - goto error_1; - } - i2c_set_clientdata(client, kr3dh); - kr3dh->client = client; - - /* detect and init hardware */ - if ((err = kr3dh_detect(client, NULL))) { - goto error_1; - } - dev_info(&client->dev, "%s found\n", id->name); - - kr3dh_hw_init(kr3dh); - kr3dh_set_delay(&client->dev, 20000000LL); - kr3dh_set_position(&client->dev, 2); - - /* setup driver interfaces */ - INIT_DELAYED_WORK(&kr3dh->work, kr3dh_work_func); - - err = kr3dh_input_init(client, kr3dh); - if (err < 0) { - goto error_1; - } - - err = sysfs_create_group(&kr3dh->input->dev.kobj, &kr3dh_attribute_group); - if (err < 0) { - goto error_2; - } - - return 0; - -error_2: - kr3dh_input_fini(kr3dh); -error_1: - kfree(kr3dh); -error_0: - return err; - - - -} - -static int kr3dh_remove(struct i2c_client *client) -{ - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - - kr3dh_set_enable(&client->dev, 0); - - sysfs_remove_group(&kr3dh->input->dev.kobj, &kr3dh_attribute_group); - kr3dh_input_fini(kr3dh); - kfree(kr3dh); - - return 0; -} - -static int kr3dh_suspend(struct i2c_client *client, pm_message_t mesg) -{ - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - - TRACE_FUNC(); - - mutex_lock(&kr3dh->enable_mutex); - - if (kr3dh_get_enable(&client->dev)) { - cancel_delayed_work_sync(&kr3dh->work); - kr3dh_power_down(kr3dh); - } - mutex_unlock(&kr3dh->enable_mutex); - - return 0; -} - -static int kr3dh_resume(struct i2c_client *client) -{ - struct kr3dh_data *kr3dh = i2c_get_clientdata(client); - int delay = atomic_read(&kr3dh->delay); - - TRACE_FUNC(); - - kr3dh_hw_init(kr3dh); - kr3dh_set_delay(&client->dev, delay); - - mutex_lock(&kr3dh->enable_mutex); - - if (kr3dh_get_enable(&client->dev)) { - kr3dh_power_up(kr3dh); - schedule_delayed_work(&kr3dh->work, - event_delay(delay) + 1); - } - mutex_unlock(&kr3dh->enable_mutex); - return 0; -} - -static const struct i2c_device_id kr3dh_id[] = { - {KR3DH_NAME, 0}, - {}, -}; - -MODULE_DEVICE_TABLE(i2c, kr3dh_id); - -struct i2c_driver kr3dh_driver ={ - .driver = { - .name = "kr3dh", - .owner = THIS_MODULE, - }, - .probe = kr3dh_probe, - .remove = kr3dh_remove, - .suspend = kr3dh_suspend, - .resume = kr3dh_resume, - .id_table = kr3dh_id, -}; - -/* - * Module init and exit - */ -static int __init kr3dh_init(void) -{ - return i2c_add_driver(&kr3dh_driver); -} -module_init(kr3dh_init); - -static void __exit kr3dh_exit(void) -{ - i2c_del_driver(&kr3dh_driver); -} -module_exit(kr3dh_exit); - -MODULE_AUTHOR("Samsung"); -MODULE_DESCRIPTION("KR3DH 3 axis accelerometer driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0.0"); - |