#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/ratelimit.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/unaligned.h>
#define WORK_REGISTER_THRESHOLD …
#define WORK_REGISTER_REPORT_RATE …
#define WORK_REGISTER_GAIN …
#define WORK_REGISTER_OFFSET …
#define WORK_REGISTER_NUM_X …
#define WORK_REGISTER_NUM_Y …
#define PMOD_REGISTER_ACTIVE …
#define PMOD_REGISTER_HIBERNATE …
#define M09_REGISTER_THRESHOLD …
#define M09_REGISTER_GAIN …
#define M09_REGISTER_OFFSET …
#define M09_REGISTER_NUM_X …
#define M09_REGISTER_NUM_Y …
#define M12_REGISTER_REPORT_RATE …
#define EV_REGISTER_THRESHOLD …
#define EV_REGISTER_GAIN …
#define EV_REGISTER_OFFSET_Y …
#define EV_REGISTER_OFFSET_X …
#define NO_REGISTER …
#define WORK_REGISTER_OPMODE …
#define FACTORY_REGISTER_OPMODE …
#define PMOD_REGISTER_OPMODE …
#define TOUCH_EVENT_DOWN …
#define TOUCH_EVENT_UP …
#define TOUCH_EVENT_ON …
#define TOUCH_EVENT_RESERVED …
#define EDT_NAME_LEN …
#define EDT_SWITCH_MODE_RETRIES …
#define EDT_SWITCH_MODE_DELAY …
#define EDT_RAW_DATA_RETRIES …
#define EDT_RAW_DATA_DELAY …
#define EDT_DEFAULT_NUM_X …
#define EDT_DEFAULT_NUM_Y …
#define M06_REG_CMD(factory) …
#define M06_REG_ADDR(factory, addr) …
enum edt_pmode { … };
enum edt_ver { … };
struct edt_reg_addr { … };
struct edt_ft5x06_ts_data { … };
struct edt_i2c_chip_data { … };
static const struct regmap_config edt_ft5x06_i2c_regmap_config = …;
static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,
u8 *buf, int buflen)
{ … }
static int edt_M06_i2c_read(void *context, const void *reg_buf, size_t reg_size,
void *val_buf, size_t val_size)
{ … }
static int edt_M06_i2c_write(void *context, const void *data, size_t count)
{ … }
static const struct regmap_config edt_M06_i2c_regmap_config = …;
static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
{ … }
struct edt_ft5x06_attribute { … };
#define EDT_ATTR(_field, _mode, _addr_m06, _addr_m09, _addr_ev, \
_limit_low, _limit_high) …
static ssize_t edt_ft5x06_setting_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{ … }
static ssize_t edt_ft5x06_setting_store(struct device *dev,
struct device_attribute *dattr,
const char *buf, size_t count)
{ … }
static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
M09_REGISTER_GAIN, EV_REGISTER_GAIN, 0, 31);
static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
M09_REGISTER_OFFSET, NO_REGISTER, 0, 31);
static EDT_ATTR(offset_x, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
EV_REGISTER_OFFSET_X, 0, 80);
static EDT_ATTR(offset_y, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
EV_REGISTER_OFFSET_Y, 0, 80);
static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
M09_REGISTER_THRESHOLD, EV_REGISTER_THRESHOLD, 0, 255);
static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
M12_REGISTER_REPORT_RATE, NO_REGISTER, 0, 255);
static ssize_t model_show(struct device *dev, struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(model);
static ssize_t fw_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{ … }
static DEVICE_ATTR_RO(fw_version);
static ssize_t header_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{ … }
static DEVICE_ATTR_RO(header_errors);
static ssize_t crc_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{ … }
static DEVICE_ATTR_RO(crc_errors);
static struct attribute *edt_ft5x06_attrs[] = …;
ATTRIBUTE_GROUPS(…);
static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
{ … }
#ifdef CONFIG_DEBUG_FS
static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
{ … }
static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
{ … }
static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode)
{
struct edt_ft5x06_ts_data *tsdata = data;
*mode = tsdata->factory_mode;
return 0;
};
static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode)
{
struct edt_ft5x06_ts_data *tsdata = data;
int retval = 0;
if (mode > 1)
return -ERANGE;
mutex_lock(&tsdata->mutex);
if (mode != tsdata->factory_mode) {
retval = mode ? edt_ft5x06_factory_mode(tsdata) :
edt_ft5x06_work_mode(tsdata);
}
mutex_unlock(&tsdata->mutex);
return retval;
};
DEFINE_SIMPLE_ATTRIBUTE(…);
static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
char __user *buf, size_t count,
loff_t *off)
{
struct edt_ft5x06_ts_data *tsdata = file->private_data;
struct i2c_client *client = tsdata->client;
int retries = EDT_RAW_DATA_RETRIES;
unsigned int val;
int i, error;
size_t read = 0;
int colbytes;
u8 *rdbuf;
if (*off < 0 || *off >= tsdata->raw_bufsize)
return 0;
mutex_lock(&tsdata->mutex);
if (!tsdata->factory_mode || !tsdata->raw_buffer) {
error = -EIO;
goto out;
}
error = regmap_write(tsdata->regmap, 0x08, 0x01);
if (error) {
dev_err(&client->dev,
"failed to write 0x08 register, error %d\n", error);
goto out;
}
do {
usleep_range(EDT_RAW_DATA_DELAY, EDT_RAW_DATA_DELAY + 100);
error = regmap_read(tsdata->regmap, 0x08, &val);
if (error) {
dev_err(&client->dev,
"failed to read 0x08 register, error %d\n",
error);
goto out;
}
if (val == 1)
break;
} while (--retries > 0);
if (retries == 0) {
dev_err(&client->dev,
"timed out waiting for register to settle\n");
error = -ETIMEDOUT;
goto out;
}
rdbuf = tsdata->raw_buffer;
colbytes = tsdata->num_y * sizeof(u16);
for (i = 0; i < tsdata->num_x; i++) {
rdbuf[0] = i;
error = regmap_bulk_read(tsdata->regmap, 0xf5, rdbuf, colbytes);
if (error)
goto out;
rdbuf += colbytes;
}
read = min_t(size_t, count, tsdata->raw_bufsize - *off);
if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) {
error = -EFAULT;
goto out;
}
*off += read;
out:
mutex_unlock(&tsdata->mutex);
return error ?: read;
};
static const struct file_operations debugfs_raw_data_fops = …;
static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
const char *debugfs_name)
{ … }
static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
{ … }
#else
static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
{
return -ENOSYS;
}
static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
const char *debugfs_name)
{
}
static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
}
#endif
static int edt_ft5x06_ts_identify(struct i2c_client *client,
struct edt_ft5x06_ts_data *tsdata)
{ … }
static void edt_ft5x06_ts_get_defaults(struct device *dev,
struct edt_ft5x06_ts_data *tsdata)
{ … }
static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
{ … }
static void edt_ft5x06_ts_set_tdata_parameters(struct edt_ft5x06_ts_data *tsdata)
{ … }
static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
{ … }
static void edt_ft5x06_exit_regmap(void *arg)
{ … }
static void edt_ft5x06_disable_regulators(void *arg)
{ … }
static int edt_ft5x06_ts_probe(struct i2c_client *client)
{ … }
static void edt_ft5x06_ts_remove(struct i2c_client *client)
{ … }
static int edt_ft5x06_ts_suspend(struct device *dev)
{ … }
static int edt_ft5x06_ts_resume(struct device *dev)
{ … }
static DEFINE_SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);
static const struct edt_i2c_chip_data edt_ft5x06_data = …;
static const struct edt_i2c_chip_data edt_ft5452_data = …;
static const struct edt_i2c_chip_data edt_ft5506_data = …;
static const struct edt_i2c_chip_data edt_ft6236_data = …;
static const struct edt_i2c_chip_data edt_ft8201_data = …;
static const struct edt_i2c_chip_data edt_ft8719_data = …;
static const struct i2c_device_id edt_ft5x06_ts_id[] = …;
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
static const struct of_device_id edt_ft5x06_of_match[] = …;
MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
static struct i2c_driver edt_ft5x06_ts_driver = …;
module_i2c_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;