summaryrefslogtreecommitdiffstats
path: root/drivers/input/rmi4
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2017-02-20 15:16:02 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-02-20 15:16:02 -0800
commit6e11617fcff3688f70650a3e40addb0043dda137 (patch)
treea24f378c1a1e9f627ca1076a8b5bbd2ad7422630 /drivers/input/rmi4
parent722c5ac708b4f5c1fcfad5fed4c95234c8b06590 (diff)
parenta1b5359271e5c77d5ec8a575b379a6ba3e867097 (diff)
Merge branch 'next' into for-linus
Prepare input updates for 4.11 merge window.
Diffstat (limited to 'drivers/input/rmi4')
-rw-r--r--drivers/input/rmi4/Kconfig27
-rw-r--r--drivers/input/rmi4/rmi_2d_sensor.c7
-rw-r--r--drivers/input/rmi4/rmi_bus.c8
-rw-r--r--drivers/input/rmi4/rmi_driver.c21
-rw-r--r--drivers/input/rmi4/rmi_driver.h16
-rw-r--r--drivers/input/rmi4/rmi_f01.c104
-rw-r--r--drivers/input/rmi4/rmi_f03.c41
-rw-r--r--drivers/input/rmi4/rmi_f30.c352
-rw-r--r--drivers/input/rmi4/rmi_f34.c142
-rw-r--r--drivers/input/rmi4/rmi_f34.h4
-rw-r--r--drivers/input/rmi4/rmi_f34v7.c11
11 files changed, 493 insertions, 240 deletions
diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
index bb7762bf2879..7172b88cd064 100644
--- a/drivers/input/rmi4/Kconfig
+++ b/drivers/input/rmi4/Kconfig
@@ -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,13 +42,13 @@ config RMI4_SMB
called rmi_smbus.
config RMI4_F03
- bool "RMI4 Function 03 (PS2 Guest)"
+ bool "RMI4 Function 03 (PS2 Guest)"
depends on RMI4_CORE
- 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_F03_SERIO
tristate
@@ -57,12 +59,10 @@ config RMI4_F03_SERIO
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.
@@ -73,7 +73,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.
@@ -83,7 +82,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.
@@ -92,7 +90,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.
@@ -103,7 +100,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
@@ -115,9 +111,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
diff --git a/drivers/input/rmi4/rmi_2d_sensor.c b/drivers/input/rmi4/rmi_2d_sensor.c
index 07007ff8e29f..8bb866c7b985 100644
--- a/drivers/input/rmi4/rmi_2d_sensor.c
+++ b/drivers/input/rmi4/rmi_2d_sensor.c
@@ -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)
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 1c40d94ca506..ae1bffe45c75 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -55,7 +55,7 @@ static void rmi_release_device(struct device *dev)
kfree(rmi_dev);
}
-static struct device_type rmi_device_type = {
+static const struct device_type rmi_device_type = {
.name = "rmi4_sensor",
.release = rmi_release_device,
};
@@ -134,7 +134,7 @@ static void rmi_release_function(struct device *dev)
kfree(fn);
}
-static struct device_type rmi_function_type = {
+static const struct device_type rmi_function_type = {
.name = "rmi4_function",
.release = rmi_release_function,
};
@@ -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;
}
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index bf5c36e229ba..d64fc92858f2 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -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;
@@ -1049,7 +1062,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
data->irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
if (!data->irq_memory) {
dev_err(dev, "Failed to allocate memory for irq masks.\n");
- return retval;
+ return -ENOMEM;
}
data->irq_status = data->irq_memory + size * 0;
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 24f8f764d171..f1a2a2266022 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -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,20 @@ 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_F03
+int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button,
+ int value);
+void rmi_f03_commit_buttons(struct rmi_function *fn);
+#else
+static inline int rmi_f03_overwrite_button(struct rmi_function *fn,
+ unsigned int button, int value)
+{
+ return 0;
+}
+static inline void rmi_f03_commit_buttons(struct rmi_function *fn) {}
+#endif
#ifdef CONFIG_RMI4_F34
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev);
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 18baf4ceb940..7f7e9176f7ea 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -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,
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index 8a7ca3e2f95e..77dad045a468 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -26,15 +26,53 @@
#define RMI_F03_BYTES_PER_DEVICE_SHIFT 4
#define RMI_F03_QUEUE_LENGTH 0x0F
+#define PSMOUSE_OOB_EXTRA_BTNS 0x01
+
struct f03_data {
struct rmi_function *fn;
struct serio *serio;
+ unsigned int overwrite_buttons;
+
u8 device_count;
u8 rx_queue_length;
};
+int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button,
+ int value)
+{
+ struct f03_data *f03 = dev_get_drvdata(&fn->dev);
+ unsigned int bit;
+
+ if (button < BTN_LEFT || button > BTN_MIDDLE)
+ return -EINVAL;
+
+ bit = BIT(button - BTN_LEFT);
+
+ if (value)
+ f03->overwrite_buttons |= bit;
+ else
+ f03->overwrite_buttons &= ~bit;
+
+ return 0;
+}
+
+void rmi_f03_commit_buttons(struct rmi_function *fn)
+{
+ struct f03_data *f03 = dev_get_drvdata(&fn->dev);
+ struct serio *serio = f03->serio;
+
+ serio_pause_rx(serio);
+ if (serio->drv) {
+ serio->drv->interrupt(serio, PSMOUSE_OOB_EXTRA_BTNS,
+ SERIO_OOB_DATA);
+ serio->drv->interrupt(serio, f03->overwrite_buttons,
+ SERIO_OOB_DATA);
+ }
+ serio_continue_rx(serio);
+}
+
static int rmi_f03_pt_write(struct serio *id, unsigned char val)
{
struct f03_data *f03 = id->port_data;
@@ -175,9 +213,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) {
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
index f4b491e3e0fd..3422464af229 100644
--- a/drivers/input/rmi4/rmi_f30.c
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -16,30 +16,24 @@
/* Defs for Query 0 */
#define RMI_F30_EXTENDED_PATTERNS 0x01
-#define RMI_F30_HAS_MAPPABLE_BUTTONS (1 << 1)
-#define RMI_F30_HAS_LED (1 << 2)
-#define RMI_F30_HAS_GPIO (1 << 3)
-#define RMI_F30_HAS_HAPTIC (1 << 4)
-#define RMI_F30_HAS_GPIO_DRV_CTL (1 << 5)
-#define RMI_F30_HAS_MECH_MOUSE_BTNS (1 << 6)
+#define RMI_F30_HAS_MAPPABLE_BUTTONS BIT(1)
+#define RMI_F30_HAS_LED BIT(2)
+#define RMI_F30_HAS_GPIO BIT(3)
+#define RMI_F30_HAS_HAPTIC BIT(4)
+#define RMI_F30_HAS_GPIO_DRV_CTL BIT(5)
+#define RMI_F30_HAS_MECH_MOUSE_BTNS BIT(6)
/* Defs for Query 1 */
#define RMI_F30_GPIO_LED_COUNT 0x1F
/* Defs for Control Registers */
#define RMI_F30_CTRL_1_GPIO_DEBOUNCE 0x01
-#define RMI_F30_CTRL_1_HALT (1 << 4)
-#define RMI_F30_CTRL_1_HALTED (1 << 5)
+#define RMI_F30_CTRL_1_HALT BIT(4)
+#define RMI_F30_CTRL_1_HALTED BIT(5)
#define RMI_F30_CTRL_10_NUM_MECH_MOUSE_BTNS 0x03
-struct rmi_f30_ctrl_data {
- int address;
- int length;
- u8 *regs;
-};
-
#define RMI_F30_CTRL_MAX_REGS 32
-#define RMI_F30_CTRL_MAX_BYTES ((RMI_F30_CTRL_MAX_REGS + 7) >> 3)
+#define RMI_F30_CTRL_MAX_BYTES DIV_ROUND_UP(RMI_F30_CTRL_MAX_REGS, 8)
#define RMI_F30_CTRL_MAX_REG_BLOCKS 11
#define RMI_F30_CTRL_REGS_MAX_SIZE (RMI_F30_CTRL_MAX_BYTES \
@@ -54,6 +48,15 @@ struct rmi_f30_ctrl_data {
+ 1 \
+ 1)
+#define TRACKSTICK_RANGE_START 3
+#define TRACKSTICK_RANGE_END 6
+
+struct rmi_f30_ctrl_data {
+ int address;
+ int length;
+ u8 *regs;
+};
+
struct f30_data {
/* Query Data */
bool has_extended_pattern;
@@ -76,18 +79,21 @@ struct f30_data {
u16 *gpioled_key_map;
struct input_dev *input;
+
+ struct rmi_function *f03;
+ bool trackstick_buttons;
};
static int rmi_f30_read_control_parameters(struct rmi_function *fn,
struct f30_data *f30)
{
- struct rmi_device *rmi_dev = fn->rmi_dev;
- int error = 0;
+ int error;
- error = rmi_read_block(rmi_dev, fn->fd.control_base_addr,
- f30->ctrl_regs, f30->ctrl_regs_size);
+ error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
+ f30->ctrl_regs, f30->ctrl_regs_size);
if (error) {
- dev_err(&rmi_dev->dev, "%s : Could not read control registers at 0x%x error (%d)\n",
+ dev_err(&fn->dev,
+ "%s: Could not read control registers at 0x%x: %d\n",
__func__, fn->fd.control_base_addr, error);
return error;
}
@@ -95,24 +101,39 @@ static int rmi_f30_read_control_parameters(struct rmi_function *fn,
return 0;
}
+static void rmi_f30_report_button(struct rmi_function *fn,
+ struct f30_data *f30, unsigned int button)
+{
+ unsigned int reg_num = button >> 3;
+ unsigned int bit_num = button & 0x07;
+ u16 key_code = f30->gpioled_key_map[button];
+ bool key_down = !(f30->data_regs[reg_num] & BIT(bit_num));
+
+ if (f30->trackstick_buttons &&
+ button >= TRACKSTICK_RANGE_START &&
+ button <= TRACKSTICK_RANGE_END) {
+ rmi_f03_overwrite_button(f30->f03, key_code, key_down);
+ } else {
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "%s: call input report key (0x%04x) value (0x%02x)",
+ __func__, key_code, key_down);
+
+ input_report_key(f30->input, key_code, key_down);
+ }
+}
+
static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
{
struct f30_data *f30 = dev_get_drvdata(&fn->dev);
- struct rmi_device *rmi_dev = fn->rmi_dev;
- struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
- int retval;
- int gpiled = 0;
- int value = 0;
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
+ int error;
int i;
- int reg_num;
-
- if (!f30->input)
- return 0;
/* Read the gpi led data. */
if (drvdata->attn_data.data) {
if (drvdata->attn_data.size < f30->register_count) {
- dev_warn(&fn->dev, "F30 interrupted, but data is missing\n");
+ dev_warn(&fn->dev,
+ "F30 interrupted, but data is missing\n");
return 0;
}
memcpy(f30->data_regs, drvdata->attn_data.data,
@@ -120,72 +141,24 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
drvdata->attn_data.data += f30->register_count;
drvdata->attn_data.size -= f30->register_count;
} else {
- retval = rmi_read_block(rmi_dev, fn->fd.data_base_addr,
- f30->data_regs, f30->register_count);
-
- if (retval) {
- dev_err(&fn->dev, "%s: Failed to read F30 data registers.\n",
- __func__);
- return retval;
- }
- }
-
- for (reg_num = 0; reg_num < f30->register_count; ++reg_num) {
- for (i = 0; gpiled < f30->gpioled_count && i < 8; ++i,
- ++gpiled) {
- if (f30->gpioled_key_map[gpiled] != 0) {
- /* buttons have pull up resistors */
- value = (((f30->data_regs[reg_num] >> i) & 0x01)
- == 0);
-
- rmi_dbg(RMI_DEBUG_FN, &fn->dev,
- "%s: call input report key (0x%04x) value (0x%02x)",
- __func__,
- f30->gpioled_key_map[gpiled], value);
- input_report_key(f30->input,
- f30->gpioled_key_map[gpiled],
- value);
- }
-
+ error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
+ f30->data_regs, f30->register_count);
+ if (error) {
+ dev_err(&fn->dev,
+ "%s: Failed to read F30 data registers: %d\n",
+ __func__, error);
+ return error;
}
}
- return 0;
-}
-
-static int rmi_f30_register_device(struct rmi_function *fn)
-{
- int i;
- struct rmi_device *rmi_dev = fn->rmi_dev;
- struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
- struct f30_data *f30 = dev_get_drvdata(&fn->dev);
- struct input_dev *input_dev;
- int button_count = 0;
-
- input_dev = drv_data->input;
- if (!input_dev) {
- dev_info(&fn->dev, "F30: no input device found, ignoring.\n");
- return -EINVAL;
- }
-
- f30->input = input_dev;
-
- set_bit(EV_KEY, input_dev->evbit);
-
- input_dev->keycode = f30->gpioled_key_map;
- input_dev->keycodesize = sizeof(u16);
- input_dev->keycodemax = f30->gpioled_count;
-
- for (i = 0; i < f30->gpioled_count; i++) {
- if (f30->gpioled_key_map[i] != 0) {
- input_set_capability(input_dev, EV_KEY,
- f30->gpioled_key_map[i]);
- button_count++;
- }
+ if (f30->has_gpio) {
+ for (i = 0; i < f30->gpioled_count; i++)
+ if (f30->gpioled_key_map[i] != KEY_RESERVED)
+ rmi_f30_report_button(fn, f30, i);
+ if (f30->trackstick_buttons)
+ rmi_f03_commit_buttons(f30->f03);
}
- if (button_count == 1)
- __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
return 0;
}
@@ -197,6 +170,12 @@ static int rmi_f30_config(struct rmi_function *fn)
rmi_get_platform_data(fn->rmi_dev);
int error;
+ if (pdata->f30_data.trackstick_buttons) {
+ /* Try [re-]establish link to F03. */
+ f30->f03 = rmi_find_function(fn->rmi_dev, 0x03);
+ f30->trackstick_buttons = f30->f03 != NULL;
+ }
+
if (pdata->f30_data.disable) {
drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
} else {
@@ -204,19 +183,20 @@ static int rmi_f30_config(struct rmi_function *fn)
error = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
f30->ctrl_regs, f30->ctrl_regs_size);
if (error) {
- dev_err(&fn->rmi_dev->dev,
- "%s : Could not write control registers at 0x%x error (%d)\n",
+ dev_err(&fn->dev,
+ "%s: Could not write control registers at 0x%x: %d\n",
__func__, fn->fd.control_base_addr, error);
return error;
}
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
}
+
return 0;
}
-static inline void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl,
- int *ctrl_addr, int len, u8 **reg)
+static void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl,
+ int *ctrl_addr, int len, u8 **reg)
{
ctrl->address = *ctrl_addr;
ctrl->length = len;
@@ -225,8 +205,7 @@ static inline void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl,
*reg += len;
}
-static inline bool rmi_f30_is_valid_button(int button,
- struct rmi_f30_ctrl_data *ctrl)
+static bool rmi_f30_is_valid_button(int button, struct rmi_f30_ctrl_data *ctrl)
{
int byte_position = button >> 3;
int bit_position = button & 0x07;
@@ -239,32 +218,66 @@ static inline bool rmi_f30_is_valid_button(int button,
(ctrl[3].regs[byte_position] & BIT(bit_position));
}
-static inline int rmi_f30_initialize(struct rmi_function *fn)
+static int rmi_f30_map_gpios(struct rmi_function *fn,
+ struct f30_data *f30)
{
- struct f30_data *f30;
- struct rmi_device *rmi_dev = fn->rmi_dev;
- const struct rmi_device_platform_data *pdata;
- int retval = 0;
- int control_address;
+ const struct rmi_device_platform_data *pdata =
+ rmi_get_platform_data(fn->rmi_dev);
+ struct input_dev *input = f30->input;
+ unsigned int button = BTN_LEFT;
+ unsigned int trackstick_button = BTN_LEFT;
+ bool button_mapped = false;
int i;
- int button;
- u8 buf[RMI_F30_QUERY_SIZE];
- u8 *ctrl_reg;
- u8 *map_memory;
- f30 = devm_kzalloc(&fn->dev, sizeof(struct f30_data),
- GFP_KERNEL);
- if (!f30)
+ f30->gpioled_key_map = devm_kcalloc(&fn->dev,
+ f30->gpioled_count,
+ sizeof(f30->gpioled_key_map[0]),
+ GFP_KERNEL);
+ if (!f30->gpioled_key_map) {
+ dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
return -ENOMEM;
+ }
- dev_set_drvdata(&fn->dev, f30);
+ for (i = 0; i < f30->gpioled_count; i++) {
+ if (!rmi_f30_is_valid_button(i, f30->ctrl))
+ continue;
+
+ if (pdata->f30_data.trackstick_buttons &&
+ i >= TRACKSTICK_RANGE_START && i < TRACKSTICK_RANGE_END) {
+ f30->gpioled_key_map[i] = trackstick_button++;
+ } else if (!pdata->f30_data.buttonpad || !button_mapped) {
+ f30->gpioled_key_map[i] = button;
+ input_set_capability(input, EV_KEY, button++);
+ button_mapped = true;
+ }
+ }
+
+ input->keycode = f30->gpioled_key_map;
+ input->keycodesize = sizeof(f30->gpioled_key_map[0]);
+ input->keycodemax = f30->gpioled_count;
+
+ /*
+ * Buttonpad could be also inferred from f30->has_mech_mouse_btns,
+ * but I am not sure, so use only the pdata info.
+ */
+ if (pdata->f30_data.buttonpad)
+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
+ return 0;
+}
- retval = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, buf,
- RMI_F30_QUERY_SIZE);
+static int rmi_f30_initialize(struct rmi_function *fn, struct f30_data *f30)
+{
+ u8 *ctrl_reg = f30->ctrl_regs;
+ int control_address = fn->fd.control_base_addr;
+ u8 buf[RMI_F30_QUERY_SIZE];
+ int error;
- if (retval) {
- dev_err(&fn->dev, "Failed to read query register.\n");
- return retval;
+ error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
+ buf, RMI_F30_QUERY_SIZE);
+ if (error) {
+ dev_err(&fn->dev, "Failed to read query register\n");
+ return error;
}
f30->has_extended_pattern = buf[0] & RMI_F30_EXTENDED_PATTERNS;
@@ -276,101 +289,71 @@ static inline int rmi_f30_initialize(struct rmi_function *fn)
f30->has_mech_mouse_btns = buf[0] & RMI_F30_HAS_MECH_MOUSE_BTNS;
f30->gpioled_count = buf[1] & RMI_F30_GPIO_LED_COUNT;
- f30->register_count = (f30->gpioled_count + 7) >> 3;
-
- control_address = fn->fd.control_base_addr;
- ctrl_reg = f30->ctrl_regs;
+ f30->register_count = DIV_ROUND_UP(f30->gpioled_count, 8);
if (f30->has_gpio && f30->has_led)
rmi_f30_set_ctrl_data(&f30->ctrl[0], &control_address,
- f30->register_count, &ctrl_reg);
+ f30->register_count, &ctrl_reg);
- rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address, sizeof(u8),
- &ctrl_reg);
+ rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address,
+ sizeof(u8), &ctrl_reg);
if (f30->has_gpio) {
rmi_f30_set_ctrl_data(&f30->ctrl[2], &control_address,
- f30->register_count, &ctrl_reg);
+ f30->register_count, &ctrl_reg);
rmi_f30_set_ctrl_data(&f30->ctrl[3], &control_address,
- f30->register_count, &ctrl_reg);
+ f30->register_count, &ctrl_reg);
}
if (f30->has_led) {
- int ctrl5_len;
-
rmi_f30_set_ctrl_data(&f30->ctrl[4], &control_address,
- f30->register_count, &ctrl_reg);
-
- if (f30->has_extended_pattern)
- ctrl5_len = 6;
- else
- ctrl5_len = 2;
+ f30->register_count, &ctrl_reg);
rmi_f30_set_ctrl_data(&f30->ctrl[5], &control_address,
- ctrl5_len, &ctrl_reg);
+ f30->has_extended_pattern ? 6 : 2,
+ &ctrl_reg);
}
if (f30->has_led || f30->has_gpio_driver_control) {
/* control 6 uses a byte per gpio/led */
rmi_f30_set_ctrl_data(&f30->ctrl[6], &control_address,
- f30->gpioled_count, &ctrl_reg);
+ f30->gpioled_count, &ctrl_reg);
}
if (f30->has_mappable_buttons) {
/* control 7 uses a byte per gpio/led */
rmi_f30_set_ctrl_data(&f30->ctrl[7], &control_address,
- f30->gpioled_count, &ctrl_reg);
+ f30->gpioled_count, &ctrl_reg);
}
if (f30->has_haptic) {
rmi_f30_set_ctrl_data(&f30->ctrl[8], &control_address,
- f30->register_count, &ctrl_reg);
+ f30->register_count, &ctrl_reg);
rmi_f30_set_ctrl_data(&f30->ctrl[9], &control_address,
- sizeof(u8), &ctrl_reg);
+ sizeof(u8), &ctrl_reg);
}
if (f30->has_mech_mouse_btns)
rmi_f30_set_ctrl_data(&f30->ctrl[10], &control_address,
- sizeof(u8), &ctrl_reg);
+ sizeof(u8), &ctrl_reg);
- f30->ctrl_regs_size = ctrl_reg - f30->ctrl_regs
- ?: RMI_F30_CTRL_REGS_MAX_SIZE;
+ f30->ctrl_regs_size = ctrl_reg -
+ f30->ctrl_regs ?: RMI_F30_CTRL_REGS_MAX_SIZE;
- retval = rmi_f30_read_control_parameters(fn, f30);
- if (retval < 0) {
+ error = rmi_f30_read_control_parameters(fn, f30);
+ if (error) {
dev_err(&fn->dev,
- "Failed to initialize F19 control params.\n");
- return retval;
- }
-
- map_memory = devm_kzalloc(&fn->dev,
- (f30->gpioled_count * (sizeof(u16))),
- GFP_KERNEL);
- if (!map_memory) {
- dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
- return -ENOMEM;
+ "Failed to initialize F30 control params: %d\n",
+ error);
+ return error;
}
- f30->gpioled_key_map = (u16 *)map_memory;
-
- pdata = rmi_get_platform_data(rmi_dev);
if (f30->has_gpio) {
- button = BTN_LEFT;
- for (i = 0; i < f30->gpioled_count; i++) {
- if (rmi_f30_is_valid_button(i, f30->ctrl)) {
- f30->gpioled_key_map[i] = button++;
-
- /*
- * buttonpad might be given by
- * f30->has_mech_mouse_btns, but I am
- * not sure, so use only the pdata info
- */
- if (pdata->f30_data.buttonpad)
- break;
- }
- }
+ error = rmi_f30_map_gpios(fn, f30);
+ if (error)
+ return error;
}
return 0;
@@ -378,26 +361,33 @@ static inline int rmi_f30_initialize(struct rmi_function *fn)
static int rmi_f30_probe(struct rmi_function *fn)
{
- int rc;
+ struct rmi_device *rmi_dev = fn->rmi_dev;
const struct rmi_device_platform_data *pdata =
- rmi_get_platform_data(fn->rmi_dev);
+ rmi_get_platform_data(rmi_dev);
+ struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
+ struct f30_data *f30;
+ int error;
if (pdata->f30_data.disable)
return 0;
- rc = rmi_f30_initialize(fn);
- if (rc < 0)
- goto error_exit;
+ if (!drv_data->input) {
+ dev_info(&fn->dev, "F30: no input device found, ignoring\n");
+ return -ENXIO;
+ }
- rc = rmi_f30_register_device(fn);
- if (rc < 0)
-