162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for MAXI MAX11801 - A Resistive touch screen controller with 462306a36Sopenharmony_ci * i2c interface 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2011 Freescale Semiconductor, Inc. 762306a36Sopenharmony_ci * Author: Zhang Jiejing <jiejing.zhang@freescale.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Based on mcs5000_ts.c 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* 1362306a36Sopenharmony_ci * This driver aims to support the series of MAXI touch chips max11801 1462306a36Sopenharmony_ci * through max11803. The main difference between these 4 chips can be 1562306a36Sopenharmony_ci * found in the table below: 1662306a36Sopenharmony_ci * ----------------------------------------------------- 1762306a36Sopenharmony_ci * | CHIP | AUTO MODE SUPPORT(FIFO) | INTERFACE | 1862306a36Sopenharmony_ci * |----------------------------------------------------| 1962306a36Sopenharmony_ci * | max11800 | YES | SPI | 2062306a36Sopenharmony_ci * | max11801 | YES | I2C | 2162306a36Sopenharmony_ci * | max11802 | NO | SPI | 2262306a36Sopenharmony_ci * | max11803 | NO | I2C | 2362306a36Sopenharmony_ci * ------------------------------------------------------ 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Currently, this driver only supports max11801. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * Data Sheet: 2862306a36Sopenharmony_ci * http://www.maxim-ic.com/datasheet/index.mvp/id/5943 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <linux/module.h> 3262306a36Sopenharmony_ci#include <linux/i2c.h> 3362306a36Sopenharmony_ci#include <linux/interrupt.h> 3462306a36Sopenharmony_ci#include <linux/input.h> 3562306a36Sopenharmony_ci#include <linux/slab.h> 3662306a36Sopenharmony_ci#include <linux/bitops.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* Register Address define */ 3962306a36Sopenharmony_ci#define GENERNAL_STATUS_REG 0x00 4062306a36Sopenharmony_ci#define GENERNAL_CONF_REG 0x01 4162306a36Sopenharmony_ci#define MESURE_RES_CONF_REG 0x02 4262306a36Sopenharmony_ci#define MESURE_AVER_CONF_REG 0x03 4362306a36Sopenharmony_ci#define ADC_SAMPLE_TIME_CONF_REG 0x04 4462306a36Sopenharmony_ci#define PANEL_SETUPTIME_CONF_REG 0x05 4562306a36Sopenharmony_ci#define DELAY_CONVERSION_CONF_REG 0x06 4662306a36Sopenharmony_ci#define TOUCH_DETECT_PULLUP_CONF_REG 0x07 4762306a36Sopenharmony_ci#define AUTO_MODE_TIME_CONF_REG 0x08 /* only for max11800/max11801 */ 4862306a36Sopenharmony_ci#define APERTURE_CONF_REG 0x09 /* only for max11800/max11801 */ 4962306a36Sopenharmony_ci#define AUX_MESURE_CONF_REG 0x0a 5062306a36Sopenharmony_ci#define OP_MODE_CONF_REG 0x0b 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* FIFO is found only in max11800 and max11801 */ 5362306a36Sopenharmony_ci#define FIFO_RD_CMD (0x50 << 1) 5462306a36Sopenharmony_ci#define MAX11801_FIFO_INT (1 << 2) 5562306a36Sopenharmony_ci#define MAX11801_FIFO_OVERFLOW (1 << 3) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define XY_BUFSIZE 4 5862306a36Sopenharmony_ci#define XY_BUF_OFFSET 4 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define MAX11801_MAX_X 0xfff 6162306a36Sopenharmony_ci#define MAX11801_MAX_Y 0xfff 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define MEASURE_TAG_OFFSET 2 6462306a36Sopenharmony_ci#define MEASURE_TAG_MASK (3 << MEASURE_TAG_OFFSET) 6562306a36Sopenharmony_ci#define EVENT_TAG_OFFSET 0 6662306a36Sopenharmony_ci#define EVENT_TAG_MASK (3 << EVENT_TAG_OFFSET) 6762306a36Sopenharmony_ci#define MEASURE_X_TAG (0 << MEASURE_TAG_OFFSET) 6862306a36Sopenharmony_ci#define MEASURE_Y_TAG (1 << MEASURE_TAG_OFFSET) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* These are the state of touch event state machine */ 7162306a36Sopenharmony_cienum { 7262306a36Sopenharmony_ci EVENT_INIT, 7362306a36Sopenharmony_ci EVENT_MIDDLE, 7462306a36Sopenharmony_ci EVENT_RELEASE, 7562306a36Sopenharmony_ci EVENT_FIFO_END 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistruct max11801_data { 7962306a36Sopenharmony_ci struct i2c_client *client; 8062306a36Sopenharmony_ci struct input_dev *input_dev; 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic u8 read_register(struct i2c_client *client, int addr) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci /* XXX: The chip ignores LSB of register address */ 8662306a36Sopenharmony_ci return i2c_smbus_read_byte_data(client, addr << 1); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic int max11801_write_reg(struct i2c_client *client, int addr, int data) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci /* XXX: The chip ignores LSB of register address */ 9262306a36Sopenharmony_ci return i2c_smbus_write_byte_data(client, addr << 1, data); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic irqreturn_t max11801_ts_interrupt(int irq, void *dev_id) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct max11801_data *data = dev_id; 9862306a36Sopenharmony_ci struct i2c_client *client = data->client; 9962306a36Sopenharmony_ci int status, i, ret; 10062306a36Sopenharmony_ci u8 buf[XY_BUFSIZE]; 10162306a36Sopenharmony_ci int x = -1; 10262306a36Sopenharmony_ci int y = -1; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci status = read_register(data->client, GENERNAL_STATUS_REG); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (status & (MAX11801_FIFO_INT | MAX11801_FIFO_OVERFLOW)) { 10762306a36Sopenharmony_ci status = read_register(data->client, GENERNAL_STATUS_REG); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_CMD, 11062306a36Sopenharmony_ci XY_BUFSIZE, buf); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* 11362306a36Sopenharmony_ci * We should get 4 bytes buffer that contains X,Y 11462306a36Sopenharmony_ci * and event tag 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_ci if (ret < XY_BUFSIZE) 11762306a36Sopenharmony_ci goto out; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci for (i = 0; i < XY_BUFSIZE; i += XY_BUFSIZE / 2) { 12062306a36Sopenharmony_ci if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_X_TAG) 12162306a36Sopenharmony_ci x = (buf[i] << XY_BUF_OFFSET) + 12262306a36Sopenharmony_ci (buf[i + 1] >> XY_BUF_OFFSET); 12362306a36Sopenharmony_ci else if ((buf[i + 1] & MEASURE_TAG_MASK) == MEASURE_Y_TAG) 12462306a36Sopenharmony_ci y = (buf[i] << XY_BUF_OFFSET) + 12562306a36Sopenharmony_ci (buf[i + 1] >> XY_BUF_OFFSET); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if ((buf[1] & EVENT_TAG_MASK) != (buf[3] & EVENT_TAG_MASK)) 12962306a36Sopenharmony_ci goto out; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci switch (buf[1] & EVENT_TAG_MASK) { 13262306a36Sopenharmony_ci case EVENT_INIT: 13362306a36Sopenharmony_ci case EVENT_MIDDLE: 13462306a36Sopenharmony_ci input_report_abs(data->input_dev, ABS_X, x); 13562306a36Sopenharmony_ci input_report_abs(data->input_dev, ABS_Y, y); 13662306a36Sopenharmony_ci input_event(data->input_dev, EV_KEY, BTN_TOUCH, 1); 13762306a36Sopenharmony_ci input_sync(data->input_dev); 13862306a36Sopenharmony_ci break; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci case EVENT_RELEASE: 14162306a36Sopenharmony_ci input_event(data->input_dev, EV_KEY, BTN_TOUCH, 0); 14262306a36Sopenharmony_ci input_sync(data->input_dev); 14362306a36Sopenharmony_ci break; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci case EVENT_FIFO_END: 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ciout: 15062306a36Sopenharmony_ci return IRQ_HANDLED; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic void max11801_ts_phy_init(struct max11801_data *data) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci struct i2c_client *client = data->client; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci /* Average X,Y, take 16 samples, average eight media sample */ 15862306a36Sopenharmony_ci max11801_write_reg(client, MESURE_AVER_CONF_REG, 0xff); 15962306a36Sopenharmony_ci /* X,Y panel setup time set to 20us */ 16062306a36Sopenharmony_ci max11801_write_reg(client, PANEL_SETUPTIME_CONF_REG, 0x11); 16162306a36Sopenharmony_ci /* Rough pullup time (2uS), Fine pullup time (10us) */ 16262306a36Sopenharmony_ci max11801_write_reg(client, TOUCH_DETECT_PULLUP_CONF_REG, 0x10); 16362306a36Sopenharmony_ci /* Auto mode init period = 5ms , scan period = 5ms*/ 16462306a36Sopenharmony_ci max11801_write_reg(client, AUTO_MODE_TIME_CONF_REG, 0xaa); 16562306a36Sopenharmony_ci /* Aperture X,Y set to +- 4LSB */ 16662306a36Sopenharmony_ci max11801_write_reg(client, APERTURE_CONF_REG, 0x33); 16762306a36Sopenharmony_ci /* Enable Power, enable Automode, enable Aperture, enable Average X,Y */ 16862306a36Sopenharmony_ci max11801_write_reg(client, OP_MODE_CONF_REG, 0x36); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic int max11801_ts_probe(struct i2c_client *client) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci struct max11801_data *data; 17462306a36Sopenharmony_ci struct input_dev *input_dev; 17562306a36Sopenharmony_ci int error; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 17862306a36Sopenharmony_ci input_dev = devm_input_allocate_device(&client->dev); 17962306a36Sopenharmony_ci if (!data || !input_dev) { 18062306a36Sopenharmony_ci dev_err(&client->dev, "Failed to allocate memory\n"); 18162306a36Sopenharmony_ci return -ENOMEM; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci data->client = client; 18562306a36Sopenharmony_ci data->input_dev = input_dev; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci input_dev->name = "max11801_ts"; 18862306a36Sopenharmony_ci input_dev->id.bustype = BUS_I2C; 18962306a36Sopenharmony_ci input_dev->dev.parent = &client->dev; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci __set_bit(EV_ABS, input_dev->evbit); 19262306a36Sopenharmony_ci __set_bit(EV_KEY, input_dev->evbit); 19362306a36Sopenharmony_ci __set_bit(BTN_TOUCH, input_dev->keybit); 19462306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_X, 0, MAX11801_MAX_X, 0, 0); 19562306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_Y, 0, MAX11801_MAX_Y, 0, 0); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci max11801_ts_phy_init(data); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci error = devm_request_threaded_irq(&client->dev, client->irq, NULL, 20062306a36Sopenharmony_ci max11801_ts_interrupt, 20162306a36Sopenharmony_ci IRQF_TRIGGER_LOW | IRQF_ONESHOT, 20262306a36Sopenharmony_ci "max11801_ts", data); 20362306a36Sopenharmony_ci if (error) { 20462306a36Sopenharmony_ci dev_err(&client->dev, "Failed to register interrupt\n"); 20562306a36Sopenharmony_ci return error; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci error = input_register_device(data->input_dev); 20962306a36Sopenharmony_ci if (error) 21062306a36Sopenharmony_ci return error; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return 0; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic const struct i2c_device_id max11801_ts_id[] = { 21662306a36Sopenharmony_ci {"max11801", 0}, 21762306a36Sopenharmony_ci { } 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max11801_ts_id); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic const struct of_device_id max11801_ts_dt_ids[] = { 22262306a36Sopenharmony_ci { .compatible = "maxim,max11801" }, 22362306a36Sopenharmony_ci { /* sentinel */ } 22462306a36Sopenharmony_ci}; 22562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max11801_ts_dt_ids); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic struct i2c_driver max11801_ts_driver = { 22862306a36Sopenharmony_ci .driver = { 22962306a36Sopenharmony_ci .name = "max11801_ts", 23062306a36Sopenharmony_ci .of_match_table = max11801_ts_dt_ids, 23162306a36Sopenharmony_ci }, 23262306a36Sopenharmony_ci .id_table = max11801_ts_id, 23362306a36Sopenharmony_ci .probe = max11801_ts_probe, 23462306a36Sopenharmony_ci}; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cimodule_i2c_driver(max11801_ts_driver); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ciMODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); 23962306a36Sopenharmony_ciMODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); 24062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 241