]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00180647-2: MAX11801: Add adc sample function in DCM mode.
authorRong Dian <b38775@freescale.com>
Thu, 26 Apr 2012 07:04:55 +0000 (15:04 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:30 +0000 (08:34 +0200)
add aux adc sample function in dcm mode
for max11801 driver on SABRESD_rev.B board.

Signed-off-by: Rong Dian <b38775@freescale.com>
drivers/input/touchscreen/max11801_ts.c

index ca88d6823a9854128f28dee6521c6d0ccb125ace..0784687d231bd470240876d39b185b22b75f5002 100755 (executable)
@@ -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
 #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;