Merge branch 'next' into for-linus

Prepare input updates for 4.10 merge window.
This commit is contained in:
Dmitry Torokhov
2016-12-16 09:31:17 -08:00
17206 changed files with 1178860 additions and 539945 deletions

View File

@@ -143,9 +143,9 @@ struct analog_port {
#include <linux/i8253.h>
#define GET_TIME(x) do { if (cpu_has_tsc) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0)
#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0)))
#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
#define GET_TIME(x) do { if (boot_cpu_has(X86_FEATURE_TSC)) x = (unsigned int)rdtsc(); else x = get_time_pit(); } while (0)
#define DELTA(x,y) (boot_cpu_has(X86_FEATURE_TSC) ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? PIT_TICK_RATE / HZ : 0)))
#define TIME_NAME (boot_cpu_has(X86_FEATURE_TSC)?"TSC":"PIT")
static unsigned int get_time_pit(void)
{
unsigned long flags;

View File

@@ -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;

View File

@@ -73,7 +73,7 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)
#ifdef CONFIG_GPIOLIB
static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
int val;
@@ -93,7 +93,7 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
static void adp5588_gpio_set_value(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
@@ -112,7 +112,7 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
int ret;
@@ -130,7 +130,7 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
static int adp5588_gpio_direction_output(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
struct adp5588_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
int ret;
@@ -210,7 +210,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
mutex_init(&kpad->gpio_lock);
error = gpiochip_add(&kpad->gc);
error = gpiochip_add_data(&kpad->gc, kpad);
if (error) {
dev_err(dev, "gpiochip_add failed, err: %d\n", error);
return error;

View File

@@ -387,7 +387,7 @@ static int adp5589_write(struct i2c_client *client, u8 reg, u8 val)
#ifdef CONFIG_GPIOLIB
static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
@@ -399,7 +399,7 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
static void adp5589_gpio_set_value(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
@@ -418,7 +418,7 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip,
static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
int ret;
@@ -438,7 +438,7 @@ static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off)
static int adp5589_gpio_direction_output(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5589_kpad *kpad = container_of(chip, struct adp5589_kpad, gc);
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
int ret;
@@ -525,9 +525,9 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad)
mutex_init(&kpad->gpio_lock);
error = gpiochip_add(&kpad->gc);
error = gpiochip_add_data(&kpad->gc, kpad);
if (error) {
dev_err(dev, "gpiochip_add failed, err: %d\n", error);
dev_err(dev, "gpiochip_add_data() failed, err: %d\n", error);
return error;
}

View File

@@ -101,7 +101,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
return -ENOMEM;
priv->syscon =
syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1");
syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon1");
if (IS_ERR(priv->syscon))
return PTR_ERR(priv->syscon);
@@ -181,7 +181,7 @@ static int clps711x_keypad_remove(struct platform_device *pdev)
}
static const struct of_device_id clps711x_keypad_of_match[] = {
{ .compatible = "cirrus,clps711x-keypad", },
{ .compatible = "cirrus,ep7209-keypad", },
{ }
};
MODULE_DEVICE_TABLE(of, clps711x_keypad_of_match);

View File

@@ -26,15 +26,15 @@
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
struct gpio_button_data {
const struct gpio_keys_button *button;
struct input_dev *input;
struct gpio_desc *gpiod;
struct timer_list release_timer;
unsigned int release_delay; /* in msecs, for IRQ-only buttons */
@@ -140,7 +140,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
*/
disable_irq(bdata->irq);
if (gpio_is_valid(bdata->button->gpio))
if (bdata->gpiod)
cancel_delayed_work_sync(&bdata->work);
else
del_timer_sync(&bdata->release_timer);
@@ -358,19 +358,20 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
const struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
int state = gpio_get_value_cansleep(button->gpio);
int state;
state = gpiod_get_value_cansleep(bdata->gpiod);
if (state < 0) {
dev_err(input->dev.parent, "failed to get gpio state\n");
dev_err(input->dev.parent,
"failed to get gpio state: %d\n", state);
return;
}
state = (state ? 1 : 0) ^ button->active_low;
if (type == EV_ABS) {
if (state)
input_event(input, type, button->code, button->value);
} else {
input_event(input, type, button->code, !!state);
input_event(input, type, button->code, state);
}
input_sync(input);
}
@@ -456,7 +457,7 @@ static void gpio_keys_quiesce_key(void *data)
{
struct gpio_button_data *bdata = data;
if (gpio_is_valid(bdata->button->gpio))
if (bdata->gpiod)
cancel_delayed_work_sync(&bdata->work);
else
del_timer_sync(&bdata->release_timer);
@@ -465,7 +466,8 @@ static void gpio_keys_quiesce_key(void *data)
static int gpio_keys_setup_key(struct platform_device *pdev,
struct input_dev *input,
struct gpio_button_data *bdata,
const struct gpio_keys_button *button)
const struct gpio_keys_button *button,
struct fwnode_handle *child)
{
const char *desc = button->desc ? button->desc : "gpio_keys";
struct device *dev = &pdev->dev;
@@ -478,18 +480,56 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
bdata->button = button;
spin_lock_init(&bdata->lock);
if (gpio_is_valid(button->gpio)) {
if (child) {
bdata->gpiod = devm_get_gpiod_from_child(dev, NULL, child);
if (IS_ERR(bdata->gpiod)) {
error = PTR_ERR(bdata->gpiod);
if (error == -ENOENT) {
/*
* GPIO is optional, we may be dealing with
* purely interrupt-driven setup.
*/
bdata->gpiod = NULL;
} else {
if (error != -EPROBE_DEFER)
dev_err(dev, "failed to get gpio: %d\n",
error);
return error;
}
} else {
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);
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;
error = devm_gpio_request_one(&pdev->dev, button->gpio,
GPIOF_IN, desc);
if (button->active_low)
flags |= GPIOF_ACTIVE_LOW;
error = devm_gpio_request_one(&pdev->dev, button->gpio, flags,
desc);
if (error < 0) {
dev_err(dev, "Failed to request GPIO %d, error %d\n",
button->gpio, error);
return error;
}
bdata->gpiod = gpio_to_desc(button->gpio);
if (!bdata->gpiod)
return -EINVAL;
}
if (bdata->gpiod) {
if (button->debounce_interval) {
error = gpio_set_debounce(button->gpio,
error = gpiod_set_debounce(bdata->gpiod,
button->debounce_interval * 1000);
/* use timer if gpiolib doesn't provide debounce */
if (error < 0)
@@ -500,7 +540,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
if (button->irq) {
bdata->irq = button->irq;
} else {
irq = gpio_to_irq(button->gpio);
irq = gpiod_to_irq(bdata->gpiod);
if (irq < 0) {
error = irq;
dev_err(dev,
@@ -518,9 +558,10 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
} else {
if (!button->irq) {
dev_err(dev, "No IRQ specified\n");
dev_err(dev, "Found button without gpio or irq\n");
return -EINVAL;
}
bdata->irq = button->irq;
if (button->type && button->type != EV_KEY) {
@@ -575,7 +616,7 @@ static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata)
for (i = 0; i < ddata->pdata->nbuttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (gpio_is_valid(bdata->button->gpio))
if (bdata->gpiod)
gpio_keys_gpio_report_event(bdata);
}
input_sync(input);
@@ -612,25 +653,18 @@ static void gpio_keys_close(struct input_dev *input)
* Handlers for alternative sources of platform_data
*/
#ifdef CONFIG_OF
/*
* Translate OpenFirmware node properties into platform_data
* Translate properties into platform_data
*/
static struct gpio_keys_platform_data *
gpio_keys_get_devtree_pdata(struct device *dev)
{
struct device_node *node, *pp;
struct gpio_keys_platform_data *pdata;
struct gpio_keys_button *button;
int error;
struct fwnode_handle *child;
int nbuttons;
int i;
node = dev->of_node;
if (!node)
return ERR_PTR(-ENODEV);
nbuttons = of_get_available_child_count(node);
nbuttons = device_get_child_node_count(dev);
if (nbuttons == 0)
return ERR_PTR(-ENODEV);
@@ -640,64 +674,47 @@ gpio_keys_get_devtree_pdata(struct device *dev)
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 = !!of_get_property(node, "autorepeat", NULL);
pdata->rep = device_property_read_bool(dev, "autorepeat");
of_property_read_string(node, "label", &pdata->name);
device_property_read_string(dev, "label", &pdata->name);
i = 0;
for_each_available_child_of_node(node, pp) {
enum of_gpio_flags flags;
device_for_each_child_node(dev, child) {
if (is_of_node(child))
button->irq =
irq_of_parse_and_map(to_of_node(child), 0);
button = &pdata->buttons[i++];
button->gpio = of_get_gpio_flags(pp, 0, &flags);
if (button->gpio < 0) {
error = button->gpio;
if (error != -ENOENT) {
if (error != -EPROBE_DEFER)
dev_err(dev,
"Failed to get gpio flags, error: %d\n",
error);
return ERR_PTR(error);
}
} else {
button->active_low = flags & OF_GPIO_ACTIVE_LOW;
}
button->irq = irq_of_parse_and_map(pp, 0);
if (!gpio_is_valid(button->gpio) && !button->irq) {
dev_err(dev, "Found button without gpios or irqs\n");
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);
}
if (of_property_read_u32(pp, "linux,code", &button->code)) {
dev_err(dev, "Button without keycode: 0x%x\n",
button->gpio);
return ERR_PTR(-EINVAL);
}
fwnode_property_read_string(child, "label", &button->desc);
button->desc = of_get_property(pp, "label", NULL);
if (of_property_read_u32(pp, "linux,input-type", &button->type))
if (fwnode_property_read_u32(child, "linux,input-type",
&button->type))
button->type = EV_KEY;
button->wakeup = of_property_read_bool(pp, "wakeup-source") ||
/* legacy name */
of_property_read_bool(pp, "gpio-key,wakeup");
button->wakeup =
fwnode_property_read_bool(child, "wakeup-source") ||
/* legacy name */
fwnode_property_read_bool(child, "gpio-key,wakeup");
button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL);
button->can_disable =
fwnode_property_read_bool(child, "linux,can-disable");
if (of_property_read_u32(pp, "debounce-interval",
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;
}
@@ -708,20 +725,11 @@ static const struct of_device_id gpio_keys_of_match[] = {
};
MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
#else
static inline struct gpio_keys_platform_data *
gpio_keys_get_devtree_pdata(struct device *dev)
{
return ERR_PTR(-ENODEV);
}
#endif
static int gpio_keys_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
struct fwnode_handle *child = NULL;
struct gpio_keys_drvdata *ddata;
struct input_dev *input;
size_t size;
@@ -774,14 +782,28 @@ static int gpio_keys_probe(struct platform_device *pdev)
const struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
error = gpio_keys_setup_key(pdev, input, bdata, button);
if (error)
if (!dev_get_platdata(dev)) {
child = device_get_next_child_node(&pdev->dev, child);
if (!child) {
dev_err(&pdev->dev,
"missing child device node for entry %d\n",
i);
return -EINVAL;
}
}
error = gpio_keys_setup_key(pdev, input, bdata, button, child);
if (error) {
fwnode_handle_put(child);
return error;
}
if (button->wakeup)
wakeup = 1;
}
fwnode_handle_put(child);
error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
if (error) {
dev_err(dev, "Unable to export keys/switches, error: %d\n",
@@ -814,8 +836,7 @@ static int gpio_keys_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int gpio_keys_suspend(struct device *dev)
static int __maybe_unused gpio_keys_suspend(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
@@ -837,7 +858,7 @@ static int gpio_keys_suspend(struct device *dev)
return 0;
}
static int gpio_keys_resume(struct device *dev)
static int __maybe_unused gpio_keys_resume(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
@@ -863,7 +884,6 @@ static int gpio_keys_resume(struct device *dev)
gpio_keys_report_state(ddata);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
@@ -873,7 +893,7 @@ static struct platform_driver gpio_keys_device_driver = {
.driver = {
.name = "gpio-keys",
.pm = &gpio_keys_pm_ops,
.of_match_table = of_match_ptr(gpio_keys_of_match),
.of_match_table = gpio_keys_of_match,
}
};

View File

@@ -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);
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);
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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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 },
{ }

View File

@@ -1,5 +1,5 @@
/*
* 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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -70,10 +70,13 @@ struct max77693_haptic {
static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)
{
int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2;
struct pwm_args pargs;
int delta;
int error;
error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period);
pwm_get_args(haptic->pwm_dev, &pargs);
delta = (pargs.period + haptic->pwm_duty) / 2;
error = pwm_config(haptic->pwm_dev, delta, pargs.period);
if (error) {
dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
return error;
@@ -234,6 +237,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct max77693_haptic *haptic = input_get_drvdata(dev);
struct pwm_args pargs;
u64 period_mag_multi;
haptic->magnitude = effect->u.rumble.strong_magnitude;
@@ -245,7 +249,8 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
* The formula to convert magnitude to pwm_duty as follows:
* - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
*/
period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude;
pwm_get_args(haptic->pwm_dev, &pargs);
period_mag_multi = (u64)pargs.period * haptic->magnitude;
haptic->pwm_duty = (unsigned int)(period_mag_multi >>
MAX_MAGNITUDE_SHIFT);
@@ -329,6 +334,12 @@ static int max77693_haptic_probe(struct platform_device *pdev)
return PTR_ERR(haptic->pwm_dev);
}
/*
* FIXME: pwm_apply_args() should be removed when switching to the
* atomic PWM API.
*/
pwm_apply_args(haptic->pwm_dev);
haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");
if (IS_ERR(haptic->motor_reg)) {
dev_err(&pdev->dev, "failed to get regulator\n");

View File

@@ -306,6 +306,12 @@ static int max8997_haptic_probe(struct platform_device *pdev)
error);
goto err_free_mem;
}
/*
* FIXME: pwm_apply_args() should be removed when switching to
* the atomic PWM API.
*/
pwm_apply_args(chip->pwm);
break;
default:

View File

@@ -115,6 +115,12 @@ static int pwm_beeper_probe(struct platform_device *pdev)
goto err_free;
}
/*
* FIXME: pwm_apply_args() should be removed when switching to
* the atomic PWM API.
*/
pwm_apply_args(beeper->pwm);
INIT_WORK(&beeper->work, pwm_beeper_work);
beeper->input = input_allocate_device();

View File

@@ -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;

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View File

@@ -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
@@ -61,3 +82,35 @@ 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.

View File

@@ -4,10 +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

View File

@@ -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;

View File

@@ -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,

View File

@@ -231,6 +231,9 @@ err_put_device:
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);
@@ -303,6 +306,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
@@ -312,6 +318,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)

View File

@@ -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

View File

@@ -17,6 +17,7 @@
#include <linux/bitmap.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/irq.h>
#include <linux/kconfig.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -34,12 +35,22 @@
#define RMI_DEVICE_RESET_CMD 0x01
#define DEFAULT_RESET_DELAY_MS 100
static void rmi_free_function_list(struct rmi_device *rmi_dev)
void rmi_free_function_list(struct rmi_device *rmi_dev)
{
struct rmi_function *fn, *tmp;
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Freeing function list\n");
devm_kfree(&rmi_dev->dev, data->irq_memory);
data->irq_memory = NULL;
data->irq_status = NULL;
data->fn_irq_bits = NULL;
data->current_irq_mask = NULL;
data->new_irq_mask = NULL;
data->f01_container = NULL;
data->f34_container = NULL;
/* Doing it in the reverse order so F01 will be removed last */
list_for_each_entry_safe_reverse(fn, tmp,
@@ -134,7 +145,7 @@ static void process_one_interrupt(struct rmi_driver_data *data,
}
}
int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct device *dev = &rmi_dev->dev;
@@ -144,7 +155,7 @@ int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
if (!data)
return 0;
if (!rmi_dev->xport->attn_data) {
if (!data->attn_data.data) {
error = rmi_read_block(rmi_dev,
data->f01_container->fd.data_base_addr + 1,
data->irq_status, data->num_of_irq_regs);
@@ -179,7 +190,81 @@ int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
return 0;
}
EXPORT_SYMBOL_GPL(rmi_process_interrupt_requests);
void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
void *data, size_t size)
{
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct rmi4_attn_data attn_data;
void *fifo_data;
if (!drvdata->enabled)
return;
fifo_data = kmemdup(data, size, GFP_ATOMIC);
if (!fifo_data)
return;
attn_data.irq_status = irq_status;
attn_data.size = size;
attn_data.data = fifo_data;
kfifo_put(&drvdata->attn_fifo, attn_data);
}
EXPORT_SYMBOL_GPL(rmi_set_attn_data);
static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
{
struct rmi_device *rmi_dev = dev_id;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct rmi4_attn_data attn_data = {0};
int ret, count;
count = kfifo_get(&drvdata->attn_fifo, &attn_data);
if (count) {
*(drvdata->irq_status) = attn_data.irq_status;
drvdata->attn_data = attn_data;
}
ret = rmi_process_interrupt_requests(rmi_dev);
if (ret)
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
"Failed to process interrupt request: %d\n", ret);
if (count)
kfree(attn_data.data);
if (!kfifo_is_empty(&drvdata->attn_fifo))
return rmi_irq_fn(irq, dev_id);
return IRQ_HANDLED;
}
static int rmi_irq_init(struct rmi_device *rmi_dev)
{
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int irq_flags = irq_get_trigger_type(pdata->irq);
int ret;
if (!irq_flags)
irq_flags = IRQF_TRIGGER_LOW;
ret = devm_request_threaded_irq(&rmi_dev->dev, pdata->irq, NULL,
rmi_irq_fn, irq_flags | IRQF_ONESHOT,
dev_name(rmi_dev->xport->dev),
rmi_dev);
if (ret < 0) {
dev_err(&rmi_dev->dev, "Failed to register interrupt %d\n",
pdata->irq);
return ret;
}
data->enabled = true;
return 0;
}
static int suspend_one_function(struct rmi_function *fn)
{
@@ -249,7 +334,7 @@ static int rmi_resume_functions(struct rmi_device *rmi_dev)
return 0;
}
static int enable_sensor(struct rmi_device *rmi_dev)
int rmi_enable_sensor(struct rmi_device *rmi_dev)
{
int retval = 0;
@@ -380,8 +465,8 @@ static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
return 0;
}
int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
u16 pdt_address)
static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
struct pdt_entry *entry, u16 pdt_address)
{
u8 buf[RMI_PDT_ENTRY_SIZE];
int error;
@@ -404,7 +489,6 @@ int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
return 0;
}
EXPORT_SYMBOL_GPL(rmi_read_pdt_entry);
static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
struct rmi_function_descriptor *fd)
@@ -423,6 +507,7 @@ static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
int page,
int *empty_pages,
void *ctx,
int (*callback)(struct rmi_device *rmi_dev,
void *ctx,
@@ -450,20 +535,30 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
return retval;
}
return (data->f01_bootloader_mode || addr == pdt_start) ?
/*
* Count number of empty PDT pages. If a gap of two pages
* or more is found, stop scanning.
*/
if (addr == pdt_start)
++*empty_pages;
else
*empty_pages = 0;
return (data->bootloader_mode || *empty_pages >= 2) ?
RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
}
static 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_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
int (*callback)(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *entry))
{
int page;
int empty_pages = 0;
int retval = RMI_SCAN_DONE;
for (page = 0; page <= RMI4_MAX_PAGE; page++) {
retval = rmi_scan_pdt_page(rmi_dev, page, ctx, callback);
retval = rmi_scan_pdt_page(rmi_dev, page, &empty_pages,
ctx, callback);
if (retval != RMI_SCAN_CONTINUE)
break;
}
@@ -601,7 +696,6 @@ free_struct_buff:
kfree(struct_buf);
return ret;
}
EXPORT_SYMBOL_GPL(rmi_read_register_desc);
const struct rmi_register_desc_item *rmi_get_register_desc_item(
struct rmi_register_descriptor *rdesc, u16 reg)
@@ -617,7 +711,6 @@ const struct rmi_register_desc_item *rmi_get_register_desc_item(
return NULL;
}
EXPORT_SYMBOL_GPL(rmi_get_register_desc_item);
size_t rmi_register_desc_calc_size(struct rmi_register_descriptor *rdesc)
{
@@ -631,7 +724,6 @@ size_t rmi_register_desc_calc_size(struct rmi_register_descriptor *rdesc)
}
return size;
}
EXPORT_SYMBOL_GPL(rmi_register_desc_calc_size);
/* Compute the register offset relative to the base address */
int rmi_register_desc_calc_reg_offset(
@@ -649,7 +741,6 @@ int rmi_register_desc_calc_reg_offset(
}
return -1;
}
EXPORT_SYMBOL_GPL(rmi_register_desc_calc_reg_offset);
bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
u8 subpacket)
@@ -658,51 +749,55 @@ bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
subpacket) == subpacket;
}
/* Indicates that flash programming is enabled (bootloader mode). */
#define RMI_F01_STATUS_BOOTLOADER(status) (!!((status) & 0x40))
/*
* Given the PDT entry for F01, read the device status register to determine
* if we're stuck in bootloader mode or not.
*
*/
static int rmi_check_bootloader_mode(struct rmi_device *rmi_dev,
const struct pdt_entry *pdt)
{
int error;
u8 device_status;
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int ret;
u8 status;
error = rmi_read(rmi_dev, pdt->data_base_addr + pdt->page_start,
&device_status);
if (error) {
dev_err(&rmi_dev->dev,
"Failed to read device status: %d.\n", error);
return error;
if (pdt->function_number == 0x34 && pdt->function_version > 1) {
ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
if (ret) {
dev_err(&rmi_dev->dev,
"Failed to read F34 status: %d.\n", ret);
return ret;
}
if (status & BIT(7))
data->bootloader_mode = true;
} else if (pdt->function_number == 0x01) {
ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
if (ret) {
dev_err(&rmi_dev->dev,
"Failed to read F01 status: %d.\n", ret);
return ret;
}
if (status & BIT(6))
data->bootloader_mode = true;
}
return RMI_F01_STATUS_BOOTLOADER(device_status);
return 0;
}
static int rmi_count_irqs(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int *irq_count = ctx;
int ret;
*irq_count += pdt->interrupt_source_count;
if (pdt->function_number == 0x01) {
data->f01_bootloader_mode =
rmi_check_bootloader_mode(rmi_dev, pdt);
if (data->f01_bootloader_mode)
dev_warn(&rmi_dev->dev,
"WARNING: RMI4 device is in bootloader mode!\n");
}
ret = rmi_check_bootloader_mode(rmi_dev, pdt);
if (ret < 0)
return ret;
return RMI_SCAN_CONTINUE;
}
static int rmi_initial_reset(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
const struct pdt_entry *pdt)
{
int error;
@@ -721,6 +816,7 @@ static int rmi_initial_reset(struct rmi_device *rmi_dev,
return RMI_SCAN_DONE;
}
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Sending reset\n");
error = rmi_write_block(rmi_dev, cmd_addr, &cmd_buf, 1);
if (error) {
dev_err(&rmi_dev->dev,
@@ -777,6 +873,8 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
if (pdt->function_number == 0x01)
data->f01_container = fn;
else if (pdt->function_number == 0x34)
data->f34_container = fn;
list_add_tail(&fn->node, &data->function_list);
@@ -787,23 +885,95 @@ err_put_fn:
return error;
}
int rmi_driver_suspend(struct rmi_device *rmi_dev)
void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake)
{
int retval = 0;
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int irq = pdata->irq;
int irq_flags;
int retval;
mutex_lock(&data->enabled_mutex);
if (data->enabled)
goto out;
enable_irq(irq);
data->enabled = true;
if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
retval = disable_irq_wake(irq);
if (!retval)
dev_warn(&rmi_dev->dev,
"Failed to disable irq for wake: %d\n",
retval);
}
/*
* Call rmi_process_interrupt_requests() after enabling irq,
* otherwise we may lose interrupt on edge-triggered systems.
*/
irq_flags = irq_get_trigger_type(pdata->irq);
if (irq_flags & IRQ_TYPE_EDGE_BOTH)
rmi_process_interrupt_requests(rmi_dev);
out:
mutex_unlock(&data->enabled_mutex);
}
void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
{
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi4_attn_data attn_data = {0};
int irq = pdata->irq;
int retval, count;
mutex_lock(&data->enabled_mutex);
if (!data->enabled)
goto out;
data->enabled = false;
disable_irq(irq);
if (enable_wake && device_may_wakeup(rmi_dev->xport->dev)) {
retval = enable_irq_wake(irq);
if (!retval)
dev_warn(&rmi_dev->dev,
"Failed to enable irq for wake: %d\n",
retval);
}
/* make sure the fifo is clean */
while (!kfifo_is_empty(&data->attn_fifo)) {
count = kfifo_get(&data->attn_fifo, &attn_data);
if (count)
kfree(attn_data.data);
}
out:
mutex_unlock(&data->enabled_mutex);
}
int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
{
int retval;
retval = rmi_suspend_functions(rmi_dev);
if (retval)
dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
retval);
rmi_disable_irq(rmi_dev, enable_wake);
return retval;
}
EXPORT_SYMBOL_GPL(rmi_driver_suspend);
int rmi_driver_resume(struct rmi_device *rmi_dev)
int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake)
{
int retval;
rmi_enable_irq(rmi_dev, clear_wake);
retval = rmi_resume_functions(rmi_dev);
if (retval)
dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
@@ -817,6 +987,9 @@ static int rmi_driver_remove(struct device *dev)
{
struct rmi_device *rmi_dev = to_rmi_device(dev);
rmi_disable_irq(rmi_dev, false);
rmi_f34_remove_sysfs(rmi_dev);
rmi_free_function_list(rmi_dev);
return 0;
@@ -843,15 +1016,95 @@ static inline int rmi_driver_of_probe(struct device *dev,
}
#endif
int rmi_probe_interrupts(struct rmi_driver_data *data)
{
struct rmi_device *rmi_dev = data->rmi_dev;
struct device *dev = &rmi_dev->dev;
int irq_count;
size_t size;
int retval;
/*
* We need to count the IRQs and allocate their storage before scanning
* the PDT and creating the function entries, because adding a new
* function can trigger events that result in the IRQ related storage
* being accessed.
*/
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
irq_count = 0;
data->bootloader_mode = false;
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
if (retval < 0) {
dev_err(dev, "IRQ counting failed with code %d.\n", retval);
return retval;
}
if (data->bootloader_mode)
dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n");
data->irq_count = irq_count;
data->num_of_irq_regs = (data->irq_count + 7) / 8;
size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
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;
}
data->irq_status = data->irq_memory + size * 0;
data->fn_irq_bits = data->irq_memory + size * 1;
data->current_irq_mask = data->irq_memory + size * 2;
data->new_irq_mask = data->irq_memory + size * 3;
return retval;
}
int rmi_init_functions(struct rmi_driver_data *data)
{
struct rmi_device *rmi_dev = data->rmi_dev;
struct device *dev = &rmi_dev->dev;
int irq_count;
int retval;
irq_count = 0;
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
if (retval < 0) {
dev_err(dev, "Function creation failed with code %d.\n",
retval);
goto err_destroy_functions;
}
if (!data->f01_container) {
dev_err(dev, "Missing F01 container!\n");
retval = -EINVAL;
goto err_destroy_functions;
}
retval = rmi_read_block(rmi_dev,
data->f01_container->fd.control_base_addr + 1,
data->current_irq_mask, data->num_of_irq_regs);
if (retval < 0) {
dev_err(dev, "%s: Failed to read current IRQ mask.\n",
__func__);
goto err_destroy_functions;
}
return 0;
err_destroy_functions:
rmi_free_function_list(rmi_dev);
return retval;
}
static int rmi_driver_probe(struct device *dev)
{
struct rmi_driver *rmi_driver;
struct rmi_driver_data *data;
struct rmi_device_platform_data *pdata;
struct rmi_device *rmi_dev;
size_t size;
void *irq_memory;
int irq_count;
int retval;
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Starting probe.\n",
@@ -917,35 +1170,12 @@ static int rmi_driver_probe(struct device *dev)
PDT_PROPERTIES_LOCATION, retval);
}
/*
* We need to count the IRQs and allocate their storage before scanning
* the PDT and creating the function entries, because adding a new
* function can trigger events that result in the IRQ related storage
* being accessed.
*/
rmi_dbg(RMI_DEBUG_CORE, dev, "Counting IRQs.\n");
irq_count = 0;
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
if (retval < 0) {
dev_err(dev, "IRQ counting failed with code %d.\n", retval);
goto err;
}
data->irq_count = irq_count;
data->num_of_irq_regs = (data->irq_count + 7) / 8;
mutex_init(&data->irq_mutex);
mutex_init(&data->enabled_mutex);
size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
if (!irq_memory) {
dev_err(dev, "Failed to allocate memory for irq masks.\n");
retval = rmi_probe_interrupts(data);
if (retval)
goto err;
}
data->irq_status = irq_memory + size * 0;
data->fn_irq_bits = irq_memory + size * 1;
data->current_irq_mask = irq_memory + size * 2;
data->new_irq_mask = irq_memory + size * 3;
if (rmi_dev->xport->input) {
/*
@@ -962,36 +1192,20 @@ static int rmi_driver_probe(struct device *dev)
dev_err(dev, "%s: Failed to allocate input device.\n",
__func__);
retval = -ENOMEM;
goto err_destroy_functions;
goto err;
}
rmi_driver_set_input_params(rmi_dev, data->input);
data->input->phys = devm_kasprintf(dev, GFP_KERNEL,
"%s/input0", dev_name(dev));
}
irq_count = 0;
rmi_dbg(RMI_DEBUG_CORE, dev, "Creating functions.");
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
if (retval < 0) {
dev_err(dev, "Function creation failed with code %d.\n",
retval);
goto err_destroy_functions;
}
retval = rmi_init_functions(data);
if (retval)
goto err;
if (!data->f01_container) {
dev_err(dev, "Missing F01 container!\n");
retval = -EINVAL;
goto err_destroy_functions;
}
retval = rmi_read_block(rmi_dev,
data->f01_container->fd.control_base_addr + 1,
data->current_irq_mask, data->num_of_irq_regs);
if (retval < 0) {
dev_err(dev, "%s: Failed to read current IRQ mask.\n",
__func__);
goto err_destroy_functions;
}
retval = rmi_f34_create_sysfs(rmi_dev);
if (retval)
goto err;
if (data->input) {
rmi_driver_set_input_name(rmi_dev, data->input);
@@ -1004,9 +1218,13 @@ static int rmi_driver_probe(struct device *dev)
}
}
retval = rmi_irq_init(rmi_dev);
if (retval < 0)
goto err_destroy_functions;
if (data->f01_container->dev.driver)
/* Driver already bound, so enable ATTN now. */
return enable_sensor(rmi_dev);
return rmi_enable_sensor(rmi_dev);
return 0;

View File

@@ -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,11 +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

View File

@@ -63,6 +63,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 */
@@ -327,12 +329,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;
}
@@ -594,6 +596,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);

View File

@@ -0,0 +1,250 @@
/*
* 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");

View File

@@ -572,31 +572,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 (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;
for (i = 0; i < rel_fingers; i++)
rmi_f11_rel_pos_report(f11, i);
}
@@ -612,7 +629,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 */
@@ -1063,8 +1080,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;
@@ -1125,6 +1142,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;
@@ -1192,11 +1211,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);
@@ -1242,12 +1283,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,
@@ -1257,7 +1307,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;
}

View File

@@ -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;
for (i = 0; i < f12->data1->num_subpackets; i++) {
if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
objects = size / F12_DATA1_BYTES_PER_OBJ;
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;
int valid_bytes = sensor->pkt_size;
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;
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;

View File

@@ -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);

View File

@@ -0,0 +1,516 @@
/*
* 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.
*/
#include <linux/kernel.h>
#include <linux/rmi.h>
#include <linux/firmware.h>
#include <asm/unaligned.h>
#include <asm/unaligned.h>
#include <linux/bitops.h>
#include "rmi_driver.h"
#include "rmi_f34.h"
static int rmi_f34_write_bootloader_id(struct f34_data *f34)
{
struct rmi_function *fn = f34->fn;
struct rmi_device *rmi_dev = fn->rmi_dev;
u8 bootloader_id[F34_BOOTLOADER_ID_LEN];
int ret;
ret = rmi_read_block(rmi_dev, fn->fd.query_base_addr,
bootloader_id, sizeof(bootloader_id));
if (ret) {
dev_err(&fn->dev, "%s: Reading bootloader ID failed: %d\n",
__func__, ret);
return ret;
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: writing bootloader id '%c%c'\n",
__func__, bootloader_id[0], bootloader_id[1]);
ret = rmi_write_block(rmi_dev,
fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET,
bootloader_id, sizeof(bootloader_id));
if (ret) {
dev_err(&fn->dev, "Failed to write bootloader ID: %d\n", ret);
return ret;
}
return 0;
}
static int rmi_f34_command(struct f34_data *f34, u8 command,
unsigned int timeout, bool write_bl_id)
{
struct rmi_function *fn = f34->fn;
struct rmi_device *rmi_dev = fn->rmi_dev;
int ret;
if (write_bl_id) {
ret = rmi_f34_write_bootloader_id(f34);
if (ret)
return ret;
}
init_completion(&f34->v5.cmd_done);
ret = rmi_read(rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
if (ret) {
dev_err(&f34->fn->dev,
"%s: Failed to read cmd register: %d (command %#02x)\n",
__func__, ret, command);
return ret;
}
f34->v5.status |= command & 0x0f;
ret = rmi_write(rmi_dev, f34->v5.ctrl_address, f34->v5.status);
if (ret < 0) {
dev_err(&f34->fn->dev,
"Failed to write F34 command %#02x: %d\n",
command, ret);
return ret;
}
if (!wait_for_completion_timeout(&f34->v5.cmd_done,
msecs_to_jiffies(timeout))) {
ret = rmi_read(rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
if (ret) {
dev_err(&f34->fn->dev,
"%s: cmd %#02x timed out: %d\n",
__func__, command, ret);
return ret;
}
if (f34->v5.status & 0x7f) {
dev_err(&f34->fn->dev,
"%s: cmd %#02x timed out, status: %#02x\n",
__func__, command, f34->v5.status);
return -ETIMEDOUT;
}
}
return 0;
}
static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
{
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
int ret;
if (f34->bl_version != 5)
return 0;
ret = rmi_read(f34->fn->rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
__func__, f34->v5.status, ret);
if (!ret && !(f34->v5.status & 0x7f))
complete(&f34->v5.cmd_done);
return 0;
}
static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
int block_count, u8 command)
{
struct rmi_function *fn = f34->fn;
struct rmi_device *rmi_dev = fn->rmi_dev;
u16 address = fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET;
u8 start_address[] = { 0, 0 };
int i;
int ret;
ret = rmi_write_block(rmi_dev, fn->fd.data_base_addr,
start_address, sizeof(start_address));
if (ret) {
dev_err(&fn->dev, "Failed to write initial zeros: %d\n", ret);
return ret;
}
for (i = 0; i < block_count; i++) {
ret = rmi_write_block(rmi_dev, address,
data, f34->v5.block_size);
if (ret) {
dev_err(&fn->dev,
"failed to write block #%d: %d\n", i, ret);
return ret;
}
ret = rmi_f34_command(f34, command, F34_IDLE_WAIT_MS, false);
if (ret) {
dev_err(&fn->dev,
"Failed to write command for block #%d: %d\n",
i, ret);
return ret;
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "wrote block %d of %d\n",
i + 1, block_count);
data += f34->v5.block_size;
}
return 0;
}
static int rmi_f34_write_firmware(struct f34_data *f34, const void *data)
{
return rmi_f34_write_blocks(f34, data, f34->v5.fw_blocks,
F34_WRITE_FW_BLOCK);
}
static int rmi_f34_write_config(struct f34_data *f34, const void *data)
{
return rmi_f34_write_blocks(f34, data, f34->v5.config_blocks,
F34_WRITE_CONFIG_BLOCK);
}
int rmi_f34_enable_flash(struct f34_data *f34)
{
return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG,
F34_ENABLE_WAIT_MS, true);
}
static int rmi_f34_flash_firmware(struct f34_data *f34,
const struct rmi_f34_firmware *syn_fw)
{
struct rmi_function *fn = f34->fn;
int ret;
if (syn_fw->image_size) {
dev_info(&fn->dev, "Erasing firmware...\n");
ret = rmi_f34_command(f34, F34_ERASE_ALL,
F34_ERASE_WAIT_MS, true);
if (ret)
return ret;
dev_info(&fn->dev, "Writing firmware (%d bytes)...\n",
syn_fw->image_size);
ret = rmi_f34_write_firmware(f34, syn_fw->data);
if (ret)
return ret;
}
if (syn_fw->config_size) {
/*
* We only need to erase config if we haven't updated
* firmware.
*/
if (!syn_fw->image_size) {
dev_info(&fn->dev, "Erasing config...\n");
ret = rmi_f34_command(f34, F34_ERASE_CONFIG,
F34_ERASE_WAIT_MS, true);
if (ret)
return ret;
}
dev_info(&fn->dev, "Writing config (%d bytes)...\n",
syn_fw->config_size);
ret = rmi_f34_write_config(f34,
&syn_fw->data[syn_fw->image_size]);
if (ret)
return ret;
}
return 0;
}
int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
{
const struct rmi_f34_firmware *syn_fw;
int ret;
syn_fw = (const struct rmi_f34_firmware *)fw->data;
BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) !=
F34_FW_IMAGE_OFFSET);
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"FW size:%d, checksum:%08x, image_size:%d, config_size:%d\n",
(int)fw->size,
le32_to_cpu(syn_fw->checksum),
le32_to_cpu(syn_fw->image_size),
le32_to_cpu(syn_fw->config_size));
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n",
syn_fw->bootloader_version,
(int)sizeof(syn_fw->product_id), syn_fw->product_id,
syn_fw->product_info[0], syn_fw->product_info[1]);
if (syn_fw->image_size &&
syn_fw->image_size != f34->v5.fw_blocks * f34->v5.block_size) {
dev_err(&f34->fn->dev,
"Bad firmware image: fw size %d, expected %d\n",
syn_fw->image_size,
f34->v5.fw_blocks * f34->v5.block_size);
ret = -EILSEQ;
goto out;
}
if (syn_fw->config_size &&
syn_fw->config_size != f34->v5.config_blocks * f34->v5.block_size) {
dev_err(&f34->fn->dev,
"Bad firmware image: config size %d, expected %d\n",
syn_fw->config_size,
f34->v5.config_blocks * f34->v5.block_size);
ret = -EILSEQ;
goto out;
}
if (syn_fw->image_size && !syn_fw->config_size) {
dev_err(&f34->fn->dev, "Bad firmware image: no config data\n");
ret = -EILSEQ;
goto out;
}
dev_info(&f34->fn->dev, "Firmware image OK\n");
mutex_lock(&f34->v5.flash_mutex);
ret = rmi_f34_flash_firmware(f34, syn_fw);
mutex_unlock(&f34->v5.flash_mutex);
out:
return ret;
}
static int rmi_firmware_update(struct rmi_driver_data *data,
const struct firmware *fw)
{
struct rmi_device *rmi_dev = data->rmi_dev;
struct device *dev = &rmi_dev->dev;
struct f34_data *f34;
int ret;
if (!data->f34_container) {
dev_warn(dev, "%s: No F34 present!\n", __func__);
return -EINVAL;
}
f34 = dev_get_drvdata(&data->f34_container->dev);
if (f34->bl_version == 7) {
if (data->pdt_props & HAS_BSR) {
dev_err(dev, "%s: LTS not supported\n", __func__);
return -ENODEV;
}
} else if (f34->bl_version != 5) {
dev_warn(dev, "F34 V%d not supported!\n",
data->f34_container->fd.function_version);
return -ENODEV;
}
/* Enter flash mode */
if (f34->bl_version == 7)
ret = rmi_f34v7_start_reflash(f34, fw);
else
ret = rmi_f34_enable_flash(f34);
if (ret)
return ret;
rmi_disable_irq(rmi_dev, false);
/* Tear down functions and re-probe */
rmi_free_function_list(rmi_dev);
ret = rmi_probe_interrupts(data);
if (ret)
return ret;
ret = rmi_init_functions(data);
if (ret)
return ret;
if (!data->bootloader_mode || !data->f34_container) {
dev_warn(dev, "%s: No F34 present or not in bootloader!\n",
__func__);
return -EINVAL;
}
rmi_enable_irq(rmi_dev, false);
f34 = dev_get_drvdata(&data->f34_container->dev);
/* Perform firmware update */
if (f34->bl_version == 7)
ret = rmi_f34v7_do_reflash(f34, fw);
else
ret = rmi_f34_update_firmware(f34, fw);
dev_info(&f34->fn->dev, "Firmware update complete, status:%d\n", ret);
rmi_disable_irq(rmi_dev, false);
/* Re-probe */
rmi_dbg(RMI_DEBUG_FN, dev, "Re-probing device\n");
rmi_free_function_list(rmi_dev);
ret = rmi_scan_pdt(rmi_dev, NULL, rmi_initial_reset);
if (ret < 0)
dev_warn(dev, "RMI reset failed!\n");
ret = rmi_probe_interrupts(data);
if (ret)
return ret;
ret = rmi_init_functions(data);
if (ret)
return ret;
rmi_enable_irq(rmi_dev, false);
if (data->f01_container->dev.driver)
/* Driver already bound, so enable ATTN now. */
return rmi_enable_sensor(rmi_dev);
rmi_dbg(RMI_DEBUG_FN, dev, "%s complete\n", __func__);
return ret;
}
static int rmi_firmware_update(struct rmi_driver_data *data,
const struct firmware *fw);
static ssize_t rmi_driver_update_fw_store(struct device *dev,
struct device_attribute *dattr,
const char *buf, size_t count)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
char fw_name[NAME_MAX];
const struct firmware *fw;
size_t copy_count = count;
int ret;
if (count == 0 || count >= NAME_MAX)
return -EINVAL;
if (buf[count - 1] == '\0' || buf[count - 1] == '\n')
copy_count -= 1;
strncpy(fw_name, buf, copy_count);
fw_name[copy_count] = '\0';
ret = request_firmware(&fw, fw_name, dev);
if (ret)
return ret;
dev_info(dev, "Flashing %s\n", fw_name);
ret = rmi_firmware_update(data, fw);
release_firmware(fw);
return ret ?: count;
}
static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);
static struct attribute *rmi_firmware_attrs[] = {
&dev_attr_update_fw.attr,
NULL
};
static struct attribute_group rmi_firmware_attr_group = {
.attrs = rmi_firmware_attrs,
};
static int rmi_f34_probe(struct rmi_function *fn)
{
struct f34_data *f34;
unsigned char f34_queries[9];
bool has_config_id;
u8 version = fn->fd.function_version;
int ret;
f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL);
if (!f34)
return -ENOMEM;
f34->fn = fn;
dev_set_drvdata(&fn->dev, f34);
/* v5 code only supported version 0, try V7 probe */
if (version > 0)
return rmi_f34v7_probe(f34);
else if (version != 0)
return -ENODEV;
f34->bl_version = 5;
ret = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
f34_queries, sizeof(f34_queries));
if (ret) {
dev_err(&fn->dev, "%s: Failed to query properties\n",
__func__);
return ret;
}
snprintf(f34->bootloader_id, sizeof(f34->bootloader_id),
"%c%c", f34_queries[0], f34_queries[1]);
mutex_init(&f34->v5.flash_mutex);
init_completion(&f34->v5.cmd_done);
f34->v5.block_size = get_unaligned_le16(&f34_queries[3]);
f34->v5.fw_blocks = get_unaligned_le16(&f34_queries[5]);
f34->v5.config_blocks = get_unaligned_le16(&f34_queries[7]);
f34->v5.ctrl_address = fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET +
f34->v5.block_size;
has_config_id = f34_queries[2] & (1 << 2);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Bootloader ID: %s\n",
f34->bootloader_id);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Block size: %d\n",
f34->v5.block_size);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "FW blocks: %d\n",
f34->v5.fw_blocks);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "CFG blocks: %d\n",
f34->v5.config_blocks);
if (has_config_id) {
ret = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
f34_queries, sizeof(f34_queries));
if (ret) {
dev_err(&fn->dev, "Failed to read F34 config ID\n");
return ret;
}
snprintf(f34->configuration_id, sizeof(f34->configuration_id),
"%02x%02x%02x%02x",
f34_queries[0], f34_queries[1],
f34_queries[2], f34_queries[3]);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Configuration ID: %s\n",
f34->configuration_id);
}
return 0;
}
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
{
return sysfs_create_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
}
void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev)
{
sysfs_remove_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
}
struct rmi_function_handler rmi_f34_handler = {
.driver = {
.name = "rmi4_f34",
},
.func = 0x34,
.probe = rmi_f34_probe,
.attention = rmi_f34_attention,
};

View File

@@ -0,0 +1,314 @@
/*
* 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 */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,764 @@
/*
* 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/kernel.h>
#include <linux/rmi.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#include "rmi_driver.h"
#define F54_NAME "rmi4_f54"
/* F54 data offsets */
#define F54_REPORT_DATA_OFFSET 3
#define F54_FIFO_OFFSET 1
#define F54_NUM_TX_OFFSET 1
#define F54_NUM_RX_OFFSET 0
/* F54 commands */
#define F54_GET_REPORT 1
#define F54_FORCE_CAL 2
/* Fixed sizes of reports */
#define F54_QUERY_LEN 27
/* F54 capabilities */
#define F54_CAP_BASELINE (1 << 2)
#define F54_CAP_IMAGE8 (1 << 3)
#define F54_CAP_IMAGE16 (1 << 6)
/**
* enum rmi_f54_report_type - RMI4 F54 report types
*
* @F54_8BIT_IMAGE: Normalized 8-Bit Image Report. The capacitance variance
* from baseline for each pixel.
*
* @F54_16BIT_IMAGE: Normalized 16-Bit Image Report. The capacitance variance
* from baseline for each pixel.
*
* @F54_RAW_16BIT_IMAGE:
* Raw 16-Bit Image Report. The raw capacitance for each
* pixel.
*
* @F54_TRUE_BASELINE: True Baseline Report. The baseline capacitance for each
* pixel.
*
* @F54_FULL_RAW_CAP: Full Raw Capacitance Report. The raw capacitance with
* low reference set to its minimum value and high
* reference set to its maximum value.
*
* @F54_FULL_RAW_CAP_RX_OFFSET_REMOVED:
* Full Raw Capacitance with Receiver Offset Removed
* Report. Set Low reference to its minimum value and high
* references to its maximum value, then report the raw
* capacitance for each pixel.
*/
enum rmi_f54_report_type {
F54_REPORT_NONE = 0,
F54_8BIT_IMAGE = 1,
F54_16BIT_IMAGE = 2,
F54_RAW_16BIT_IMAGE = 3,
F54_TRUE_BASELINE = 9,
F54_FULL_RAW_CAP = 19,
F54_FULL_RAW_CAP_RX_OFFSET_REMOVED = 20,
F54_MAX_REPORT_TYPE,
};
const char *rmi_f54_report_type_names[] = {
[F54_REPORT_NONE] = "Unknown",
[F54_8BIT_IMAGE] = "Normalized 8-Bit Image",
[F54_16BIT_IMAGE] = "Normalized 16-Bit Image",
[F54_RAW_16BIT_IMAGE] = "Raw 16-Bit Image",
[F54_TRUE_BASELINE] = "True Baseline",
[F54_FULL_RAW_CAP] = "Full Raw Capacitance",
[F54_FULL_RAW_CAP_RX_OFFSET_REMOVED]
= "Full Raw Capacitance RX Offset Removed",
};
struct rmi_f54_reports {
int start;
int size;
};
struct f54_data {
struct rmi_function *fn;
u8 qry[F54_QUERY_LEN];
u8 num_rx_electrodes;
u8 num_tx_electrodes;
u8 capabilities;
u16 clock_rate;
u8 family;
enum rmi_f54_report_type report_type;
u8 *report_data;
int report_size;
struct rmi_f54_reports standard_report[2];
bool is_busy;
struct mutex status_mutex;
struct mutex data_mutex;
struct workqueue_struct *workqueue;
struct delayed_work work;
unsigned long timeout;
struct completion cmd_done;
/* V4L2 support */
struct v4l2_device v4l2;
struct v4l2_pix_format format;
struct video_device vdev;
struct vb2_queue queue;
struct mutex lock;
int input;
enum rmi_f54_report_type inputs[F54_MAX_REPORT_TYPE];
};
/*
* Basic checks on report_type to ensure we write a valid type
* to the sensor.
*/
static bool is_f54_report_type_valid(struct f54_data *f54,
enum rmi_f54_report_type reptype)
{
switch (reptype) {
case F54_8BIT_IMAGE:
return f54->capabilities & F54_CAP_IMAGE8;
case F54_16BIT_IMAGE:
case F54_RAW_16BIT_IMAGE:
return f54->capabilities & F54_CAP_IMAGE16;
case F54_TRUE_BASELINE:
return f54->capabilities & F54_CAP_IMAGE16;
case F54_FULL_RAW_CAP:
case F54_FULL_RAW_CAP_RX_OFFSET_REMOVED:
return true;
default:
return false;
}
}
static enum rmi_f54_report_type rmi_f54_get_reptype(struct f54_data *f54,
unsigned int i)
{
if (i >= F54_MAX_REPORT_TYPE)
return F54_REPORT_NONE;
return f54->inputs[i];
}
static void rmi_f54_create_input_map(struct f54_data *f54)
{
int i = 0;
enum rmi_f54_report_type reptype;
for (reptype = 1; reptype < F54_MAX_REPORT_TYPE; reptype++) {
if (!is_f54_report_type_valid(f54, reptype))
continue;
f54->inputs[i++] = reptype;
}
/* Remaining values are zero via kzalloc */
}
static int rmi_f54_request_report(struct rmi_function *fn, u8 report_type)
{
struct f54_data *f54 = dev_get_drvdata(&fn->dev);
struct rmi_device *rmi_dev = fn->rmi_dev;
int error;
/* Write Report Type into F54_AD_Data0 */
if (f54->report_type != report_type) {
error = rmi_write(rmi_dev, f54->fn->fd.data_base_addr,
report_type);
if (error)
return error;
f54->report_type = report_type;
}
/*
* Small delay after disabling interrupts to avoid race condition
* in firmare. This value is a bit higher than absolutely necessary.
* Should be removed once issue is resolved in firmware.
*/
usleep_range(2000, 3000);
mutex_lock(&f54->data_mutex);
error = rmi_write(rmi_dev, fn->fd.command_base_addr, F54_GET_REPORT);
if (error < 0)
goto unlock;
init_completion(&f54->cmd_done);
f54->is_busy = 1;
f54->timeout = jiffies + msecs_to_jiffies(100);
queue_delayed_work(f54->workqueue, &f54->work, 0);
unlock:
mutex_unlock(&f54->data_mutex);
return error;
}
static size_t rmi_f54_get_report_size(struct f54_data *f54)
{
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)) {
case F54_8BIT_IMAGE:
size = rx * tx;
break;
case F54_16BIT_IMAGE:
case F54_RAW_16BIT_IMAGE:
case F54_TRUE_BASELINE:
case F54_FULL_RAW_CAP:
case F54_FULL_RAW_CAP_RX_OFFSET_REMOVED:
size = sizeof(u16) * rx * tx;
break;
default:
size = 0;
}
return size;
}
static int rmi_f54_get_pixel_fmt(enum rmi_f54_report_type reptype, u32 *pixfmt)
{
int ret = 0;
switch (reptype) {
case F54_8BIT_IMAGE:
*pixfmt = V4L2_TCH_FMT_DELTA_TD08;
break;
case F54_16BIT_IMAGE:
*pixfmt = V4L2_TCH_FMT_DELTA_TD16;
break;
case F54_RAW_16BIT_IMAGE:
case F54_TRUE_BASELINE:
case F54_FULL_RAW_CAP:
case F54_FULL_RAW_CAP_RX_OFFSET_REMOVED:
*pixfmt = V4L2_TCH_FMT_TU16;
break;
case F54_REPORT_NONE:
case F54_MAX_REPORT_TYPE:
ret = -EINVAL;
break;
}
return ret;
}
static const struct v4l2_file_operations rmi_f54_video_fops = {
.owner = THIS_MODULE,
.open = v4l2_fh_open,
.release = vb2_fop_release,
.unlocked_ioctl = video_ioctl2,
.read = vb2_fop_read,
.mmap = vb2_fop_mmap,
.poll = vb2_fop_poll,
};
static int rmi_f54_queue_setup(struct vb2_queue *q, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[],
struct device *alloc_devs[])
{
struct f54_data *f54 = q->drv_priv;
if (*nplanes)
return sizes[0] < rmi_f54_get_report_size(f54) ? -EINVAL : 0;
*nplanes = 1;
sizes[0] = rmi_f54_get_report_size(f54);
return 0;
}
static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
{
struct f54_data *f54 = vb2_get_drv_priv(vb->vb2_queue);
u16 *ptr;
enum vb2_buffer_state state;
enum rmi_f54_report_type reptype;
int ret;
mutex_lock(&f54->status_mutex);
reptype = rmi_f54_get_reptype(f54, f54->input);
if (reptype == F54_REPORT_NONE) {
state = VB2_BUF_STATE_ERROR;
goto done;
}
if (f54->is_busy) {
state = VB2_BUF_STATE_ERROR;
goto done;
}
ret = rmi_f54_request_report(f54->fn, reptype);
if (ret) {
dev_err(&f54->fn->dev, "Error requesting F54 report\n");
state = VB2_BUF_STATE_ERROR;
goto done;
}
/* get frame data */
mutex_lock(&f54->data_mutex);
while (f54->is_busy) {
mutex_unlock(&f54->data_mutex);
if (!wait_for_completion_timeout(&f54->cmd_done,
msecs_to_jiffies(1000))) {
dev_err(&f54->fn->dev, "Timed out\n");
state = VB2_BUF_STATE_ERROR;
goto done;
}
mutex_lock(&f54->data_mutex);
}
ptr = vb2_plane_vaddr(vb, 0);
if (!ptr) {
dev_err(&f54->fn->dev, "Error acquiring frame ptr\n");
state = VB2_BUF_STATE_ERROR;
goto data_done;
}
memcpy(ptr, f54->report_data, f54->report_size);
vb2_set_plane_payload(vb, 0, rmi_f54_get_report_size(f54));
state = VB2_BUF_STATE_DONE;
data_done:
mutex_unlock(&f54->data_mutex);
done:
vb2_buffer_done(vb, state);
mutex_unlock(&f54->status_mutex);
}
/* V4L2 structures */
static const struct vb2_ops rmi_f54_queue_ops = {
.queue_setup = rmi_f54_queue_setup,
.buf_queue = rmi_f54_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
static const struct vb2_queue rmi_f54_queue = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ,
.buf_struct_size = sizeof(struct vb2_buffer),
.ops = &rmi_f54_queue_ops,
.mem_ops = &vb2_vmalloc_memops,
.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
.min_buffers_needed = 1,
};
static int rmi_f54_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct f54_data *f54 = video_drvdata(file);
strlcpy(cap->driver, F54_NAME, sizeof(cap->driver));
strlcpy(cap->card, SYNAPTICS_INPUT_DEVICE_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"rmi4:%s", dev_name(&f54->fn->dev));
return 0;
}
static int rmi_f54_vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
struct f54_data *f54 = video_drvdata(file);
enum rmi_f54_report_type reptype;
reptype = rmi_f54_get_reptype(f54, i->index);
if (reptype == F54_REPORT_NONE)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_TOUCH;
strlcpy(i->name, rmi_f54_report_type_names[reptype], sizeof(i->name));
return 0;
}
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;
reptype = rmi_f54_get_reptype(f54, i);
if (reptype == F54_REPORT_NONE)
return -EINVAL;
ret = rmi_f54_get_pixel_fmt(reptype, &f->pixelformat);
if (ret)
return ret;
f54->input = i;
f->width = rx;
f->height = tx;
f->field = V4L2_FIELD_NONE;
f->colorspace = V4L2_COLORSPACE_RAW;
f->bytesperline = f->width * sizeof(u16);
f->sizeimage = f->width * f->height * sizeof(u16);
return 0;
}
static int rmi_f54_vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
return rmi_f54_set_input(video_drvdata(file), i);
}
static int rmi_f54_vidioc_g_input(struct file *file, void *priv,
unsigned int *i)
{
struct f54_data *f54 = video_drvdata(file);
*i = f54->input;
return 0;
}
static int rmi_f54_vidioc_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
struct f54_data *f54 = video_drvdata(file);
f->fmt.pix = f54->format;
return 0;
}
static int rmi_f54_vidioc_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *fmt)
{
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
switch (fmt->index) {
case 0:
fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
break;
case 1:
fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD08;
break;
case 2:
fmt->pixelformat = V4L2_TCH_FMT_TU16;
break;
default:
return -EINVAL;
}
return 0;
}
static int rmi_f54_vidioc_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
a->parm.capture.readbuffers = 1;
a->parm.capture.timeperframe.numerator = 1;
a->parm.capture.timeperframe.denominator = 10;
return 0;
}
static const struct v4l2_ioctl_ops rmi_f54_video_ioctl_ops = {
.vidioc_querycap = rmi_f54_vidioc_querycap,
.vidioc_enum_fmt_vid_cap = rmi_f54_vidioc_enum_fmt,
.vidioc_s_fmt_vid_cap = rmi_f54_vidioc_fmt,
.vidioc_g_fmt_vid_cap = rmi_f54_vidioc_fmt,
.vidioc_try_fmt_vid_cap = rmi_f54_vidioc_fmt,
.vidioc_g_parm = rmi_f54_vidioc_g_parm,
.vidioc_enum_input = rmi_f54_vidioc_enum_input,
.vidioc_g_input = rmi_f54_vidioc_g_input,
.vidioc_s_input = rmi_f54_vidioc_s_input,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
};
static const struct video_device rmi_f54_video_device = {
.name = "Synaptics RMI4",
.fops = &rmi_f54_video_fops,
.ioctl_ops = &rmi_f54_video_ioctl_ops,
.release = video_device_release_empty,
.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING,
};
static void rmi_f54_work(struct work_struct *work)
{
struct f54_data *f54 = container_of(work, struct f54_data, work.work);
struct rmi_function *fn = f54->fn;
u8 fifo[2];
struct rmi_f54_reports *report;
int report_size;
u8 command;
u8 *data;
int error;
data = f54->report_data;
report_size = rmi_f54_get_report_size(f54);
if (report_size == 0) {
dev_err(&fn->dev, "Bad report size, report type=%d\n",
f54->report_type);
error = -EINVAL;
goto error; /* retry won't help */
}
f54->standard_report[0].size = report_size;
report = f54->standard_report;
mutex_lock(&f54->data_mutex);
/*
* Need to check if command has completed.
* If not try again later.
*/
error = rmi_read(fn->rmi_dev, f54->fn->fd.command_base_addr,
&command);
if (error) {
dev_err(&fn->dev, "Failed to read back command\n");
goto error;
}
if (command & F54_GET_REPORT) {
if (time_after(jiffies, f54->timeout)) {
dev_err(&fn->dev, "Get report command timed out\n");
error = -ETIMEDOUT;
}
report_size = 0;
goto error;
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Get report command completed, reading data\n");
report_size = 0;
for (; report->size; report++) {
fifo[0] = report->start & 0xff;
fifo[1] = (report->start >> 8) & 0xff;
error = rmi_write_block(fn->rmi_dev,
fn->fd.data_base_addr + F54_FIFO_OFFSET,
fifo, sizeof(fifo));
if (error) {
dev_err(&fn->dev, "Failed to set fifo start offset\n");
goto abort;
}
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr +
F54_REPORT_DATA_OFFSET, data,
report->size);
if (error) {
dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n",
__func__, report->size, error);
goto abort;
}
data += report->size;
report_size += report->size;
}
abort:
f54->report_size = error ? 0 : report_size;
error:
if (error)
report_size = 0;
if (report_size == 0 && !error) {
queue_delayed_work(f54->workqueue, &f54->work,
msecs_to_jiffies(1));
} else {
f54->is_busy = false;
complete(&f54->cmd_done);
}
mutex_unlock(&f54->data_mutex);
}
static int rmi_f54_attention(struct rmi_function *fn, unsigned long *irqbits)
{
return 0;
}
static int rmi_f54_config(struct rmi_function *fn)
{
struct rmi_driver *drv = fn->rmi_dev->driver;
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
return 0;
}
static int rmi_f54_detect(struct rmi_function *fn)
{
int error;
struct f54_data *f54;
f54 = dev_get_drvdata(&fn->dev);
error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
&f54->qry, sizeof(f54->qry));
if (error) {
dev_err(&fn->dev, "%s: Failed to query F54 properties\n",
__func__);
return error;
}
f54->num_rx_electrodes = f54->qry[0];
f54->num_tx_electrodes = f54->qry[1];
f54->capabilities = f54->qry[2];
f54->clock_rate = f54->qry[3] | (f54->qry[4] << 8);
f54->family = f54->qry[5];
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 num_rx_electrodes: %d\n",
f54->num_rx_electrodes);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 num_tx_electrodes: %d\n",
f54->num_tx_electrodes);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 capabilities: 0x%x\n",
f54->capabilities);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 clock rate: 0x%x\n",
f54->clock_rate);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 family: 0x%x\n",
f54->family);
f54->is_busy = false;
return 0;
}
static int rmi_f54_probe(struct rmi_function *fn)
{
struct f54_data *f54;
int ret;
u8 rx, tx;
f54 = devm_kzalloc(&fn->dev, sizeof(struct f54_data), GFP_KERNEL);
if (!f54)
return -ENOMEM;
f54->fn = fn;
dev_set_drvdata(&fn->dev, f54);
ret = rmi_f54_detect(fn);
if (ret)
return ret;
mutex_init(&f54->data_mutex);
mutex_init(&f54->status_mutex);
rx = f54->num_rx_electrodes;
tx = f54->num_tx_electrodes;
f54->report_data = devm_kzalloc(&fn->dev,
sizeof(u16) * tx * rx,
GFP_KERNEL);
if (f54->report_data == NULL)
return -ENOMEM;
INIT_DELAYED_WORK(&f54->work, rmi_f54_work);
f54->workqueue = create_singlethread_workqueue("rmi4-poller");
if (!f54->workqueue)
return -ENOMEM;
rmi_f54_create_input_map(f54);
/* register video device */
strlcpy(f54->v4l2.name, F54_NAME, sizeof(f54->v4l2.name));
ret = v4l2_device_register(&fn->dev, &f54->v4l2);
if (ret) {
dev_err(&fn->dev, "Unable to register video dev.\n");
goto remove_wq;
}
/* initialize the queue */
mutex_init(&f54->lock);
f54->queue = rmi_f54_queue;
f54->queue.drv_priv = f54;
f54->queue.lock = &f54->lock;
f54->queue.dev = &fn->dev;
ret = vb2_queue_init(&f54->queue);
if (ret)
goto remove_v4l2;
f54->vdev = rmi_f54_video_device;
f54->vdev.v4l2_dev = &f54->v4l2;
f54->vdev.lock = &f54->lock;
f54->vdev.vfl_dir = VFL_DIR_RX;
f54->vdev.queue = &f54->queue;
video_set_drvdata(&f54->vdev, f54);
ret = video_register_device(&f54->vdev, VFL_TYPE_TOUCH, -1);
if (ret) {
dev_err(&fn->dev, "Unable to register video subdevice.");
goto remove_v4l2;
}
return 0;
remove_v4l2:
v4l2_device_unregister(&f54->v4l2);
remove_wq:
cancel_delayed_work_sync(&f54->work);
flush_workqueue(f54->workqueue);
destroy_workqueue(f54->workqueue);
return ret;
}
static void rmi_f54_remove(struct rmi_function *fn)
{
struct f54_data *f54 = dev_get_drvdata(&fn->dev);
video_unregister_device(&f54->vdev);
v4l2_device_unregister(&f54->v4l2);
}
struct rmi_function_handler rmi_f54_handler = {
.driver = {
.name = F54_NAME,
},
.func = 0x54,
.probe = rmi_f54_probe,
.config = rmi_f54_config,
.attention = rmi_f54_attention,
.remove = rmi_f54_remove,
};

View File

@@ -0,0 +1,131 @@
/*
* 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,
};

View File

@@ -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);

View File

@@ -0,0 +1,447 @@
/*
* Copyright (c) 2015 - 2016 Red Hat, Inc
* Copyright (c) 2011, 2012 Synaptics Incorporated
* Copyright (c) 2011 Unixphere
*
* 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/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kconfig.h>
#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/rmi.h>
#include <linux/slab.h>
#include "rmi_driver.h"
#define SMB_PROTOCOL_VERSION_ADDRESS 0xfd
#define SMB_MAX_COUNT 32
#define RMI_SMB2_MAP_SIZE 8 /* 8 entry of 4 bytes each */
#define RMI_SMB2_MAP_FLAGS_WE 0x01
struct mapping_table_entry {
__le16 rmiaddr;
u8 readcount;
u8 flags;
};
struct rmi_smb_xport {
struct rmi_transport_dev xport;
struct i2c_client *client;
struct mutex page_mutex;
int page;
u8 table_index;
struct mutex mappingtable_mutex;
struct mapping_table_entry mapping_table[RMI_SMB2_MAP_SIZE];
};
static int rmi_smb_get_version(struct rmi_smb_xport *rmi_smb)
{
struct i2c_client *client = rmi_smb->client;
int retval;
/* Check if for SMBus new version device by reading version byte. */
retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS);
if (retval < 0) {
dev_err(&client->dev, "failed to get SMBus version number!\n");
return retval;
}
return retval + 1;
}
/* SMB block write - wrapper over ic2_smb_write_block */
static int smb_block_write(struct rmi_transport_dev *xport,
u8 commandcode, const void *buf, size_t len)
{
struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport);
struct i2c_client *client = rmi_smb->client;
int retval;
retval = i2c_smbus_write_block_data(client, commandcode, len, buf);
rmi_dbg(RMI_DEBUG_XPORT, &client->dev,
"wrote %zd bytes at %#04x: %d (%*ph)\n",
len, commandcode, retval, (int)len, buf);
return retval;
}
/*
* The function to get command code for smbus operations and keeps
* records to the driver mapping table
*/
static int rmi_smb_get_command_code(struct rmi_transport_dev *xport,
u16 rmiaddr, int bytecount, bool isread, u8 *commandcode)
{
struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport);
int i;
int retval;
struct mapping_table_entry mapping_data[1];
mutex_lock(&rmi_smb->mappingtable_mutex);
for (i = 0; i < RMI_SMB2_MAP_SIZE; i++) {
if (rmi_smb->mapping_table[i].rmiaddr == rmiaddr) {
if (isread) {
if (rmi_smb->mapping_table[i].readcount
== bytecount) {
*commandcode = i;
retval = 0;
goto exit;
}
} else {
if (rmi_smb->mapping_table[i].flags &
RMI_SMB2_MAP_FLAGS_WE) {
*commandcode = i;
retval = 0;
goto exit;
}
}
}
}
i = rmi_smb->table_index;
rmi_smb->table_index = (i + 1) % RMI_SMB2_MAP_SIZE;
/* constructs mapping table data entry. 4 bytes each entry */
memset(mapping_data, 0, sizeof(mapping_data));
mapping_data[0].rmiaddr = cpu_to_le16(rmiaddr);
mapping_data[0].readcount = bytecount;
mapping_data[0].flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0;
retval = smb_block_write(xport, i + 0x80, mapping_data,
sizeof(mapping_data));
if (retval < 0) {
/*
* if not written to device mapping table
* clear the driver mapping table records
*/
rmi_smb->mapping_table[i].rmiaddr = 0x0000;
rmi_smb->mapping_table[i].readcount = 0;
rmi_smb->mapping_table[i].flags = 0;
goto exit;
}
/* save to the driver level mapping table */
rmi_smb->mapping_table[i].rmiaddr = rmiaddr;
rmi_smb->mapping_table[i].readcount = bytecount;
rmi_smb->mapping_table[i].flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0;
*commandcode = i;
exit:
mutex_unlock(&rmi_smb->mappingtable_mutex);
return retval;
}
static int rmi_smb_write_block(struct rmi_transport_dev *xport, u16 rmiaddr,
const void *databuff, size_t len)
{
int retval = 0;
u8 commandcode;
struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport);
int cur_len = (int)len;
mutex_lock(&rmi_smb->page_mutex);
while (cur_len > 0) {
/*
* break into 32 bytes chunks to write get command code
*/
int block_len = min_t(int, len, SMB_MAX_COUNT);
retval = rmi_smb_get_command_code(xport, rmiaddr, block_len,
false, &commandcode);
if (retval < 0)
goto exit;
retval = smb_block_write(xport, commandcode,
databuff, block_len);
if (retval < 0)
goto exit;
/* prepare to write next block of bytes */
cur_len -= SMB_MAX_COUNT;
databuff += SMB_MAX_COUNT;
rmiaddr += SMB_MAX_COUNT;
}
exit:
mutex_unlock(&rmi_smb->page_mutex);
return retval;
}
/* SMB block read - wrapper over ic2_smb_read_block */
static int smb_block_read(struct rmi_transport_dev *xport,
u8 commandcode, void *buf, size_t len)
{
struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport);
struct i2c_client *client = rmi_smb->client;
int retval;
retval = i2c_smbus_read_block_data(client, commandcode, buf);
if (retval < 0)
return retval;
return retval;
}
static int rmi_smb_read_block(struct rmi_transport_dev *xport, u16 rmiaddr,
void *databuff, size_t len)
{
struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport);
int retval;
u8 commandcode;
int cur_len = (int)len;
mutex_lock(&rmi_smb->page_mutex);
memset(databuff, 0, len);
while (cur_len > 0) {
/* break into 32 bytes chunks to write get command code */
int block_len = min_t(int, cur_len, SMB_MAX_COUNT);
retval = rmi_smb_get_command_code(xport, rmiaddr, block_len,
true, &commandcode);
if (retval < 0)
goto exit;
retval = smb_block_read(xport, commandcode,
databuff, block_len);
if (retval < 0)
goto exit;
/* prepare to read next block of bytes */
cur_len -= SMB_MAX_COUNT;
databuff += SMB_MAX_COUNT;
rmiaddr += SMB_MAX_COUNT;
}
retval = 0;
exit:
mutex_unlock(&rmi_smb->page_mutex);
return retval;
}
static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb)
{
/* the mapping table has been flushed, discard the current one */
mutex_lock(&rmi_smb->mappingtable_mutex);
memset(rmi_smb->mapping_table, 0, sizeof(rmi_smb->mapping_table));
mutex_unlock(&rmi_smb->mappingtable_mutex);
}
static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb)
{
int retval;
/* we need to get the smbus version to activate the touchpad */
retval = rmi_smb_get_version(rmi_smb);
if (retval < 0)
return retval;
return 0;
}
static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr)
{
struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport);
rmi_smb_clear_state(rmi_smb);
/*
* we do not call the actual reset command, it has to be handled in
* PS/2 or there will be races between PS/2 and SMBus.
* PS/2 should ensure that a psmouse_reset is called before
* intializing the device and after it has been removed to be in a known
* state.
*/
return rmi_smb_enable_smbus_mode(rmi_smb);
}
static const struct rmi_transport_ops rmi_smb_ops = {
.write_block = rmi_smb_write_block,
.read_block = rmi_smb_read_block,
.reset = rmi_smb_reset,
};
static int rmi_smb_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev);
struct rmi_smb_xport *rmi_smb;
int retval;
int smbus_version;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_SMBUS_HOST_NOTIFY)) {
dev_err(&client->dev,
"adapter does not support required functionality.\n");
return -ENODEV;
}
if (client->irq <= 0) {
dev_err(&client->dev, "no IRQ provided, giving up.\n");
return client->irq ? client->irq : -ENODEV;
}
rmi_smb = devm_kzalloc(&client->dev, sizeof(struct rmi_smb_xport),
GFP_KERNEL);
if (!rmi_smb)
return -ENOMEM;
if (!pdata) {
dev_err(&client->dev, "no platform data, aborting\n");
return -ENOMEM;
}
rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s.\n",
dev_name(&client->dev));
rmi_smb->client = client;
mutex_init(&rmi_smb->page_mutex);
mutex_init(&rmi_smb->mappingtable_mutex);
rmi_smb->xport.dev = &client->dev;
rmi_smb->xport.pdata = *pdata;
rmi_smb->xport.pdata.irq = client->irq;
rmi_smb->xport.proto_name = "smb2";
rmi_smb->xport.ops = &rmi_smb_ops;
retval = rmi_smb_get_version(rmi_smb);
if (retval < 0)
return retval;
smbus_version = retval;
rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
smbus_version);
if (smbus_version != 2) {
dev_err(&client->dev, "Unrecognized SMB version %d.\n",
smbus_version);
return -ENODEV;
}
i2c_set_clientdata(client, rmi_smb);
retval = rmi_register_transport_device(&rmi_smb->xport);
if (retval) {
dev_err(&client->dev, "Failed to register transport driver at 0x%.2X.\n",
client->addr);
i2c_set_clientdata(client, NULL);
return retval;
}
dev_info(&client->dev, "registered rmi smb driver at %#04x.\n",
client->addr);
return 0;
}
static int rmi_smb_remove(struct i2c_client *client)
{
struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
rmi_unregister_transport_device(&rmi_smb->xport);
return 0;
}
static int __maybe_unused rmi_smb_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
int ret;
ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, true);
if (ret)
dev_warn(dev, "Failed to suspend device: %d\n", ret);
return ret;
}
static int __maybe_unused rmi_smb_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
int ret;
ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, false);
if (ret)
dev_warn(dev, "Failed to suspend device: %d\n", ret);
return ret;
}
static int __maybe_unused rmi_smb_resume(struct device *dev)
{
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
struct rmi_device *rmi_dev = rmi_smb->xport.rmi_dev;
int ret;
rmi_smb_reset(&rmi_smb->xport, 0);
rmi_reset(rmi_dev);
ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, true);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
return 0;
}
static int __maybe_unused rmi_smb_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
int ret;
ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, false);
if (ret)
dev_warn(dev, "Failed to resume device: %d\n", ret);
return 0;
}
static const struct dev_pm_ops rmi_smb_pm = {
SET_SYSTEM_SLEEP_PM_OPS(rmi_smb_suspend, rmi_smb_resume)
SET_RUNTIME_PM_OPS(rmi_smb_runtime_suspend, rmi_smb_runtime_resume,
NULL)
};
static const struct i2c_device_id rmi_id[] = {
{ "rmi4_smbus", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rmi_id);
static struct i2c_driver rmi_smb_driver = {
.driver = {
.name = "rmi4_smbus",
.pm = &rmi_smb_pm,
},
.id_table = rmi_id,
.probe = rmi_smb_probe,
.remove = rmi_smb_remove,
};
module_i2c_driver(rmi_smb_driver);
MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>");
MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>");
MODULE_DESCRIPTION("RMI4 SMBus driver");
MODULE_LICENSE("GPL");

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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.
*/

View File

@@ -115,6 +115,15 @@ config TOUCHSCREEN_ATMEL_MXT
To compile this driver as a module, choose M here: the
module will be called atmel_mxt_ts.
config TOUCHSCREEN_ATMEL_MXT_T37
bool "Support T37 Diagnostic Data"
depends on TOUCHSCREEN_ATMEL_MXT
depends on VIDEO_V4L2=y || (TOUCHSCREEN_ATMEL_MXT=m && VIDEO_V4L2=m)
select VIDEOBUF2_VMALLOC
help
Say Y here if you want support to output data from the T37
Diagnostic Data object using a V4L device.
config TOUCHSCREEN_AUO_PIXCIR
tristate "AUO in-cell touchscreen using Pixcir ICs"
depends on I2C

View File

@@ -379,7 +379,7 @@ static const struct attribute_group ad7879_attr_group = {
static int ad7879_gpio_direction_input(struct gpio_chip *chip,
unsigned gpio)
{
struct ad7879 *ts = container_of(chip, struct ad7879, gc);
struct ad7879 *ts = gpiochip_get_data(chip);
int err;
mutex_lock(&ts->mutex);
@@ -393,7 +393,7 @@ static int ad7879_gpio_direction_input(struct gpio_chip *chip,
static int ad7879_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int level)
{
struct ad7879 *ts = container_of(chip, struct ad7879, gc);
struct ad7879 *ts = gpiochip_get_data(chip);
int err;
mutex_lock(&ts->mutex);
@@ -412,7 +412,7 @@ static int ad7879_gpio_direction_output(struct gpio_chip *chip,
static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
struct ad7879 *ts = container_of(chip, struct ad7879, gc);
struct ad7879 *ts = gpiochip_get_data(chip);
u16 val;
mutex_lock(&ts->mutex);
@@ -425,7 +425,7 @@ static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
static void ad7879_gpio_set_value(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct ad7879 *ts = container_of(chip, struct ad7879, gc);
struct ad7879 *ts = gpiochip_get_data(chip);
mutex_lock(&ts->mutex);
if (value)
@@ -456,7 +456,7 @@ static int ad7879_gpio_add(struct ad7879 *ts,
ts->gc.owner = THIS_MODULE;
ts->gc.parent = ts->dev;
ret = gpiochip_add(&ts->gc);
ret = gpiochip_add_data(&ts->gc, ts);
if (ret)
dev_err(ts->dev, "failed to register gpio %d\n",
ts->gc.base);

View File

@@ -4,6 +4,7 @@
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Copyright (C) 2011-2014 Atmel Corporation
* Copyright (C) 2012 Google, Inc.
* Copyright (C) 2016 Zodiac Inflight Innovations
*
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
@@ -28,6 +29,10 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
/* Firmware files */
#define MXT_FW_NAME "maxtouch.fw"
@@ -99,6 +104,8 @@ struct t7_config {
/* MXT_TOUCH_MULTI_T9 field */
#define MXT_T9_CTRL 0
#define MXT_T9_XSIZE 3
#define MXT_T9_YSIZE 4
#define MXT_T9_ORIENT 9
#define MXT_T9_RANGE 18
@@ -119,11 +126,31 @@ struct t9_range {
/* MXT_TOUCH_MULTI_T9 orient */
#define MXT_T9_ORIENT_SWITCH (1 << 0)
#define MXT_T9_ORIENT_INVERTX (1 << 1)
#define MXT_T9_ORIENT_INVERTY (1 << 2)
/* MXT_SPT_COMMSCONFIG_T18 */
#define MXT_COMMS_CTRL 0
#define MXT_COMMS_CMD 1
/* MXT_DEBUG_DIAGNOSTIC_T37 */
#define MXT_DIAGNOSTIC_PAGEUP 0x01
#define MXT_DIAGNOSTIC_DELTAS 0x10
#define MXT_DIAGNOSTIC_REFS 0x11
#define MXT_DIAGNOSTIC_SIZE 128
#define MXT_FAMILY_1386 160
#define MXT1386_COLUMNS 3
#define MXT1386_PAGES_PER_COLUMN 8
struct t37_debug {
#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
u8 mode;
u8 page;
u8 data[MXT_DIAGNOSTIC_SIZE];
#endif
};
/* Define for MXT_GEN_COMMAND_T6 */
#define MXT_BOOT_VALUE 0xa5
#define MXT_RESET_VALUE 0x01
@@ -133,10 +160,14 @@ struct t9_range {
#define MXT_T100_CTRL 0
#define MXT_T100_CFG1 1
#define MXT_T100_TCHAUX 3
#define MXT_T100_XSIZE 9
#define MXT_T100_XRANGE 13
#define MXT_T100_YSIZE 20
#define MXT_T100_YRANGE 24
#define MXT_T100_CFG_SWITCHXY BIT(5)
#define MXT_T100_CFG_INVERTY BIT(6)
#define MXT_T100_CFG_INVERTX BIT(7)
#define MXT_T100_TCHAUX_VECT BIT(0)
#define MXT_T100_TCHAUX_AMPL BIT(1)
@@ -205,6 +236,37 @@ struct mxt_object {
u8 num_report_ids;
} __packed;
struct mxt_dbg {
u16 t37_address;
u16 diag_cmd_address;
struct t37_debug *t37_buf;
unsigned int t37_pages;
unsigned int t37_nodes;
struct v4l2_device v4l2;
struct v4l2_pix_format format;
struct video_device vdev;
struct vb2_queue queue;
struct mutex lock;
int input;
};
enum v4l_dbg_inputs {
MXT_V4L_INPUT_DELTAS,
MXT_V4L_INPUT_REFS,
MXT_V4L_INPUT_MAX,
};
static const struct v4l2_file_operations mxt_video_fops = {
.owner = THIS_MODULE,
.open = v4l2_fh_open,
.release = vb2_fop_release,
.unlocked_ioctl = video_ioctl2,
.read = vb2_fop_read,
.mmap = vb2_fop_mmap,
.poll = vb2_fop_poll,
};
/* Each client has this additional data */
struct mxt_data {
struct i2c_client *client;
@@ -216,7 +278,11 @@ struct mxt_data {
unsigned int irq;
unsigned int max_x;
unsigned int max_y;
bool invertx;
bool inverty;
bool xy_switch;
u8 xsize;
u8 ysize;
bool in_bootloader;
u16 mem_size;
u8 t100_aux_ampl;
@@ -233,6 +299,7 @@ struct mxt_data {
u8 num_touchids;
u8 multitouch;
struct t7_config t7_cfg;
struct mxt_dbg dbg;
/* Cached parameters from object table */
u16 T5_address;
@@ -257,6 +324,11 @@ struct mxt_data {
struct completion crc_completion;
};
struct mxt_vb2_buffer {
struct vb2_buffer vb;
struct list_head list;
};
static size_t mxt_obj_size(const struct mxt_object *obj)
{
return obj->size_minus_one + 1;
@@ -1503,6 +1575,11 @@ static void mxt_free_input_device(struct mxt_data *data)
static void mxt_free_object_table(struct mxt_data *data)
{
#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
video_unregister_device(&data->dbg.vdev);
v4l2_device_unregister(&data->dbg.v4l2);
#endif
kfree(data->object_table);
data->object_table = NULL;
kfree(data->msg_buf);
@@ -1660,6 +1737,18 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
if (!object)
return -EINVAL;
error = __mxt_read_reg(client,
object->start_address + MXT_T9_XSIZE,
sizeof(data->xsize), &data->xsize);
if (error)
return error;
error = __mxt_read_reg(client,
object->start_address + MXT_T9_YSIZE,
sizeof(data->ysize), &data->ysize);
if (error)
return error;
error = __mxt_read_reg(client,
object->start_address + MXT_T9_RANGE,
sizeof(range), &range);
@@ -1676,6 +1765,8 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
return error;
data->xy_switch = orient & MXT_T9_ORIENT_SWITCH;
data->invertx = orient & MXT_T9_ORIENT_INVERTX;
data->inverty = orient & MXT_T9_ORIENT_INVERTY;
return 0;
}
@@ -1710,6 +1801,18 @@ static int mxt_read_t100_config(struct mxt_data *data)
data->max_y = get_unaligned_le16(&range_y);
error = __mxt_read_reg(client,
object->start_address + MXT_T100_XSIZE,
sizeof(data->xsize), &data->xsize);
if (error)
return error;
error = __mxt_read_reg(client,
object->start_address + MXT_T100_YSIZE,
sizeof(data->ysize), &data->ysize);
if (error)
return error;
/* read orientation config */
error = __mxt_read_reg(client,
object->start_address + MXT_T100_CFG1,
@@ -1718,6 +1821,8 @@ static int mxt_read_t100_config(struct mxt_data *data)
return error;
data->xy_switch = cfg & MXT_T100_CFG_SWITCHXY;
data->invertx = cfg & MXT_T100_CFG_INVERTX;
data->inverty = cfg & MXT_T100_CFG_INVERTY;
/* allocate aux bytes */
error = __mxt_read_reg(client,
@@ -2043,6 +2148,420 @@ recheck:
return 0;
}
#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x,
unsigned int y)
{
struct mxt_info *info = &data->info;
struct mxt_dbg *dbg = &data->dbg;
unsigned int ofs, page;
unsigned int col = 0;
unsigned int col_width;
if (info->family_id == MXT_FAMILY_1386) {
col_width = info->matrix_ysize / MXT1386_COLUMNS;
col = y / col_width;
y = y % col_width;
} else {
col_width = info->matrix_ysize;
}
ofs = (y + (x * col_width)) * sizeof(u16);
page = ofs / MXT_DIAGNOSTIC_SIZE;
ofs %= MXT_DIAGNOSTIC_SIZE;
if (info->family_id == MXT_FAMILY_1386)
page += col * MXT1386_PAGES_PER_COLUMN;
return get_unaligned_le16(&dbg->t37_buf[page].data[ofs]);
}
static int mxt_convert_debug_pages(struct mxt_data *data, u16 *outbuf)
{
struct mxt_dbg *dbg = &data->dbg;
unsigned int x = 0;
unsigned int y = 0;
unsigned int i, rx, ry;
for (i = 0; i < dbg->t37_nodes; i++) {
/* Handle orientation */
rx = data->xy_switch ? y : x;
ry = data->xy_switch ? x : y;
rx = data->invertx ? (data->xsize - 1 - rx) : rx;
ry = data->inverty ? (data->ysize - 1 - ry) : ry;
outbuf[i] = mxt_get_debug_value(data, rx, ry);
/* Next value */
if (++x >= (data->xy_switch ? data->ysize : data->xsize)) {
x = 0;
y++;
}
}
return 0;
}
static int mxt_read_diagnostic_debug(struct mxt_data *data, u8 mode,
u16 *outbuf)
{
struct mxt_dbg *dbg = &data->dbg;
int retries = 0;
int page;
int ret;
u8 cmd = mode;
struct t37_debug *p;
u8 cmd_poll;
for (page = 0; page < dbg->t37_pages; page++) {
p = dbg->t37_buf + page;
ret = mxt_write_reg(data->client, dbg->diag_cmd_address,
cmd);
if (ret)
return ret;
retries = 0;
msleep(20);
wait_cmd:
/* Read back command byte */
ret = __mxt_read_reg(data->client, dbg->diag_cmd_address,
sizeof(cmd_poll), &cmd_poll);
if (ret)
return ret;
/* Field is cleared once the command has been processed */
if (cmd_poll) {
if (retries++ > 100)
return -EINVAL;
msleep(20);
goto wait_cmd;
}
/* Read T37 page */
ret = __mxt_read_reg(data->client, dbg->t37_address,
sizeof(struct t37_debug), p);
if (ret)
return ret;
if (p->mode != mode || p->page != page) {
dev_err(&data->client->dev, "T37 page mismatch\n");
return -EINVAL;
}
dev_dbg(&data->client->dev, "%s page:%d retries:%d\n",
__func__, page, retries);
/* For remaining pages, write PAGEUP rather than mode */
cmd = MXT_DIAGNOSTIC_PAGEUP;
}
return mxt_convert_debug_pages(data, outbuf);
}
static int mxt_queue_setup(struct vb2_queue *q,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], struct device *alloc_devs[])
{
struct mxt_data *data = q->drv_priv;
size_t size = data->dbg.t37_nodes * sizeof(u16);
if (*nplanes)
return sizes[0] < size ? -EINVAL : 0;
*nplanes = 1;
sizes[0] = size;
return 0;
}
static void mxt_buffer_queue(struct vb2_buffer *vb)
{
struct mxt_data *data = vb2_get_drv_priv(vb->vb2_queue);
u16 *ptr;
int ret;
u8 mode;
ptr = vb2_plane_vaddr(vb, 0);
if (!ptr) {
dev_err(&data->client->dev, "Error acquiring frame ptr\n");
goto fault;
}
switch (data->dbg.input) {
case MXT_V4L_INPUT_DELTAS:
default:
mode = MXT_DIAGNOSTIC_DELTAS;
break;
case MXT_V4L_INPUT_REFS:
mode = MXT_DIAGNOSTIC_REFS;
break;
}
ret = mxt_read_diagnostic_debug(data, mode, ptr);
if (ret)
goto fault;
vb2_set_plane_payload(vb, 0, data->dbg.t37_nodes * sizeof(u16));
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
return;
fault:
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}
/* V4L2 structures */
static const struct vb2_ops mxt_queue_ops = {
.queue_setup = mxt_queue_setup,
.buf_queue = mxt_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
static const struct vb2_queue mxt_queue = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ,
.buf_struct_size = sizeof(struct mxt_vb2_buffer),
.ops = &mxt_queue_ops,
.mem_ops = &vb2_vmalloc_memops,
.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
.min_buffers_needed = 1,
};
static int mxt_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct mxt_data *data = video_drvdata(file);
strlcpy(cap->driver, "atmel_mxt_ts", sizeof(cap->driver));
strlcpy(cap->card, "atmel_mxt_ts touch", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"I2C:%s", dev_name(&data->client->dev));
return 0;
}
static int mxt_vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
if (i->index >= MXT_V4L_INPUT_MAX)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_TOUCH;
switch (i->index) {
case MXT_V4L_INPUT_REFS:
strlcpy(i->name, "Mutual Capacitance References",
sizeof(i->name));
break;
case MXT_V4L_INPUT_DELTAS:
strlcpy(i->name, "Mutual Capacitance Deltas", sizeof(i->name));
break;
}
return 0;
}
static int mxt_set_input(struct mxt_data *data, unsigned int i)
{
struct v4l2_pix_format *f = &data->dbg.format;
if (i >= MXT_V4L_INPUT_MAX)
return -EINVAL;
if (i == MXT_V4L_INPUT_DELTAS)
f->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
else
f->pixelformat = V4L2_TCH_FMT_TU16;
f->width = data->xy_switch ? data->ysize : data->xsize;
f->height = data->xy_switch ? data->xsize : data->ysize;
f->field = V4L2_FIELD_NONE;
f->colorspace = V4L2_COLORSPACE_RAW;
f->bytesperline = f->width * sizeof(u16);
f->sizeimage = f->width * f->height * sizeof(u16);
data->dbg.input = i;
return 0;
}
static int mxt_vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
return mxt_set_input(video_drvdata(file), i);
}
static int mxt_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
struct mxt_data *data = video_drvdata(file);
*i = data->dbg.input;
return 0;
}
static int mxt_vidioc_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
struct mxt_data *data = video_drvdata(file);
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->fmt.pix = data->dbg.format;
return 0;
}
static int mxt_vidioc_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *fmt)
{
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
switch (fmt->index) {
case 0:
fmt->pixelformat = V4L2_TCH_FMT_TU16;
break;
case 1:
fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
break;
default:
return -EINVAL;
}
return 0;
}
static int mxt_vidioc_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
a->parm.capture.readbuffers = 1;
a->parm.capture.timeperframe.numerator = 1;
a->parm.capture.timeperframe.denominator = 10;
return 0;
}
static const struct v4l2_ioctl_ops mxt_video_ioctl_ops = {
.vidioc_querycap = mxt_vidioc_querycap,
.vidioc_enum_fmt_vid_cap = mxt_vidioc_enum_fmt,
.vidioc_s_fmt_vid_cap = mxt_vidioc_fmt,
.vidioc_g_fmt_vid_cap = mxt_vidioc_fmt,
.vidioc_try_fmt_vid_cap = mxt_vidioc_fmt,
.vidioc_g_parm = mxt_vidioc_g_parm,
.vidioc_enum_input = mxt_vidioc_enum_input,
.vidioc_g_input = mxt_vidioc_g_input,
.vidioc_s_input = mxt_vidioc_s_input,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
};
static const struct video_device mxt_video_device = {
.name = "Atmel maxTouch",
.fops = &mxt_video_fops,
.ioctl_ops = &mxt_video_ioctl_ops,
.release = video_device_release_empty,
.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING,
};
static void mxt_debug_init(struct mxt_data *data)
{
struct mxt_info *info = &data->info;
struct mxt_dbg *dbg = &data->dbg;
struct mxt_object *object;
int error;
object = mxt_get_object(data, MXT_GEN_COMMAND_T6);
if (!object)
goto error;
dbg->diag_cmd_address = object->start_address + MXT_COMMAND_DIAGNOSTIC;
object = mxt_get_object(data, MXT_DEBUG_DIAGNOSTIC_T37);
if (!object)
goto error;
if (mxt_obj_size(object) != sizeof(struct t37_debug)) {
dev_warn(&data->client->dev, "Bad T37 size");
goto error;
}
dbg->t37_address = object->start_address;
/* Calculate size of data and allocate buffer */
dbg->t37_nodes = data->xsize * data->ysize;
if (info->family_id == MXT_FAMILY_1386)
dbg->t37_pages = MXT1386_COLUMNS * MXT1386_PAGES_PER_COLUMN;
else
dbg->t37_pages = DIV_ROUND_UP(data->xsize *
data->info.matrix_ysize *
sizeof(u16),
sizeof(dbg->t37_buf->data));
dbg->t37_buf = devm_kmalloc_array(&data->client->dev, dbg->t37_pages,
sizeof(struct t37_debug), GFP_KERNEL);
if (!dbg->t37_buf)
goto error;
/* init channel to zero */
mxt_set_input(data, 0);
/* register video device */
snprintf(dbg->v4l2.name, sizeof(dbg->v4l2.name), "%s", "atmel_mxt_ts");
error = v4l2_device_register(&data->client->dev, &dbg->v4l2);
if (error)
goto error;
/* initialize the queue */
mutex_init(&dbg->lock);
dbg->queue = mxt_queue;
dbg->queue.drv_priv = data;
dbg->queue.lock = &dbg->lock;
dbg->queue.dev = &data->client->dev;
error = vb2_queue_init(&dbg->queue);
if (error)
goto error_unreg_v4l2;
dbg->vdev = mxt_video_device;
dbg->vdev.v4l2_dev = &dbg->v4l2;
dbg->vdev.lock = &dbg->lock;
dbg->vdev.vfl_dir = VFL_DIR_RX;
dbg->vdev.queue = &dbg->queue;
video_set_drvdata(&dbg->vdev, data);
error = video_register_device(&dbg->vdev, VFL_TYPE_TOUCH, -1);
if (error)
goto error_unreg_v4l2;
return;
error_unreg_v4l2:
v4l2_device_unregister(&dbg->v4l2);
error:
dev_warn(&data->client->dev, "Error initializing T37\n");
}
#else
static void mxt_debug_init(struct mxt_data *data)
{
}
#endif
static int mxt_configure_objects(struct mxt_data *data,
const struct firmware *cfg)
{
@@ -2070,6 +2589,8 @@ static int mxt_configure_objects(struct mxt_data *data,
dev_warn(dev, "No touch object detected\n");
}
mxt_debug_init(data);
dev_info(dev,
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
info->family_id, info->variant_id, info->version >> 4,

View File

@@ -1499,7 +1499,7 @@ static int cyttsp4_core_sleep_(struct cyttsp4 *cd)
if (IS_BOOTLOADER(mode[0], mode[1])) {
mutex_unlock(&cd->system_lock);
dev_err(cd->dev, "%s: Device in BOOTLADER mode.\n", __func__);
dev_err(cd->dev, "%s: Device in BOOTLOADER mode.\n", __func__);
rc = -EINVAL;
goto error;
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -29,6 +29,7 @@
#include <linux/input/touchscreen.h>
#include <linux/pm.h>
#include <linux/irq.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h>
@@ -73,6 +74,7 @@ struct silead_ts_data {
struct i2c_client *client;
struct gpio_desc *gpio_power;
struct input_dev *input;
struct regulator_bulk_data regulators[2];
char fw_name[64];
struct touchscreen_properties prop;
u32 max_fingers;
@@ -433,6 +435,13 @@ static int silead_ts_set_default_fw_name(struct silead_ts_data *data,
}
#endif
static void silead_disable_regulator(void *arg)
{
struct silead_ts_data *data = arg;
regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
}
static int silead_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -465,6 +474,26 @@ static int silead_ts_probe(struct i2c_client *client,
if (client->irq <= 0)
return -ENODEV;
data->regulators[0].supply = "vddio";
data->regulators[1].supply = "avdd";
error = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators),
data->regulators);
if (error)
return error;
/*
* Enable regulators at probe and disable them at remove, we need
* to keep the chip powered otherwise it forgets its firmware.
*/
error = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
data->regulators);
if (error)
return error;
error = devm_add_action_or_reset(dev, silead_disable_regulator, data);
if (error)
return error;
/* Power GPIO pin */
data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
if (IS_ERR(data->gpio_power)) {

View File

@@ -115,7 +115,6 @@
struct sun4i_ts_data {
struct device *dev;
struct input_dev *input;
struct thermal_zone_device *tz;
void __iomem *base;
unsigned int irq;
bool ignore_fifo_data;
@@ -366,10 +365,7 @@ static int sun4i_ts_probe(struct platform_device *pdev)
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
ts->tz = thermal_zone_of_sensor_register(ts->dev, 0, ts,
&sun4i_ts_tz_ops);
if (IS_ERR(ts->tz))
ts->tz = NULL;
devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, &sun4i_ts_tz_ops);
writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
@@ -377,7 +373,6 @@ static int sun4i_ts_probe(struct platform_device *pdev)
error = input_register_device(ts->input);
if (error) {
writel(0, ts->base + TP_INT_FIFOC);
thermal_zone_of_sensor_unregister(ts->dev, ts->tz);
return error;
}
}
@@ -394,8 +389,6 @@ static int sun4i_ts_remove(struct platform_device *pdev)
if (ts->input)
input_unregister_device(ts->input);
thermal_zone_of_sensor_unregister(ts->dev, ts->tz);
/* Deactivate all IRQs */
writel(0, ts->base + TP_INT_FIFOC);

View File

@@ -126,7 +126,7 @@ struct sur40_image_header {
#define VIDEO_PACKET_SIZE 16384
/* polling interval (ms) */
#define POLL_INTERVAL 4
#define POLL_INTERVAL 1
/* maximum number of contacts FIXME: this is a guess? */
#define MAX_CONTACTS 64
@@ -139,6 +139,27 @@ struct sur40_image_header {
#define SUR40_GET_STATE 0xc5 /* 4 bytes state (?) */
#define SUR40_GET_SENSORS 0xb1 /* 8 bytes sensors */
static const struct v4l2_pix_format sur40_pix_format[] = {
{
.pixelformat = V4L2_TCH_FMT_TU08,
.width = SENSOR_RES_X / 2,
.height = SENSOR_RES_Y / 2,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_SRGB,
.bytesperline = SENSOR_RES_X / 2,
.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
},
{
.pixelformat = V4L2_PIX_FMT_GREY,
.width = SENSOR_RES_X / 2,
.height = SENSOR_RES_Y / 2,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_SRGB,
.bytesperline = SENSOR_RES_X / 2,
.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
}
};
/* master device state */
struct sur40_state {
@@ -149,9 +170,9 @@ struct sur40_state {
struct v4l2_device v4l2;
struct video_device vdev;
struct mutex lock;
struct v4l2_pix_format pix_fmt;
struct vb2_queue queue;
struct vb2_alloc_ctx *alloc_ctx;
struct list_head buf_list;
spinlock_t qlock;
int sequence;
@@ -170,7 +191,6 @@ struct sur40_buffer {
/* forward declarations */
static const struct video_device sur40_video_device;
static const struct v4l2_pix_format sur40_video_format;
static const struct vb2_queue sur40_queue;
static void sur40_process_video(struct sur40_state *sur40);
@@ -421,7 +441,7 @@ static void sur40_process_video(struct sur40_state *sur40)
goto err_poll;
}
if (le32_to_cpu(img->size) != sur40_video_format.sizeimage) {
if (le32_to_cpu(img->size) != sur40->pix_fmt.sizeimage) {
dev_err(sur40->dev, "image size mismatch\n");
goto err_poll;
}
@@ -432,7 +452,7 @@ static void sur40_process_video(struct sur40_state *sur40)
result = usb_sg_init(&sgr, sur40->usbdev,
usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
sgt->sgl, sgt->nents, sur40_video_format.sizeimage, 0);
sgt->sgl, sgt->nents, sur40->pix_fmt.sizeimage, 0);
if (result < 0) {
dev_err(sur40->dev, "error %d in usb_sg_init\n", result);
goto err_poll;
@@ -448,7 +468,7 @@ static void sur40_process_video(struct sur40_state *sur40)
/* return error if streaming was stopped in the meantime */
if (sur40->sequence == -1)
goto err_poll;
return;
/* mark as finished */
new_buf->vb.vb2_buf.timestamp = ktime_get_ns();
@@ -580,26 +600,21 @@ static int sur40_probe(struct usb_interface *interface,
sur40->queue = sur40_queue;
sur40->queue.drv_priv = sur40;
sur40->queue.lock = &sur40->lock;
sur40->queue.dev = sur40->dev;
/* initialize the queue */
error = vb2_queue_init(&sur40->queue);
if (error)
goto err_unreg_v4l2;
sur40->alloc_ctx = vb2_dma_sg_init_ctx(sur40->dev);
if (IS_ERR(sur40->alloc_ctx)) {
dev_err(sur40->dev, "Can't allocate buffer context");
error = PTR_ERR(sur40->alloc_ctx);
goto err_unreg_v4l2;
}
sur40->pix_fmt = sur40_pix_format[0];
sur40->vdev = sur40_video_device;
sur40->vdev.v4l2_dev = &sur40->v4l2;
sur40->vdev.lock = &sur40->lock;
sur40->vdev.queue = &sur40->queue;
video_set_drvdata(&sur40->vdev, sur40);
error = video_register_device(&sur40->vdev, VFL_TYPE_GRABBER, -1);
error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1);
if (error) {
dev_err(&interface->dev,
"Unable to register video subdevice.");
@@ -633,7 +648,6 @@ static void sur40_disconnect(struct usb_interface *interface)
video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2);
vb2_dma_sg_cleanup_ctx(sur40->alloc_ctx);
input_unregister_polled_device(sur40->input);
input_free_polled_device(sur40->input);
@@ -653,19 +667,18 @@ static void sur40_disconnect(struct usb_interface *interface)
*/
static int sur40_queue_setup(struct vb2_queue *q,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
unsigned int sizes[], struct device *alloc_devs[])
{
struct sur40_state *sur40 = vb2_get_drv_priv(q);
if (q->num_buffers + *nbuffers < 3)
*nbuffers = 3 - q->num_buffers;
alloc_ctxs[0] = sur40->alloc_ctx;
if (*nplanes)
return sizes[0] < sur40_video_format.sizeimage ? -EINVAL : 0;
return sizes[0] < sur40->pix_fmt.sizeimage ? -EINVAL : 0;
*nplanes = 1;
sizes[0] = sur40_video_format.sizeimage;
sizes[0] = sur40->pix_fmt.sizeimage;
return 0;
}
@@ -677,7 +690,7 @@ static int sur40_queue_setup(struct vb2_queue *q,
static int sur40_buffer_prepare(struct vb2_buffer *vb)
{
struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
unsigned long size = sur40_video_format.sizeimage;
unsigned long size = sur40->pix_fmt.sizeimage;
if (vb2_plane_size(vb, 0) < size) {
dev_err(&sur40->usbdev->dev, "buffer too small (%lu < %lu)\n",
@@ -736,6 +749,7 @@ static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count)
static void sur40_stop_streaming(struct vb2_queue *vq)
{
struct sur40_state *sur40 = vb2_get_drv_priv(vq);
vb2_wait_for_all_buffers(vq);
sur40->sequence = -1;
/* Release all active buffers */
@@ -751,7 +765,7 @@ static int sur40_vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -763,7 +777,7 @@ static int sur40_vidioc_enum_input(struct file *file, void *priv,
{
if (i->index != 0)
return -EINVAL;
i->type = V4L2_INPUT_TYPE_CAMERA;
i->type = V4L2_INPUT_TYPE_TOUCH;
i->std = V4L2_STD_UNKNOWN;
strlcpy(i->name, "In-Cell Sensor", sizeof(i->name));
i->capabilities = 0;
@@ -781,20 +795,70 @@ static int sur40_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
return 0;
}
static int sur40_vidioc_fmt(struct file *file, void *priv,
static int sur40_vidioc_try_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
f->fmt.pix = sur40_video_format;
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_GREY:
f->fmt.pix = sur40_pix_format[1];
break;
default:
f->fmt.pix = sur40_pix_format[0];
break;
}
return 0;
}
static int sur40_vidioc_s_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
struct sur40_state *sur40 = video_drvdata(file);
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_GREY:
sur40->pix_fmt = sur40_pix_format[1];
break;
default:
sur40->pix_fmt = sur40_pix_format[0];
break;
}
f->fmt.pix = sur40->pix_fmt;
return 0;
}
static int sur40_vidioc_g_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
struct sur40_state *sur40 = video_drvdata(file);
f->fmt.pix = sur40->pix_fmt;
return 0;
}
static int sur40_ioctl_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
p->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
p->parm.capture.timeperframe.numerator = 1;
p->parm.capture.timeperframe.denominator = 60;
p->parm.capture.readbuffers = 3;
return 0;
}
static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
if (f->index >= ARRAY_SIZE(sur40_pix_format))
return -EINVAL;
strlcpy(f->description, "8-bit greyscale", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_GREY;
f->pixelformat = sur40_pix_format[f->index].pixelformat;
f->flags = 0;
return 0;
}
@@ -802,25 +866,31 @@ static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
static int sur40_vidioc_enum_framesizes(struct file *file, void *priv,
struct v4l2_frmsizeenum *f)
{
if ((f->index != 0) || (f->pixel_format != V4L2_PIX_FMT_GREY))
struct sur40_state *sur40 = video_drvdata(file);
if ((f->index != 0) || ((f->pixel_format != V4L2_TCH_FMT_TU08)
&& (f->pixel_format != V4L2_PIX_FMT_GREY)))
return -EINVAL;
f->type = V4L2_FRMSIZE_TYPE_DISCRETE;
f->discrete.width = sur40_video_format.width;
f->discrete.height = sur40_video_format.height;
f->discrete.width = sur40->pix_fmt.width;
f->discrete.height = sur40->pix_fmt.height;
return 0;
}
static int sur40_vidioc_enum_frameintervals(struct file *file, void *priv,
struct v4l2_frmivalenum *f)
{
if ((f->index > 1) || (f->pixel_format != V4L2_PIX_FMT_GREY)
|| (f->width != sur40_video_format.width)
|| (f->height != sur40_video_format.height))
return -EINVAL;
struct sur40_state *sur40 = video_drvdata(file);
if ((f->index > 0) || ((f->pixel_format != V4L2_TCH_FMT_TU08)
&& (f->pixel_format != V4L2_PIX_FMT_GREY))
|| (f->width != sur40->pix_fmt.width)
|| (f->height != sur40->pix_fmt.height))
return -EINVAL;
f->type = V4L2_FRMIVAL_TYPE_DISCRETE;
f->discrete.denominator = 60/(f->index+1);
f->discrete.denominator = 60;
f->discrete.numerator = 1;
return 0;
}
@@ -873,13 +943,16 @@ static const struct v4l2_ioctl_ops sur40_video_ioctl_ops = {
.vidioc_querycap = sur40_vidioc_querycap,
.vidioc_enum_fmt_vid_cap = sur40_vidioc_enum_fmt,
.vidioc_try_fmt_vid_cap = sur40_vidioc_fmt,
.vidioc_s_fmt_vid_cap = sur40_vidioc_fmt,
.vidioc_g_fmt_vid_cap = sur40_vidioc_fmt,
.vidioc_try_fmt_vid_cap = sur40_vidioc_try_fmt,
.vidioc_s_fmt_vid_cap = sur40_vidioc_s_fmt,
.vidioc_g_fmt_vid_cap = sur40_vidioc_g_fmt,
.vidioc_enum_framesizes = sur40_vidioc_enum_framesizes,
.vidioc_enum_frameintervals = sur40_vidioc_enum_frameintervals,
.vidioc_g_parm = sur40_ioctl_parm,
.vidioc_s_parm = sur40_ioctl_parm,
.vidioc_enum_input = sur40_vidioc_enum_input,
.vidioc_g_input = sur40_vidioc_g_input,
.vidioc_s_input = sur40_vidioc_s_input,
@@ -902,16 +975,6 @@ static const struct video_device sur40_video_device = {
.release = video_device_release_empty,
};
static const struct v4l2_pix_format sur40_video_format = {
.pixelformat = V4L2_PIX_FMT_GREY,
.width = SENSOR_RES_X / 2,
.height = SENSOR_RES_Y / 2,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_SRGB,
.bytesperline = SENSOR_RES_X / 2,
.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
};
/* USB-specific object needed to register this driver with the USB subsystem. */
static struct usb_driver sur40_driver = {
.name = DRIVER_SHORT,