Commit af79ce47 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 subsystem updates from Dmitry Torokhov:

 - updated support for Synaptics RMI4 devices, including support for
   SMBus controllers, firmware update support, sensor tuning, and PS/2
   guest support

 - ALPS driver now supports tracksticks on SS5 controllers

 - i8042 now uses chassis info to skip selftest on Asus laptops as list
   of individual models became too unwieldy

 - miscellaneous fixes to other drivers

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (67 commits)
  Input: imx6ul_tsc - generalize the averaging property
  Input: drv260x - use generic device properties
  Input: drv260x - use temporary for &client->dev
  Input: drv260x - fix input device's parent assignment
  Input: synaptics-rmi4 - add support for F34 V7 bootloader
  Input: drv260x - fix initializing overdrive voltage
  Input: ALPS - fix protcol -> protocol
  Input: i8042 - comment #else/#endif of CONFIG_PNP
  Input: lpc32xx-keys - fix invalid error handling of a requested irq
  Input: synaptics-rmi4 - fix debug for sensor clip
  Input: synaptics-rmi4 - store the attn data in the driver
  Input: synaptics-rmi4 - allow to add attention data
  Input: synaptics-rmi4 - f03 - grab data passed by transport device
  Input: synaptics-rmi4 - add support for F03
  Input: imx6ul_tsc - convert int to u32
  Input: imx6ul_tsc - add mask when set REG_ADC_CFG
  Input: synaptics-rmi4 - have only one struct platform data
  Input: synaptics-rmi4 - remove EXPORT_SYMBOL_GPL for internal functions
  Input: synaptics-rmi4 - remove mutex calls while updating the firmware
  Input: drv2667 - fix misuse of regmap_update_bits
  ...
parents c07dee73 f26e8817
* Dialog DA9062/63 OnKey Module
* Dialog DA9061/62/63 OnKey Module
This module is part of the DA9062/DA9063. For more details about entire
chips see Documentation/devicetree/bindings/mfd/da9062.txt and
Documentation/devicetree/bindings/mfd/da9063.txt
This module is part of the DA9061/DA9062/DA9063. For more details about entire
DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
For DA9063 see Documentation/devicetree/bindings/mfd/da9063.txt
This module provides KEY_POWER, KEY_SLEEP and events.
This module provides the KEY_POWER event.
Required properties:
- compatible: should be one of:
dlg,da9062-onkey
dlg,da9063-onkey
- compatible: should be one of the following valid compatible string lines:
"dlg,da9061-onkey", "dlg,da9062-onkey"
"dlg,da9062-onkey"
"dlg,da9063-onkey"
Optional properties:
- dlg,disable-key-power : Disable power-down using a long key-press. If this
- dlg,disable-key-power : Disable power-down using a long key-press. If this
entry exists the OnKey driver will remove support for the KEY_POWER key
press. If this entry does not exist then by default the key-press
triggered power down is enabled and the OnKey will support both KEY_POWER
and KEY_SLEEP.
press when triggered using a long press of the OnKey.
Example:
pmic0: da9062@58 {
Example: DA9063
pmic0: da9063@58 {
onkey {
compatible = "dlg,da9063-onkey";
dlg,disable-key-power;
};
};
Example: DA9062
pmic0: da9062@58 {
onkey {
compatible = "dlg,da9062-onkey";
dlg,disable-key-power;
};
};
Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
pmic0: da9061@58 {
onkey {
compatible = "dlg,da9061-onkey", "dlg,da9062-onkey";
dlg,disable-key-power;
};
};
......@@ -17,6 +17,8 @@ Optional properties:
This value depends on the touch screen.
- pre-charge-time: the touch screen need some time to precharge.
This value depends on the touch screen.
- touchscreen-average-samples: Number of data samples which are averaged for
each read. Valid values are 1, 4, 8, 16 and 32.
Example:
tsc: tsc@02040000 {
......@@ -32,5 +34,6 @@ Example:
xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
measure-delay-time = <0xfff>;
pre-charge-time = <0xffff>;
touchscreen-average-samples = <32>;
status = "okay";
};
......@@ -18,6 +18,8 @@ Optional properties:
- touchscreen-inverted-y : See touchscreen.txt
- touchscreen-swapped-x-y : See touchscreen.txt
- silead,max-fingers : maximum number of fingers the touchscreen can detect
- vddio-supply : regulator phandle for controller VDDIO
- avdd-supply : regulator phandle for controller AVDD
Example:
......
......@@ -14,6 +14,9 @@ Optional properties for Touchscreens:
- touchscreen-fuzz-pressure : pressure noise value of the absolute input
device (arbitrary range dependent on the
controller)
- touchscreen-average-samples : Number of data samples which are averaged
for each read (valid values dependent on the
controller)
- touchscreen-inverted-x : X axis is inverted (boolean)
- touchscreen-inverted-y : Y axis is inverted (boolean)
- touchscreen-swapped-x-y : X and Y axis are swapped (boolean)
......
......@@ -134,6 +134,7 @@ static const struct xpad_device {
{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
......@@ -1044,9 +1045,9 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
packet->data[7] = 0x00;
packet->data[8] = strong / 512; /* left actuator */
packet->data[9] = weak / 512; /* right actuator */
packet->data[10] = 0xFF;
packet->data[11] = 0x00;
packet->data[12] = 0x00;
packet->data[10] = 0xFF; /* on period */
packet->data[11] = 0x00; /* off period */
packet->data[12] = 0xFF; /* repeat count */
packet->len = 13;
packet->pending = true;
break;
......
This diff is collapsed.
......@@ -30,10 +30,10 @@
#define DRV_NAME "gpio-keys-polled"
struct gpio_keys_button_data {
struct gpio_desc *gpiod;
int last_state;
int count;
int threshold;
int can_sleep;
};
struct gpio_keys_polled_dev {
......@@ -46,7 +46,7 @@ struct gpio_keys_polled_dev {
};
static void gpio_keys_button_event(struct input_polled_dev *dev,
struct gpio_keys_button *button,
const struct gpio_keys_button *button,
int state)
{
struct gpio_keys_polled_dev *bdev = dev->private;
......@@ -70,21 +70,22 @@ static void gpio_keys_button_event(struct input_polled_dev *dev,
}
static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
struct gpio_keys_button *button,
const struct gpio_keys_button *button,
struct gpio_keys_button_data *bdata)
{
int state;
if (bdata->can_sleep)
state = !!gpiod_get_value_cansleep(button->gpiod);
else
state = !!gpiod_get_value(button->gpiod);
gpio_keys_button_event(dev, button, state);
state = gpiod_get_value_cansleep(bdata->gpiod);
if (state < 0) {
dev_err(dev->input->dev.parent,
"failed to get gpio state: %d\n", state);
} else {
gpio_keys_button_event(dev, button, state);
if (state != bdata->last_state) {
bdata->count = 0;
bdata->last_state = state;
if (state != bdata->last_state) {
bdata->count = 0;
bdata->last_state = state;
}
}
}
......@@ -142,48 +143,35 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
pdata->disable(bdev->dev);
}
static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
static struct gpio_keys_platform_data *
gpio_keys_polled_get_devtree_pdata(struct device *dev)
{
struct gpio_keys_platform_data *pdata;
struct gpio_keys_button *button;
struct fwnode_handle *child;
int error;
int nbuttons;
nbuttons = device_get_child_node_count(dev);
if (nbuttons == 0)
return NULL;
return ERR_PTR(-EINVAL);
pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
button = (struct gpio_keys_button *)(pdata + 1);
pdata->buttons = button;
pdata->nbuttons = nbuttons;
pdata->rep = device_property_present(dev, "autorepeat");
device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
device_for_each_child_node(dev, child) {
struct gpio_desc *desc;
desc = devm_get_gpiod_from_child(dev, NULL, child);
if (IS_ERR(desc)) {
error = PTR_ERR(desc);
if (error != -EPROBE_DEFER)
dev_err(dev,
"Failed to get gpio flags, error: %d\n",
error);
fwnode_handle_put(child);
return ERR_PTR(error);
}
button = &pdata->buttons[pdata->nbuttons++];
button->gpiod = desc;
if (fwnode_property_read_u32(child, "linux,code", &button->code)) {
dev_err(dev, "Button without keycode: %d\n",
pdata->nbuttons - 1);
if (fwnode_property_read_u32(child, "linux,code",
&button->code)) {
dev_err(dev, "button without keycode\n");
fwnode_handle_put(child);
return ERR_PTR(-EINVAL);
}
......@@ -206,10 +194,9 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
if (fwnode_property_read_u32(child, "debounce-interval",
&button->debounce_interval))
button->debounce_interval = 5;
}
if (pdata->nbuttons == 0)
return ERR_PTR(-EINVAL);
button++;
}
return pdata;
}
......@@ -220,7 +207,7 @@ static void gpio_keys_polled_set_abs_params(struct input_dev *input,
int i, min = 0, max = 0;
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
const struct gpio_keys_button *button = &pdata->buttons[i];
if (button->type != EV_ABS || button->code != code)
continue;
......@@ -230,6 +217,7 @@ static void gpio_keys_polled_set_abs_params(struct input_dev *input,
if (button->value > max)
max = button->value;
}
input_set_abs_params(input, code, min, max, 0, 0);
}
......@@ -242,6 +230,7 @@ MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
static int gpio_keys_polled_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fwnode_handle *child = NULL;
const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
struct gpio_keys_polled_dev *bdev;
struct input_polled_dev *poll_dev;
......@@ -254,10 +243,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
pdata = gpio_keys_polled_get_devtree_pdata(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
if (!pdata) {
dev_err(dev, "missing platform data\n");
return -EINVAL;
}
}
if (!pdata->poll_interval) {
......@@ -300,20 +285,48 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
__set_bit(EV_REP, input->evbit);
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
const struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_keys_button_data *bdata = &bdev->data[i];
unsigned int type = button->type ?: EV_KEY;
if (button->wakeup) {
dev_err(dev, DRV_NAME " does not support wakeup\n");
fwnode_handle_put(child);
return -EINVAL;
}
/*
* Legacy GPIO number so request the GPIO here and
* convert it to descriptor.
*/
if (!button->gpiod && gpio_is_valid(button->gpio)) {
if (!dev_get_platdata(dev)) {
/* No legacy static platform data */
child = device_get_next_child_node(dev, child);
if (!child) {
dev_err(dev, "missing child device node\n");
return -EINVAL;
}
bdata->gpiod = devm_get_gpiod_from_child(dev, NULL,
child);
if (IS_ERR(bdata->gpiod)) {
error = PTR_ERR(bdata->gpiod);
if (error != -EPROBE_DEFER)
dev_err(dev,
"failed to get gpio: %d\n",
error);
fwnode_handle_put(child);
return error;
}
error = gpiod_direction_input(bdata->gpiod);
if (error) {
dev_err(dev, "Failed to configure GPIO %d as input: %d\n",
desc_to_gpio(bdata->gpiod), error);
fwnode_handle_put(child);
return error;
}
} else if (gpio_is_valid(button->gpio)) {
/*
* Legacy GPIO number so request the GPIO here and
* convert it to descriptor.
*/
unsigned flags = GPIOF_IN;
if (button->active_low)
......@@ -322,18 +335,21 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
error = devm_gpio_request_one(&pdev->dev, button->gpio,
flags, button->desc ? : DRV_NAME);
if (error) {
dev_err(dev, "unable to claim gpio %u, err=%d\n",
dev_err(dev,
"unable to claim gpio %u, err=%d\n",
button->gpio, error);
return error;
}
button->gpiod = gpio_to_desc(button->gpio);
bdata->gpiod = gpio_to_desc(button->gpio);
if (!bdata->gpiod) {
dev_err(dev,
"unable to convert gpio %u to descriptor\n",
button->gpio);
return -EINVAL;
}
}
if (IS_ERR(button->gpiod))
return PTR_ERR(button->gpiod);
bdata->can_sleep = gpiod_cansleep(button->gpiod);
bdata->last_state = -1;
bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
pdata->poll_interval);
......@@ -344,6 +360,8 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
button->code);
}
fwnode_handle_put(child);
bdev->poll_dev = poll_dev;
bdev->dev = dev;
bdev->pdata = pdata;
......
......@@ -182,7 +182,7 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0 || irq >= NR_IRQS) {
if (irq < 0) {
dev_err(&pdev->dev, "failed to get platform irq\n");
return -EINVAL;
}
......
......@@ -316,7 +316,7 @@ static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad)
error = of_property_read_u32(np, "marvell,debounce-interval",
&pdata->debounce_interval);
if (error) {
dev_err(dev, "failed to parse debpunce-interval\n");
dev_err(dev, "failed to parse debounce-interval\n");
return error;
}
......
......@@ -164,11 +164,18 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)
int error, col, row;
u8 reg, state, code;
/* Initial read of the key event FIFO */
error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
do {
error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
if (error < 0) {
dev_err(&keypad_data->client->dev,
"unable to read REG_KEY_EVENT_A\n");
break;
}
/* Assume that key code 0 signifies empty FIFO */
if (reg <= 0)
break;
/* Assume that key code 0 signifies empty FIFO */
while (error >= 0 && reg > 0) {
state = reg & KEY_EVENT_VALUE;
code = reg & KEY_EVENT_CODE;
......@@ -184,11 +191,7 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)
/* Read for next loop */
error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
}
if (error < 0)
dev_err(&keypad_data->client->dev,
"unable to read REG_KEY_EVENT_A\n");
} while (1);
input_sync(input);
}
......
......@@ -625,11 +625,12 @@ config INPUT_DA9055_ONKEY
will be called da9055_onkey.
config INPUT_DA9063_ONKEY
tristate "Dialog DA9062/63 OnKey"
tristate "Dialog DA9063/62/61 OnKey"
depends on MFD_DA9063 || MFD_DA9062
help
Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
as an input device capable of reporting the power button status.
Support the ONKEY of Dialog DA9063, DA9062 and DA9061 Power
Management ICs as an input device capable of reporting the
power button status.
To compile this driver as a module, choose M here: the module
will be called da9063_onkey.
......
......@@ -538,8 +538,13 @@ static int bma150_probe(struct i2c_client *client,
return -EIO;
}
/*
* Note if the IIO CONFIG_BMA180 driver is enabled we want to fail
* the probe for the bma180 as the iio driver is preferred.
*/
chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
if (chip_id != BMA150_CHIP_ID && chip_id != BMA180_CHIP_ID) {
if (chip_id != BMA150_CHIP_ID &&
(IS_ENABLED(CONFIG_BMA180) || chip_id != BMA180_CHIP_ID)) {
dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
return -EINVAL;
}
......@@ -643,7 +648,9 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
static const struct i2c_device_id bma150_id[] = {
{ "bma150", 0 },
#if !IS_ENABLED(CONFIG_BMA180)
{ "bma180", 0 },
#endif
{ "smb380", 0 },
{ "bma023", 0 },
{ }
......
/*
* OnKey device driver for DA9063 and DA9062 PMICs
* OnKey device driver for DA9063, DA9062 and DA9061 PMICs
* Copyright (C) 2015 Dialog Semiconductor Ltd.
*
* This program is free software; you can redistribute it and/or
......@@ -87,6 +87,7 @@ static const struct of_device_id da9063_compatible_reg_id_table[] = {
{ .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
{ },
};
MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
static void da9063_poll_on(struct work_struct *work)
{
......@@ -149,13 +150,13 @@ static void da9063_poll_on(struct work_struct *work)
* and then send shutdown command
*/
dev_dbg(&onkey->input->dev,
"Sending SHUTDOWN to DA9063 ...\n");
"Sending SHUTDOWN to PMIC ...\n");
error = regmap_write(onkey->regmap,
config->onkey_shutdown,
config->onkey_shutdown_mask);
if (error)
dev_err(&onkey->input->dev,
"Cannot SHUTDOWN DA9063: %d\n",
"Cannot SHUTDOWN PMIC: %d\n",
error);
}
}
......@@ -300,6 +301,6 @@ static struct platform_driver da9063_onkey_driver = {
module_platform_driver(da9063_onkey_driver);
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
......@@ -18,8 +18,6 @@
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/delay.h>
......@@ -27,7 +25,6 @@
#include <linux/regulator/consumer.h>
#include <dt-bindings/input/ti-drv260x.h>
#include <linux/platform_data/drv260x-pdata.h>
#define DRV260X_STATUS 0x0
#define DRV260X_MODE 0x1
......@@ -468,90 +465,39 @@ static const struct regmap_config drv260x_regmap_config = {
.cache_type = REGCACHE_NONE,
};
#ifdef CONFIG_OF
static int drv260x_parse_dt(struct device *dev,
struct drv260x_data *haptics)
{
struct device_node *np = dev->of_node;
unsigned int voltage;
int error;
error = of_property_read_u32(np, "mode", &haptics->mode);
if (error) {
dev_err(dev, "%s: No entry for mode\n", __func__);
return error;
}
error = of_property_read_u32(np, "library-sel", &haptics->library);
if (error) {
dev_err(dev, "%s: No entry for library selection\n",
__func__);
return error;
}
error = of_property_read_u32(np, "vib-rated-mv", &voltage);
if (!error)
haptics->rated_voltage = drv260x_calculate_voltage(voltage);
error = of_property_read_u32(np, "vib-overdrive-mv", &voltage);
if (!error)
haptics->overdrive_voltage = drv260x_calculate_voltage(voltage);
return 0;
}
#else
static inline int drv260x_parse_dt(struct device *dev,
struct drv260x_data *haptics)
{
dev_err(dev, "no platform data defined\n");
return -EINVAL;
}
#endif
static int drv260x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct drv260x_platform_data *pdata = dev_get_platdata(&client->dev);
struct device *dev = &client->dev;
struct drv260x_data *haptics;
u32 voltage;
int error;
haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
haptics = devm_kzalloc(dev, sizeof(*haptics), GFP_KERNEL);
if (!haptics)
return -ENOMEM;
haptics->rated_voltage = DRV260X_DEF_OD_CLAMP_VOLT;
haptics->rated_voltage = DRV260X_DEF_RATED_VOLT;
if (pdata) {
haptics->mode = pdata->mode;
haptics->library = pdata->library_selection;
if (pdata->vib_overdrive_voltage)
haptics->overdrive_voltage = drv260x_calculate_voltage(pdata->vib_overdrive_voltage);
if (pdata->vib_rated_voltage)
haptics->rated_voltage = drv260x_calculate_voltage(pdata->vib_rated_voltage);
} else if (client->dev.of_node) {
error = drv260x_parse_dt(&client->dev, haptics);
if (error)
return error;
} else {
dev_err(&client->dev, "Platform data not set\n");
return -ENODEV;
error = device_property_read_u32(dev, "mode", &haptics->mode);
if (error) {
dev_err(dev, "Can't fetch 'mode' property: %d\n", error);
return error;
}
if (haptics->mode < DRV260X_LRA_MODE ||
haptics->mode > DRV260X_ERM_MODE) {
dev_err(&client->dev,
"Vibrator mode is invalid: %i\n",
haptics->mode);
dev_err(dev, "Vibrator mode is invalid: %i\n", haptics->mode);
return -EINVAL;
}
error = device_property_read_u32(dev, "library-sel", &haptics->library);
if (error) {
dev_err(dev, "Can't fetch 'library-sel' property: %d\n", error);
return error;
}
if (haptics->library < DRV260X_LIB_EMPTY ||
haptics->library > DRV260X_ERM_LIB_F) {
dev_err(&client->dev,
dev_err(dev,
"Library value is invalid: %i\n", haptics->library);
return -EINVAL;
}
......@@ -559,40 +505,44 @@ static int drv260x_probe(struct i2c_client *client,
if (haptics->mode == DRV260X_LRA_MODE &&
haptics->library != DRV260X_LIB_EMPTY &&
haptics->library != DRV260X_LIB_LRA) {
dev_err(&client->dev,
"LRA Mode with ERM Library mismatch\n");
dev_err(dev, "LRA Mode with ERM Library mismatch\n");
return -EINVAL;
}
if (haptics->mode == DRV260X_ERM_MODE &&
(haptics->library == DRV260X_LIB_EMPTY ||
haptics->library == DRV260X_LIB_LRA)) {
dev_err(&client->dev,
"ERM Mode with LRA Library mismatch\n");
dev_err(dev, "ERM Mode with LRA Library mismatch\n");
return -EINVAL;
}
haptics->regulator = devm_regulator_get(&client->dev, "vbat");
error = device_property_read_u32(dev, "vib-rated-mv", &voltage);
haptics->rated_voltage = error ? DRV260X_DEF_RATED_VOLT :
drv260x_calculate_voltage(voltage);
error = device_property_read_u32(dev, "vib-overdrive-mv", &voltage);
haptics->overdrive_voltage = error ? DRV260X_DEF_OD_CLAMP_VOLT :
drv260x_calculate_voltage(voltage);
haptics->regulator = devm_regulator_get(dev, "vbat");
if (IS_ERR(haptics->regulator)) {
error = PTR_ERR(haptics->regulator);
dev_err(&client->dev,
"unable to get regulator, error: %d\n", error);
dev_err(dev, "unable to get regulator, error: %d\n", error);
return error;
}
haptics->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
haptics->enable_gpio = devm_gpiod_get_optional(dev, "enable",
GPIOD_OUT_HIGH);
if (IS_ERR(haptics->enable_gpio))
return PTR_ERR(haptics->enable_gpio);
haptics->input_dev = devm_input_allocate_device(&client->dev);
haptics->input_dev = devm_input_allocate_device(dev);
if (!haptics->input_dev) {
dev_err(&client->dev, "Failed to allocate input device\n");
return -ENOMEM;
}
haptics->input_dev->name = "drv260x:haptics";
haptics->input_dev->dev.parent = client->dev.parent;
haptics->input_dev->close = drv260x_close;
input_set_drvdata(haptics->input_dev, haptics);
input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
......@@ -600,8 +550,7 @@ static int drv260x_probe(struct i2c_client *client,
error = input_ff_create_memless(haptics->input_dev, NULL,
drv260x_haptics_play);
if (error) {
dev_err(&client->dev, "input_ff_create() failed: %d\n",
error);
dev_err(dev, "input_ff_create() failed: %d\n", error);
return error;
}
......@@ -613,21 +562,19 @@ static int drv260x_probe(struct i2c_client *client,
haptics->regmap = devm_regmap_init_i2c(client, &drv260x_regmap_config);
if (IS_ERR(haptics->regmap)) {
error = PTR_ERR(haptics->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
error);
dev_err(dev, "Failed to allocate register map: %d\n", error);
return error;
}
error = drv260x_init(haptics);
if (error) {
dev_err(&client->dev, "Device init failed: %d\n", error);
dev_err(dev, "Device init failed: %d\n", error);
return error;
}
error = input_register_device(haptics->input_dev);
if (error) {
dev_err(&client->dev, "couldn't register input device: %d\n",
error);
dev_err(dev, "couldn't register input device: %d\n", error);
return error;
}
......
......@@ -125,8 +125,8 @@ static void drv2665_close(struct input_dev *input)
cancel_work_sync(&haptics->work);
error = regmap_update_bits(haptics->regmap,
DRV2665_CTRL_2, DRV2665_STANDBY, 1);
error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
DRV2665_STANDBY, DRV2665_STANDBY);
if (error)
dev_err(&haptics->client->dev,
"Failed to enter standby mode: %d\n", error);
......@@ -240,7 +240,7 @@ static int __maybe_unused drv2665_suspend(struct device *dev)
if (haptics->input_dev->users) {
ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
DRV2665_STANDBY, 1);
DRV2665_STANDBY, DRV2665_STANDBY);
if (ret) {
dev_err(dev, "Failed to set standby mode\n");
regulator_disable(haptics->regulator);
......
......@@ -256,7 +256,7 @@ static void drv2667_close(struct input_dev *input)
cancel_work_sync(&haptics->work);
error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
DRV2667_STANDBY, 1);
DRV2667_STANDBY, DRV2667_STANDBY);
if (error)
dev_err(&haptics->client->dev,
"Failed to enter standby mode: %d\n", error);
......@@ -415,7 +415,7 @@ static int __maybe_unused drv2667_suspend(struct device *dev)
if (haptics->input_dev->users) {
ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
DRV2667_STANDBY, 1);
DRV2667_STANDBY, DRV2667_STANDBY);
if (ret) {
dev_err(dev, "Failed to set standby mode\n");
regulator_disable(haptics->regulator);
......
......@@ -17,6 +17,7 @@
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
/*
......@@ -92,7 +93,7 @@ soc_button_device_create(struct platform_device *pdev,
continue;
gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
if (gpio < 0)
if (!gpio_is_valid(gpio))
continue;
gpio_keys[n_buttons].type = info->event_type;
......@@ -166,6 +167,11 @@ static int soc_button_probe(struct platform_device *pdev)
button_info = (struct soc_button_info *)id->driver_data;
if (gpiod_count(&pdev->dev, KBUILD_MODNAME) <= 0) {
dev_dbg(&pdev->dev, "no GPIO attached, ignoring...\n");
return -ENODEV;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
......
......@@ -1153,15 +1153,13 @@ static void alps_process_packet_v7(struct psmouse *psmouse)
alps_process_touchpad_packet_v7(psmouse);
}
static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
static enum SS4_PACKET_ID alps_get_pkt_id_ss4_v2(unsigned char *byte)
{
unsigned char pkt_id = SS4_PACKET_ID_IDLE;
enum SS4_PACKET_ID pkt_id = SS4_PACKET_ID_IDLE;
switch (byte[3] & 0x30) {
case 0x00:
if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 &&
(byte[3] & 0x88) == 0x08 && byte[4] == 0x10 &&
byte[5] == 0x00) {
if (SS4_IS_IDLE_V2(byte)) {
pkt_id = SS4_PACKET_ID_IDLE;
} else {
pkt_id = SS4_PACKET_ID_ONE;
......@@ -1188,7 +1186,7 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
unsigned char *p, struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
unsigned char pkt_id;
enum SS4_PACKET_ID pkt_id;
unsigned int no_data_x, no_data_y;
pkt_id = alps_get_pkt_id_ss4_v2(p);
......@@ -1267,18 +1265,12 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
break;
case SS4_PACKET_ID_STICK:
if (!(priv->flags & ALPS_DUALPOINT)) {
psmouse_warn(psmouse,
"Rejected trackstick packet from non DualPoint device");
} else {
int x = (s8)(((p[0] & 1) << 7) | (p[1] & 0x7f));
int y = (s8)(((p[3] & 1) << 7) | (p[2] & 0x7f));
int pressure = (s8)(p[4] & 0x7f);
input_report_rel(priv->dev2, REL_X, x);
input_report_rel(priv->dev2, REL_Y, -y);
input_report_abs(priv->dev2, ABS_PRESSURE, pressure);
}
/*
* x, y, and pressure are decoded in
* alps_process_packet_ss4_v2()
*/
f->first_mp = 0;
f->is_mp = 0;
break;
case SS4_PACKET_ID_IDLE:
......@@ -1346,6 +1338,27 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
priv->multi_packet = 0;
/* Report trackstick */
if (alps_get_pkt_id_ss4_v2(packet) == SS4_PACKET_ID_STICK) {
if (!(priv->flags & ALPS_DUALPOINT)) {
psmouse_warn(psmouse,
"Rejected trackstick packet from non DualPoint device");
return;
}
input_report_rel(dev2, REL_X, SS4_TS_X_V2(packet));
input_report_rel(dev2, REL_Y, SS4_TS_Y_V2(packet));
input_report_abs(dev2, ABS_PRESSURE, SS4_TS_Z_V2(packet));
input_report_key(dev2, BTN_LEFT, f->ts_left);
input_report_key(dev2, BTN_RIGHT, f->ts_right);
input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
input_sync(dev2);
return;
}
/* Report touchpad */
alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4);
input_mt_report_finger_count(dev, f->fingers);
......@@ -1356,13 +1369,6 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
input_report_abs(dev, ABS_PRESSURE, f->pressure);
input_sync(dev);
if (priv->flags & ALPS_DUALPOINT) {
input_report_key(dev2, BTN_LEFT, f->ts_left);
input_report_key(dev2, BTN_RIGHT, f->ts_right);
input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
input_sync(dev2);
}
}
static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
......
......@@ -54,7 +54,15 @@ enum SS4_PACKET_ID {
#define SS4_MASK_NORMAL_BUTTONS 0x07
#define SS4_1F_X_V2(_b) ((_b[0] & 0x0007) | \
#define SS4_IS_IDLE_V2(_b) (((_b[0]) == 0x18) && \
((_b[1]) == 0x10) && \
((_b[2]) == 0x00) && \
((_b[3] & 0x88) == 0x08) && \
((_b[4]) == 0x10) && \
((_b[5]) == 0x00) \
)
#define SS4_1F_X_V2(_b) (((_b[0]) & 0x0007) | \
((_b[1] << 3) & 0x0078) | \
((_b[1] << 2) & 0x0380) | \
((_b[2] << 5) & 0x1C00) \
......@@ -101,6 +109,18 @@ enum SS4_PACKET_ID {
#define SS4_IS_MF_CONTINUE(_b) ((_b[2] & 0x10) == 0x10)
#define SS4_IS_5F_DETECTED(_b) ((_b[2] & 0x10) == 0x10)
#define SS4_TS_X_V2(_b) (s8)( \
((_b[0] & 0x01) << 7) | \
(_b[1] & 0x7F) \
)
#define SS4_TS_Y_V2(_b) (s8)( \
((_b[3] & 0x01) << 7) | \
(_b[2] & 0x7F) \
)
#define SS4_TS_Z_V2(_b) (s8)(_b[4] & 0x7F)
#define SS4_MFPACKET_NO_AX 8160 /* X-Coordinate value */
#define SS4_MFPACKET_NO_AY 4080 /* Y-Coordinate value */
......@@ -146,7 +166,7 @@ struct alps_protocol_info {
* (aka command mode response) identifies the firmware minor version. This
* can be used to distinguish different hardware models which are not
* uniquely identifiable through their E7 responses.
* @protocol_info: information about protcol used by the device.
* @protocol_info: information about protocol used by the device.
*
* Many (but not all) ALPS touchpads can be identified by looking at the
* values returned in the "E7 report" and/or the "EC report." This table
......
......@@ -1093,19 +1093,18 @@ static int elan_probe(struct i2c_client *client,
if (error)
return error;
dev_info(&client->dev,
"Elan Touchpad: Module ID: 0x%04x, Firmware: 0x%04x, Sample: 0x%04x, IAP: 0x%04x\n",
data->product_id,
data->fw_version,
data->sm_version,
data->iap_version);
dev_dbg(&client->dev,
"Elan Touchpad Information:\n"
" Module product ID: 0x%04x\n"
" Firmware Version: 0x%04x\n"
" Sample Version: 0x%04x\n"
" IAP Version: 0x%04x\n"
"Elan Touchpad Extra Information:\n"
" Max ABS X,Y: %d,%d\n"
" Width X,Y: %d,%d\n"
" Resolution X,Y: %d,%d (dots/mm)\n",
data->product_id,
data->fw_version,
data->sm_version,
data->iap_version,
data->max_x, data->max_y,
data->width_x, data->width_y,
data->x_res, data->y_res);
......
......@@ -27,6 +27,27 @@ config RMI4_SPI
If unsure, say N.
config RMI4_SMB
tristate "RMI4 SMB Support"
depends on RMI4_CORE && I2C
help
Say Y here if you want to support RMI4 devices connected to an SMB
bus.
If unsure, say N.
To compile this driver as a module, choose M here: the module will be
called rmi_smbus.
config RMI4_F03
bool "RMI4 Function 03 (PS2 Guest)"
depends on RMI4_CORE && SERIO
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.
config RMI4_2D_SENSOR
bool
depends on RMI4_CORE
......@@ -62,13 +83,34 @@ config RMI4_F30
Function 30 provides GPIO and LED support for RMI4 devices. This
includes support for buttons on TouchPads and ClickPads.
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.
Function 34 provides support for upgrading the firmware on the RMI4
device via the firmware loader interface. This is triggered using a
sysfs attribute.
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
help
Say Y here if you want to add support for RMI4 function 54
Function 54 provides access to various diagnostic features in certain
RMI4 touch sensors.
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.
......@@ -4,11 +4,15 @@ rmi_core-y := rmi_bus.o rmi_driver.o rmi_f01.o
rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
# Function drivers
rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
rmi_core-$(CONFIG_RMI4_F54) += rmi_f54.o
rmi_core-$(CONFIG_RMI4_F55) += rmi_f55.o
# Transports
obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o
obj-$(CONFIG_RMI4_SPI) += rmi_spi.o
obj-$(CONFIG_RMI4_SMB) += rmi_smbus.o
......@@ -177,10 +177,12 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
sensor->dmax = DMAX * res_x;
}
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
input_set_abs_params(input, ABS_MT_TOOL_TYPE,
0, MT_TOOL_MAX, 0, 0);
if (sensor->sensor_type == rmi_sensor_touchpad)
input_flags = INPUT_MT_POINTER;
......
......@@ -67,6 +67,8 @@ struct rmi_2d_sensor {
u8 report_rel;
u8 x_mm;
u8 y_mm;
enum rmi_reg_state dribble;
enum rmi_reg_state palm_detect;
};
int rmi_2d_sensor_of_probe(struct device *dev,
......
......@@ -230,6 +230,9 @@ int rmi_register_function(struct rmi_function *fn)
void rmi_unregister_function(struct rmi_function *fn)
{
rmi_dbg(RMI_DEBUG_CORE, &fn->dev, "Unregistering F%02X.\n",
fn->fd.function_number);
device_del(&fn->dev);
of_node_put(fn->dev.of_node);
put_device(&fn->dev);
......@@ -302,6 +305,9 @@ struct bus_type rmi_bus_type = {
static struct rmi_function_handler *fn_handlers[] = {
&rmi_f01_handler,
#ifdef CONFIG_RMI4_F03
&rmi_f03_handler,
#endif
#ifdef CONFIG_RMI4_F11
&rmi_f11_handler,
#endif
......@@ -311,9 +317,15 @@ static struct rmi_function_handler *fn_handlers[] = {
#ifdef CONFIG_RMI4_F30
&rmi_f30_handler,
#endif
#ifdef CONFIG_RMI4_F34
&rmi_f34_handler,
#endif
#ifdef CONFIG_RMI4_F54
&rmi_f54_handler,
#endif
#ifdef CONFIG_RMI4_F55
&rmi_f55_handler,
#endif
};
static void __rmi_unregister_function_handlers(int start_idx)
......
......@@ -104,6 +104,18 @@ rmi_get_platform_data(struct rmi_device *d)
bool rmi_is_physical_device(struct device *dev);
/**
* rmi_reset - reset a RMI4 device
* @d: Pointer to an RMI device
*
* Calls for a reset of each function implemented by a specific device.
* Returns 0 on success or a negative error code.
*/
static inline int rmi_reset(struct rmi_device *d)
{
return d->driver->reset_handler(d);
}
/**
* rmi_read - read a single byte
* @d: Pointer to an RMI device
......
This diff is collapsed.
......@@ -51,9 +51,6 @@ struct pdt_entry {
u8 function_number;
};
int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
u16 pdt_address);
#define RMI_REG_DESC_PRESENSE_BITS (32 * BITS_PER_BYTE)
#define RMI_REG_DESC_SUBPACKET_BITS (37 * BITS_PER_BYTE)
......@@ -95,12 +92,40 @@ bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
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);
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,
const struct pdt_entry *entry));
int rmi_probe_interrupts(struct rmi_driver_data *data);
void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake);
void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake);
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);
#ifdef CONFIG_RMI4_F34
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev);
void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev);
#else
static inline int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
{
return 0;
}
static inline void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev)
{
}
#endif /* CONFIG_RMI_F34 */
extern struct rmi_function_handler rmi_f01_handler;
extern struct rmi_function_handler rmi_f03_handler;
extern struct rmi_function_handler rmi_f11_handler;
extern struct rmi_function_handler rmi_f12_handler;
extern struct rmi_function_handler rmi_f30_handler;
extern struct rmi_function_handler rmi_f34_handler;
extern struct rmi_function_handler rmi_f54_handler;
extern struct rmi_function_handler rmi_f55_handler;
#endif
......@@ -62,6 +62,8 @@ struct f01_basic_properties {
#define RMI_F01_STATUS_CODE(status) ((status) & 0x0f)
/* The device has lost its configuration for some reason. */
#define RMI_F01_STATUS_UNCONFIGURED(status) (!!((status) & 0x80))
/* The device is in bootloader mode */
#define RMI_F01_STATUS_BOOTLOADER(status) ((status) & 0x40)
/* Control register bits */
......@@ -326,12 +328,12 @@ static int rmi_f01_probe(struct rmi_function *fn)
}
switch (pdata->power_management.nosleep) {
case RMI_F01_NOSLEEP_DEFAULT:
case RMI_REG_STATE_DEFAULT:
break;
case RMI_F01_NOSLEEP_OFF:
case RMI_REG_STATE_OFF:
f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_NOSLEEP_BIT;
break;
case RMI_F01_NOSLEEP_ON:
case RMI_REG_STATE_ON:
f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT;
break;
}
......@@ -593,6 +595,10 @@ static int rmi_f01_attention(struct rmi_function *fn,
return error;
}
if (RMI_F01_STATUS_BOOTLOADER(device_status))
dev_warn(&fn->dev,
"Device in bootloader mode, please update firmware\n");
if (RMI_F01_STATUS_UNCONFIGURED(device_status)) {
dev_warn(&fn->dev, "Device reset detected.\n");
error = rmi_dev->driver->reset_handler(rmi_dev);
......
/*
* Copyright (C) 2015-2016 Red Hat
* Copyright (C) 2015 Lyude Paul <thatslyude@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/serio.h>
#include <linux/notifier.h>
#include "rmi_driver.h"
#define RMI_F03_RX_DATA_OFB 0x01
#define RMI_F03_OB_SIZE 2
#define RMI_F03_OB_OFFSET 2
#define RMI_F03_OB_DATA_OFFSET 1
#define RMI_F03_OB_FLAG_TIMEOUT BIT(6)
#define RMI_F03_OB_FLAG_PARITY BIT(7)
#define RMI_F03_DEVICE_COUNT 0x07
#define RMI_F03_BYTES_PER_DEVICE 0x07
#define RMI_F03_BYTES_PER_DEVICE_SHIFT 4
#define RMI_F03_QUEUE_LENGTH 0x0F
struct f03_data {
struct rmi_function *fn;
struct serio *serio;
u8 device_count;
u8 rx_queue_length;
};
static int rmi_f03_pt_write(struct serio *id, unsigned char val)
{
struct f03_data *f03 = id->port_data;
int error;
rmi_dbg(RMI_DEBUG_FN, &f03->fn->dev,
"%s: Wrote %.2hhx to PS/2 passthrough address",
__func__, val);
error = rmi_write(f03->fn->rmi_dev, f03->fn->fd.data_base_addr, val);
if (error) {
dev_err(&f03->fn->dev,
"%s: Failed to write to F03 TX register (%d).\n",
__func__, error);
return error;
}
return 0;
}
static int rmi_f03_initialize(struct f03_data *f03)
{
struct rmi_function *fn = f03->fn;
struct device *dev = &fn->dev;
int error;
u8 bytes_per_device;
u8 query1;
u8 query2[RMI_F03_DEVICE_COUNT * RMI_F03_BYTES_PER_DEVICE];
size_t query2_len;
error = rmi_read(fn->rmi_dev, fn->fd.query_base_addr, &query1);
if (error) {
dev_err(dev, "Failed to read query register (%d).\n", error);
return error;
}
f03->device_count = query1 & RMI_F03_DEVICE_COUNT;
bytes_per_device = (query1 >> RMI_F03_BYTES_PER_DEVICE_SHIFT) &
RMI_F03_BYTES_PER_DEVICE;
query2_len = f03->device_count * bytes_per_device;
/*
* The first generation of image sensors don't have a second part to
* their f03 query, as such we have to set some of these values manually
*/
if (query2_len < 1) {
f03->device_count = 1;
f03->rx_queue_length = 7;
} else {
error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + 1,
query2, query2_len);
if (error) {
dev_err(dev,
"Failed to read second set of query registers (%d).\n",
error);
return error;
}
f03->rx_queue_length = query2[0] & RMI_F03_QUEUE_LENGTH;
}
return 0;
}
static int rmi_f03_register_pt(struct f03_data *f03)
{
struct serio *serio;
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
serio->id.type = SERIO_8042;
serio->write = rmi_f03_pt_write;
serio->port_data = f03;
strlcpy(serio->name, "Synaptics RMI4 PS/2 pass-through",
sizeof(serio->name));
strlcpy(serio->phys, "synaptics-rmi4-pt/serio1",
sizeof(serio->phys));
serio->dev.parent = &f03->fn->dev;
f03->serio = serio;
serio_register_port(serio);
return 0;
}
static int rmi_f03_probe(struct rmi_function *fn)
{
struct device *dev = &fn->dev;
struct f03_data *f03;
int error;
f03 = devm_kzalloc(dev, sizeof(struct f03_data), GFP_KERNEL);
if (!f03)
return -ENOMEM;
f03->fn = fn;
error = rmi_f03_initialize(f03);
if (error < 0)
return error;
if (f03->device_count != 1)
dev_warn(dev, "found %d devices on PS/2 passthrough",
f03->device_count);
dev_set_drvdata(dev, f03);
error = rmi_f03_register_pt(f03);
if (error)
return error;
return 0;
}
static int rmi_f03_config(struct rmi_function *fn)
{
fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
return 0;
}
static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
{
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
u16 data_addr = fn->fd.data_base_addr;
const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
u8 ob_status;
u8 ob_data;
unsigned int serio_flags;
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) {
dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
return 0;
}
memcpy(obs, drvdata->attn_data.data, ob_len);
drvdata->attn_data.data += ob_len;
drvdata->attn_data.size -= ob_len;
} else {
/* Grab all of the data registers, and check them for data */
error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
&obs, ob_len);
if (error) {
dev_err(&fn->dev,
"%s: Failed to read F03 output buffers: %d\n",
__func__, error);
serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
return error;
}
}
for (i = 0; i < ob_len; i += RMI_F03_OB_SIZE) {
ob_status = obs[i];
ob_data = obs[i + RMI_F03_OB_DATA_OFFSET];
serio_flags = 0;
if (!(ob_status & RMI_F03_RX_DATA_OFB))
continue;
if (ob_status & RMI_F03_OB_FLAG_TIMEOUT)
serio_flags |= SERIO_TIMEOUT;
if (ob_status & RMI_F03_OB_FLAG_PARITY)
serio_flags |= SERIO_PARITY;
rmi_dbg(RMI_DEBUG_FN, &fn->dev,
"%s: Received %.2hhx from PS2 guest T: %c P: %c\n",
__func__, ob_data,
serio_flags & SERIO_TIMEOUT ? 'Y' : 'N',
serio_flags & SERIO_PARITY ? 'Y' : 'N');
serio_interrupt(f03->serio, ob_data, serio_flags);
}
return 0;
}
static void rmi_f03_remove(struct rmi_function *fn)
{
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
serio_unregister_port(f03->serio);
}
struct rmi_function_handler rmi_f03_handler = {
.driver = {
.name = "rmi4_f03",
},
.func = 0x03,
.probe = rmi_f03_probe,
.config = rmi_f03_config,
.attention = rmi_f03_attention,
.remove = rmi_f03_remove,
};
MODULE_AUTHOR("Lyude Paul <thatslyude@gmail.com>");
MODULE_DESCRIPTION("RMI F03 module");
MODULE_LICENSE("GPL");
......@@ -571,31 +571,48 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger)
static void rmi_f11_finger_handler(struct f11_data *f11,
struct rmi_2d_sensor *sensor,
unsigned long *irq_bits, int num_irq_regs)
unsigned long *irq_bits, int num_irq_regs,
int size)
{
const u8 *f_state = f11->data.f_state;
u8 finger_state;
u8 i;
int abs_fingers;
int rel_fingers;
int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
num_irq_regs * 8);
int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
num_irq_regs * 8);
for (i = 0; i < sensor->nbr_fingers; i++) {
/* Possible of having 4 fingers per f_statet register */
finger_state = rmi_f11_parse_finger_state(f_state, i);
if (finger_state == F11_RESERVED) {
pr_err("Invalid finger state[%d]: 0x%02x", i,
finger_state);
continue;
}
if (abs_bits) {
if (abs_size > size)
abs_fingers = size / RMI_F11_ABS_BYTES;
else
abs_fingers = sensor->nbr_fingers;
for (i = 0; i < abs_fingers; i++) {
/* Possible of having 4 fingers per f_state register */
finger_state = rmi_f11_parse_finger_state(f_state, i);
if (finger_state == F11_RESERVED) {
pr_err("Invalid finger state[%d]: 0x%02x", i,
finger_state);
continue;
}
if (abs_bits)
rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i],
finger_state, i);
}
}
if (rel_bits) {
if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
else
rel_fingers = sensor->nbr_fingers;
if (rel_bits)
for (i = 0; i < rel_fingers; i++)
rmi_f11_rel_pos_report(f11, i);
}
......@@ -611,7 +628,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
sensor->nbr_fingers,
sensor->dmax);
for (i = 0; i < sensor->nbr_fingers; i++) {
for (i = 0; i < abs_fingers; i++) {
finger_state = rmi_f11_parse_finger_state(f_state, i);
if (finger_state == F11_RESERVED)
/* no need to send twice the error */
......@@ -1062,8 +1079,8 @@ static int rmi_f11_initialize(struct rmi_function *fn)
rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata);
if (rc)
return rc;
} else if (pdata->sensor_pdata) {
f11->sensor_pdata = *pdata->sensor_pdata;
} else {
f11->sensor_pdata = pdata->sensor_pdata;
}
f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait;
......@@ -1124,6 +1141,8 @@ static int rmi_f11_initialize(struct rmi_function *fn)
sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad;
sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking;
sensor->dmax = f11->sensor_pdata.dmax;
sensor->dribble = f11->sensor_pdata.dribble;
sensor->palm_detect = f11->sensor_pdata.palm_detect;
if (f11->sens_query.has_physical_props) {
sensor->x_mm = f11->sens_query.x_sensor_size_mm;
......@@ -1191,11 +1210,33 @@ static int rmi_f11_initialize(struct rmi_function *fn)
ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] =
sensor->axis_align.delta_y_threshold;
if (f11->sens_query.has_dribble)
ctrl->ctrl0_11[0] = ctrl->ctrl0_11[0] & ~BIT(6);
if (f11->sens_query.has_dribble) {
switch (sensor->dribble) {
case RMI_REG_STATE_OFF:
ctrl->ctrl0_11[0] &= ~BIT(6);
break;
case RMI_REG_STATE_ON:
ctrl->ctrl0_11[0] |= BIT(6);
break;
case RMI_REG_STATE_DEFAULT:
default:
break;
}
}
if (f11->sens_query.has_palm_det)
ctrl->ctrl0_11[11] = ctrl->ctrl0_11[11] & ~BIT(0);
if (f11->sens_query.has_palm_det) {
switch (sensor->palm_detect) {
case RMI_REG_STATE_OFF:
ctrl->ctrl0_11[11] &= ~BIT(0);
break;
case RMI_REG_STATE_ON:
ctrl->ctrl0_11[11] |= BIT(0);
break;
case RMI_REG_STATE_DEFAULT:
default:
break;
}
}
rc = f11_write_control_regs(fn, &f11->sens_query,
&f11->dev_controls, fn->fd.query_base_addr);
......@@ -1241,12 +1282,21 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
struct f11_data *f11 = dev_get_drvdata(&fn->dev);
u16 data_base_addr = fn->fd.data_base_addr;
int error;
int valid_bytes = f11->sensor.pkt_size;
if (rmi_dev->xport->attn_data) {
memcpy(f11->sensor.data_pkt, rmi_dev->xport->attn_data,
f11->sensor.attn_size);
rmi_dev->xport->attn_data += f11->sensor.attn_size;
rmi_dev->xport->attn_size -= f11->sensor.attn_size;
if (drvdata->attn_data.data) {
/*
* The valid data in the attention report is less then
* expected. Only process the complete fingers.
*/
if (f11->sensor.attn_size > drvdata->attn_data.size)
valid_bytes = drvdata->attn_data.size;
else
valid_bytes = f11->sensor.attn_size;
memcpy(f11->sensor.data_pkt, drvdata->attn_data.data,
valid_bytes);
drvdata->attn_data.data += f11->sensor.attn_size;
drvdata->attn_data.size -= f11->sensor.attn_size;
} else {
error = rmi_read_block(rmi_dev,
data_base_addr, f11->sensor.data_pkt,
......@@ -1256,7 +1306,7 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
}
rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
drvdata->num_of_irq_regs);
drvdata->num_of_irq_regs, valid_bytes);
return 0;
}
......
......@@ -26,9 +26,12 @@ enum rmi_f12_object_type {
RMI_F12_OBJECT_SMALL_OBJECT = 0x0D,
};
#define F12_DATA1_BYTES_PER_OBJ 8
struct f12_data {
struct rmi_2d_sensor sensor;
struct rmi_2d_sensor_platform_data sensor_pdata;
bool has_dribble;
u16 data_addr;
......@@ -68,10 +71,6 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
u8 buf[15];
int pitch_x = 0;
int pitch_y = 0;
int clip_x_low = 0;
int clip_x_high = 0;
int clip_y_low = 0;
int clip_y_high = 0;
int rx_receivers = 0;
int tx_receivers = 0;
int sensor_flags = 0;
......@@ -124,7 +123,9 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x low: %d x high: %d y low: %d y high: %d\n",
__func__, clip_x_low, clip_x_high, clip_y_low, clip_y_high);
__func__,
sensor->axis_align.clip_x_low, sensor->axis_align.clip_x_high,
sensor->axis_align.clip_y_low, sensor->axis_align.clip_y_high);
if (rmi_register_desc_has_subpacket(item, 3)) {
rx_receivers = buf[offset];
......@@ -146,12 +147,16 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
return 0;
}
static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1)
static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
{
int i;
struct rmi_2d_sensor *sensor = &f12->sensor;
int objects = f12->data1->num_subpackets;
if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
objects = size / F12_DATA1_BYTES_PER_OBJ;
for (i = 0; i < f12->data1->num_subpackets; i++) {
for (i = 0; i < objects; i++) {
struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
obj->type = RMI_2D_OBJECT_NONE;
......@@ -182,7 +187,7 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1)
rmi_2d_sensor_abs_process(sensor, obj, i);
data1 += 8;
data1 += F12_DATA1_BYTES_PER_OBJ;
}
if (sensor->kernel_tracking)
......@@ -192,7 +197,7 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1)
sensor->nbr_fingers,
sensor->dmax);
for (i = 0; i < sensor->nbr_fingers; i++)
for (i = 0; i < objects; i++)
rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
}
......@@ -201,14 +206,20 @@ static int rmi_f12_attention(struct rmi_function *fn,
{
int retval;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
struct rmi_2d_sensor *sensor = &f12->sensor;
if (rmi_dev->xport->attn_data) {
memcpy(sensor->data_pkt, rmi_dev->xport->attn_data,
sensor->attn_size);
rmi_dev->xport->attn_data += sensor->attn_size;
rmi_dev->xport->attn_size -= sensor->attn_size;
int valid_bytes = sensor->pkt_size;
if (drvdata->attn_data.data) {
if (sensor->attn_size > drvdata->attn_data.size)
valid_bytes = drvdata->attn_data.size;
else
valid_bytes = sensor->attn_size;
memcpy(sensor->data_pkt, drvdata->attn_data.data,
valid_bytes);
drvdata->attn_data.data += sensor->attn_size;
drvdata->attn_data.size -= sensor->attn_size;
} else {
retval = rmi_read_block(rmi_dev, f12->data_addr,
sensor->data_pkt, sensor->pkt_size);
......@@ -221,19 +232,83 @@ static int rmi_f12_attention(struct rmi_function *fn,
if (f12->data1)
rmi_f12_process_objects(f12,
&sensor->data_pkt[f12->data1_offset]);
&sensor->data_pkt[f12->data1_offset], valid_bytes);
input_mt_sync_frame(sensor->input);
return 0;
}
static int rmi_f12_write_control_regs(struct rmi_function *fn)
{
int ret;
const struct rmi_register_desc_item *item;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
int control_size;
char buf[3];
u16 control_offset = 0;
u8 subpacket_offset = 0;
if (f12->has_dribble
&& (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
if (item) {
control_offset = rmi_register_desc_calc_reg_offset(
&f12->control_reg_desc, 20);
/*
* The byte containing the EnableDribble bit will be
* in either byte 0 or byte 2 of control 20. Depending
* on the existence of subpacket 0. If control 20 is
* larger then 3 bytes, just read the first 3.
*/
control_size = min(item->reg_size, 3UL);
ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
+ control_offset, buf, control_size);
if (ret)
return ret;
if (rmi_register_desc_has_subpacket(item, 0))
subpacket_offset += 1;
switch (f12->sensor.dribble) {
case RMI_REG_STATE_OFF:
buf[subpacket_offset] &= ~BIT(2);
break;
case RMI_REG_STATE_ON:
buf[subpacket_offset] |= BIT(2);
break;
case RMI_REG_STATE_DEFAULT:
default:
break;
}
ret = rmi_write_block(rmi_dev,
fn->fd.control_base_addr + control_offset,
buf, control_size);
if (ret)
return ret;
}
}
return 0;
}
static int rmi_f12_config(struct rmi_function *fn)
{
struct rmi_driver *drv = fn->rmi_dev->driver;
int ret;
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
ret = rmi_f12_write_control_regs(fn);
if (ret)
dev_warn(&fn->dev,
"Failed to write F12 control registers: %d\n", ret);
return 0;
}
......@@ -247,7 +322,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
const struct rmi_register_desc_item *item;
struct rmi_2d_sensor *sensor;
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_transport_dev *xport = rmi_dev->xport;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
u16 data_offset = 0;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
......@@ -260,7 +335,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
++query_addr;
if (!(buf & 0x1)) {
if (!(buf & BIT(0))) {
dev_err(&fn->dev,
"Behavior of F12 without register descriptors is undefined.\n");
return -ENODEV;
......@@ -270,12 +345,14 @@ static int rmi_f12_probe(struct rmi_function *fn)
if (!f12)
return -ENOMEM;
f12->has_dribble = !!(buf & BIT(3));
if (fn->dev.of_node) {
ret = rmi_2d_sensor_of_probe(&fn->dev, &f12->sensor_pdata);
if (ret)
return ret;
} else if (pdata->sensor_pdata) {
f12->sensor_pdata = *pdata->sensor_pdata;
} else {
f12->sensor_pdata = pdata->sensor_pdata;
}
ret = rmi_read_register_desc(rmi_dev, query_addr,
......@@ -318,6 +395,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
sensor->x_mm = f12->sensor_pdata.x_mm;
sensor->y_mm = f12->sensor_pdata.y_mm;
sensor->dribble = f12->sensor_pdata.dribble;
if (sensor->sensor_type == rmi_sensor_default)
sensor->sensor_type =
......@@ -343,7 +421,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
* HID attention reports.
*/
item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
......@@ -357,15 +435,15 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
......@@ -377,22 +455,22 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
if (item && !xport->attn_data) {
if (item && !drvdata->attn_data.data) {
f12->data6 = item;
f12->data6_offset = data_offset;
data_offset += item->reg_size;
}
item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
if (item && !xport->attn_data) {
if (item && !drvdata->attn_data.data) {
f12->data9 = item;
f12->data9_offset = data_offset;
data_offset += item->reg_size;
......@@ -401,27 +479,27 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
if (item && !xport->attn_data)
if (item && !drvdata->attn_data.data)
data_offset += item->reg_size;
item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
if (item && !xport->attn_data) {
if (item && !drvdata->attn_data.data) {
f12->data15 = item;
f12->data15_offset = data_offset;
data_offset += item->reg_size;
......
......@@ -99,6 +99,7 @@ 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;
......@@ -109,11 +110,15 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
return 0;
/* Read the gpi led data. */
if (rmi_dev->xport->attn_data) {
memcpy(f30->data_regs, rmi_dev->xport->attn_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");
return 0;
}
memcpy(f30->data_regs, drvdata->attn_data.data,
f30->register_count);
rmi_dev->xport->attn_data += f30->register_count;
rmi_dev->xport->attn_size -= f30->register_count;
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);
......@@ -192,7 +197,7 @@ static int rmi_f30_config(struct rmi_function *fn)
rmi_get_platform_data(fn->rmi_dev);
int error;
if (pdata->f30_data && pdata->f30_data->disable) {
if (pdata->f30_data.disable) {
drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
} else {
/* Write Control Register values back to device */
......@@ -351,7 +356,7 @@ static inline int rmi_f30_initialize(struct rmi_function *fn)
f30->gpioled_key_map = (u16 *)map_memory;
pdata = rmi_get_platform_data(rmi_dev);
if (pdata && f30->has_gpio) {
if (f30->has_gpio) {
button = BTN_LEFT;
for (i = 0; i < f30->gpioled_count; i++) {
if (rmi_f30_is_valid_button(i, f30->ctrl)) {
......@@ -362,8 +367,7 @@ static inline int rmi_f30_initialize(struct rmi_function *fn)
* f30->has_mech_mouse_btns, but I am
* not sure, so use only the pdata info
*/
if (pdata->f30_data &&
pdata->f30_data->buttonpad)
if (pdata->f30_data.buttonpad)
break;
}
}
......@@ -378,7 +382,7 @@ static int rmi_f30_probe(struct rmi_function *fn)
const struct rmi_device_platform_data *pdata =
rmi_get_platform_data(fn->rmi_dev);
if (pdata->f30_data && pdata->f30_data->disable)
if (pdata->f30_data.disable)
return 0;
rc = rmi_f30_initialize(fn);
......
This diff is collapsed.
/*
* Copyright (c) 2007-2016, Synaptics Incorporated
* Copyright (C) 2016 Zodiac Inflight Innovations
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#ifndef _RMI_F34_H
#define _RMI_F34_H
/* F34 image file offsets. */
#define F34_FW_IMAGE_OFFSET 0x100
/* F34 register offsets. */
#define F34_BLOCK_DATA_OFFSET 2
/* F34 commands */
#define F34_WRITE_FW_BLOCK 0x2
#define F34_ERASE_ALL 0x3
#define F34_READ_CONFIG_BLOCK 0x5
#define F34_WRITE_CONFIG_BLOCK 0x6
#define F34_ERASE_CONFIG 0x7
#define F34_ENABLE_FLASH_PROG 0xf
#define F34_STATUS_IN_PROGRESS 0xff
#define F34_STATUS_IDLE 0x80
#define F34_IDLE_WAIT_MS 500
#define F34_ENABLE_WAIT_MS 300
#define F34_ERASE_WAIT_MS 5000
#define F34_BOOTLOADER_ID_LEN 2
/* F34 V7 defines */
#define V7_FLASH_STATUS_OFFSET 0
#define V7_PARTITION_ID_OFFSET 1
#define V7_BLOCK_NUMBER_OFFSET 2
#define V7_TRANSFER_LENGTH_OFFSET 3
#define V7_COMMAND_OFFSET 4
#define V7_PAYLOAD_OFFSET 5
#define V7_BOOTLOADER_ID_OFFSET 1
#define IMAGE_HEADER_VERSION_10 0x10
#define CONFIG_ID_SIZE 32
#define PRODUCT_ID_SIZE 10
#define ENABLE_WAIT_MS (1 * 1000)
#define WRITE_WAIT_MS (3 * 1000)
#define MIN_SLEEP_TIME_US 50
#define MAX_SLEEP_TIME_US 100
#define HAS_BSR BIT(5)
#define HAS_CONFIG_ID BIT(3)
#define HAS_GUEST_CODE BIT(6)
#define HAS_DISP_CFG BIT(5)
/* F34 V7 commands */
#define CMD_V7_IDLE 0
#define CMD_V7_ENTER_BL 1
#define CMD_V7_READ 2
#define CMD_V7_WRITE 3
#define CMD_V7_ERASE 4
#define CMD_V7_ERASE_AP 5
#define CMD_V7_SENSOR_ID 6
#define v7_CMD_IDLE 0
#define v7_CMD_WRITE_FW 1
#define v7_CMD_WRITE_CONFIG 2
#define v7_CMD_WRITE_LOCKDOWN 3
#define v7_CMD_WRITE_GUEST_CODE 4
#define v7_CMD_READ_CONFIG 5
#define v7_CMD_ERASE_ALL 6
#define v7_CMD_ERASE_UI_FIRMWARE 7
#define v7_CMD_ERASE_UI_CONFIG 8
#define v7_CMD_ERASE_BL_CONFIG 9
#define v7_CMD_ERASE_DISP_CONFIG 10
#define v7_CMD_ERASE_FLASH_CONFIG 11
#define v7_CMD_ERASE_GUEST_CODE 12
#define v7_CMD_ENABLE_FLASH_PROG 13
#define v7_UI_CONFIG_AREA 0
#define v7_PM_CONFIG_AREA 1
#define v7_BL_CONFIG_AREA 2
#define v7_DP_CONFIG_AREA 3
#define v7_FLASH_CONFIG_AREA 4
/* F34 V7 partition IDs */
#define BOOTLOADER_PARTITION 1
#define DEVICE_CONFIG_PARTITION 2
#define FLASH_CONFIG_PARTITION 3
#define MANUFACTURING_BLOCK_PARTITION 4
#define GUEST_SERIALIZATION_PARTITION 5
#define GLOBAL_PARAMETERS_PARTITION 6
#define CORE_CODE_PARTITION 7
#define CORE_CONFIG_PARTITION 8
#define GUEST_CODE_PARTITION 9
#define DISPLAY_CONFIG_PARTITION 10
/* F34 V7 container IDs */
#define TOP_LEVEL_CONTAINER 0
#define UI_CONTAINER 1
#define UI_CONFIG_CONTAINER 2
#define BL_CONTAINER 3
#define BL_IMAGE_CONTAINER 4
#define BL_CONFIG_CONTAINER 5
#define BL_LOCKDOWN_INFO_CONTAINER 6
#define PERMANENT_CONFIG_CONTAINER 7
#define GUEST_CODE_CONTAINER 8
#define BL_PROTOCOL_DESCRIPTOR_CONTAINER 9
#define UI_PROTOCOL_DESCRIPTOR_CONTAINER 10
#define RMI_SELF_DISCOVERY_CONTAINER 11
#define RMI_PAGE_CONTENT_CONTAINER 12
#define GENERAL_INFORMATION_CONTAINER 13
#define DEVICE_CONFIG_CONTAINER 14
#define FLASH_CONFIG_CONTAINER 15
#define GUEST_SERIALIZATION_CONTAINER 16
#define GLOBAL_PARAMETERS_CONTAINER 17
#define CORE_CODE_CONTAINER 18
#define CORE_CONFIG_CONTAINER 19
#define DISPLAY_CONFIG_CONTAINER 20
struct f34v7_query_1_7 {
u8 bl_minor_revision; /* query 1 */
u8 bl_major_revision;
__le32 bl_fw_id; /* query 2 */
u8 minimum_write_size; /* query 3 */
__le16 block_size;
__le16 flash_page_size;
__le16 adjustable_partition_area_size; /* query 4 */
__le16 flash_config_length; /* query 5 */
__le16 payload_length; /* query 6 */
u8 partition_support[4]; /* query 7 */
} __packed;
struct f34v7_data_1_5 {
u8 partition_id;
__le16 block_offset;
__le16 transfer_length;
u8 command;
u8 payload[2];
} __packed;
struct block_data {
const void *data;
int size;
};
struct partition_table {
u8 partition_id;
u8 byte_1_reserved;
__le16 partition_length;
__le16 start_physical_address;
__le16 partition_properties;
} __packed;
struct physical_address {
u16 ui_firmware;
u16 ui_config;
u16 dp_config;
u16 guest_code;
};
struct container_descriptor {
__le32 content_checksum;
__le16 container_id;
u8 minor_version;
u8 major_version;
u8 reserved_08;
u8 reserved_09;
u8 reserved_0a;
u8 reserved_0b;
u8 container_option_flags[4];
__le32 content_options_length;
__le32 content_options_address;
__le32 content_length;
__le32 content_address;
} __packed;
struct block_count {
u16 ui_firmware;
u16 ui_config;
u16 dp_config;
u16 fl_config;
u16 pm_config;
u16 bl_config;
u16 lockdown;
u16 guest_code;
};
struct image_header_10 {
__le32 checksum;
u8 reserved_04;
u8 reserved_05;
u8 minor_header_version;
u8 major_header_version;
u8 reserved_08;
u8 reserved_09;
u8 reserved_0a;
u8 reserved_0b;
__le32 top_level_container_start_addr;
};
struct image_metadata {
bool contains_firmware_id;
bool contains_bootloader;
bool contains_display_cfg;
bool contains_guest_code;
bool contains_flash_config;
unsigned int firmware_id;
unsigned int checksum;
unsigned int bootloader_size;
unsigned int display_cfg_offset;
unsigned char bl_version;
unsigned char product_id[PRODUCT_ID_SIZE + 1];
unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1];
struct block_data bootloader;
struct block_data ui_firmware;
struct block_data ui_config;
struct block_data dp_config;
struct block_data fl_config;
struct block_data bl_config;
struct block_data guest_code;
struct block_data lockdown;
struct block_count blkcount;
struct physical_address phyaddr;
};
struct register_offset {
u8 properties;
u8 properties_2;
u8 block_size;
u8 block_count;
u8 gc_block_count;
u8 flash_status;
u8 partition_id;
u8 block_number;
u8 transfer_length;
u8 flash_cmd;
u8 payload;
};
struct rmi_f34_firmware {
__le32 checksum;
u8 pad1[3];
u8 bootloader_version;
__le32 image_size;
__le32 config_size;
u8 product_id[10];
u8 product_info[2];
u8 pad2[228];
u8 data[];
};
struct f34v5_data {
u16 block_size;
u16 fw_blocks;
u16 config_blocks;
u16 ctrl_address;
u8 status;
struct completion cmd_done;
struct mutex flash_mutex;
};
struct f34v7_data {
bool has_display_cfg;
bool has_guest_code;
bool force_update;
bool in_bl_mode;
u8 *read_config_buf;
size_t read_config_buf_size;
u8 command;
u8 flash_status;
u16 block_size;
u16 config_block_count;
u16 config_size;
u16 config_area;
u16 flash_config_length;
u16 payload_length;
u8 partitions;
u16 partition_table_bytes;
bool new_partition_table;
struct register_offset off;
struct block_count blkcount;
struct physical_address phyaddr;
struct image_metadata img;
const void *config_data;
const void *image;
};
struct f34_data {
struct rmi_function *fn;
u8 bl_version;
unsigned char bootloader_id[5];
unsigned char configuration_id[CONFIG_ID_SIZE*2 + 1];
union {
struct f34v5_data v5;
struct f34v7_data v7;
};
};
int rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw);
int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw);
int rmi_f34v7_probe(struct f34_data *f34);
#endif /* _RMI_F34_H */
This diff is collapsed.
......@@ -200,7 +200,7 @@ static int rmi_f54_request_report(struct rmi_function *fn, u8 report_type)
error = rmi_write(rmi_dev, fn->fd.command_base_addr, F54_GET_REPORT);
if (error < 0)
return error;
goto unlock;
init_completion(&f54->cmd_done);
......@@ -209,15 +209,18 @@ static int rmi_f54_request_report(struct rmi_function *fn, u8 report_type)
queue_delayed_work(f54->workqueue, &f54->work, 0);
unlock:
mutex_unlock(&f54->data_mutex);
return 0;
return error;
}
static size_t rmi_f54_get_report_size(struct f54_data *f54)
{
u8 rx = f54->num_rx_electrodes ? : f54->num_rx_electrodes;
u8 tx = f54->num_tx_electrodes ? : f54->num_tx_electrodes;
struct rmi_device *rmi_dev = f54->fn->rmi_dev;
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
u8 rx = drv_data->num_rx_electrodes ? : f54->num_rx_electrodes;
u8 tx = drv_data->num_tx_electrodes ? : f54->num_tx_electrodes;
size_t size;
switch (rmi_f54_get_reptype(f54, f54->input)) {
......@@ -401,6 +404,10 @@ static int rmi_f54_vidioc_enum_input(struct file *file, void *priv,
static int rmi_f54_set_input(struct f54_data *f54, unsigned int i)
{
struct rmi_device *rmi_dev = f54->fn->rmi_dev;
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
u8 rx = drv_data->num_rx_electrodes ? : f54->num_rx_electrodes;
u8 tx = drv_data->num_tx_electrodes ? : f54->num_tx_electrodes;
struct v4l2_pix_format *f = &f54->format;
enum rmi_f54_report_type reptype;
int ret;
......@@ -415,8 +422,8 @@ static int rmi_f54_set_input(struct f54_data *f54, unsigned int i)
f54->input = i;
f->width = f54->num_rx_electrodes;
f->height = f54->num_tx_electrodes;
f->width = rx;
f->height = tx;
f->field = V4L2_FIELD_NONE;
f->colorspace = V4L2_COLORSPACE_RAW;
f->bytesperline = f->width * sizeof(u16);
......
/*
* Copyright (c) 2012-2015 Synaptics Incorporated
* Copyright (C) 2016 Zodiac Inflight Innovations
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/rmi.h>
#include <linux/slab.h>
#include "rmi_driver.h"
#define F55_NAME "rmi4_f55"
/* F55 data offsets */
#define F55_NUM_RX_OFFSET 0
#define F55_NUM_TX_OFFSET 1
#define F55_PHYS_CHAR_OFFSET 2
/* Only read required query registers */
#define F55_QUERY_LEN 3
/* F55 capabilities */
#define F55_CAP_SENSOR_ASSIGN BIT(0)
struct f55_data {
struct rmi_function *fn;
u8 qry[F55_QUERY_LEN];
u8 num_rx_electrodes;
u8 cfg_num_rx_electrodes;
u8 num_tx_electrodes;
u8 cfg_num_tx_electrodes;
};
static int rmi_f55_detect(struct rmi_function *fn)
{
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
struct f55_data *f55;
int error;
f55 = dev_get_drvdata(&fn->dev);
error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
&f55->qry, sizeof(f55->qry));
if (error) {
dev_err(&fn->dev, "%s: Failed to query F55 properties\n",
__func__);
return error;
}
f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
drv_data->num_rx_electrodes = f55->cfg_num_rx_electrodes;
drv_data->num_tx_electrodes = f55->cfg_num_rx_electrodes;
if (f55->qry[F55_PHYS_CHAR_OFFSET] & F55_CAP_SENSOR_ASSIGN) {
int i, total;
u8 buf[256];
/*
* Calculate the number of enabled receive and transmit
* electrodes by reading F55:Ctrl1 (sensor receiver assignment)
* and F55:Ctrl2 (sensor transmitter assignment). The number of
* enabled electrodes is the sum of all field entries with a
* value other than 0xff.
*/
error = rmi_read_block(fn->rmi_dev,
fn->fd.control_base_addr + 1,
buf, f55->num_rx_electrodes);
if (!error) {
total = 0;
for (i = 0; i < f55->num_rx_electrodes; i++) {
if (buf[i] != 0xff)
total++;
}
f55->cfg_num_rx_electrodes = total;
drv_data->num_rx_electrodes = total;
}
error = rmi_read_block(fn->rmi_dev,
fn->fd.control_base_addr + 2,
buf, f55->num_tx_electrodes);
if (!error) {
total = 0;
for (i = 0; i < f55->num_tx_electrodes; i++) {
if (buf[i] != 0xff)
total++;
}
f55->cfg_num_tx_electrodes = total;
drv_data->num_tx_electrodes = total;
}
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_rx_electrodes: %d (raw %d)\n",
f55->cfg_num_rx_electrodes, f55->num_rx_electrodes);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_tx_electrodes: %d (raw %d)\n",
f55->cfg_num_tx_electrodes, f55->num_tx_electrodes);
return 0;
}
static int rmi_f55_probe(struct rmi_function *fn)
{
struct f55_data *f55;
f55 = devm_kzalloc(&fn->dev, sizeof(struct f55_data), GFP_KERNEL);
if (!f55)
return -ENOMEM;
f55->fn = fn;
dev_set_drvdata(&fn->dev, f55);
return rmi_f55_detect(fn);
}
struct rmi_function_handler rmi_f55_handler = {
.driver = {
.name = F55_NAME,
},
.func = 0x55,
.probe = rmi_f55_probe,
};
......@@ -9,7 +9,6 @@
#include <linux/i2c.h>
#include <linux/rmi.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
......@@ -35,8 +34,6 @@ struct rmi_i2c_xport {
struct mutex page_mutex;
int page;
int irq;
u8 *tx_buf;
size_t tx_buf_size;
......@@ -177,42 +174,6 @@ static const struct rmi_transport_ops rmi_i2c_ops = {
.read_block = rmi_i2c_read_block,
};
static irqreturn_t rmi_i2c_irq(int irq, void *dev_id)
{
struct rmi_i2c_xport *rmi_i2c = dev_id;
struct rmi_device *rmi_dev = rmi_i2c->xport.rmi_dev;
int ret;
ret = rmi_process_interrupt_requests(rmi_dev);
if (ret)
rmi_dbg(RMI_DEBUG_XPORT, &rmi_dev->dev,
"Failed to process interrupt request: %d\n", ret);
return IRQ_HANDLED;
}
static int rmi_i2c_init_irq(struct i2c_client *client)
{
struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
int irq_flags = irqd_get_trigger_type(irq_get_irq_data(rmi_i2c->irq));
int ret;
if (!irq_flags)
irq_flags = IRQF_TRIGGER_LOW;
ret = devm_request_threaded_irq(&client->dev, rmi_i2c->irq, NULL,
rmi_i2c_irq, irq_flags | IRQF_ONESHOT, client->name,
rmi_i2c);
if (ret < 0) {
dev_warn(&client->dev, "Failed to register interrupt %d\n",
rmi_i2c->irq);
return ret;
}
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id rmi_i2c_of_match[] = {
{ .compatible = "syna,rmi4-i2c" },
......@@ -255,8 +216,7 @@ static int rmi_i2c_probe(struct i2c_client *client,
if (!client->dev.of_node && client_pdata)
*pdata = *client_pdata;
if (client->irq > 0)
rmi_i2c->irq = client->irq;
pdata->irq = client->irq;
rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s.\n",
dev_name(&client->dev));
......@@ -321,10 +281,6 @@ static int rmi_i2c_probe(struct i2c_client *client,
if (retval)
return retval;
retval = rmi_i2c_init_irq(client);
if (retval < 0)
return retval;
dev_info(&client->dev, "registered rmi i2c driver at %#04x.\n",
client->addr);
return 0;
......@@ -337,18 +293,10 @@ static int rmi_i2c_suspend(struct device *dev)
struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
int ret;
ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev);
ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev, true);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
disable_irq(rmi_i2c->irq);
if (device_may_wakeup(&client->dev)) {
ret = enable_irq_wake(rmi_i2c->irq);
if (!ret)
dev_warn(dev, "Failed to enable irq for wake: %d\n",
ret);
}
regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
rmi_i2c->supplies);
......@@ -368,15 +316,7 @@ static int rmi_i2c_resume(struct device *dev)
msleep(rmi_i2c->startup_delay);
enable_irq(rmi_i2c->irq);
if (device_may_wakeup(&client->dev)) {
ret = disable_irq_wake(rmi_i2c->irq);
if (!ret)
dev_warn(dev, "Failed to disable irq for wake: %d\n",
ret);
}
ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev);
ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev, true);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
......@@ -391,12 +331,10 @@ static int rmi_i2c_runtime_suspend(struct device *dev)
struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
int ret;
ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev);
ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev, false);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
disable_irq(rmi_i2c->irq);
regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
rmi_i2c->supplies);
......@@ -416,9 +354,7 @@ static int rmi_i2c_runtime_resume(struct device *dev)
msleep(rmi_i2c->startup_delay);
enable_irq(rmi_i2c->irq);
ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev);
ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev, false);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
......
This diff is collapsed.
......@@ -12,7 +12,6 @@
#include <linux/rmi.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/irq.h>
#include <linux/of.h>
#include "rmi_driver.h"
......@@ -44,8 +43,6 @@ struct rmi_spi_xport {
struct mutex page_mutex;
int page;
int irq;
u8 *rx_buf;
u8 *tx_buf;
int xfer_buf_size;
......@@ -326,41 +323,6 @@ static const struct rmi_transport_ops rmi_spi_ops = {
.read_block = rmi_spi_read_block,
};
static irqreturn_t rmi_spi_irq(int irq, void *dev_id)
{
struct rmi_spi_xport *rmi_spi = dev_id;
struct rmi_device *rmi_dev = rmi_spi->xport.rmi_dev;
int ret;
ret = rmi_process_interrupt_requests(rmi_dev);
if (ret)
rmi_dbg(RMI_DEBUG_XPORT, &rmi_dev->dev,
"Failed to process interrupt request: %d\n", ret);
return IRQ_HANDLED;
}
static int rmi_spi_init_irq(struct spi_device *spi)
{
struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
int irq_flags = irqd_get_trigger_type(irq_get_irq_data(rmi_spi->irq));
int ret;
if (!irq_flags)
irq_flags = IRQF_TRIGGER_LOW;
ret = devm_request_threaded_irq(&spi->dev, rmi_spi->irq, NULL,
rmi_spi_irq, irq_flags | IRQF_ONESHOT,
dev_name(&spi->dev), rmi_spi);
if (ret < 0) {
dev_warn(&spi->dev, "Failed to register interrupt %d\n",
rmi_spi->irq);
return ret;
}
return 0;
}
#ifdef CONFIG_OF
static int rmi_spi_of_probe(struct spi_device *spi,
struct rmi_device_platform_data *pdata)
......@@ -440,8 +402,7 @@ static int rmi_spi_probe(struct spi_device *spi)
return retval;
}
if (spi->irq > 0)
rmi_spi->irq = spi->irq;
pdata->irq = spi->irq;
rmi_spi->spi = spi;
mutex_init(&rmi_spi->page_mutex);
......@@ -477,10 +438,6 @@ static int rmi_spi_probe(struct spi_device *spi)
if (retval)
return retval;
retval = rmi_spi_init_irq(spi);
if (retval < 0)
return retval;
dev_info(&spi->dev, "registered RMI SPI driver\n");
return 0;
}
......@@ -492,17 +449,10 @@ static int rmi_spi_suspend(struct device *dev)
struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
int ret;
ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev);
ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev, true);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
disable_irq(rmi_spi->irq);
if (device_may_wakeup(&spi->dev)) {
ret = enable_irq_wake(rmi_spi->irq);
if (!ret)
dev_warn(dev, "Failed to enable irq for wake: %d\n",
ret);
}
return ret;
}
......@@ -512,15 +462,7 @@ static int rmi_spi_resume(struct device *dev)
struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
int ret;
enable_irq(rmi_spi->irq);
if (device_may_wakeup(&spi->dev)) {
ret = disable_irq_wake(rmi_spi->irq);
if (!ret)
dev_warn(dev, "Failed to disable irq for wake: %d\n",
ret);
}
ret = rmi_driver_resume(rmi_spi->xport.rmi_dev);
ret = rmi_driver_resume(rmi_spi->xport.rmi_dev, true);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
......@@ -535,12 +477,10 @@ static int rmi_spi_runtime_suspend(struct device *dev)
struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
int ret;
ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev);
ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev, false);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
disable_irq(rmi_spi->irq);
return 0;
}
......@@ -550,9 +490,7 @@ static int rmi_spi_runtime_resume(struct device *dev)
struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
int ret;
enable_irq(rmi_spi->irq);
ret = rmi_driver_resume(rmi_spi->xport.rmi_dev);
ret = rmi_driver_resume(rmi_spi->xport.rmi_dev, false);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
......
......@@ -517,79 +517,7 @@ static const struct dmi_system_id i8042_dmi_noselftest_table[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "R409L"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"),
DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
},
},
{ }
......@@ -1131,10 +1059,10 @@ static int __init i8042_pnp_init(void)
return 0;
}
#else
#else /* !CONFIG_PNP */
static inline int i8042_pnp_init(void) { return 0; }
static inline void i8042_pnp_exit(void) { }
#endif
#endif /* CONFIG_PNP */
static int __init i8042_platform_init(void)
{
......
......@@ -387,7 +387,7 @@ static int i8042_aux_write(struct serio *serio, unsigned char c)
/*
* i8042_aux_close attempts to clear AUX or KBD port state by disabling
* i8042_port_close attempts to clear AUX or KBD port state by disabling
* and then re-enabling it.
*/
......
......@@ -55,6 +55,7 @@ static const struct of_device_id mx25_tcq_ids[] = {
{ .compatible = "fsl,imx25-tcq", },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, mx25_tcq_ids);
#define TSC_4WIRE_PRE_INDEX 0
#define TSC_4WIRE_X_INDEX 1
......
......@@ -21,17 +21,25 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/log2.h>
/* ADC configuration registers field define */
#define ADC_AIEN (0x1 << 7)
#define ADC_CONV_DISABLE 0x1F
#define ADC_AVGE (0x1 << 5)
#define ADC_CAL (0x1 << 7)
#define ADC_CALF 0x2
#define ADC_12BIT_MODE (0x2 << 2)
#define ADC_CONV_MODE_MASK (0x3 << 2)
#define ADC_IPG_CLK 0x00
#define ADC_INPUT_CLK_MASK 0x3
#define ADC_CLK_DIV_8 (0x03 << 5)
#define ADC_CLK_DIV_MASK (0x3 << 5)
#define ADC_SHORT_SAMPLE_MODE (0x0 << 4)
#define ADC_SAMPLE_MODE_MASK (0x1 << 4)
#define ADC_HARDWARE_TRIGGER (0x1 << 13)
#define ADC_AVGS_SHIFT 14
#define ADC_AVGS_MASK (0x3 << 14)
#define SELECT_CHANNEL_4 0x04
#define SELECT_CHANNEL_1 0x01
#define DISABLE_CONVERSION_INT (0x0 << 7)
......@@ -84,8 +92,10 @@ struct imx6ul_tsc {
struct clk *adc_clk;
struct gpio_desc *xnur_gpio;
int measure_delay_time;
int pre_charge_time;
u32 measure_delay_time;
u32 pre_charge_time;
bool average_enable;
u32 average_select;
struct completion completion;
};
......@@ -96,17 +106,23 @@ struct imx6ul_tsc {
*/
static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
{
int adc_hc = 0;
int adc_gc;
int adc_gs;
int adc_cfg;
int timeout;
u32 adc_hc = 0;
u32 adc_gc;
u32 adc_gs;
u32 adc_cfg;
unsigned long timeout;
reinit_completion(&tsc->completion);
adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
adc_cfg &= ~(ADC_CONV_MODE_MASK | ADC_INPUT_CLK_MASK);
adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK;
adc_cfg &= ~(ADC_CLK_DIV_MASK | ADC_SAMPLE_MODE_MASK);
adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
if (tsc->average_enable) {
adc_cfg &= ~ADC_AVGS_MASK;
adc_cfg |= (tsc->average_select) << ADC_AVGS_SHIFT;
}
adc_cfg &= ~ADC_HARDWARE_TRIGGER;
writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
......@@ -118,6 +134,8 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
/* start ADC calibration */
adc_gc = readl(tsc->adc_regs + REG_ADC_GC);
adc_gc |= ADC_CAL;
if (tsc->average_enable)
adc_gc |= ADC_AVGE;
writel(adc_gc, tsc->adc_regs + REG_ADC_GC);
timeout = wait_for_completion_timeout
......@@ -148,7 +166,7 @@ static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
*/
static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
{
int adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
u32 adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
adc_hc0 = DISABLE_CONVERSION_INT;
writel(adc_hc0, tsc->adc_regs + REG_ADC_HC0);
......@@ -173,8 +191,8 @@ static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
*/
static void imx6ul_tsc_set(struct imx6ul_tsc *tsc)
{
int basic_setting = 0;
int start;
u32 basic_setting = 0;
u32 start;
basic_setting |= tsc->measure_delay_time << 8;
basic_setting |= DETECT_4_WIRE_MODE | AUTO_MEASURE;
......@@ -209,8 +227,8 @@ static int imx6ul_tsc_init(struct imx6ul_tsc *tsc)
static void imx6ul_tsc_disable(struct imx6ul_tsc *tsc)
{
int tsc_flow;
int adc_cfg;
u32 tsc_flow;
u32 adc_cfg;
/* TSC controller enters to idle status */
tsc_flow = readl(tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
......@@ -227,8 +245,8 @@ static void imx6ul_tsc_disable(struct imx6ul_tsc *tsc)
static bool tsc_wait_detect_mode(struct imx6ul_tsc *tsc)
{
unsigned long timeout = jiffies + msecs_to_jiffies(2);
int state_machine;
int debug_mode2;
u32 state_machine;
u32 debug_mode2;
do {
if (time_after(jiffies, timeout))
......@@ -246,10 +264,10 @@ static bool tsc_wait_detect_mode(struct imx6ul_tsc *tsc)
static irqreturn_t tsc_irq_fn(int irq, void *dev_id)
{
struct imx6ul_tsc *tsc = dev_id;
int status;
int value;
int x, y;
int start;
u32 status;
u32 value;
u32 x, y;
u32 start;
status = readl(tsc->tsc_regs + REG_TSC_INT_STATUS);
......@@ -289,8 +307,8 @@ static irqreturn_t tsc_irq_fn(int irq, void *dev_id)
static irqreturn_t adc_irq_fn(int irq, void *dev_id)
{
struct imx6ul_tsc *tsc = dev_id;
int coco;
int value;
u32 coco;
u32 value;
coco = readl(tsc->adc_regs + REG_ADC_HS);
if (coco & 0x01) {
......@@ -346,6 +364,7 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
int err;
int tsc_irq;
int adc_irq;
u32 average_samples;
tsc = devm_kzalloc(&pdev->dev, sizeof(*tsc), GFP_KERNEL);
if (!tsc)
......@@ -450,6 +469,30 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
if (err)
tsc->pre_charge_time = 0xfff;
err = of_property_read_u32(np, "touchscreen-average-samples",
&average_samples);
if (err)
average_samples = 1;
switch (average_samples) {
case 1:
tsc->average_enable = false;
tsc->average_select = 0; /* value unused; initialize anyway */
break;
case 4:
case 8:
case 16:
case 32:
tsc->average_enable = true;
tsc->average_select = ilog2(average_samples) - 2;
break;
default:
dev_err(&pdev->dev,
"touchscreen-average-samples (%u) must be 1, 4, 8, 16 or 32\n",
average_samples);
return -EINVAL;
}
err = input_register_device(tsc->input);
if (err) {
dev_err(&pdev->dev,
......
......@@ -33,7 +33,7 @@
/*****************************************************************
* Protocol
* Version : MIP 4.0 Rev 4.6
* Version : MIP 4.0 Rev 5.4
*****************************************************************/
/* Address */
......@@ -81,6 +81,9 @@
#define MIP4_R1_INFO_IC_HW_CATEGORY 0x77
#define MIP4_R1_INFO_CONTACT_THD_SCR 0x78
#define MIP4_R1_INFO_CONTACT_THD_KEY 0x7A
#define MIP4_R1_INFO_PID 0x7C
#define MIP4_R1_INFO_VID 0x7E
#define MIP4_R1_INFO_SLAVE_ADDR 0x80
#define MIP4_R0_EVENT 0x02
#define MIP4_R1_EVENT_SUPPORTED_FUNC 0x00
......@@ -157,7 +160,9 @@ struct mip4_ts {
char phys[32];
char product_name[16];
u16 product_id;
char ic_name[4];
char fw_name[32];
unsigned int max_x;
unsigned int max_y;
......@@ -264,6 +269,23 @@ static int mip4_query_device(struct mip4_ts *ts)
dev_dbg(&ts->client->dev, "product name: %.*s\n",
(int)sizeof(ts->product_name), ts->product_name);
/* Product ID */
cmd[0] = MIP4_R0_INFO;
cmd[1] = MIP4_R1_INFO_PID;
error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, 2);
if (error) {
dev_warn(&ts->client->dev,
"Failed to retrieve product id: %d\n", error);
} else {
ts->product_id = get_unaligned_le16(&buf[0]);
dev_dbg(&ts->client->dev, "product id: %04X\n", ts->product_id);
}
/* Firmware name */
snprintf(ts->fw_name, sizeof(ts->fw_name),
"melfas_mip4_%04X.fw", ts->product_id);
dev_dbg(&ts->client->dev, "firmware name: %s\n", ts->fw_name);
/* IC name */
cmd[0] = MIP4_R0_INFO;
cmd[1] = MIP4_R1_INFO_IC_NAME;
......@@ -1269,11 +1291,11 @@ static ssize_t mip4_sysfs_fw_update(struct device *dev,
const struct firmware *fw;
int error;
error = request_firmware(&fw, MIP4_FW_NAME, dev);
error = request_firmware(&fw, ts->fw_name, dev);
if (error) {
dev_err(&ts->client->dev,
"Failed to retrieve firmware %s: %d\n",
MIP4_FW_NAME, error);
ts->fw_name, error);
return error;
}
......@@ -1348,6 +1370,25 @@ static ssize_t mip4_sysfs_read_hw_version(struct device *dev,
static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL);
static ssize_t mip4_sysfs_read_product_id(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct mip4_ts *ts = i2c_get_clientdata(client);
size_t count;
mutex_lock(&ts->input->mutex);
count = snprintf(buf, PAGE_SIZE, "%04X\n", ts->product_id);
mutex_unlock(&ts->input->mutex);
return count;
}
static DEVICE_ATTR(product_id, S_IRUGO, mip4_sysfs_read_product_id, NULL);
static ssize_t mip4_sysfs_read_ic_name(struct device *dev,
struct device_attribute *attr,
char *buf)
......@@ -1371,6 +1412,7 @@ static DEVICE_ATTR(ic_name, S_IRUGO, mip4_sysfs_read_ic_name, NULL);
static struct attribute *mip4_attrs[] = {
&dev_attr_fw_version.attr,
&dev_attr_hw_version.attr,
&dev_attr_product_id.attr,
&dev_attr_ic_name.attr,
&dev_attr_update_fw.attr,
NULL,
......@@ -1435,6 +1477,7 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id)
input->id.bustype = BUS_I2C;
input->id.vendor = 0x13c5;
input->id.product = ts->product_id;
input->open = mip4_input_open;
input->close = mip4_input_close;
......@@ -1572,6 +1615,6 @@ static struct i2c_driver mip4_driver = {
module_i2c_driver(mip4_driver);
MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen");
MODULE_VERSION("2016.09.28");
MODULE_VERSION("2016.10.31");
MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>");
MODULE_LICENSE("GPL");
......@@ -669,7 +669,7 @@ static int raydium_i2c_do_update_firmware(struct raydium_data *ts,
if (ts->boot_mode == RAYDIUM_TS_MAIN) {
dev_err(&client->dev,
"failied to jump to boot loader: %d\n",
"failed to jump to boot loader: %d\n",
error);
return -EIO;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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