From 5d4b45a1dd7b00feab57624035dcdbc1bab2e0f8 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sun, 21 Jul 2019 20:20:28 +0300 Subject: Input: add support for the FlySky FS-iA6B RC receiver This patch adds support for the FlySky FS-iA6B RC receiver (serial IBUS). It allows the usage of the FlySky FS-i6 and other AFHDS compliant remote controls as a joystick input device. To use it, a patch to inputattach which adds the FS-iA6B as a 115200 baud serial device is required. I will upstream it after this patch is merged. More information about the hardware can be found here: https://notsyncing.net/?p=blog&b=2018.linux-fsia6b Signed-off-by: Markus Koch Signed-off-by: Dmitry Torokhov --- include/uapi/linux/serio.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h index a0cac1d8670d..50e991952c97 100644 --- a/include/uapi/linux/serio.h +++ b/include/uapi/linux/serio.h @@ -82,5 +82,6 @@ #define SERIO_EGALAX 0x3f #define SERIO_PULSE8_CEC 0x40 #define SERIO_RAINSHADOW_CEC 0x41 +#define SERIO_FSIA6B 0x42 #endif /* _UAPI_SERIO_H */ -- cgit v1.2.3 From 3b51c44bd6936e86a7180abd9aebc4387a479253 Mon Sep 17 00:00:00 2001 From: Atif Niyaz Date: Wed, 24 Jul 2019 22:26:31 +0300 Subject: Input: allow drivers specify timestamp for input events Currently, evdev stamps events with timestamps acquired in evdev_events() However, this timestamping may not be accurate in terms of measuring when the actual event happened. Let's allow individual drivers specify timestamp in order to provide a more accurate sense of time for the event. It is expected that drivers will set the timestamp in their hard interrupt routine. Signed-off-by: Atif Niyaz Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 35 ++++++++--------------------------- drivers/input/input.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/input.h | 14 ++++++++++++++ 3 files changed, 62 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 867c2cfd0038..d7dd6fcf2db0 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -25,13 +25,6 @@ #include #include "input-compat.h" -enum evdev_clock_type { - EV_CLK_REAL = 0, - EV_CLK_MONO, - EV_CLK_BOOT, - EV_CLK_MAX -}; - struct evdev { int open; struct input_handle handle; @@ -53,7 +46,7 @@ struct evdev_client { struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; - unsigned int clk_type; + enum input_clock_type clk_type; bool revoked; unsigned long *evmasks[EV_CNT]; unsigned int bufsize; @@ -149,17 +142,10 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { + ktime_t *ev_time = input_get_timestamp(client->evdev->handle.dev); + struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]); struct input_event ev; - ktime_t time; - struct timespec64 ts; - time = client->clk_type == EV_CLK_REAL ? - ktime_get_real() : - client->clk_type == EV_CLK_MONO ? - ktime_get() : - ktime_get_boottime(); - - ts = ktime_to_timespec64(time); ev.input_event_sec = ts.tv_sec; ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC; ev.type = EV_SYN; @@ -188,18 +174,18 @@ static void evdev_queue_syn_dropped(struct evdev_client *client) static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) { unsigned long flags; - unsigned int clk_type; + enum input_clock_type clk_type; switch (clkid) { case CLOCK_REALTIME: - clk_type = EV_CLK_REAL; + clk_type = INPUT_CLK_REAL; break; case CLOCK_MONOTONIC: - clk_type = EV_CLK_MONO; + clk_type = INPUT_CLK_MONO; break; case CLOCK_BOOTTIME: - clk_type = EV_CLK_BOOT; + clk_type = INPUT_CLK_BOOT; break; default: return -EINVAL; @@ -307,12 +293,7 @@ static void evdev_events(struct input_handle *handle, { struct evdev *evdev = handle->private; struct evdev_client *client; - ktime_t ev_time[EV_CLK_MAX]; - - ev_time[EV_CLK_MONO] = ktime_get(); - ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); - ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO], - TK_OFFS_BOOT); + ktime_t *ev_time = input_get_timestamp(handle->dev); rcu_read_lock(); diff --git a/drivers/input/input.c b/drivers/input/input.c index 7f3c5fcb9ed6..7494a0dede79 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1894,6 +1894,46 @@ void input_free_device(struct input_dev *dev) } EXPORT_SYMBOL(input_free_device); +/** + * input_set_timestamp - set timestamp for input events + * @dev: input device to set timestamp for + * @timestamp: the time at which the event has occurred + * in CLOCK_MONOTONIC + * + * This function is intended to provide to the input system a more + * accurate time of when an event actually occurred. The driver should + * call this function as soon as a timestamp is acquired ensuring + * clock conversions in input_set_timestamp are done correctly. + * + * The system entering suspend state between timestamp acquisition and + * calling input_set_timestamp can result in inaccurate conversions. + */ +void input_set_timestamp(struct input_dev *dev, ktime_t timestamp) +{ + dev->timestamp[INPUT_CLK_MONO] = timestamp; + dev->timestamp[INPUT_CLK_REAL] = ktime_mono_to_real(timestamp); + dev->timestamp[INPUT_CLK_BOOT] = ktime_mono_to_any(timestamp, + TK_OFFS_BOOT); +} +EXPORT_SYMBOL(input_set_timestamp); + +/** + * input_get_timestamp - get timestamp for input events + * @dev: input device to get timestamp from + * + * A valid timestamp is a timestamp of non-zero value. + */ +ktime_t *input_get_timestamp(struct input_dev *dev) +{ + const ktime_t invalid_timestamp = ktime_set(0, 0); + + if (!ktime_compare(dev->timestamp[INPUT_CLK_MONO], invalid_timestamp)) + input_set_timestamp(dev, ktime_get()); + + return dev->timestamp; +} +EXPORT_SYMBOL(input_get_timestamp); + /** * input_set_capability - mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event diff --git a/include/linux/input.h b/include/linux/input.h index 510e78558c10..e95a439d8bd5 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -33,6 +33,13 @@ struct input_value { __s32 value; }; +enum input_clock_type { + INPUT_CLK_REAL = 0, + INPUT_CLK_MONO, + INPUT_CLK_BOOT, + INPUT_CLK_MAX +}; + /** * struct input_dev - represents an input device * @name: name of the device @@ -114,6 +121,8 @@ struct input_value { * @vals: array of values queued in the current frame * @devres_managed: indicates that devices is managed with devres framework * and needs not be explicitly unregistered or freed. + * @timestamp: storage for a timestamp set by input_set_timestamp called + * by a driver */ struct input_dev { const char *name; @@ -184,6 +193,8 @@ struct input_dev { struct input_value *vals; bool devres_managed; + + ktime_t timestamp[INPUT_CLK_MAX]; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) @@ -382,6 +393,9 @@ void input_close_device(struct input_handle *); int input_flush_device(struct input_handle *handle, struct file *file); +void input_set_timestamp(struct input_dev *dev, ktime_t timestamp); +ktime_t *input_get_timestamp(struct input_dev *dev); + void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value); -- cgit v1.2.3 From 060157e1dbc133075a2e20786d6ff6d4b41909f9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 14:55:43 -0700 Subject: Input: remove w90x900 keyboard driver The ARM w90x900 platform is getting removed, so this driver is obsolete. Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 11 -- drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/w90p910_keypad.c | 264 --------------------------- include/linux/platform_data/keypad-w90p910.h | 16 -- 4 files changed, 292 deletions(-) delete mode 100644 drivers/input/keyboard/w90p910_keypad.c delete mode 100644 include/linux/platform_data/keypad-w90p910.h (limited to 'include') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 8e9c3ea9d5e7..c1da129a4eb5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -731,17 +731,6 @@ config KEYBOARD_XTKBD To compile this driver as a module, choose M here: the module will be called xtkbd. -config KEYBOARD_W90P910 - tristate "W90P910 Matrix Keypad support" - depends on ARCH_W90X900 - select INPUT_MATRIXKMAP - help - Say Y here to enable the matrix keypad on evaluation board - based on W90P910. - - To compile this driver as a module, choose M here: the - module will be called w90p910_keypad. - config KEYBOARD_CROS_EC tristate "ChromeOS EC keyboard" select INPUT_MATRIXKMAP diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 06a0af6efeae..9510325c0c5d 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -68,4 +68,3 @@ obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o -obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c deleted file mode 100644 index c88d05d6108a..000000000000 --- a/drivers/input/keyboard/w90p910_keypad.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2008-2009 Nuvoton technology corporation. - * - * Wan ZongShun - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Keypad Interface Control Registers */ -#define KPI_CONF 0x00 -#define KPI_3KCONF 0x04 -#define KPI_LPCONF 0x08 -#define KPI_STATUS 0x0C - -#define IS1KEY (0x01 << 16) -#define INTTR (0x01 << 21) -#define KEY0R (0x0f << 3) -#define KEY0C 0x07 -#define DEBOUNCE_BIT 0x08 -#define KSIZE0 (0x01 << 16) -#define KSIZE1 (0x01 << 17) -#define KPSEL (0x01 << 19) -#define ENKP (0x01 << 18) - -#define KGET_RAW(n) (((n) & KEY0R) >> 3) -#define KGET_COLUMN(n) ((n) & KEY0C) - -#define W90P910_NUM_ROWS 8 -#define W90P910_NUM_COLS 8 -#define W90P910_ROW_SHIFT 3 - -struct w90p910_keypad { - const struct w90p910_keypad_platform_data *pdata; - struct clk *clk; - struct input_dev *input_dev; - void __iomem *mmio_base; - int irq; - unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS]; -}; - -static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, - unsigned int status) -{ - struct input_dev *input_dev = keypad->input_dev; - unsigned int row = KGET_RAW(status); - unsigned int col = KGET_COLUMN(status); - unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); - unsigned int key = keypad->keymap[code]; - - input_event(input_dev, EV_MSC, MSC_SCAN, code); - input_report_key(input_dev, key, 1); - input_sync(input_dev); - - input_event(input_dev, EV_MSC, MSC_SCAN, code); - input_report_key(input_dev, key, 0); - input_sync(input_dev); -} - -static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) -{ - struct w90p910_keypad *keypad = dev_id; - unsigned int kstatus, val; - - kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS); - - val = INTTR | IS1KEY; - - if (kstatus & val) - w90p910_keypad_scan_matrix(keypad, kstatus); - - return IRQ_HANDLED; -} - -static int w90p910_keypad_open(struct input_dev *dev) -{ - struct w90p910_keypad *keypad = input_get_drvdata(dev); - const struct w90p910_keypad_platform_data *pdata = keypad->pdata; - unsigned int val, config; - - /* Enable unit clock */ - clk_enable(keypad->clk); - - val = __raw_readl(keypad->mmio_base + KPI_CONF); - val |= (KPSEL | ENKP); - val &= ~(KSIZE0 | KSIZE1); - - config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT); - - val |= config; - - __raw_writel(val, keypad->mmio_base + KPI_CONF); - - return 0; -} - -static void w90p910_keypad_close(struct input_dev *dev) -{ - struct w90p910_keypad *keypad = input_get_drvdata(dev); - - /* Disable clock unit */ - clk_disable(keypad->clk); -} - -static int w90p910_keypad_probe(struct platform_device *pdev) -{ - const struct w90p910_keypad_platform_data *pdata = - dev_get_platdata(&pdev->dev); - const struct matrix_keymap_data *keymap_data; - struct w90p910_keypad *keypad; - struct input_dev *input_dev; - struct resource *res; - int irq; - int error; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; - } - - keymap_data = pdata->keymap_data; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get keypad irq\n"); - return -ENXIO; - } - - keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!keypad || !input_dev) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); - error = -ENOMEM; - goto failed_free; - } - - keypad->pdata = pdata; - keypad->input_dev = input_dev; - keypad->irq = irq; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); - error = -ENXIO; - goto failed_free; - } - - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (res == NULL) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - error = -EBUSY; - goto failed_free; - } - - keypad->mmio_base = ioremap(res->start, resource_size(res)); - if (keypad->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - error = -ENXIO; - goto failed_free_res; - } - - keypad->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(keypad->clk)) { - dev_err(&pdev->dev, "failed to get keypad clock\n"); - error = PTR_ERR(keypad->clk); - goto failed_free_io; - } - - /* set multi-function pin for w90p910 kpi. */ - mfp_set_groupi(&pdev->dev); - - input_dev->name = pdev->name; - input_dev->id.bustype = BUS_HOST; - input_dev->open = w90p910_keypad_open; - input_dev->close = w90p910_keypad_close; - input_dev->dev.parent = &pdev->dev; - - error = matrix_keypad_build_keymap(keymap_data, NULL, - W90P910_NUM_ROWS, W90P910_NUM_COLS, - keypad->keymap, input_dev); - if (error) { - dev_err(&pdev->dev, "failed to build keymap\n"); - goto failed_put_clk; - } - - error = request_irq(keypad->irq, w90p910_keypad_irq_handler, - 0, pdev->name, keypad); - if (error) { - dev_err(&pdev->dev, "failed to request IRQ\n"); - goto failed_put_clk; - } - - __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, keypad); - - /* Register the input device */ - error = input_register_device(input_dev); - if (error) { - dev_err(&pdev->dev, "failed to register input device\n"); - goto failed_free_irq; - } - - platform_set_drvdata(pdev, keypad); - return 0; - -failed_free_irq: - free_irq(irq, keypad); -failed_put_clk: - clk_put(keypad->clk); -failed_free_io: - iounmap(keypad->mmio_base); -failed_free_res: - release_mem_region(res->start, resource_size(res)); -failed_free: - input_free_device(input_dev); - kfree(keypad); - return error; -} - -static int w90p910_keypad_remove(struct platform_device *pdev) -{ - struct w90p910_keypad *keypad = platform_get_drvdata(pdev); - struct resource *res; - - free_irq(keypad->irq, keypad); - - clk_put(keypad->clk); - - input_unregister_device(keypad->input_dev); - - iounmap(keypad->mmio_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - kfree(keypad); - - return 0; -} - -static struct platform_driver w90p910_keypad_driver = { - .probe = w90p910_keypad_probe, - .remove = w90p910_keypad_remove, - .driver = { - .name = "nuc900-kpi", - }, -}; -module_platform_driver(w90p910_keypad_driver); - -MODULE_AUTHOR("Wan ZongShun "); -MODULE_DESCRIPTION("w90p910 keypad driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-keypad"); diff --git a/include/linux/platform_data/keypad-w90p910.h b/include/linux/platform_data/keypad-w90p910.h deleted file mode 100644 index 206ca4ecd93f..000000000000 --- a/include/linux/platform_data/keypad-w90p910.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_W90P910_KEYPAD_H -#define __ASM_ARCH_W90P910_KEYPAD_H - -#include - -extern void mfp_set_groupi(struct device *dev); - -struct w90p910_keypad_platform_data { - const struct matrix_keymap_data *keymap_data; - - unsigned int prescale; - unsigned int debounce; -}; - -#endif /* __ASM_ARCH_W90P910_KEYPAD_H */ -- cgit v1.2.3 From e95656ea15e54d4e6a192d560d84008b53fc1eb5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 18 Apr 2017 17:28:30 -0700 Subject: Input: add support for polling to input devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separating "normal" and "polled" input devices was a mistake, as often we want to allow the very same device work on both interrupt-driven and polled mode, depending on the board on which the device is used. This introduces new APIs: - input_setup_polling - input_set_poll_interval - input_set_min_poll_interval - input_set_max_poll_interval These new APIs allow switching an input device into polled mode with sysfs attributes matching drivers using input_polled_dev APIs that will be eventually removed. Tested-by: Michal Vokáč Acked-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/Makefile | 2 +- drivers/input/input-poller.c | 213 +++++++++++++++++++++++++++++++++++++++++++ drivers/input/input-poller.h | 18 ++++ drivers/input/input.c | 36 ++++++-- include/linux/input.h | 12 +++ 5 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 drivers/input/input-poller.c create mode 100644 drivers/input/input-poller.h (limited to 'include') diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 40de6a7be641..e35650930371 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -6,7 +6,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_INPUT) += input-core.o -input-core-y := input.o input-compat.o input-mt.o ff-core.o +input-core-y := input.o input-compat.o input-mt.o input-poller.o ff-core.o obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o diff --git a/drivers/input/input-poller.c b/drivers/input/input-poller.c new file mode 100644 index 000000000000..1b3d28964bb2 --- /dev/null +++ b/drivers/input/input-poller.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Support for polling mode for input devices. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "input-poller.h" + +struct input_dev_poller { + void (*poll)(struct input_dev *dev); + + unsigned int poll_interval; /* msec */ + unsigned int poll_interval_max; /* msec */ + unsigned int poll_interval_min; /* msec */ + + struct input_dev *input; + struct delayed_work work; +}; + +static void input_dev_poller_queue_work(struct input_dev_poller *poller) +{ + unsigned long delay; + + delay = msecs_to_jiffies(poller->poll_interval); + if (delay >= HZ) + delay = round_jiffies_relative(delay); + + queue_delayed_work(system_freezable_wq, &poller->work, delay); +} + +static void input_dev_poller_work(struct work_struct *work) +{ + struct input_dev_poller *poller = + container_of(work, struct input_dev_poller, work.work); + + poller->poll(poller->input); + input_dev_poller_queue_work(poller); +} + +void input_dev_poller_finalize(struct input_dev_poller *poller) +{ + if (!poller->poll_interval) + poller->poll_interval = 500; + if (!poller->poll_interval_max) + poller->poll_interval_max = poller->poll_interval; +} + +void input_dev_poller_start(struct input_dev_poller *poller) +{ + /* Only start polling if polling is enabled */ + if (poller->poll_interval > 0) { + poller->poll(poller->input); + input_dev_poller_queue_work(poller); + } +} + +void input_dev_poller_stop(struct input_dev_poller *poller) +{ + cancel_delayed_work_sync(&poller->work); +} + +int input_setup_polling(struct input_dev *dev, + void (*poll_fn)(struct input_dev *dev)) +{ + struct input_dev_poller *poller; + + poller = kzalloc(sizeof(*poller), GFP_KERNEL); + if (!poller) { + /* + * We want to show message even though kzalloc() may have + * printed backtrace as knowing what instance of input + * device we were dealing with is helpful. + */ + dev_err(dev->dev.parent ?: &dev->dev, + "%s: unable to allocate poller structure\n", __func__); + return -ENOMEM; + } + + INIT_DELAYED_WORK(&poller->work, input_dev_poller_work); + poller->input = dev; + poller->poll = poll_fn; + + dev->poller = poller; + return 0; +} +EXPORT_SYMBOL(input_setup_polling); + +static bool input_dev_ensure_poller(struct input_dev *dev) +{ + if (!dev->poller) { + dev_err(dev->dev.parent ?: &dev->dev, + "poller structure has not been set up\n"); + return false; + } + + return true; +} + +void input_set_poll_interval(struct input_dev *dev, unsigned int interval) +{ + if (input_dev_ensure_poller(dev)) + dev->poller->poll_interval = interval; +} +EXPORT_SYMBOL(input_set_poll_interval); + +void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval) +{ + if (input_dev_ensure_poller(dev)) + dev->poller->poll_interval_min = interval; +} +EXPORT_SYMBOL(input_set_min_poll_interval); + +void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval) +{ + if (input_dev_ensure_poller(dev)) + dev->poller->poll_interval_max = interval; +} +EXPORT_SYMBOL(input_set_max_poll_interval); + +/* SYSFS interface */ + +static ssize_t input_dev_get_poll_interval(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct input_dev *input = to_input_dev(dev); + + return sprintf(buf, "%d\n", input->poller->poll_interval); +} + +static ssize_t input_dev_set_poll_interval(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct input_dev *input = to_input_dev(dev); + struct input_dev_poller *poller = input->poller; + unsigned int interval; + int err; + + err = kstrtouint(buf, 0, &interval); + if (err) + return err; + + if (interval < poller->poll_interval_min) + return -EINVAL; + + if (interval > poller->poll_interval_max) + return -EINVAL; + + mutex_lock(&input->mutex); + + poller->poll_interval = interval; + + if (input->users) { + cancel_delayed_work_sync(&poller->work); + if (poller->poll_interval > 0) + input_dev_poller_queue_work(poller); + } + + mutex_unlock(&input->mutex); + + return count; +} + +static DEVICE_ATTR(poll, 0644, + input_dev_get_poll_interval, input_dev_set_poll_interval); + +static ssize_t input_dev_get_poll_max(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + + return sprintf(buf, "%d\n", input->poller->poll_interval_max); +} + +static DEVICE_ATTR(max, 0444, input_dev_get_poll_max, NULL); + +static ssize_t input_dev_get_poll_min(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_dev *input = to_input_dev(dev); + + return sprintf(buf, "%d\n", input->poller->poll_interval_min); +} + +static DEVICE_ATTR(min, 0444, input_dev_get_poll_min, NULL); + +static umode_t input_poller_attrs_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct input_dev *input = to_input_dev(dev); + + return input->poller ? attr->mode : 0; +} + +static struct attribute *input_poller_attrs[] = { + &dev_attr_poll.attr, + &dev_attr_max.attr, + &dev_attr_min.attr, + NULL +}; + +struct attribute_group input_poller_attribute_group = { + .is_visible = input_poller_attrs_visible, + .attrs = input_poller_attrs, +}; diff --git a/drivers/input/input-poller.h b/drivers/input/input-poller.h new file mode 100644 index 000000000000..e3fca0be1d32 --- /dev/null +++ b/drivers/input/input-poller.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _INPUT_POLLER_H +#define _INPUT_POLLER_H + +/* + * Support for polling mode for input devices. + */ +#include + +struct input_dev_poller; + +void input_dev_poller_finalize(struct input_dev_poller *poller); +void input_dev_poller_start(struct input_dev_poller *poller); +void input_dev_poller_stop(struct input_dev_poller *poller); + +extern struct attribute_group input_poller_attribute_group; + +#endif /* _INPUT_POLLER_H */ diff --git a/drivers/input/input.c b/drivers/input/input.c index 7494a0dede79..c08aa3596144 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -24,6 +24,7 @@ #include #include #include "input-compat.h" +#include "input-poller.h" MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input core"); @@ -603,20 +604,31 @@ int input_open_device(struct input_handle *handle) handle->open++; - if (!dev->users++ && dev->open) - retval = dev->open(dev); + if (dev->users++) { + /* + * Device is already opened, so we can exit immediately and + * report success. + */ + goto out; + } - if (retval) { - dev->users--; - if (!--handle->open) { + if (dev->open) { + retval = dev->open(dev); + if (retval) { + dev->users--; + handle->open--; /* * Make sure we are not delivering any more events * through this handle */ synchronize_rcu(); + goto out; } } + if (dev->poller) + input_dev_poller_start(dev->poller); + out: mutex_unlock(&dev->mutex); return retval; @@ -655,8 +667,13 @@ void input_close_device(struct input_handle *handle) __input_release_device(handle); - if (!--dev->users && dev->close) - dev->close(dev); + if (!--dev->users) { + if (dev->poller) + input_dev_poller_stop(dev->poller); + + if (dev->close) + dev->close(dev); + } if (!--handle->open) { /* @@ -1502,6 +1519,7 @@ static const struct attribute_group *input_dev_attr_groups[] = { &input_dev_attr_group, &input_dev_id_attr_group, &input_dev_caps_attr_group, + &input_poller_attribute_group, NULL }; @@ -1511,6 +1529,7 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); + kfree(dev->poller); kfree(dev->absinfo); kfree(dev->vals); kfree(dev); @@ -2175,6 +2194,9 @@ int input_register_device(struct input_dev *dev) if (!dev->setkeycode) dev->setkeycode = input_default_setkeycode; + if (dev->poller) + input_dev_poller_finalize(dev->poller); + error = device_add(&dev->dev); if (error) goto err_free_vals; diff --git a/include/linux/input.h b/include/linux/input.h index e95a439d8bd5..94f277cd806a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -21,6 +21,8 @@ #include #include +struct input_dev_poller; + /** * struct input_value - input value representation * @type: type of value (EV_KEY, EV_ABS, etc) @@ -71,6 +73,8 @@ enum input_clock_type { * not sleep * @ff: force feedback structure associated with the device if device * supports force feedback effects + * @poller: poller structure associated with the device if device is + * set up to use polling mode * @repeat_key: stores key code of the last key pressed; used to implement * software autorepeat * @timer: timer for software autorepeat @@ -156,6 +160,8 @@ struct input_dev { struct ff_device *ff; + struct input_dev_poller *poller; + unsigned int repeat_key; struct timer_list timer; @@ -372,6 +378,12 @@ void input_unregister_device(struct input_dev *); void input_reset_device(struct input_dev *); +int input_setup_polling(struct input_dev *dev, + void (*poll_fn)(struct input_dev *dev)); +void input_set_poll_interval(struct input_dev *dev, unsigned int interval); +void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval); +void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval); + int __must_check input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); -- cgit v1.2.3 From a1b70a44b80af641a441937803cb8251e8e6d8e3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 11:03:59 -0700 Subject: Input: bu21013_ts - convert to use GPIO descriptors This driver can use GPIO descriptors rather than GPIO numbers without any problems, convert it. Name the field variables after the actual pins on the chip rather than the "reset" and "touch" names from the devicetree bindings that are vaguely inaccurate. No in-tree users pass GPIO numbers in platform data so drop this. Descriptor tables can be used to get these GPIOs from a board file if need be. Signed-off-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/bu21013.txt | 5 +- drivers/input/touchscreen/bu21013_ts.c | 86 ++++++++++------------ include/linux/input/bu21013.h | 4 - 3 files changed, 41 insertions(+), 54 deletions(-) (limited to 'include') diff --git a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt index 56d835242af2..43899fc36ecf 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/bu21013.txt @@ -2,10 +2,11 @@ Required properties: - compatible : "rohm,bu21013_tp" - - reg : I2C device address + - reg : I2C device address + - reset-gpios : GPIO pin enabling (selecting) chip (CS) Optional properties: - - touch-gpio : GPIO pin registering a touch event + - touch-gpios : GPIO pin registering a touch event - -supply : Phandle to a regulator supply - rohm,touch-max-x : Maximum outward permitted limit in the X axis - rohm,touch-max-y : Maximum outward permitted limit in the Y axis diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 1d703e230ac3..c20f86f98ffc 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -14,11 +14,9 @@ #include #include #include -#include +#include #include -#include -#define PEN_DOWN_INTR 0 #define MAX_FINGERS 2 #define RESET_DELAY 30 #define PENUP_TIMEOUT (10) @@ -143,8 +141,9 @@ * @touch_stopped: touch stop flag * @chip: pointer to the touch panel controller * @in_dev: pointer to the input device structure - * @intr_pin: interrupt pin value * @regulator: pointer to the Regulator used for touch screen + * @cs_gpiod: chip select GPIO line + * @int_gpiod: touch interrupt GPIO line * * Touch panel device data structure */ @@ -154,8 +153,9 @@ struct bu21013_ts_data { const struct bu21013_platform_device *chip; struct input_dev *in_dev; struct regulator *regulator; + struct gpio_desc *cs_gpiod; + struct gpio_desc *int_gpiod; unsigned int irq; - unsigned int intr_pin; bool touch_stopped; }; @@ -257,20 +257,21 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) { struct bu21013_ts_data *data = device_data; struct i2c_client *i2c = data->client; + int keep_polling; int retval; do { retval = bu21013_do_touch_report(data); if (retval < 0) { dev_err(&i2c->dev, "bu21013_do_touch_report failed\n"); - return IRQ_NONE; + break; } - data->intr_pin = gpio_get_value(data->chip->touch_pin); - if (data->intr_pin == PEN_DOWN_INTR) + keep_polling = gpiod_get_value(data->int_gpiod); + if (keep_polling) wait_event_timeout(data->wait, data->touch_stopped, msecs_to_jiffies(2)); - } while (!data->intr_pin && !data->touch_stopped); + } while (keep_polling && !data->touch_stopped); return IRQ_HANDLED; } @@ -425,28 +426,6 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) free_irq(bu21013_data->irq, bu21013_data); } -/** - * bu21013_cs_disable() - deconfigures the touch panel controller - * @bu21013_data: device structure pointer - * - * This function is used to deconfigure the chip selection - * for touch panel controller. - */ -static void bu21013_cs_disable(struct bu21013_ts_data *bu21013_data) -{ - int error; - - error = gpio_direction_output(bu21013_data->chip->cs_pin, 0); - if (error < 0) - dev_warn(&bu21013_data->client->dev, - "%s: gpio direction failed, error: %d\n", - __func__, error); - else - gpio_set_value(bu21013_data->chip->cs_pin, 0); - - gpio_free(bu21013_data->chip->cs_pin); -} - #ifdef CONFIG_OF static const struct bu21013_platform_device * bu21013_parse_dt(struct device *dev) @@ -471,9 +450,6 @@ bu21013_parse_dt(struct device *dev) of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); - pdata->touch_pin = of_get_named_gpio(np, "touch-gpio", 0); - pdata->cs_pin = of_get_named_gpio(np, "reset-gpio", 0); - pdata->ext_clk = false; return pdata; @@ -516,11 +492,6 @@ static int bu21013_probe(struct i2c_client *client, return PTR_ERR(pdata); } - if (!gpio_is_valid(pdata->touch_pin)) { - dev_err(&client->dev, "invalid touch_pin supplied\n"); - return -EINVAL; - } - bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL); in_dev = input_allocate_device(); if (!bu21013_data || !in_dev) { @@ -529,16 +500,26 @@ static int bu21013_probe(struct i2c_client *client, goto err_free_mem; } + /* Named "INT" on the chip, DT binding is "touch" */ + bu21013_data->int_gpiod = gpiod_get(&client->dev, "touch", GPIOD_IN); + error = PTR_ERR_OR_ZERO(bu21013_data->int_gpiod); + if (error) { + if (error != -EPROBE_DEFER) + dev_err(&client->dev, "failed to get INT GPIO\n"); + goto err_free_mem; + } + gpiod_set_consumer_name(bu21013_data->int_gpiod, "BU21013 INT"); + bu21013_data->in_dev = in_dev; bu21013_data->chip = pdata; bu21013_data->client = client; - bu21013_data->irq = gpio_to_irq(pdata->touch_pin); + bu21013_data->irq = gpiod_to_irq(bu21013_data->int_gpiod); bu21013_data->regulator = regulator_get(&client->dev, "avdd"); if (IS_ERR(bu21013_data->regulator)) { dev_err(&client->dev, "regulator_get failed\n"); error = PTR_ERR(bu21013_data->regulator); - goto err_free_mem; + goto err_put_int_gpio; } error = regulator_enable(bu21013_data->regulator); @@ -550,13 +531,16 @@ static int bu21013_probe(struct i2c_client *client, bu21013_data->touch_stopped = false; init_waitqueue_head(&bu21013_data->wait); - /* configure the gpio pins */ - error = gpio_request_one(pdata->cs_pin, GPIOF_OUT_INIT_HIGH, - "touchp_reset"); - if (error < 0) { - dev_err(&client->dev, "Unable to request gpio reset_pin\n"); + /* Named "CS" on the chip, DT binding is "reset" */ + bu21013_data->cs_gpiod = gpiod_get(&client->dev, "reset", + GPIOD_OUT_HIGH); + error = PTR_ERR_OR_ZERO(bu21013_data->cs_gpiod); + if (error) { + if (error != -EPROBE_DEFER) + dev_err(&client->dev, "failed to get CS GPIO\n"); goto err_disable_regulator; } + gpiod_set_consumer_name(bu21013_data->cs_gpiod, "BU21013 CS"); /* configure the touch panel controller */ error = bu21013_init_chip(bu21013_data); @@ -604,11 +588,14 @@ static int bu21013_probe(struct i2c_client *client, err_free_irq: bu21013_free_irq(bu21013_data); err_cs_disable: - bu21013_cs_disable(bu21013_data); + gpiod_set_value(bu21013_data->cs_gpiod, 0); + gpiod_put(bu21013_data->cs_gpiod); err_disable_regulator: regulator_disable(bu21013_data->regulator); err_put_regulator: regulator_put(bu21013_data->regulator); +err_put_int_gpio: + gpiod_put(bu21013_data->int_gpiod); err_free_mem: input_free_device(in_dev); kfree(bu21013_data); @@ -628,13 +615,16 @@ static int bu21013_remove(struct i2c_client *client) bu21013_free_irq(bu21013_data); - bu21013_cs_disable(bu21013_data); + gpiod_set_value(bu21013_data->cs_gpiod, 0); + gpiod_put(bu21013_data->cs_gpiod); input_unregister_device(bu21013_data->in_dev); regulator_disable(bu21013_data->regulator); regulator_put(bu21013_data->regulator); + gpiod_put(bu21013_data->int_gpiod); + kfree(bu21013_data); return 0; diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h index 7e5b7e978e8a..58b1a9d44443 100644 --- a/include/linux/input/bu21013.h +++ b/include/linux/input/bu21013.h @@ -11,8 +11,6 @@ * struct bu21013_platform_device - Handle the platform data * @touch_x_max: touch x max * @touch_y_max: touch y max - * @cs_pin: chip select pin - * @touch_pin: touch gpio pin * @ext_clk: external clock flag * @x_flip: x flip flag * @y_flip: y flip flag @@ -23,8 +21,6 @@ struct bu21013_platform_device { int touch_x_max; int touch_y_max; - unsigned int cs_pin; - unsigned int touch_pin; bool ext_clk; bool x_flip; bool y_flip; -- cgit v1.2.3 From 1eb7b4cacc01771ae42fcbc5ae9a4bc1d13c1dbc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 8 Aug 2019 12:09:43 -0700 Subject: Input: bu21013_ts - remove support for platform data There are no current users of the platform data in the tree, and any new users should either use device tree, or static device properties to describe the device. This change drop the platform data definition and handling and moves the driver over to generic device properties API. We also drop support for the external clock. If it is needed we will have to extend the bindings to supply the clock reference and handle it properly in the driver. Also, wakeup setting should be coming from I2C client. Tested-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 109 +++++++++++---------------------- include/linux/input/bu21013.h | 30 --------- 2 files changed, 37 insertions(+), 102 deletions(-) delete mode 100644 include/linux/input/bu21013.h (limited to 'include') diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 2b8538a63945..f3b3e4c72c84 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -4,18 +4,18 @@ * Author: Naveen Kumar G for ST-Ericsson */ -#include +#include #include -#include +#include #include -#include #include -#include -#include -#include +#include +#include #include -#include -#include +#include +#include +#include +#include #define MAX_FINGERS 2 #define RESET_DELAY 30 @@ -137,23 +137,32 @@ /** * struct bu21013_ts - touch panel data structure * @client: pointer to the i2c client - * @touch_stopped: touch stop flag - * @chip: pointer to the touch panel controller * @in_dev: pointer to the input device structure * @regulator: pointer to the Regulator used for touch screen * @cs_gpiod: chip select GPIO line * @int_gpiod: touch interrupt GPIO line + * @irq: interrupt number the device is using + * @touch_x_max: maximum X coordinate reported by the device + * @touch_y_max: maximum Y coordinate reported by the device + * @x_flip: indicates that the driver should invert X coordinate before + * reporting + * @y_flip: indicates that the driver should invert Y coordinate before + * reporting + * @touch_stopped: touch stop flag * * Touch panel device data structure */ struct bu21013_ts { struct i2c_client *client; - const struct bu21013_platform_device *chip; struct input_dev *in_dev; struct regulator *regulator; struct gpio_desc *cs_gpiod; struct gpio_desc *int_gpiod; unsigned int irq; + u32 touch_x_max; + u32 touch_y_max; + bool x_flip; + bool y_flip; bool touch_stopped; }; @@ -208,10 +217,10 @@ static int bu21013_do_touch_report(struct bu21013_ts *ts) } for (i = 0; i < finger_down_count; i++) { - if (ts->chip->x_flip) - pos_x[i] = ts->chip->touch_x_max - pos_x[i]; - if (ts->chip->y_flip) - pos_y[i] = ts->chip->touch_y_max - pos_y[i]; + if (ts->x_flip) + pos_x[i] = ts->touch_x_max - pos_x[i]; + if (ts->y_flip) + pos_y[i] = ts->touch_y_max - pos_y[i]; input_report_abs(ts->in_dev, ABS_MT_POSITION_X, pos_x[i]); @@ -304,14 +313,9 @@ static int bu21013_init_chip(struct bu21013_ts *ts) return error; } - if (ts->chip->ext_clk) - error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, - BU21013_CLK_MODE_EXT | - BU21013_CLK_MODE_CALIB); - else - error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, - BU21013_CLK_MODE_DIV | - BU21013_CLK_MODE_CALIB); + error = i2c_smbus_write_byte_data(client, BU21013_CLK_MODE_REG, + BU21013_CLK_MODE_DIV | + BU21013_CLK_MODE_CALIB); if (error) { dev_err(&client->dev, "BU21013_CLK_MODE reg write failed\n"); return error; @@ -388,43 +392,6 @@ static int bu21013_init_chip(struct bu21013_ts *ts) return 0; } -#ifdef CONFIG_OF -static const struct bu21013_platform_device * -bu21013_parse_dt(struct device *dev) -{ - struct device_node *np = dev->of_node; - struct bu21013_platform_device *pdata; - - if (!np) { - dev_err(dev, "no device tree or platform data\n"); - return ERR_PTR(-EINVAL); - } - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return ERR_PTR(-ENOMEM); - - pdata->y_flip = pdata->x_flip = false; - - pdata->x_flip = of_property_read_bool(np, "rohm,flip-x"); - pdata->y_flip = of_property_read_bool(np, "rohm,flip-y"); - - of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); - of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); - - pdata->ext_clk = false; - - return pdata; -} -#else -static inline const struct bu21013_platform_device * -bu21013_parse_dt(struct device *dev) -{ - dev_err(dev, "no platform data available\n"); - return ERR_PTR(-EINVAL); -} -#endif - static void bu21013_power_off(void *_ts) { struct bu21013_ts *ts = _ts; @@ -442,8 +409,6 @@ static void bu21013_disable_chip(void *_ts) static int bu21013_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct bu21013_platform_device *pdata = - dev_get_platdata(&client->dev); struct bu21013_ts *ts; struct input_dev *in_dev; int error; @@ -454,19 +419,20 @@ static int bu21013_probe(struct i2c_client *client, return -EIO; } - if (!pdata) { - pdata = bu21013_parse_dt(&client->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } - ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); if (!ts) return -ENOMEM; - ts->chip = pdata; ts->client = client; + ts->x_flip = device_property_read_bool(&client->dev, "rohm,flip-x"); + ts->y_flip = device_property_read_bool(&client->dev, "rohm,flip-y"); + + device_property_read_u32(&client->dev, "rohm,touch-max-x", + &ts->touch_x_max); + device_property_read_u32(&client->dev, "rohm,touch-max-y", + &ts->touch_y_max); + in_dev = devm_input_allocate_device(&client->dev); if (!in_dev) { dev_err(&client->dev, "device memory alloc failed\n"); @@ -483,9 +449,9 @@ static int bu21013_probe(struct i2c_client *client, __set_bit(EV_ABS, in_dev->evbit); input_set_abs_params(in_dev, ABS_MT_POSITION_X, - 0, pdata->touch_x_max, 0, 0); + 0, ts->touch_x_max, 0, 0); input_set_abs_params(in_dev, ABS_MT_POSITION_Y, - 0, pdata->touch_y_max, 0, 0); + 0, ts->touch_y_max, 0, 0); input_set_drvdata(in_dev, ts); ts->regulator = devm_regulator_get(&client->dev, "avdd"); @@ -560,7 +526,6 @@ static int bu21013_probe(struct i2c_client *client, return error; } - device_init_wakeup(&client->dev, pdata->wakeup); i2c_set_clientdata(client, ts); return 0; diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h deleted file mode 100644 index 58b1a9d44443..000000000000 --- a/include/linux/input/bu21013.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Naveen Kumar G for ST-Ericsson - */ - -#ifndef _BU21013_H -#define _BU21013_H - -/** - * struct bu21013_platform_device - Handle the platform data - * @touch_x_max: touch x max - * @touch_y_max: touch y max - * @ext_clk: external clock flag - * @x_flip: x flip flag - * @y_flip: y flip flag - * @wakeup: wakeup flag - * - * This is used to handle the platform data - */ -struct bu21013_platform_device { - int touch_x_max; - int touch_y_max; - bool ext_clk; - bool x_flip; - bool y_flip; - bool wakeup; -}; - -#endif -- cgit v1.2.3