summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorRong Dian <b38775@freescale.com>2012-04-26 15:04:55 +0800
committerJason Liu <r64343@freescale.com>2012-07-20 13:36:38 +0800
commit072d8e6d46862b1cfb91f12498a45aba7d3de167 (patch)
treee5e75ad1781edd5fac9cbf035cdefc3b8f415b64 /drivers/input
parent61c1326b0899e7f7cf30014a50db5641d04d68a8 (diff)
ENGR00180647-2: MAX11801: Add adc sample function in DCM mode.
add aux adc sample function in dcm mode for max11801 driver on SABRESD_rev.B board. Signed-off-by: Rong Dian <b38775@freescale.com>
Diffstat (limited to 'drivers/input')
-rwxr-xr-xdrivers/input/touchscreen/max11801_ts.c286
1 files changed, 224 insertions, 62 deletions
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index ca88d6823a98..0784687d231b 100755
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -2,7 +2,7 @@
* Driver for MAXI MAX11801 - A Resistive touch screen controller with
* i2c interface
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
* Author: Zhang Jiejing <jiejing.zhang@freescale.com>
*
* Based on mcs5000_ts.c
@@ -38,6 +38,8 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
+
/* Register Address define */
#define GENERNAL_STATUS_REG 0x00
@@ -53,13 +55,32 @@
#define AUX_MESURE_CONF_REG 0x0a
#define OP_MODE_CONF_REG 0x0b
+#define Panel_Setup_X (0x69 << 1)
+#define Panel_Setup_Y (0x6b << 1)
+
+#define XY_combined_measurement (0x70 << 1)
+#define X_measurement (0x78 << 1)
+#define Y_measurement (0x7a << 1)
+#define AUX_measurement (0x76 << 1)
+
/* FIFO is found only in max11800 and max11801 */
#define FIFO_RD_CMD (0x50 << 1)
#define MAX11801_FIFO_INT (1 << 2)
#define MAX11801_FIFO_OVERFLOW (1 << 3)
+#define MAX11801_EDGE_INT (1 << 1)
+
+#define FIFO_RD_X_MSB (0x52 << 1)
+#define FIFO_RD_X_LSB (0x53 << 1)
+#define FIFO_RD_Y_MSB (0x54 << 1)
+#define FIFO_RD_Y_LSB (0x55 << 1)
+#define FIFO_RD_AUX_MSB (0x5a << 1)
+#define FIFO_RD_AUX_LSB (0x5b << 1)
#define XY_BUFSIZE 4
#define XY_BUF_OFFSET 4
+#define X_BUFSIZE 2
+#define Y_BUFSIZE 2
+#define AUX_BUFSIZE 2
#define MAX11801_MAX_X 0xfff
#define MAX11801_MAX_Y 0xfff
@@ -83,6 +104,57 @@ struct max11801_data {
struct i2c_client *client;
struct input_dev *input_dev;
};
+struct i2c_client *max11801_client;
+unsigned int max11801_workmode;
+
+static int max11801_dcm_write_command(struct i2c_client *client, int command)
+{
+ return i2c_smbus_write_byte(client, command);
+}
+
+static u32 max11801_dcm_sample_aux(struct i2c_client *client)
+{
+ u8 temp_buf;
+ u8 aux_buf[AUX_BUFSIZE];
+ int ret;
+ int aux = 0;
+ u32 sample_data = 0;
+ /* AUX_measurement*/
+ max11801_dcm_write_command(client, AUX_measurement);
+ mdelay(5);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_MSB,
+ 1, &temp_buf);
+ aux_buf[0] = temp_buf;
+ if (ret < 1)
+ printk(KERN_DEBUG "FIFO_RD_AUX_MSB read fails\n");
+ mdelay(5);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_LSB,
+ 1, &temp_buf);
+ aux_buf[1] = temp_buf;
+ if (ret < 1)
+ printk(KERN_DEBUG "FIFO_RD_AUX_LSB read fails\n");
+ aux = (aux_buf[0] << 4) +
+ (aux_buf[1] >> 4);
+ printk(KERN_DEBUG "aux: %4x\n", aux);
+ /*
+ voltage = (9170*aux)/7371;
+ voltage is (26.2*3150*aux)/(16.2*0xFFF)
+ V(aux)=3150*sample/0xFFF,V(battery)=212*V(aux)/81
+ sample_data = (14840*aux)/7371-1541;
+ */
+ sample_data = (14840*aux)/7371;
+ pr_debug("FIFO_RD_AUX_MSB: %2x,FIFO_RD_AUX_LSB: %2x\n",
+ aux_buf[0], aux_buf[1]);
+ return sample_data;
+}
+
+u32 max11801_read_adc(void)
+{
+ u32 adc_data;
+ adc_data = max11801_dcm_sample_aux(max11801_client);
+ return adc_data;
+}
+EXPORT_SYMBOL_GPL(max11801_read_adc);
static u8 read_register(struct i2c_client *client, int addr)
{
@@ -109,76 +181,166 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
struct i2c_client *client = data->client;
int status, i, ret;
u8 buf[XY_BUFSIZE];
+ u8 x_buf[X_BUFSIZE];
+ u8 y_buf[Y_BUFSIZE];
+ u8 temp_buf[1];
int x = -1;
int y = -1;
status = read_register(data->client, GENERNAL_STATUS_REG);
-
- if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
- status = read_register(data->client, GENERNAL_STATUS_REG);
-
- ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
- XY_BUFSIZE, buf);
-
- /*
- * We should get 4 bytes buffer that contains X,Y
- * and event tag
- */
- if (ret < XY_BUFSIZE)
- goto out;
-
- for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
- if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
- x = (buf[i] << XY_BUF_OFFSET) +
- (buf[i + 1] >> XY_BUF_OFFSET);
- else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
- y = (buf[i] << XY_BUF_OFFSET) +
- (buf[i + 1] >> XY_BUF_OFFSET);
- }
-
- if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
- goto out;
-
- switch (buf[1] & EVENT_TAG_MASK) {
- case EVENT_INIT:
- /* fall through */
- case EVENT_MIDDLE:
- calibration_pointer(&x, &y);
- input_report_abs(data->input_dev, ABS_X, x);
- input_report_abs(data->input_dev, ABS_Y, y);
- input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
- input_sync(data->input_dev);
- break;
-
- case EVENT_RELEASE:
- input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
- input_sync(data->input_dev);
- break;
-
- case EVENT_FIFO_END:
- break;
- }
- }
+ if (max11801_workmode == 0) {
+ if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
+ status = read_register(data->client, GENERNAL_STATUS_REG);
+
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
+ XY_BUFSIZE, buf);
+
+ /*
+ * We should get 4 bytes buffer that contains X,Y
+ * and event tag
+ */
+ if (ret < XY_BUFSIZE)
+ goto out;
+
+ for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
+ if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
+ x = (buf[i] << XY_BUF_OFFSET) +
+ (buf[i + 1] >> XY_BUF_OFFSET);
+ else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
+ y = (buf[i] << XY_BUF_OFFSET) +
+ (buf[i + 1] >> XY_BUF_OFFSET);
+ }
+
+ if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK))
+ goto out;
+
+ switch (buf[1] & EVENT_TAG_MASK) {
+ case EVENT_INIT:
+ /* fall through */
+ case EVENT_MIDDLE:
+ calibration_pointer(&x, &y);
+ input_report_abs(data->input_dev, ABS_X, x);
+ input_report_abs(data->input_dev, ABS_Y, y);
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_RELEASE:
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_FIFO_END:
+ break;
+ }
+ }
out:
- return IRQ_HANDLED;
+return IRQ_HANDLED;
+ }
+ else if (max11801_workmode == 1) {
+ if (status & (MAX11801_EDGE_INT)) {
+ status = read_register(data->client, GENERNAL_STATUS_REG);
+
+ /* X = panel setup*/
+ max11801_dcm_write_command(client, Panel_Setup_X);
+ /* X_measurement*/
+ max11801_dcm_write_command(client, X_measurement);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_X_MSB,
+ 1, temp_buf);
+ x_buf[0] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_X_LSB,
+ 1, temp_buf);
+ x_buf[1] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+ /* Y = panel setup*/
+ max11801_dcm_write_command(client, Panel_Setup_Y);
+ /* Y_measurement*/
+ max11801_dcm_write_command(client, Y_measurement);
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_Y_MSB,
+ 1, temp_buf);
+ y_buf[0] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+ ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_Y_LSB,
+ 1, temp_buf);
+ y_buf[1] = temp_buf[0];
+ if (ret < 1)
+ goto out2;
+
+ if ((x_buf[1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
+ x = (x_buf[0] << XY_BUF_OFFSET) +
+ (x_buf[1] >> XY_BUF_OFFSET);
+ if ((y_buf[1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG)
+ y = (y_buf[0] << XY_BUF_OFFSET) +
+ (y_buf[1] >> XY_BUF_OFFSET);
+
+ if ((x_buf[1] & EVENT_TAG_MASK) != (y_buf[1] & EVENT_TAG_MASK))
+ goto out2;
+
+ switch (x_buf[1] & EVENT_TAG_MASK) {
+ case EVENT_INIT:
+ /* fall through */
+ case EVENT_MIDDLE:
+ calibration_pointer(&x, &y);
+ input_report_abs(data->input_dev, ABS_X, x);
+ input_report_abs(data->input_dev, ABS_Y, y);
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_RELEASE:
+ input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0);
+ input_sync(data->input_dev);
+ break;
+
+ case EVENT_FIFO_END:
+ break;
+ }
+ }
+ }
+out2:
+return IRQ_HANDLED;
}
static void __devinit max11801_ts_phy_init(struct max11801_data *data)
{
struct i2c_client *client = data->client;
-
- /* Average X,Y, take 16 samples, average eight media sample */
- max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
- /* X,Y panel setup time set to 20us */
- max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
- /* Rough pullup time (2uS), Fine pullup time (10us) */
- max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
- /* Auto mode init period = 5ms , scan period = 5ms*/
- max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
- /* Aperture X,Y set to +- 4LSB */
- max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
- /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
- max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ max11801_client = client;
+ if (max11801_workmode == 0) {
+ /* Average X,Y, take 16 samples, average eight media sample */
+ max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
+ /* X,Y panel setup time set to 20us */
+ max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
+ /* Rough pullup time (2uS), Fine pullup time (10us) */
+ max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
+ /* Auto mode init period = 5ms , scan period = 5ms*/
+ max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
+ /* Aperture X,Y set to +- 4LSB */
+ max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
+ /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */
+ max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
+ }
+ if (max11801_workmode == 1) {
+ /* Average X,Y, take 16 samples, average eight media sample */
+ max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff);
+ /* X,Y panel setup time set to 20us */
+ max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11);
+ /* Rough pullup time (2uS), Fine pullup time (10us) */
+ max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10);
+ /* Auto mode init period = 5ms , scan period = 5ms*/
+ max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa);
+ /* Aperture X,Y set to +- 4LSB */
+ max11801_write_reg(client, APERTURE_CONF_REG, 0x33);
+ /* Enable Power, enable Direct conversion mode , enable Aperture, enable Average X,Y */
+ max11801_write_reg(client, OP_MODE_CONF_REG, 0x16);
+ /* Delay initial=1ms, Sampling time 2us ,Averaging sample depth 2 samples, Resolution 12bit */
+ max11801_write_reg(client, AUX_MESURE_CONF_REG, 0x76);
+ /* Use edge interrupt with direct conversion mode */
+ max11801_write_reg(client, GENERNAL_CONF_REG, 0xf3);
+ }
}
static int __devinit max11801_ts_probe(struct i2c_client *client,
@@ -195,7 +357,7 @@ static int __devinit max11801_ts_probe(struct i2c_client *client,
error = -ENOMEM;
goto err_free_mem;
}
-
+ max11801_workmode = *(int *)(client->dev).platform_data;
data->client = client;
data->input_dev = input_dev;