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
Person | Tokens | Prop | Commits | CommitProp |
Daniel Kurtz | 19 | 100.00% | 1 | 100.00% |
Total | 19 | 100.00% | 1 | 100.00% |
static size_t mxt_obj_instances(const struct mxt_object *obj)
{
return obj->instances_minus_one + 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Kurtz | 19 | 100.00% | 1 | 100.00% |
Total | 19 | 100.00% | 1 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 58 | 61.05% | 2 | 50.00% |
Iiro Valkonen | 37 | 38.95% | 2 | 50.00% |
Total | 95 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 21 | 63.64% | 1 | 33.33% |
Nick Dyer | 11 | 33.33% | 1 | 33.33% |
Iiro Valkonen | 1 | 3.03% | 1 | 33.33% |
Total | 33 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Benson Leung | 57 | 65.52% | 1 | 33.33% |
Nick Dyer | 24 | 27.59% | 1 | 33.33% |
Iiro Valkonen | 6 | 6.90% | 1 | 33.33% |
Total | 87 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Nick Dyer | 125 | 100.00% | 1 | 100.00% |
Total | 125 | 100.00% | 1 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Nick Dyer | 125 | 100.00% | 1 | 100.00% |
Total | 125 | 100.00% | 1 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Nick Dyer | 91 | 84.26% | 3 | 75.00% |
Benson Leung | 17 | 15.74% | 1 | 25.00% |
Total | 108 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Nick Dyer | 91 | 91.00% | 2 | 66.67% |
Dmitry Torokhov | 9 | 9.00% | 1 | 33.33% |
Total | 100 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Nick Dyer | 111 | 100.00% | 2 | 100.00% |
Total | 111 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 81 | 40.70% | 1 | 9.09% |
Nick Dyer | 63 | 31.66% | 6 | 54.55% |
Benson Leung | 43 | 21.61% | 2 | 18.18% |
Iiro Valkonen | 12 | 6.03% | 2 | 18.18% |
Total | 199 | 100.00% | 11 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 41 | 50.62% | 1 | 25.00% |
Nick Dyer | 38 | 46.91% | 2 | 50.00% |
Iiro Valkonen | 2 | 2.47% | 1 | 25.00% |
Total | 81 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 160 | 82.90% | 1 | 33.33% |
Daniel Kurtz | 32 | 16.58% | 1 | 33.33% |
Iiro Valkonen | 1 | 0.52% | 1 | 33.33% |
Total | 193 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Daniel Kurtz | 80 | 53.33% | 2 | 66.67% |
Joonyoung Shim | 70 | 46.67% | 1 | 33.33% |
Total | 150 | 100.00% | 3 | 100.00% |
static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
{
return __mxt_write_reg(client, reg, 1, &val);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 24 | 80.00% | 1 | 50.00% |
Daniel Kurtz | 6 | 20.00% | 1 | 50.00% |
Total | 30 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Joonyoung Shim | 71 | 89.87% | 1 | 25.00% |
Nick Dyer | 4 | 5.06% | 2 | 50.00% |
Iiro Valkonen | 4 | 5.06% | 1 | 25.00% |
Total | 79 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Nick Dyer | 190 | 100.00% | 1 | 100.00% |
Total | 190 | 100.00% | 1 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 73 | 100.00% | 1 | 100.00% |
Total | 73 | 100.00% | 1 | 100.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