Merge branch 'synaptics-rmi4' into next

Bring in latest RMI4 support in preparation to the merge window.
This commit is contained in:
Dmitry Torokhov 2017-02-06 14:17:39 -08:00
commit d5e6e0fa44
10 changed files with 268 additions and 57 deletions

View File

@ -9,9 +9,11 @@ config RMI4_CORE
If unsure, say Y.
if RMI4_CORE
config RMI4_I2C
tristate "RMI4 I2C Support"
depends on RMI4_CORE && I2C
depends on I2C
help
Say Y here if you want to support RMI4 devices connected to an I2C
bus.
@ -20,7 +22,7 @@ config RMI4_I2C
config RMI4_SPI
tristate "RMI4 SPI Support"
depends on RMI4_CORE && SPI
depends on SPI
help
Say Y here if you want to support RMI4 devices connected to a SPI
bus.
@ -29,7 +31,7 @@ config RMI4_SPI
config RMI4_SMB
tristate "RMI4 SMB Support"
depends on RMI4_CORE && I2C
depends on I2C
help
Say Y here if you want to support RMI4 devices connected to an SMB
bus.
@ -40,23 +42,20 @@ config RMI4_SMB
called rmi_smbus.
config RMI4_F03
bool "RMI4 Function 03 (PS2 Guest)"
depends on RMI4_CORE
bool "RMI4 Function 03 (PS2 Guest)"
depends on SERIO=y || RMI4_CORE=SERIO
help
Say Y here if you want to add support for RMI4 function 03.
help
Say Y here if you want to add support for RMI4 function 03.
Function 03 provides PS2 guest support for RMI4 devices. This
includes support for TrackPoints on TouchPads.
Function 03 provides PS2 guest support for RMI4 devices. This
includes support for TrackPoints on TouchPads.
config RMI4_2D_SENSOR
bool
depends on RMI4_CORE
config RMI4_F11
bool "RMI4 Function 11 (2D pointing)"
select RMI4_2D_SENSOR
depends on RMI4_CORE
help
Say Y here if you want to add support for RMI4 function 11.
@ -67,7 +66,6 @@ config RMI4_F11
config RMI4_F12
bool "RMI4 Function 12 (2D pointing)"
select RMI4_2D_SENSOR
depends on RMI4_CORE
help
Say Y here if you want to add support for RMI4 function 12.
@ -77,7 +75,6 @@ config RMI4_F12
config RMI4_F30
bool "RMI4 Function 30 (GPIO LED)"
depends on RMI4_CORE
help
Say Y here if you want to add support for RMI4 function 30.
@ -86,7 +83,6 @@ config RMI4_F30
config RMI4_F34
bool "RMI4 Function 34 (Device reflash)"
depends on RMI4_CORE
select FW_LOADER
help
Say Y here if you want to add support for RMI4 function 34.
@ -97,7 +93,6 @@ config RMI4_F34
config RMI4_F54
bool "RMI4 Function 54 (Analog diagnostics)"
depends on RMI4_CORE
depends on VIDEO_V4L2=y || (RMI4_CORE=m && VIDEO_V4L2=m)
select VIDEOBUF2_VMALLOC
select RMI4_F55
@ -109,9 +104,10 @@ config RMI4_F54
config RMI4_F55
bool "RMI4 Function 55 (Sensor tuning)"
depends on RMI4_CORE
help
Say Y here if you want to add support for RMI4 function 55
Function 55 provides access to the RMI4 touch sensor tuning
mechanism.
endif # RMI_CORE

View File

@ -144,8 +144,13 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
int input_flags = 0;
if (sensor->report_abs) {
if (sensor->axis_align.swap_axes)
if (sensor->axis_align.swap_axes) {
swap(sensor->max_x, sensor->max_y);
swap(sensor->axis_align.clip_x_low,
sensor->axis_align.clip_y_low);
swap(sensor->axis_align.clip_x_high,
sensor->axis_align.clip_y_high);
}
sensor->min_x = sensor->axis_align.clip_x_low;
if (sensor->axis_align.clip_x_high)

View File

@ -261,10 +261,10 @@ int __rmi_register_function_handler(struct rmi_function_handler *handler,
driver->probe = rmi_function_probe;
driver->remove = rmi_function_remove;
error = driver_register(&handler->driver);
error = driver_register(driver);
if (error) {
pr_err("driver_register() failed for %s, error: %d\n",
handler->driver.name, error);
driver->name, error);
return error;
}

View File

@ -265,6 +265,19 @@ static int rmi_irq_init(struct rmi_device *rmi_dev)
return 0;
}
struct rmi_function *rmi_find_function(struct rmi_device *rmi_dev, u8 number)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi_function *entry;
list_for_each_entry(entry, &data->function_list, node) {
if (entry->fd.function_number == number)
return entry;
}
return NULL;
}
static int suspend_one_function(struct rmi_function *fn)
{
struct rmi_function_handler *fh;
@ -364,7 +377,7 @@ static void rmi_driver_set_input_name(struct rmi_device *rmi_dev,
struct input_dev *input)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
char *device_name = rmi_f01_get_product_ID(data->f01_container);
const char *device_name = rmi_f01_get_product_ID(data->f01_container);
char *name;
name = devm_kasprintf(&rmi_dev->dev, GFP_KERNEL,
@ -836,7 +849,7 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
{
struct device *dev = &rmi_dev->dev;
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi_driver_data *data = dev_get_drvdata(dev);
int *current_irq_count = ctx;
struct rmi_function *fn;
int i;
@ -1040,7 +1053,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
}
if (data->bootloader_mode)
dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n");
dev_warn(dev, "Device in bootloader mode.\n");
data->irq_count = irq_count;
data->num_of_irq_regs = (data->irq_count + 7) / 8;

View File

@ -93,6 +93,7 @@ bool rmi_is_physical_driver(struct device_driver *);
int rmi_register_physical_driver(void);
void rmi_unregister_physical_driver(void);
void rmi_free_function_list(struct rmi_device *rmi_dev);
struct rmi_function *rmi_find_function(struct rmi_device *rmi_dev, u8 number);
int rmi_enable_sensor(struct rmi_device *rmi_dev);
int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
int (*callback)(struct rmi_device *rmi_dev, void *ctx,
@ -104,7 +105,7 @@ int rmi_init_functions(struct rmi_driver_data *data);
int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
const struct pdt_entry *pdt);
char *rmi_f01_get_product_ID(struct rmi_function *fn);
const char *rmi_f01_get_product_ID(struct rmi_function *fn);
#ifdef CONFIG_RMI4_F34
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev);

View File

@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <asm/unaligned.h>
#include "rmi_driver.h"
#define RMI_PRODUCT_ID_LENGTH 10
@ -54,6 +55,7 @@ struct f01_basic_properties {
u8 product_id[RMI_PRODUCT_ID_LENGTH + 1];
u16 productinfo;
u32 firmware_id;
u32 package_id;
};
/* F01 device status bits */
@ -220,8 +222,19 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
has_build_id_query = !!(queries[0] & BIT(1));
}
if (has_package_id_query)
if (has_package_id_query) {
ret = rmi_read_block(rmi_dev, prod_info_addr,
queries, sizeof(__le64));
if (ret) {
dev_err(&rmi_dev->dev,
"Failed to read package info: %d\n",
ret);
return ret;
}
props->package_id = get_unaligned_le64(queries);
prod_info_addr++;
}
if (has_build_id_query) {
ret = rmi_read_block(rmi_dev, prod_info_addr, queries,
@ -241,13 +254,90 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
return 0;
}
char *rmi_f01_get_product_ID(struct rmi_function *fn)
const char *rmi_f01_get_product_ID(struct rmi_function *fn)
{
struct f01_data *f01 = dev_get_drvdata(&fn->dev);
return f01->properties.product_id;
}
static ssize_t rmi_driver_manufacturer_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%d\n",
f01->properties.manufacturer_id);
}
static DEVICE_ATTR(manufacturer_id, 0444,
rmi_driver_manufacturer_id_show, NULL);
static ssize_t rmi_driver_dom_show(struct device *dev,
struct device_attribute *dattr, char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.dom);
}
static DEVICE_ATTR(date_of_manufacture, 0444, rmi_driver_dom_show, NULL);
static ssize_t rmi_driver_product_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.product_id);
}
static DEVICE_ATTR(product_id, 0444, rmi_driver_product_id_show, NULL);
static ssize_t rmi_driver_firmware_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", f01->properties.firmware_id);
}
static DEVICE_ATTR(firmware_id, 0444, rmi_driver_firmware_id_show, NULL);
static ssize_t rmi_driver_package_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
u32 package_id = f01->properties.package_id;
return scnprintf(buf, PAGE_SIZE, "%04x.%04x\n",
package_id & 0xffff, (package_id >> 16) & 0xffff);
}
static DEVICE_ATTR(package_id, 0444, rmi_driver_package_id_show, NULL);
static struct attribute *rmi_f01_attrs[] = {
&dev_attr_manufacturer_id.attr,
&dev_attr_date_of_manufacture.attr,
&dev_attr_product_id.attr,
&dev_attr_firmware_id.attr,
&dev_attr_package_id.attr,
NULL
};
static struct attribute_group rmi_f01_attr_group = {
.attrs = rmi_f01_attrs,
};
#ifdef CONFIG_OF
static int rmi_f01_of_probe(struct device *dev,
struct rmi_device_platform_data *pdata)
@ -480,9 +570,18 @@ static int rmi_f01_probe(struct rmi_function *fn)
dev_set_drvdata(&fn->dev, f01);
error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
if (error)
dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error);
return 0;
}
static void rmi_f01_remove(struct rmi_function *fn)
{
sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
}
static int rmi_f01_config(struct rmi_function *fn)
{
struct f01_data *f01 = dev_get_drvdata(&fn->dev);
@ -622,6 +721,7 @@ struct rmi_function_handler rmi_f01_handler = {
},
.func = 0x01,
.probe = rmi_f01_probe,
.remove = rmi_f01_remove,
.config = rmi_f01_config,
.attention = rmi_f01_attention,
.suspend = rmi_f01_suspend,

View File

@ -175,9 +175,6 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
int i;
int error;
if (!rmi_dev)
return -ENODEV;
if (drvdata->attn_data.data) {
/* First grab the data passed by the transport device */
if (drvdata->attn_data.size < ob_len) {

View File

@ -157,6 +157,9 @@ static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
i + 1, block_count);
data += f34->v5.block_size;
f34->update_progress += f34->v5.block_size;
f34->update_status = (f34->update_progress * 100) /
f34->update_size;
}
return 0;
@ -174,7 +177,7 @@ static int rmi_f34_write_config(struct f34_data *f34, const void *data)
F34_WRITE_CONFIG_BLOCK);
}
int rmi_f34_enable_flash(struct f34_data *f34)
static int rmi_f34_enable_flash(struct f34_data *f34)
{
return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG,
F34_ENABLE_WAIT_MS, true);
@ -184,9 +187,14 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
const struct rmi_f34_firmware *syn_fw)
{
struct rmi_function *fn = f34->fn;
u32 image_size = le32_to_cpu(syn_fw->image_size);
u32 config_size = le32_to_cpu(syn_fw->config_size);
int ret;
if (syn_fw->image_size) {
f34->update_progress = 0;
f34->update_size = image_size + config_size;
if (image_size) {
dev_info(&fn->dev, "Erasing firmware...\n");
ret = rmi_f34_command(f34, F34_ERASE_ALL,
F34_ERASE_WAIT_MS, true);
@ -194,18 +202,18 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
return ret;
dev_info(&fn->dev, "Writing firmware (%d bytes)...\n",
syn_fw->image_size);
image_size);
ret = rmi_f34_write_firmware(f34, syn_fw->data);
if (ret)
return ret;
}
if (syn_fw->config_size) {
if (config_size) {
/*
* We only need to erase config if we haven't updated
* firmware.
*/
if (!syn_fw->image_size) {
if (!image_size) {
dev_info(&fn->dev, "Erasing config...\n");
ret = rmi_f34_command(f34, F34_ERASE_CONFIG,
F34_ERASE_WAIT_MS, true);
@ -214,9 +222,8 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
}
dev_info(&fn->dev, "Writing config (%d bytes)...\n",
syn_fw->config_size);
ret = rmi_f34_write_config(f34,
&syn_fw->data[syn_fw->image_size]);
config_size);
ret = rmi_f34_write_config(f34, &syn_fw->data[image_size]);
if (ret)
return ret;
}
@ -224,21 +231,23 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
return 0;
}
int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
static int rmi_f34_update_firmware(struct f34_data *f34,
const struct firmware *fw)
{
const struct rmi_f34_firmware *syn_fw;
const struct rmi_f34_firmware *syn_fw =
(const struct rmi_f34_firmware *)fw->data;
u32 image_size = le32_to_cpu(syn_fw->image_size);
u32 config_size = le32_to_cpu(syn_fw->config_size);
int ret;
syn_fw = (const struct rmi_f34_firmware *)fw->data;
BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) !=
F34_FW_IMAGE_OFFSET);
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"FW size:%d, checksum:%08x, image_size:%d, config_size:%d\n",
(int)fw->size,
"FW size:%zd, checksum:%08x, image_size:%d, config_size:%d\n",
fw->size,
le32_to_cpu(syn_fw->checksum),
le32_to_cpu(syn_fw->image_size),
le32_to_cpu(syn_fw->config_size));
image_size, config_size);
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n",
@ -246,27 +255,25 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
(int)sizeof(syn_fw->product_id), syn_fw->product_id,
syn_fw->product_info[0], syn_fw->product_info[1]);
if (syn_fw->image_size &&
syn_fw->image_size != f34->v5.fw_blocks * f34->v5.block_size) {
if (image_size && image_size != f34->v5.fw_blocks * f34->v5.block_size) {
dev_err(&f34->fn->dev,
"Bad firmware image: fw size %d, expected %d\n",
syn_fw->image_size,
f34->v5.fw_blocks * f34->v5.block_size);
image_size, f34->v5.fw_blocks * f34->v5.block_size);
ret = -EILSEQ;
goto out;
}
if (syn_fw->config_size &&
syn_fw->config_size != f34->v5.config_blocks * f34->v5.block_size) {
if (config_size &&
config_size != f34->v5.config_blocks * f34->v5.block_size) {
dev_err(&f34->fn->dev,
"Bad firmware image: config size %d, expected %d\n",
syn_fw->config_size,
config_size,
f34->v5.config_blocks * f34->v5.block_size);
ret = -EILSEQ;
goto out;
}
if (syn_fw->image_size && !syn_fw->config_size) {
if (image_size && !config_size) {
dev_err(&f34->fn->dev, "Bad firmware image: no config data\n");
ret = -EILSEQ;
goto out;
@ -283,6 +290,63 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
return ret;
}
static int rmi_f34_status(struct rmi_function *fn)
{
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
/*
* The status is the percentage complete, or once complete,
* zero for success or a negative return code.
*/
return f34->update_status;
}
static ssize_t rmi_driver_bootloader_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct rmi_function *fn = data->f34_container;
struct f34_data *f34;
if (fn) {
f34 = dev_get_drvdata(&fn->dev);
if (f34->bl_version == 5)
return scnprintf(buf, PAGE_SIZE, "%c%c\n",
f34->bootloader_id[0],
f34->bootloader_id[1]);
else
return scnprintf(buf, PAGE_SIZE, "V%d.%d\n",
f34->bootloader_id[1],
f34->bootloader_id[0]);
}
return 0;
}
static DEVICE_ATTR(bootloader_id, 0444, rmi_driver_bootloader_id_show, NULL);
static ssize_t rmi_driver_configuration_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct rmi_function *fn = data->f34_container;
struct f34_data *f34;
if (fn) {
f34 = dev_get_drvdata(&fn->dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", f34->configuration_id);
}
return 0;
}
static DEVICE_ATTR(configuration_id, 0444,
rmi_driver_configuration_id_show, NULL);
static int rmi_firmware_update(struct rmi_driver_data *data,
const struct firmware *fw)
{
@ -346,7 +410,13 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
else
ret = rmi_f34_update_firmware(f34, fw);
dev_info(&f34->fn->dev, "Firmware update complete, status:%d\n", ret);
if (ret) {
f34->update_status = ret;
dev_err(&f34->fn->dev,
"Firmware update failed, status: %d\n", ret);
} else {
dev_info(&f34->fn->dev, "Firmware update complete\n");
}
rmi_disable_irq(rmi_dev, false);
@ -377,9 +447,6 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
return ret;
}
static int rmi_firmware_update(struct rmi_driver_data *data,
const struct firmware *fw);
static ssize_t rmi_driver_update_fw_store(struct device *dev,
struct device_attribute *dattr,
const char *buf, size_t count)
@ -414,8 +481,27 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev,
static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);
static ssize_t rmi_driver_update_fw_status_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
int update_status = 0;
if (data->f34_container)
update_status = rmi_f34_status(data->f34_container);
return scnprintf(buf, PAGE_SIZE, "%d\n", update_status);
}
static DEVICE_ATTR(update_fw_status, 0444,
rmi_driver_update_fw_status_show, NULL);
static struct attribute *rmi_firmware_attrs[] = {
&dev_attr_bootloader_id.attr,
&dev_attr_configuration_id.attr,
&dev_attr_update_fw.attr,
&dev_attr_update_fw_status.attr,
NULL
};
@ -441,8 +527,6 @@ static int rmi_f34_probe(struct rmi_function *fn)
/* v5 code only supported version 0, try V7 probe */
if (version > 0)
return rmi_f34v7_probe(f34);
else if (version != 0)
return -ENODEV;
f34->bl_version = 5;

View File

@ -301,6 +301,10 @@ struct f34_data {
unsigned char bootloader_id[5];
unsigned char configuration_id[CONFIG_ID_SIZE*2 + 1];
int update_status;
int update_progress;
int update_size;
union {
struct f34v5_data v5;
struct f34v7_data v7;

View File

@ -588,6 +588,7 @@ static int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34)
u16 block_count;
block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.ui_firmware) {
dev_err(&f34->fn->dev,
@ -604,6 +605,7 @@ static int rmi_f34v7_check_ui_config_size(struct f34_data *f34)
u16 block_count;
block_count = f34->v7.img.ui_config.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.ui_config) {
dev_err(&f34->fn->dev, "UI config size mismatch\n");
@ -618,6 +620,7 @@ static int rmi_f34v7_check_dp_config_size(struct f34_data *f34)
u16 block_count;
block_count = f34->v7.img.dp_config.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.dp_config) {
dev_err(&f34->fn->dev, "Display config size mismatch\n");
@ -632,6 +635,8 @@ static int rmi_f34v7_check_guest_code_size(struct f34_data *f34)
u16 block_count;
block_count = f34->v7.img.guest_code.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.guest_code) {
dev_err(&f34->fn->dev, "Guest code size mismatch\n");
return -EINVAL;
@ -645,6 +650,7 @@ static int rmi_f34v7_check_bl_config_size(struct f34_data *f34)
u16 block_count;
block_count = f34->v7.img.bl_config.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.bl_config) {
dev_err(&f34->fn->dev, "Bootloader config size mismatch\n");
@ -881,6 +887,9 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
block_ptr += (transfer * f34->v7.block_size);
remaining -= transfer;
f34->update_progress += transfer;
f34->update_status = (f34->update_progress * 100) /
f34->update_size;
} while (remaining);
return 0;
@ -1191,6 +1200,8 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw)
rmi_f34v7_read_queries_bl_version(f34);
f34->v7.image = fw->data;
f34->update_progress = 0;
f34->update_size = 0;
ret = rmi_f34v7_parse_image_info(f34);
if (ret < 0)