cregit-Linux how code gets into the kernel

Release 4.11 drivers/input/touchscreen/atmel_mxt_ts.c

/*
 * Atmel maXTouch Touchscreen driver
 *
 * Copyright (C) 2010 Samsung Electronics Co.Ltd
 * Copyright (C) 2011-2014 Atmel Corporation
 * Copyright (C) 2012 Google, Inc.
 * Copyright (C) 2016 Zodiac Inflight Innovations
 *
 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 */

#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/platform_data/atmel_mxt_ts.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>

/* Firmware files */

#define MXT_FW_NAME		"maxtouch.fw"

#define MXT_CFG_NAME		"maxtouch.cfg"

#define MXT_CFG_MAGIC		"OBP_RAW V1"

/* Registers */

#define MXT_OBJECT_START	0x07

#define MXT_OBJECT_SIZE		6

#define MXT_INFO_CHECKSUM_SIZE	3

#define MXT_MAX_BLOCK_WRITE	256

/* Object types */

#define MXT_DEBUG_DIAGNOSTIC_T37	37

#define MXT_GEN_MESSAGE_T5		5

#define MXT_GEN_COMMAND_T6		6

#define MXT_GEN_POWER_T7		7

#define MXT_GEN_ACQUIRE_T8		8

#define MXT_GEN_DATASOURCE_T53		53

#define MXT_TOUCH_MULTI_T9		9

#define MXT_TOUCH_KEYARRAY_T15		15

#define MXT_TOUCH_PROXIMITY_T23		23

#define MXT_TOUCH_PROXKEY_T52		52

#define MXT_PROCI_GRIPFACE_T20		20

#define MXT_PROCG_NOISE_T22		22

#define MXT_PROCI_ONETOUCH_T24		24

#define MXT_PROCI_TWOTOUCH_T27		27

#define MXT_PROCI_GRIP_T40		40

#define MXT_PROCI_PALM_T41		41

#define MXT_PROCI_TOUCHSUPPRESSION_T42	42

#define MXT_PROCI_STYLUS_T47		47

#define MXT_PROCG_NOISESUPPRESSION_T48	48

#define MXT_SPT_COMMSCONFIG_T18		18

#define MXT_SPT_GPIOPWM_T19		19

#define MXT_SPT_SELFTEST_T25		25

#define MXT_SPT_CTECONFIG_T28		28

#define MXT_SPT_USERDATA_T38		38

#define MXT_SPT_DIGITIZER_T43		43

#define MXT_SPT_MESSAGECOUNT_T44	44

#define MXT_SPT_CTECONFIG_T46		46

#define MXT_TOUCH_MULTITOUCHSCREEN_T100 100

/* MXT_GEN_MESSAGE_T5 object */

#define MXT_RPTID_NOMSG		0xff

/* MXT_GEN_COMMAND_T6 field */

#define MXT_COMMAND_RESET	0

#define MXT_COMMAND_BACKUPNV	1

#define MXT_COMMAND_CALIBRATE	2

#define MXT_COMMAND_REPORTALL	3

#define MXT_COMMAND_DIAGNOSTIC	5

/* Define for T6 status byte */

#define MXT_T6_STATUS_RESET	(1 << 7)

#define MXT_T6_STATUS_OFL	(1 << 6)

#define MXT_T6_STATUS_SIGERR	(1 << 5)

#define MXT_T6_STATUS_CAL	(1 << 4)

#define MXT_T6_STATUS_CFGERR	(1 << 3)

#define MXT_T6_STATUS_COMSERR	(1 << 2)

/* MXT_GEN_POWER_T7 field */

struct t7_config {
	
u8 idle;
	
u8 active;
} 
__packed;


#define MXT_POWER_CFG_RUN		0

#define MXT_POWER_CFG_DEEPSLEEP		1

/* MXT_TOUCH_MULTI_T9 field */

#define MXT_T9_CTRL		0

#define MXT_T9_XSIZE		3

#define MXT_T9_YSIZE		4

#define MXT_T9_ORIENT		9

#define MXT_T9_RANGE		18

/* MXT_TOUCH_MULTI_T9 status */

#define MXT_T9_UNGRIP		(1 << 0)

#define MXT_T9_SUPPRESS		(1 << 1)

#define MXT_T9_AMP		(1 << 2)

#define MXT_T9_VECTOR		(1 << 3)

#define MXT_T9_MOVE		(1 << 4)

#define MXT_T9_RELEASE		(1 << 5)

#define MXT_T9_PRESS		(1 << 6)

#define MXT_T9_DETECT		(1 << 7)


struct t9_range {
	
__le16 x;
	
__le16 y;
} 
__packed;

/* MXT_TOUCH_MULTI_T9 orient */

#define MXT_T9_ORIENT_SWITCH	(1 << 0)

#define MXT_T9_ORIENT_INVERTX	(1 << 1)

#define MXT_T9_ORIENT_INVERTY	(1 << 2)

/* MXT_SPT_COMMSCONFIG_T18 */

#define MXT_COMMS_CTRL		0

#define MXT_COMMS_CMD		1

/* MXT_DEBUG_DIAGNOSTIC_T37 */

#define MXT_DIAGNOSTIC_PAGEUP	0x01

#define MXT_DIAGNOSTIC_DELTAS	0x10

#define MXT_DIAGNOSTIC_REFS	0x11

#define MXT_DIAGNOSTIC_SIZE	128


#define MXT_FAMILY_1386			160

#define MXT1386_COLUMNS			3

#define MXT1386_PAGES_PER_COLUMN	8


struct t37_debug {
#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
	
u8 mode;
	
u8 page;
	
u8 data[MXT_DIAGNOSTIC_SIZE];
#endif
};

/* Define for MXT_GEN_COMMAND_T6 */

#define MXT_BOOT_VALUE		0xa5

#define MXT_RESET_VALUE		0x01

#define MXT_BACKUP_VALUE	0x55

/* T100 Multiple Touch Touchscreen */

#define MXT_T100_CTRL		0

#define MXT_T100_CFG1		1

#define MXT_T100_TCHAUX		3

#define MXT_T100_XSIZE		9

#define MXT_T100_XRANGE		13

#define MXT_T100_YSIZE		20

#define MXT_T100_YRANGE		24


#define MXT_T100_CFG_SWITCHXY	BIT(5)

#define MXT_T100_CFG_INVERTY	BIT(6)

#define MXT_T100_CFG_INVERTX	BIT(7)


#define MXT_T100_TCHAUX_VECT	BIT(0)

#define MXT_T100_TCHAUX_AMPL	BIT(1)

#define MXT_T100_TCHAUX_AREA	BIT(2)


#define MXT_T100_DETECT		BIT(7)

#define MXT_T100_TYPE_MASK	0x70


enum t100_type {
	
MXT_T100_TYPE_FINGER		= 1,
	
MXT_T100_TYPE_PASSIVE_STYLUS	= 2,
	
MXT_T100_TYPE_HOVERING_FINGER	= 4,
	
MXT_T100_TYPE_GLOVE		= 5,
	
MXT_T100_TYPE_LARGE_TOUCH	= 6,
};


#define MXT_DISTANCE_ACTIVE_TOUCH	0

#define MXT_DISTANCE_HOVERING		1


#define MXT_TOUCH_MAJOR_DEFAULT		1

#define MXT_PRESSURE_DEFAULT		1

/* Delay times */

#define MXT_BACKUP_TIME		50	
/* msec */

#define MXT_RESET_TIME		200	
/* msec */

#define MXT_RESET_TIMEOUT	3000	
/* msec */

#define MXT_CRC_TIMEOUT		1000	
/* msec */

#define MXT_FW_RESET_TIME	3000	
/* msec */

#define MXT_FW_CHG_TIMEOUT	300	
/* msec */

/* Command to unlock bootloader */

#define MXT_UNLOCK_CMD_MSB	0xaa

#define MXT_UNLOCK_CMD_LSB	0xdc

/* Bootloader mode status */

#define MXT_WAITING_BOOTLOAD_CMD	0xc0	
/* valid 7 6 bit only */

#define MXT_WAITING_FRAME_DATA	0x80	
/* valid 7 6 bit only */

#define MXT_FRAME_CRC_CHECK	0x02

#define MXT_FRAME_CRC_FAIL	0x03

#define MXT_FRAME_CRC_PASS	0x04

#define MXT_APP_CRC_FAIL	0x40	
/* valid 7 8 bit only */

#define MXT_BOOT_STATUS_MASK	0x3f

#define MXT_BOOT_EXTENDED_ID	(1 << 5)

#define MXT_BOOT_ID_MASK	0x1f

/* Touchscreen absolute values */

#define MXT_MAX_AREA		0xff


#define MXT_PIXELS_PER_MM	20


struct mxt_info {
	
u8 family_id;
	
u8 variant_id;
	
u8 version;
	
u8 build;
	
u8 matrix_xsize;
	
u8 matrix_ysize;
	
u8 object_num;
};


struct mxt_object {
	
u8 type;
	
u16 start_address;
	
u8 size_minus_one;
	
u8 instances_minus_one;
	
u8 num_report_ids;
} 
__packed;


struct mxt_dbg {
	
u16 t37_address;
	
u16 diag_cmd_address;
	
struct t37_debug *t37_buf;
	
unsigned int t37_pages;
	
unsigned int t37_nodes;

	
struct v4l2_device v4l2;
	
struct v4l2_pix_format format;
	
struct video_device vdev;
	
struct vb2_queue queue;
	
struct mutex lock;
	
int input;
};


enum v4l_dbg_inputs {
	
MXT_V4L_INPUT_DELTAS,
	
MXT_V4L_INPUT_REFS,
	
MXT_V4L_INPUT_MAX,
};


static const struct v4l2_file_operations mxt_video_fops = {
	.owner = THIS_MODULE,
	.open = v4l2_fh_open,
	.release = vb2_fop_release,
	.unlocked_ioctl = video_ioctl2,
	.read = vb2_fop_read,
	.mmap = vb2_fop_mmap,
	.poll = vb2_fop_poll,
};

/* Each client has this additional data */

struct mxt_data {
	
struct i2c_client *client;
	
struct input_dev *input_dev;
	
char phys[64];		/* device physical location */
	
const struct mxt_platform_data *pdata;
	
struct mxt_object *object_table;
	
struct mxt_info info;
	
unsigned int irq;
	
unsigned int max_x;
	
unsigned int max_y;
	
bool invertx;
	
bool inverty;
	
bool xy_switch;
	
u8 xsize;
	
u8 ysize;
	
bool in_bootloader;
	
u16 mem_size;
	
u8 t100_aux_ampl;
	
u8 t100_aux_area;
	
u8 t100_aux_vect;
	
u8 max_reportid;
	
u32 config_crc;
	
u32 info_crc;
	
u8 bootloader_addr;
	
u8 *msg_buf;
	
u8 t6_status;
	
bool update_input;
	
u8 last_message_count;
	
u8 num_touchids;
	
u8 multitouch;
	
struct t7_config t7_cfg;
	
struct mxt_dbg dbg;

	/* Cached parameters from object table */
	
u16 T5_address;
	
u8 T5_msg_size;
	
u8 T6_reportid;
	
u16 T6_address;
	
u16 T7_address;
	
u8 T9_reportid_min;
	
u8 T9_reportid_max;
	
u8 T19_reportid;
	
u16 T44_address;
	
u8 T100_reportid_min;
	
u8 T100_reportid_max;

	/* for fw update in bootloader */
	
struct completion bl_completion;

	/* for reset handling */
	
struct completion reset_completion;

	/* for config update handling */
	
struct completion crc_completion;
};


struct mxt_vb2_buffer {
	
struct vb2_buffer	vb;
	
struct list_head	list;
};


static size_t mxt_obj_size(const struct mxt_object *obj) { return obj->size_minus_one + 1; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Kurtz19100.00%1100.00%
Total19100.00%1100.00%


static size_t mxt_obj_instances(const struct mxt_object *obj) { return obj->instances_minus_one + 1; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Kurtz19100.00%1100.00%
Total19100.00%1100.00%


static bool mxt_object_readable(unsigned int type) { switch (type) { case MXT_GEN_COMMAND_T6: case MXT_GEN_POWER_T7: case MXT_GEN_ACQUIRE_T8: case MXT_GEN_DATASOURCE_T53: case MXT_TOUCH_MULTI_T9: case MXT_TOUCH_KEYARRAY_T15: case MXT_TOUCH_PROXIMITY_T23: case MXT_TOUCH_PROXKEY_T52: case MXT_PROCI_GRIPFACE_T20: case MXT_PROCG_NOISE_T22: case MXT_PROCI_ONETOUCH_T24: case MXT_PROCI_TWOTOUCH_T27: case MXT_PROCI_GRIP_T40: case MXT_PROCI_PALM_T41: case MXT_PROCI_TOUCHSUPPRESSION_T42: case MXT_PROCI_STYLUS_T47: case MXT_PROCG_NOISESUPPRESSION_T48: case MXT_SPT_COMMSCONFIG_T18: case MXT_SPT_GPIOPWM_T19: case MXT_SPT_SELFTEST_T25: case MXT_SPT_CTECONFIG_T28: case MXT_SPT_USERDATA_T38: case MXT_SPT_DIGITIZER_T43: case MXT_SPT_CTECONFIG_T46: return true; default: return false; } }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim5861.05%250.00%
Iiro Valkonen3738.95%250.00%
Total95100.00%4100.00%


static void mxt_dump_message(struct mxt_data *data, u8 *message) { dev_dbg(&data->client->dev, "message: %*ph\n", data->T5_msg_size, message); }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim2163.64%133.33%
Nick Dyer1133.33%133.33%
Iiro Valkonen13.03%133.33%
Total33100.00%3100.00%


static int mxt_wait_for_completion(struct mxt_data *data, struct completion *comp, unsigned int timeout_ms) { struct device *dev = &data->client->dev; unsigned long timeout = msecs_to_jiffies(timeout_ms); long ret; ret = wait_for_completion_interruptible_timeout(comp, timeout); if (ret < 0) { return ret; } else if (ret == 0) { dev_err(dev, "Wait for completion timed out.\n"); return -ETIMEDOUT; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Benson Leung5765.52%133.33%
Nick Dyer2427.59%133.33%
Iiro Valkonen66.90%133.33%
Total87100.00%3100.00%


static int mxt_bootloader_read(struct mxt_data *data, u8 *val, unsigned int count) { int ret; struct i2c_msg msg; msg.addr = data->bootloader_addr; msg.flags = data->client->flags & I2C_M_TEN; msg.flags |= I2C_M_RD; msg.len = count; msg.buf = val; ret = i2c_transfer(data->client->adapter, &msg, 1); if (ret == 1) { ret = 0; } else { ret = ret < 0 ? ret : -EIO; dev_err(&data->client->dev, "%s: i2c recv failed (%d)\n", __func__, ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Nick Dyer125100.00%1100.00%
Total125100.00%1100.00%


static int mxt_bootloader_write(struct mxt_data *data, const u8 * const val, unsigned int count) { int ret; struct i2c_msg msg; msg.addr = data->bootloader_addr; msg.flags = data->client->flags & I2C_M_TEN; msg.len = count; msg.buf = (u8 *)val; ret = i2c_transfer(data->client->adapter, &msg, 1); if (ret == 1) { ret = 0; } else { ret = ret < 0 ? ret : -EIO; dev_err(&data->client->dev, "%s: i2c send failed (%d)\n", __func__, ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Nick Dyer125100.00%1100.00%
Total125100.00%1100.00%


static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) { u8 appmode = data->client->addr; u8 bootloader; switch (appmode) { case 0x4a: case 0x4b: /* Chips after 1664S use different scheme */ if (retry || data->info.family_id >= 0xa2) { bootloader = appmode - 0x24; break; } /* Fall through for normal case */ case 0x4c: case 0x4d: case 0x5a: case 0x5b: bootloader = appmode - 0x26; break; default: dev_err(&data->client->dev, "Appmode i2c address 0x%02x not found\n", appmode); return -EINVAL; } data->bootloader_addr = bootloader; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Nick Dyer9184.26%375.00%
Benson Leung1715.74%125.00%
Total108100.00%4100.00%


static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) { struct device *dev = &data->client->dev; int error; u8 val; bool crc_failure; error = mxt_lookup_bootloader_address(data, alt_address); if (error) return error; error = mxt_bootloader_read(data, &val, 1); if (error) return error; /* Check app crc fail mode */ crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL; dev_err(dev, "Detected bootloader, status:%02X%s\n", val, crc_failure ? ", APP_CRC_FAIL" : ""); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Nick Dyer9191.00%266.67%
Dmitry Torokhov99.00%133.33%
Total100100.00%3100.00%


static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val) { struct device *dev = &data->client->dev; u8 buf[3]; if (val & MXT_BOOT_EXTENDED_ID) { if (mxt_bootloader_read(data, &buf[0], 3) != 0) { dev_err(dev, "%s: i2c failure\n", __func__); return val; } dev_dbg(dev, "Bootloader ID:%d Version:%d\n", buf[1], buf[2]); return buf[0]; } else { dev_dbg(dev, "Bootloader ID:%d\n", val & MXT_BOOT_ID_MASK); return val; } }

Contributors

PersonTokensPropCommitsCommitProp
Nick Dyer111100.00%2100.00%
Total111100.00%2100.00%


static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, bool wait) { struct device *dev = &data->client->dev; u8 val; int ret; recheck: if (wait) { /* * In application update mode, the interrupt * line signals state transitions. We must wait for the * CHG assertion before reading the status byte. * Once the status byte has been read, the line is deasserted. */ ret = mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_CHG_TIMEOUT); if (ret) { /* * TODO: handle -ERESTARTSYS better by terminating * fw update process before returning to userspace * by writing length 0x000 to device (iff we are in * WAITING_FRAME_DATA state). */ dev_err(dev, "Update wait error %d\n", ret); return ret; } } ret = mxt_bootloader_read(data, &val, 1); if (ret) return ret; if (state == MXT_WAITING_BOOTLOAD_CMD) val = mxt_get_bootloader_version(data, val); switch (state) { case MXT_WAITING_BOOTLOAD_CMD: case MXT_WAITING_FRAME_DATA: case MXT_APP_CRC_FAIL: val &= ~MXT_BOOT_STATUS_MASK; break; case MXT_FRAME_CRC_PASS: if (val == MXT_FRAME_CRC_CHECK) { goto recheck; } else if (val == MXT_FRAME_CRC_FAIL) { dev_err(dev, "Bootloader CRC fail\n"); return -EINVAL; } break; default: return -EINVAL; } if (val != state) { dev_err(dev, "Invalid bootloader state %02X != %02X\n", val, state); return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim8140.70%19.09%
Nick Dyer6331.66%654.55%
Benson Leung4321.61%218.18%
Iiro Valkonen126.03%218.18%
Total199100.00%11100.00%


static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock) { int ret; u8 buf[2]; if (unlock) { buf[0] = MXT_UNLOCK_CMD_LSB; buf[1] = MXT_UNLOCK_CMD_MSB; } else { buf[0] = 0x01; buf[1] = 0x01; } ret = mxt_bootloader_write(data, buf, 2); if (ret) return ret; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim4150.62%125.00%
Nick Dyer3846.91%250.00%
Iiro Valkonen22.47%125.00%
Total81100.00%4100.00%


static int __mxt_read_reg(struct i2c_client *client, u16 reg, u16 len, void *val) { struct i2c_msg xfer[2]; u8 buf[2]; int ret; buf[0] = reg & 0xff; buf[1] = (reg >> 8) & 0xff; /* Write register */ xfer[0].addr = client->addr; xfer[0].flags = 0; xfer[0].len = 2; xfer[0].buf = buf; /* Read data */ xfer[1].addr = client->addr; xfer[1].flags = I2C_M_RD; xfer[1].len = len; xfer[1].buf = val; ret = i2c_transfer(client->adapter, xfer, 2); if (ret == 2) { ret = 0; } else { if (ret >= 0) ret = -EIO; dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", __func__, ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim16082.90%133.33%
Daniel Kurtz3216.58%133.33%
Iiro Valkonen10.52%133.33%
Total193100.00%3100.00%


static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len, const void *val) { u8 *buf; size_t count; int ret; count = len + 2; buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = reg & 0xff; buf[1] = (reg >> 8) & 0xff; memcpy(&buf[2], val, len); ret = i2c_master_send(client, buf, count); if (ret == count) { ret = 0; } else { if (ret >= 0) ret = -EIO; dev_err(&client->dev, "%s: i2c send failed (%d)\n", __func__, ret); } kfree(buf); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Kurtz8053.33%266.67%
Joonyoung Shim7046.67%133.33%
Total150100.00%3100.00%


static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) { return __mxt_write_reg(client, reg, 1, &val); }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim2480.00%150.00%
Daniel Kurtz620.00%150.00%
Total30100.00%2100.00%


static struct mxt_object * mxt_get_object(struct mxt_data *data, u8 type) { struct mxt_object *object; int i; for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; if (object->type == type) return object; } dev_warn(&data->client->dev, "Invalid object type T%u\n", type); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Joonyoung Shim7189.87%125.00%
Nick Dyer45.06%250.00%
Iiro Valkonen45.06%125.00%
Total79100.00%4100.00%


static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg) { struct device *dev = &data->client->dev; u8 status = msg[1]; u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16); complete(&data->crc_completion); if (crc != data->config_crc) { data->config_crc = crc; dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc); } /* Detect reset */ if (status & MXT_T6_STATUS_RESET) complete(&data->reset_completion); /* Output debug if status has changed */ if (status != data->t6_status) dev_dbg(dev, "T6 Status 0x%02X%s%s%s%s%s%s%s\n", status, status == 0 ? " OK" : "", status & MXT_T6_STATUS_RESET ? " RESET" : "", status & MXT_T6_STATUS_OFL ? " OFL" : "", status & MXT_T6_STATUS_SIGERR ? " SIGERR" : "", status & MXT_T6_STATUS_CAL ? " CAL" : "", status & MXT_T6_STATUS_CFGERR ? " CFGERR" : "", status & MXT_T6_STATUS_COMSERR ? " COMSERR" : ""); /* Save current status */ data->t6_status = status; }

Contributors

PersonTokensPropCommitsCommitProp
Nick Dyer190100.00%1100.00%
Total190100.00%1100.00%


static int mxt_write_object(struct mxt_data *data, u8 type, u8 offset, u8 val) { struct mxt_object *object; u16 reg; object = mxt_get_object(data, type); if (!object || offset >= mxt_obj_size(object)) return -EINVAL; reg = object->start_address; return mxt_write_reg(data->client, reg + offset, val); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds73100.00%1100.00%
Total73100.00%1100.00%


static void mxt_input_button(struct mxt_data *data, u8 *message) { struct input_dev *input = data->input_dev; const struct mxt_platform_data *pdata = data->pdata; int i; for (i = 0; i < pdata->t19_num_keys; i++) { if (pdata->t19_keymap