Commit ecd649b3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
 "Just a few driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: atmel_mxt_ts - add missing compatible strings to OF device table
  Input: atmel_mxt_ts - fix the firmware update
  Input: atmel_mxt_ts - add touchpad button mapping for Samsung Chromebook Pro
  MAINTAINERS: Rakesh Iyer can't be reached anymore
  Input: hideep_ts - fix a typo in Kconfig
  Input: alps - fix reporting pressure of v3 trackstick
  Input: leds - fix out of bound access
  Input: synaptics-rmi4 - fix an unchecked out of memory error path
parents 3b6f9793 f6eeb9e5
...@@ -4,6 +4,13 @@ Required properties: ...@@ -4,6 +4,13 @@ Required properties:
- compatible: - compatible:
atmel,maxtouch atmel,maxtouch
The following compatibles have been used in various products but are
deprecated:
atmel,qt602240_ts
atmel,atmel_mxt_ts
atmel,atmel_mxt_tp
atmel,mXT224
- reg: The I2C address of the device - reg: The I2C address of the device
- interrupts: The sink for the touchpad's IRQ output - interrupts: The sink for the touchpad's IRQ output
......
...@@ -13853,7 +13853,6 @@ S: Supported ...@@ -13853,7 +13853,6 @@ S: Supported
F: drivers/iommu/tegra* F: drivers/iommu/tegra*
TEGRA KBC DRIVER TEGRA KBC DRIVER
M: Rakesh Iyer <riyer@nvidia.com>
M: Laxman Dewangan <ldewangan@nvidia.com> M: Laxman Dewangan <ldewangan@nvidia.com>
S: Supported S: Supported
F: drivers/input/keyboard/tegra-kbc.c F: drivers/input/keyboard/tegra-kbc.c
......
...@@ -88,6 +88,7 @@ static int input_leds_connect(struct input_handler *handler, ...@@ -88,6 +88,7 @@ static int input_leds_connect(struct input_handler *handler,
const struct input_device_id *id) const struct input_device_id *id)
{ {
struct input_leds *leds; struct input_leds *leds;
struct input_led *led;
unsigned int num_leds; unsigned int num_leds;
unsigned int led_code; unsigned int led_code;
int led_no; int led_no;
...@@ -119,14 +120,13 @@ static int input_leds_connect(struct input_handler *handler, ...@@ -119,14 +120,13 @@ static int input_leds_connect(struct input_handler *handler,
led_no = 0; led_no = 0;
for_each_set_bit(led_code, dev->ledbit, LED_CNT) { for_each_set_bit(led_code, dev->ledbit, LED_CNT) {
struct input_led *led = &leds->leds[led_no]; if (!input_led_info[led_code].name)
continue;
led = &leds->leds[led_no];
led->handle = &leds->handle; led->handle = &leds->handle;
led->code = led_code; led->code = led_code;
if (!input_led_info[led_code].name)
continue;
led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s",
dev_name(&dev->dev), dev_name(&dev->dev),
input_led_info[led_code].name); input_led_info[led_code].name);
......
...@@ -583,7 +583,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) ...@@ -583,7 +583,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
z = packet[4] & 0x7c; z = packet[4] & 0x7f;
/* /*
* The x and y values tend to be quite large, and when used * The x and y values tend to be quite large, and when used
......
...@@ -147,8 +147,11 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi, ...@@ -147,8 +147,11 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi,
if (len > RMI_SPI_XFER_SIZE_LIMIT) if (len > RMI_SPI_XFER_SIZE_LIMIT)
return -EINVAL; return -EINVAL;
if (rmi_spi->xfer_buf_size < len) if (rmi_spi->xfer_buf_size < len) {
rmi_spi_manage_pools(rmi_spi, len); ret = rmi_spi_manage_pools(rmi_spi, len);
if (ret < 0)
return ret;
}
if (addr == 0) if (addr == 0)
/* /*
......
...@@ -362,7 +362,7 @@ config TOUCHSCREEN_HIDEEP ...@@ -362,7 +362,7 @@ config TOUCHSCREEN_HIDEEP
If unsure, say N. If unsure, say N.
To compile this driver as a moudle, choose M here : the To compile this driver as a module, choose M here : the
module will be called hideep_ts. module will be called hideep_ts.
config TOUCHSCREEN_ILI210X config TOUCHSCREEN_ILI210X
......
...@@ -280,7 +280,8 @@ struct mxt_data { ...@@ -280,7 +280,8 @@ struct mxt_data {
struct input_dev *input_dev; struct input_dev *input_dev;
char phys[64]; /* device physical location */ char phys[64]; /* device physical location */
struct mxt_object *object_table; struct mxt_object *object_table;
struct mxt_info info; struct mxt_info *info;
void *raw_info_block;
unsigned int irq; unsigned int irq;
unsigned int max_x; unsigned int max_x;
unsigned int max_y; unsigned int max_y;
...@@ -460,12 +461,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) ...@@ -460,12 +461,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
{ {
u8 appmode = data->client->addr; u8 appmode = data->client->addr;
u8 bootloader; u8 bootloader;
u8 family_id = data->info ? data->info->family_id : 0;
switch (appmode) { switch (appmode) {
case 0x4a: case 0x4a:
case 0x4b: case 0x4b:
/* Chips after 1664S use different scheme */ /* Chips after 1664S use different scheme */
if (retry || data->info.family_id >= 0xa2) { if (retry || family_id >= 0xa2) {
bootloader = appmode - 0x24; bootloader = appmode - 0x24;
break; break;
} }
...@@ -692,7 +694,7 @@ mxt_get_object(struct mxt_data *data, u8 type) ...@@ -692,7 +694,7 @@ mxt_get_object(struct mxt_data *data, u8 type)
struct mxt_object *object; struct mxt_object *object;
int i; int i;
for (i = 0; i < data->info.object_num; i++) { for (i = 0; i < data->info->object_num; i++) {
object = data->object_table + i; object = data->object_table + i;
if (object->type == type) if (object->type == type)
return object; return object;
...@@ -1462,12 +1464,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) ...@@ -1462,12 +1464,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
data_pos += offset; data_pos += offset;
} }
if (cfg_info.family_id != data->info.family_id) { if (cfg_info.family_id != data->info->family_id) {
dev_err(dev, "Family ID mismatch!\n"); dev_err(dev, "Family ID mismatch!\n");
return -EINVAL; return -EINVAL;
} }
if (cfg_info.variant_id != data->info.variant_id) { if (cfg_info.variant_id != data->info->variant_id) {
dev_err(dev, "Variant ID mismatch!\n"); dev_err(dev, "Variant ID mismatch!\n");
return -EINVAL; return -EINVAL;
} }
...@@ -1512,7 +1514,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) ...@@ -1512,7 +1514,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
/* Malloc memory to store configuration */ /* Malloc memory to store configuration */
cfg_start_ofs = MXT_OBJECT_START + cfg_start_ofs = MXT_OBJECT_START +
data->info.object_num * sizeof(struct mxt_object) + data->info->object_num * sizeof(struct mxt_object) +
MXT_INFO_CHECKSUM_SIZE; MXT_INFO_CHECKSUM_SIZE;
config_mem_size = data->mem_size - cfg_start_ofs; config_mem_size = data->mem_size - cfg_start_ofs;
config_mem = kzalloc(config_mem_size, GFP_KERNEL); config_mem = kzalloc(config_mem_size, GFP_KERNEL);
...@@ -1563,20 +1565,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg) ...@@ -1563,20 +1565,6 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
return ret; return ret;
} }
static int mxt_get_info(struct mxt_data *data)
{
struct i2c_client *client = data->client;
struct mxt_info *info = &data->info;
int error;
/* Read 7-byte info block starting at address 0 */
error = __mxt_read_reg(client, 0, sizeof(*info), info);
if (error)
return error;
return 0;
}
static void mxt_free_input_device(struct mxt_data *data) static void mxt_free_input_device(struct mxt_data *data)
{ {
if (data->input_dev) { if (data->input_dev) {
...@@ -1591,9 +1579,10 @@ static void mxt_free_object_table(struct mxt_data *data) ...@@ -1591,9 +1579,10 @@ static void mxt_free_object_table(struct mxt_data *data)
video_unregister_device(&data->dbg.vdev); video_unregister_device(&data->dbg.vdev);
v4l2_device_unregister(&data->dbg.v4l2); v4l2_device_unregister(&data->dbg.v4l2);
#endif #endif
kfree(data->object_table);
data->object_table = NULL; data->object_table = NULL;
data->info = NULL;
kfree(data->raw_info_block);
data->raw_info_block = NULL;
kfree(data->msg_buf); kfree(data->msg_buf);
data->msg_buf = NULL; data->msg_buf = NULL;
data->T5_address = 0; data->T5_address = 0;
...@@ -1609,34 +1598,18 @@ static void mxt_free_object_table(struct mxt_data *data) ...@@ -1609,34 +1598,18 @@ static void mxt_free_object_table(struct mxt_data *data)
data->max_reportid = 0; data->max_reportid = 0;
} }
static int mxt_get_object_table(struct mxt_data *data) static int mxt_parse_object_table(struct mxt_data *data,
struct mxt_object *object_table)
{ {
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
size_t table_size;
struct mxt_object *object_table;
int error;
int i; int i;
u8 reportid; u8 reportid;
u16 end_address; u16 end_address;
table_size = data->info.object_num * sizeof(struct mxt_object);
object_table = kzalloc(table_size, GFP_KERNEL);
if (!object_table) {
dev_err(&data->client->dev, "Failed to allocate memory\n");
return -ENOMEM;
}
error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
object_table);
if (error) {
kfree(object_table);
return error;
}
/* Valid Report IDs start counting from 1 */ /* Valid Report IDs start counting from 1 */
reportid = 1; reportid = 1;
data->mem_size = 0; data->mem_size = 0;
for (i = 0; i < data->info.object_num; i++) { for (i = 0; i < data->info->object_num; i++) {
struct mxt_object *object = object_table + i; struct mxt_object *object = object_table + i;
u8 min_id, max_id; u8 min_id, max_id;
...@@ -1660,8 +1633,8 @@ static int mxt_get_object_table(struct mxt_data *data) ...@@ -1660,8 +1633,8 @@ static int mxt_get_object_table(struct mxt_data *data)
switch (object->type) { switch (object->type) {
case MXT_GEN_MESSAGE_T5: case MXT_GEN_MESSAGE_T5:
if (data->info.family_id == 0x80 && if (data->info->family_id == 0x80 &&
data->info.version < 0x20) { data->info->version < 0x20) {
/* /*
* On mXT224 firmware versions prior to V2.0 * On mXT224 firmware versions prior to V2.0
* read and discard unused CRC byte otherwise * read and discard unused CRC byte otherwise
...@@ -1716,24 +1689,102 @@ static int mxt_get_object_table(struct mxt_data *data) ...@@ -1716,24 +1689,102 @@ static int mxt_get_object_table(struct mxt_data *data)
/* If T44 exists, T5 position has to be directly after */ /* If T44 exists, T5 position has to be directly after */
if (data->T44_address && (data->T5_address != data->T44_address + 1)) { if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
dev_err(&client->dev, "Invalid T44 position\n"); dev_err(&client->dev, "Invalid T44 position\n");
error = -EINVAL; return -EINVAL;
goto free_object_table;
} }
data->msg_buf = kcalloc(data->max_reportid, data->msg_buf = kcalloc(data->max_reportid,
data->T5_msg_size, GFP_KERNEL); data->T5_msg_size, GFP_KERNEL);
if (!data->msg_buf) { if (!data->msg_buf)
dev_err(&client->dev, "Failed to allocate message buffer\n"); return -ENOMEM;
return 0;
}
static int mxt_read_info_block(struct mxt_data *data)
{
struct i2c_client *client = data->client;
int error;
size_t size;
void *id_buf, *buf;
uint8_t num_objects;
u32 calculated_crc;
u8 *crc_ptr;
/* If info block already allocated, free it */
if (data->raw_info_block)
mxt_free_object_table(data);
/* Read 7-byte ID information block starting at address 0 */
size = sizeof(struct mxt_info);
id_buf = kzalloc(size, GFP_KERNEL);
if (!id_buf)
return -ENOMEM;
error = __mxt_read_reg(client, 0, size, id_buf);
if (error)
goto err_free_mem;
/* Resize buffer to give space for rest of info block */
num_objects = ((struct mxt_info *)id_buf)->object_num;
size += (num_objects * sizeof(struct mxt_object))
+ MXT_INFO_CHECKSUM_SIZE;
buf = krealloc(id_buf, size, GFP_KERNEL);
if (!buf) {
error = -ENOMEM; error = -ENOMEM;
goto free_object_table; goto err_free_mem;
} }
id_buf = buf;
data->object_table = object_table; /* Read rest of info block */
error = __mxt_read_reg(client, MXT_OBJECT_START,
size - MXT_OBJECT_START,
id_buf + MXT_OBJECT_START);
if (error)
goto err_free_mem;
return 0; /* Extract & calculate checksum */
crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE;
data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16);
calculated_crc = mxt_calculate_crc(id_buf, 0,
size - MXT_INFO_CHECKSUM_SIZE);
/*
* CRC mismatch can be caused by data corruption due to I2C comms
* issue or else device is not using Object Based Protocol (eg i2c-hid)
*/
if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) {
dev_err(&client->dev,
"Info Block CRC error calculated=0x%06X read=0x%06X\n",
calculated_crc, data->info_crc);
error = -EIO;
goto err_free_mem;
}
free_object_table: data->raw_info_block = id_buf;
data->info = (struct mxt_info *)id_buf;
dev_info(&client->dev,
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
data->info->family_id, data->info->variant_id,
data->info->version >> 4, data->info->version & 0xf,
data->info->build, data->info->object_num);
/* Parse object table information */
error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START);
if (error) {
dev_err(&client->dev, "Error %d parsing object table\n", error);
mxt_free_object_table(data); mxt_free_object_table(data);
goto err_free_mem;
}
data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
return 0;
err_free_mem:
kfree(id_buf);
return error; return error;
} }
...@@ -2046,7 +2097,7 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -2046,7 +2097,7 @@ static int mxt_initialize(struct mxt_data *data)
int error; int error;
while (1) { while (1) {
error = mxt_get_info(data); error = mxt_read_info_block(data);
if (!error) if (!error)
break; break;
...@@ -2077,16 +2128,9 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -2077,16 +2128,9 @@ static int mxt_initialize(struct mxt_data *data)
msleep(MXT_FW_RESET_TIME); msleep(MXT_FW_RESET_TIME);
} }
/* Get object table information */
error = mxt_get_object_table(data);
if (error) {
dev_err(&client->dev, "Error %d reading object table\n", error);
return error;
}
error = mxt_acquire_irq(data); error = mxt_acquire_irq(data);
if (error) if (error)
goto err_free_object_table; return error;
error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME, error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
&client->dev, GFP_KERNEL, data, &client->dev, GFP_KERNEL, data,
...@@ -2094,14 +2138,10 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -2094,14 +2138,10 @@ static int mxt_initialize(struct mxt_data *data)
if (error) { if (error) {
dev_err(&client->dev, "Failed to invoke firmware loader: %d\n", dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
error); error);
goto err_free_object_table; return error;
} }
return 0; return 0;
err_free_object_table:
mxt_free_object_table(data);
return error;
} }
static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
...@@ -2162,7 +2202,7 @@ static int mxt_init_t7_power_cfg(struct mxt_data *data) ...@@ -2162,7 +2202,7 @@ static int mxt_init_t7_power_cfg(struct mxt_data *data)
static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x, static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x,
unsigned int y) unsigned int y)
{ {
struct mxt_info *info = &data->info; struct mxt_info *info = data->info;
struct mxt_dbg *dbg = &data->dbg; struct mxt_dbg *dbg = &data->dbg;
unsigned int ofs, page; unsigned int ofs, page;
unsigned int col = 0; unsigned int col = 0;
...@@ -2490,7 +2530,7 @@ static const struct video_device mxt_video_device = { ...@@ -2490,7 +2530,7 @@ static const struct video_device mxt_video_device = {
static void mxt_debug_init(struct mxt_data *data) static void mxt_debug_init(struct mxt_data *data)
{ {
struct mxt_info *info = &data->info; struct mxt_info *info = data->info;
struct mxt_dbg *dbg = &data->dbg; struct mxt_dbg *dbg = &data->dbg;
struct mxt_object *object; struct mxt_object *object;
int error; int error;
...@@ -2576,7 +2616,6 @@ static int mxt_configure_objects(struct mxt_data *data, ...@@ -2576,7 +2616,6 @@ static int mxt_configure_objects(struct mxt_data *data,
const struct firmware *cfg) const struct firmware *cfg)
{ {
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
struct mxt_info *info = &data->info;
int error; int error;
error = mxt_init_t7_power_cfg(data); error = mxt_init_t7_power_cfg(data);
...@@ -2601,11 +2640,6 @@ static int mxt_configure_objects(struct mxt_data *data, ...@@ -2601,11 +2640,6 @@ static int mxt_configure_objects(struct mxt_data *data,
mxt_debug_init(data); mxt_debug_init(data);
dev_info(dev,
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
info->family_id, info->variant_id, info->version >> 4,
info->version & 0xf, info->build, info->object_num);
return 0; return 0;
} }
...@@ -2614,7 +2648,7 @@ static ssize_t mxt_fw_version_show(struct device *dev, ...@@ -2614,7 +2648,7 @@ static ssize_t mxt_fw_version_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mxt_data *data = dev_get_drvdata(dev); struct mxt_data *data = dev_get_drvdata(dev);
struct mxt_info *info = &data->info; struct mxt_info *info = data->info;
return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
info->version >> 4, info->version & 0xf, info->build); info->version >> 4, info->version & 0xf, info->build);
} }
...@@ -2624,7 +2658,7 @@ static ssize_t mxt_hw_version_show(struct device *dev, ...@@ -2624,7 +2658,7 @@ static ssize_t mxt_hw_version_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct mxt_data *data = dev_get_drvdata(dev); struct mxt_data *data = dev_get_drvdata(dev);
struct mxt_info *info = &data->info; struct mxt_info *info = data->info;
return scnprintf(buf, PAGE_SIZE, "%u.%u\n", return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
info->family_id, info->variant_id); info->family_id, info->variant_id);
} }
...@@ -2663,7 +2697,7 @@ static ssize_t mxt_object_show(struct device *dev, ...@@ -2663,7 +2697,7 @@ static ssize_t mxt_object_show(struct device *dev,
return -ENOMEM; return -ENOMEM;
error = 0; error = 0;
for (i = 0; i < data->info.object_num; i++) { for (i = 0; i < data->info->object_num; i++) {
object = data->object_table + i; object = data->object_table + i;
if (!mxt_object_readable(object->type)) if (!mxt_object_readable(object->type))
...@@ -3034,6 +3068,15 @@ static const struct dmi_system_id mxt_dmi_table[] = { ...@@ -3034,6 +3068,15 @@ static const struct dmi_system_id mxt_dmi_table[] = {
}, },
.driver_data = samus_platform_data, .driver_data = samus_platform_data,
}, },
{
/* Samsung Chromebook Pro */
.ident = "Samsung Chromebook Pro",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
DMI_MATCH(DMI_PRODUCT_NAME, "Caroline"),
},
.driver_data = samus_platform_data,
},
{ {
/* Other Google Chromebooks */ /* Other Google Chromebooks */
.ident = "Chromebook", .ident = "Chromebook",
...@@ -3254,6 +3297,11 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); ...@@ -3254,6 +3297,11 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
static const struct of_device_id mxt_of_match[] = { static const struct of_device_id mxt_of_match[] = {
{ .compatible = "atmel,maxtouch", }, { .compatible = "atmel,maxtouch", },
/* Compatibles listed below are deprecated */
{ .compatible = "atmel,qt602240_ts", },
{ .compatible = "atmel,atmel_mxt_ts", },
{ .compatible = "atmel,atmel_mxt_tp", },
{ .compatible = "atmel,mXT224", },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, mxt_of_match); MODULE_DEVICE_TABLE(of, mxt_of_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment