1
0
Fork 0

MLK-11703-1: input: touchscreen: max11801_ts: Add DCM mode for max11801 ADC

We need add DCM mode/AUX mode for ADC converter function of max11801, so
that it can be used to read voltage of battery. Meanwhile, let the driver
based on device tree. The patchset is based on below patch (V3.5.7):

commit 4001774cf51f0140ae7e4e8e0ec1d86475790682
Author: Rong Dian <b38775@freescale.com>
Date:   Fri Jan 18 14:24:28 2013 +0800

    Engr00240284-1 MAX11801: Add DCM aux adc sample function

        1.Add direct conversion mode operations
	2.Add aux adc sample function

Signed-off-by: Robin Gong <b38343@freescale.com>
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
5.4-rM2-2.2.x-imx-squashed
Robin Gong 2013-08-13 16:58:26 +08:00 committed by Dong Aisheng
parent 219d54332a
commit 901b3581cd
1 changed files with 144 additions and 13 deletions

View File

@ -3,7 +3,7 @@
* Driver for MAXI MAX11801 - A Resistive touch screen controller with
* i2c interface
*
* Copyright (C) 2011 Freescale Semiconductor, Inc.
* Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
* Author: Zhang Jiejing <jiejing.zhang@freescale.com>
*
* Based on mcs5000_ts.c
@ -34,6 +34,10 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
/* Register Address define */
#define GENERNAL_STATUS_REG 0x00
@ -49,13 +53,30 @@
#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 AUX_BUFSIZE 2
#define MAX11801_MAX_X 0xfff
#define MAX11801_MAX_Y 0xfff
@ -80,6 +101,64 @@ struct max11801_data {
struct input_dev *input_dev;
};
static struct i2c_client *max11801_client;
static unsigned int max11801_workmode;
static u8 aux_buf[AUX_BUFSIZE];
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)
{
int ret;
int aux = 0;
u32 sample_data;
/* AUX_measurement */
max11801_dcm_write_command(client, AUX_measurement);
mdelay(5);
ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_MSB,
1, &aux_buf[0]);
if (ret < 1) {
dev_err(&client->dev, "FIFO_RD_AUX_MSB read fails\n");
return ret;
}
mdelay(5);
ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_LSB,
1, &aux_buf[1]);
if (ret < 1) {
dev_err(&client->dev, "FIFO_RD_AUX_LSB read fails\n");
return ret;
}
aux = (aux_buf[0] << 4) + (aux_buf[1] >> 4);
/*
* 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;
return sample_data;
}
u32 max11801_read_adc(void)
{
u32 adc_data;
if (!max11801_client) {
pr_err("FAIL max11801_client not initialize\n");
return -1;
}
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)
{
/* XXX: The chip ignores LSB of register address */
@ -100,21 +179,52 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
u8 buf[XY_BUFSIZE];
int x = -1;
int y = -1;
u8 command = FIFO_RD_X_MSB;
status = read_register(data->client, GENERNAL_STATUS_REG);
if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) {
if ((!max11801_workmode && (status & (MAX11801_FIFO_INT |
MAX11801_FIFO_OVERFLOW))) || (max11801_workmode && (status &
MAX11801_EDGE_INT))) {
status = read_register(data->client, GENERNAL_STATUS_REG);
if (!max11801_workmode) {
/* ACM mode */
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;
} else {
/* DCM mode */
/* X = panel setup */
max11801_dcm_write_command(client, Panel_Setup_X);
/* X_measurement */
max11801_dcm_write_command(client, X_measurement);
for (i = 0; i < 2; i++) {
ret = i2c_smbus_read_i2c_block_data(client,
command, 1, &buf[i]);
if (ret < 1)
goto out;
ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD,
XY_BUFSIZE, buf);
command = FIFO_RD_X_LSB;
}
/*
* We should get 4 bytes buffer that contains X,Y
* and event tag
*/
if (ret < XY_BUFSIZE)
goto out;
/* Y = panel setup */
max11801_dcm_write_command(client, Panel_Setup_Y);
/* Y_measurement */
max11801_dcm_write_command(client, Y_measurement);
command = FIFO_RD_Y_MSB;
for (i = 2; i < XY_BUFSIZE; i++) {
ret = i2c_smbus_read_i2c_block_data(client,
command, 1, &buf[i]);
if (ret < 1)
goto out;
command = FIFO_RD_Y_LSB;
}
}
for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) {
if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG)
@ -133,6 +243,7 @@ static irqreturn_t max11801_ts_interrupt(int irq, void *dev_id)
/* fall through */
case EVENT_MIDDLE:
input_report_abs(data->input_dev, ABS_X, x);
y = MAX11801_MAX_Y - y; /* Calibration */
input_report_abs(data->input_dev, ABS_Y, y);
input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1);
input_sync(data->input_dev);
@ -155,7 +266,8 @@ static void 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_client = 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);
@ -166,7 +278,22 @@ static void max11801_ts_phy_init(struct max11801_data *data)
/* 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)
max11801_write_reg(client, OP_MODE_CONF_REG, 0x36);
else {
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 max11801_ts_probe(struct i2c_client *client,
@ -175,6 +302,7 @@ static int max11801_ts_probe(struct i2c_client *client,
struct max11801_data *data;
struct input_dev *input_dev;
int error;
struct device_node *of_node = client->dev.of_node;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
input_dev = devm_input_allocate_device(&client->dev);
@ -196,6 +324,9 @@ static int max11801_ts_probe(struct i2c_client *client,
input_set_abs_params(input_dev, ABS_X, 0, MAX11801_MAX_X, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, MAX11801_MAX_Y, 0, 0);
if (of_property_read_u32(of_node, "work-mode", &max11801_workmode))
max11801_workmode = *(int *)(client->dev).platform_data;
max11801_ts_phy_init(data);
error = devm_request_threaded_irq(&client->dev, client->irq, NULL,