aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/misc/ad714x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/misc/ad714x.c')
-rw-r--r--drivers/input/misc/ad714x.c253
1 files changed, 83 insertions, 170 deletions
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c
index c431d09e401..7a61e9ee682 100644
--- a/drivers/input/misc/ad714x.c
+++ b/drivers/input/misc/ad714x.c
@@ -1,17 +1,17 @@
/*
* AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A
*
- * Copyright 2009 Analog Devices Inc.
+ * Copyright 2009-2011 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#include <linux/device.h>
-#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/input/ad714x.h>
+#include <linux/module.h>
#include "ad714x.h"
#define AD714X_PWR_CTRL 0x0
@@ -59,7 +59,6 @@
#define STAGE11_AMBIENT 0x27D
#define PER_STAGE_REG_NUM 36
-#define STAGE_NUM 12
#define STAGE_CFGREG_NUM 8
#define SYS_CFGREG_NUM 8
@@ -79,13 +78,7 @@ struct ad714x_slider_drv {
struct ad714x_wheel_drv {
int abs_pos;
int flt_pos;
- int pre_mean_value;
int pre_highest_stage;
- int pre_mean_value_no_offset;
- int mean_value;
- int mean_value_no_offset;
- int pos_offset;
- int pos_ratio;
int highest_stage;
enum ad714x_device_state state;
struct input_dev *input;
@@ -130,27 +123,6 @@ struct ad714x_driver_data {
* information to integrate all things which will be private data
* of spi/i2c device
*/
-struct ad714x_chip {
- unsigned short h_state;
- unsigned short l_state;
- unsigned short c_state;
- unsigned short adc_reg[STAGE_NUM];
- unsigned short amb_reg[STAGE_NUM];
- unsigned short sensor_val[STAGE_NUM];
-
- struct ad714x_platform_data *hw;
- struct ad714x_driver_data *sw;
-
- int irq;
- struct device *dev;
- ad714x_read_t read;
- ad714x_write_t write;
-
- struct mutex mutex;
-
- unsigned product;
- unsigned version;
-};
static void ad714x_use_com_int(struct ad714x_chip *ad714x,
int start_stage, int end_stage)
@@ -158,15 +130,15 @@ static void ad714x_use_com_int(struct ad714x_chip *ad714x,
unsigned short data;
unsigned short mask;
- mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage);
+ mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);
- ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
- data |= 1 << start_stage;
- ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
+ ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1);
+ data |= 1 << end_stage;
+ ad714x->write(ad714x, STG_COM_INT_EN_REG, data);
- ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
+ ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1);
data &= ~mask;
- ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
+ ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data);
}
static void ad714x_use_thr_int(struct ad714x_chip *ad714x,
@@ -175,15 +147,15 @@ static void ad714x_use_thr_int(struct ad714x_chip *ad714x,
unsigned short data;
unsigned short mask;
- mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage);
+ mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);
- ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
- data &= ~(1 << start_stage);
- ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
+ ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1);
+ data &= ~(1 << end_stage);
+ ad714x->write(ad714x, STG_COM_INT_EN_REG, data);
- ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
+ ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1);
data |= mask;
- ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
+ ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data);
}
static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x,
@@ -279,15 +251,16 @@ static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
int i;
+ ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage,
+ &ad714x->adc_reg[hw->start_stage],
+ hw->end_stage - hw->start_stage + 1);
+
for (i = hw->start_stage; i <= hw->end_stage; i++) {
- ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
- &ad714x->adc_reg[i]);
- ad714x->read(ad714x->dev,
- STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
- &ad714x->amb_reg[i]);
-
- ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] -
- ad714x->amb_reg[i]);
+ ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
+ &ad714x->amb_reg[i], 1);
+
+ ad714x->sensor_val[i] =
+ abs(ad714x->adc_reg[i] - ad714x->amb_reg[i]);
}
}
@@ -404,7 +377,6 @@ static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx)
ad714x_slider_cal_highest_stage(ad714x, idx);
ad714x_slider_cal_abs_pos(ad714x, idx);
ad714x_slider_cal_flt_pos(ad714x, idx);
-
input_report_abs(sw->input, ABS_X, sw->flt_pos);
input_report_key(sw->input, BTN_TOUCH, 1);
} else {
@@ -451,15 +423,16 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
int i;
+ ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage,
+ &ad714x->adc_reg[hw->start_stage],
+ hw->end_stage - hw->start_stage + 1);
+
for (i = hw->start_stage; i <= hw->end_stage; i++) {
- ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
- &ad714x->adc_reg[i]);
- ad714x->read(ad714x->dev,
- STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
- &ad714x->amb_reg[i]);
+ ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
+ &ad714x->amb_reg[i], 1);
if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
- ad714x->sensor_val[i] = ad714x->adc_reg[i] -
- ad714x->amb_reg[i];
+ ad714x->sensor_val[i] =
+ ad714x->adc_reg[i] - ad714x->amb_reg[i];
else
ad714x->sensor_val[i] = 0;
}
@@ -468,104 +441,41 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
/*
* When the scroll wheel is activated, we compute the absolute position based
* on the sensor values. To calculate the position, we first determine the
- * sensor that has the greatest response among the 8 sensors that constitutes
- * the scrollwheel. Then we determined the 2 sensors on either sides of the
+ * sensor that has the greatest response among the sensors that constitutes
+ * the scrollwheel. Then we determined the sensors on either sides of the
* sensor with the highest response and we apply weights to these sensors. The
- * result of this computation gives us the mean value which defined by the
- * following formula:
- * For i= second_before_highest_stage to i= second_after_highest_stage
- * v += Sensor response(i)*WEIGHT*(i+3)
- * w += Sensor response(i)
- * Mean_Value=v/w
- * pos_on_scrollwheel = (Mean_Value - position_offset) / position_ratio
+ * result of this computation gives us the mean value.
*/
-#define WEIGHT_FACTOR 30
-/* This constant prevents the "PositionOffset" from reaching a big value */
-#define OFFSET_POSITION_CLAMP 120
static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
{
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
int stage_num = hw->end_stage - hw->start_stage + 1;
- int second_before, first_before, highest, first_after, second_after;
+ int first_before, highest, first_after;
int a_param, b_param;
- /* Calculate Mean value */
-
- second_before = (sw->highest_stage + stage_num - 2) % stage_num;
first_before = (sw->highest_stage + stage_num - 1) % stage_num;
highest = sw->highest_stage;
first_after = (sw->highest_stage + stage_num + 1) % stage_num;
- second_after = (sw->highest_stage + stage_num + 2) % stage_num;
-
- if (((sw->highest_stage - hw->start_stage) > 1) &&
- ((hw->end_stage - sw->highest_stage) > 1)) {
- a_param = ad714x->sensor_val[second_before] *
- (second_before - hw->start_stage + 3) +
- ad714x->sensor_val[first_before] *
- (second_before - hw->start_stage + 3) +
- ad714x->sensor_val[highest] *
- (second_before - hw->start_stage + 3) +
- ad714x->sensor_val[first_after] *
- (first_after - hw->start_stage + 3) +
- ad714x->sensor_val[second_after] *
- (second_after - hw->start_stage + 3);
- } else {
- a_param = ad714x->sensor_val[second_before] *
- (second_before - hw->start_stage + 1) +
- ad714x->sensor_val[first_before] *
- (second_before - hw->start_stage + 2) +
- ad714x->sensor_val[highest] *
- (second_before - hw->start_stage + 3) +
- ad714x->sensor_val[first_after] *
- (first_after - hw->start_stage + 4) +
- ad714x->sensor_val[second_after] *
- (second_after - hw->start_stage + 5);
- }
- a_param *= WEIGHT_FACTOR;
- b_param = ad714x->sensor_val[second_before] +
+ a_param = ad714x->sensor_val[highest] *
+ (highest - hw->start_stage) +
+ ad714x->sensor_val[first_before] *
+ (highest - hw->start_stage - 1) +
+ ad714x->sensor_val[first_after] *
+ (highest - hw->start_stage + 1);
+ b_param = ad714x->sensor_val[highest] +
ad714x->sensor_val[first_before] +
- ad714x->sensor_val[highest] +
- ad714x->sensor_val[first_after] +
- ad714x->sensor_val[second_after];
-
- sw->pre_mean_value = sw->mean_value;
- sw->mean_value = a_param / b_param;
-
- /* Calculate the offset */
-
- if ((sw->pre_highest_stage == hw->end_stage) &&
- (sw->highest_stage == hw->start_stage))
- sw->pos_offset = sw->mean_value;
- else if ((sw->pre_highest_stage == hw->start_stage) &&
- (sw->highest_stage == hw->end_stage))
- sw->pos_offset = sw->pre_mean_value;
-
- if (sw->pos_offset > OFFSET_POSITION_CLAMP)
- sw->pos_offset = OFFSET_POSITION_CLAMP;
-
- /* Calculate the mean value without the offset */
-
- sw->pre_mean_value_no_offset = sw->mean_value_no_offset;
- sw->mean_value_no_offset = sw->mean_value - sw->pos_offset;
- if (sw->mean_value_no_offset < 0)
- sw->mean_value_no_offset = 0;
-
- /* Calculate ratio to scale down to NUMBER_OF_WANTED_POSITIONS */
-
- if ((sw->pre_highest_stage == hw->end_stage) &&
- (sw->highest_stage == hw->start_stage))
- sw->pos_ratio = (sw->pre_mean_value_no_offset * 100) /
- hw->max_coord;
- else if ((sw->pre_highest_stage == hw->start_stage) &&
- (sw->highest_stage == hw->end_stage))
- sw->pos_ratio = (sw->mean_value_no_offset * 100) /
- hw->max_coord;
- sw->abs_pos = (sw->mean_value_no_offset * 100) / sw->pos_ratio;
+ ad714x->sensor_val[first_after];
+
+ sw->abs_pos = ((hw->max_coord / (hw->end_stage - hw->start_stage)) *
+ a_param) / b_param;
+
if (sw->abs_pos > hw->max_coord)
sw->abs_pos = hw->max_coord;
+ else if (sw->abs_pos < 0)
+ sw->abs_pos = 0;
}
static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
@@ -639,9 +549,8 @@ static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx)
ad714x_wheel_cal_highest_stage(ad714x, idx);
ad714x_wheel_cal_abs_pos(ad714x, idx);
ad714x_wheel_cal_flt_pos(ad714x, idx);
-
input_report_abs(sw->input, ABS_WHEEL,
- sw->abs_pos);
+ sw->flt_pos);
input_report_key(sw->input, BTN_TOUCH, 1);
} else {
/* When the user lifts off the sensor, configure
@@ -668,15 +577,16 @@ static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
int i;
+ ad714x->read(ad714x, CDC_RESULT_S0 + hw->x_start_stage,
+ &ad714x->adc_reg[hw->x_start_stage],
+ hw->x_end_stage - hw->x_start_stage + 1);
+
for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) {
- ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
- &ad714x->adc_reg[i]);
- ad714x->read(ad714x->dev,
- STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
- &ad714x->amb_reg[i]);
+ ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
+ &ad714x->amb_reg[i], 1);
if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
- ad714x->sensor_val[i] = ad714x->adc_reg[i] -
- ad714x->amb_reg[i];
+ ad714x->sensor_val[i] =
+ ad714x->adc_reg[i] - ad714x->amb_reg[i];
else
ad714x->sensor_val[i] = 0;
}
@@ -962,7 +872,7 @@ static int ad714x_hw_detect(struct ad714x_chip *ad714x)
{
unsigned short data;
- ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data);
+ ad714x->read(ad714x, AD714X_PARTID_REG, &data, 1);
switch (data & 0xFFF0) {
case AD7142_PARTID:
ad714x->product = 0x7142;
@@ -1011,23 +921,20 @@ static void ad714x_hw_init(struct ad714x_chip *ad714x)
for (i = 0; i < STAGE_NUM; i++) {
reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM;
for (j = 0; j < STAGE_CFGREG_NUM; j++)
- ad714x->write(ad714x->dev, reg_base + j,
+ ad714x->write(ad714x, reg_base + j,
ad714x->hw->stage_cfg_reg[i][j]);
}
for (i = 0; i < SYS_CFGREG_NUM; i++)
- ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i,
+ ad714x->write(ad714x, AD714X_SYSCFG_REG + i,
ad714x->hw->sys_cfg_reg[i]);
for (i = 0; i < SYS_CFGREG_NUM; i++)
- ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i,
- &data);
+ ad714x->read(ad714x, AD714X_SYSCFG_REG + i, &data, 1);
- ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF);
+ ad714x->write(ad714x, AD714X_STG_CAL_EN_REG, 0xFFF);
/* clear all interrupts */
- ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
- ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
- ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
+ ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
}
static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
@@ -1037,9 +944,7 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
mutex_lock(&ad714x->mutex);
- ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state);
- ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state);
- ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state);
+ ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
for (i = 0; i < ad714x->hw->button_num; i++)
ad714x_button_state_machine(ad714x, i);
@@ -1063,9 +968,10 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
int error;
struct input_dev *input[MAX_DEVICE_NUM];
- struct ad714x_platform_data *plat_data = dev->platform_data;
+ struct ad714x_platform_data *plat_data = dev_get_platdata(dev);
struct ad714x_chip *ad714x;
void *drv_mem;
+ unsigned long irqflags;
struct ad714x_button_drv *bt_drv;
struct ad714x_slider_drv *sd_drv;
@@ -1079,7 +985,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
goto err_out;
}
- if (dev->platform_data == NULL) {
+ if (dev_get_platdata(dev) == NULL) {
dev_err(dev, "platform data for ad714x doesn't exist\n");
error = -EINVAL;
goto err_out;
@@ -1149,6 +1055,8 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
+ input[alloc_idx]->name = "ad714x_captouch_slider";
+ input[alloc_idx]->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
if (error)
@@ -1179,6 +1087,8 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
+ input[alloc_idx]->name = "ad714x_captouch_wheel";
+ input[alloc_idx]->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
if (error)
@@ -1212,6 +1122,8 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
+ input[alloc_idx]->name = "ad714x_captouch_pad";
+ input[alloc_idx]->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
if (error)
@@ -1240,6 +1152,8 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
input[alloc_idx]->id.bustype = bus_type;
input[alloc_idx]->id.product = ad714x->product;
input[alloc_idx]->id.version = ad714x->version;
+ input[alloc_idx]->name = "ad714x_captouch_button";
+ input[alloc_idx]->dev.parent = dev;
error = input_register_device(input[alloc_idx]);
if (error)
@@ -1248,8 +1162,11 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
alloc_idx++;
}
+ irqflags = plat_data->irqflags ?: IRQF_TRIGGER_FALLING;
+ irqflags |= IRQF_ONESHOT;
+
error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
- IRQF_TRIGGER_FALLING, "ad714x_captouch", ad714x);
+ irqflags, "ad714x_captouch", ad714x);
if (error) {
dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
goto err_unreg_dev;
@@ -1306,7 +1223,7 @@ int ad714x_disable(struct ad714x_chip *ad714x)
mutex_lock(&ad714x->mutex);
data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3;
- ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data);
+ ad714x->write(ad714x, AD714X_PWR_CTRL, data);
mutex_unlock(&ad714x->mutex);
@@ -1316,24 +1233,20 @@ EXPORT_SYMBOL(ad714x_disable);
int ad714x_enable(struct ad714x_chip *ad714x)
{
- unsigned short data;
-
dev_dbg(ad714x->dev, "%s enter\n", __func__);
mutex_lock(&ad714x->mutex);
/* resume to non-shutdown mode */
- ad714x->write(ad714x->dev, AD714X_PWR_CTRL,
+ ad714x->write(ad714x, AD714X_PWR_CTRL,
ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]);
/* make sure the interrupt output line is not low level after resume,
* otherwise we will get no chance to enter falling-edge irq again
*/
- ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
- ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
- ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
+ ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3);
mutex_unlock(&ad714x->mutex);