Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Jan 2019 02:56:59 +0000 (18:56 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Jan 2019 02:56:59 +0000 (18:56 -0800)
Pull input updates from Dmitry Torokhov:
 "A tiny pull request this merge window unfortunately, should get more
  material in for the next release:

   - new driver for Raspberry Pi's touchscreen (firmware interface)

   - miscellaneous input driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: elan_i2c - add ACPI ID for touchpad in ASUS Aspire F5-573G
  Input: atmel_mxt_ts - don't try to free unallocated kernel memory
  Input: drv2667 - fix indentation issues
  Input: touchscreen - fix coding style issue
  Input: add official Raspberry Pi's touchscreen driver
  Input: nomadik-ske-keypad - fix a loop timeout test
  Input: rotary-encoder - don't log EPROBE_DEFER to kernel log
  Input: olpc_apsp - remove set but not used variable 'np'
  Input: olpc_apsp - enable the SP clock
  Input: olpc_apsp - check FIFO status on open(), not probe()
  Input: olpc_apsp - drop CONFIG_OLPC dependency
  clk: mmp2: add SP clock
  dt-bindings: marvell,mmp2: Add clock id for the SP clock
  Input: ad7879 - drop platform data support

20 files changed:
Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt [new file with mode: 0644]
Documentation/devicetree/bindings/serio/olpc,ap-sp.txt
drivers/clk/mmp/clk-of-mmp2.c
drivers/input/keyboard/nomadik-ske-keypad.c
drivers/input/misc/drv2667.c
drivers/input/misc/rotary_encoder.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/serio/Kconfig
drivers/input/serio/olpc_apsp.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ad7879.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/ektf2127.c
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/inexio.c
drivers/input/touchscreen/mtouch.c
drivers/input/touchscreen/raspberrypi-ts.c [new file with mode: 0644]
include/dt-bindings/clock/marvell,mmp2.h
include/linux/platform_data/ad7879.h [deleted file]

diff --git a/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt
new file mode 100644 (file)
index 0000000..2a1af24
--- /dev/null
@@ -0,0 +1,26 @@
+Raspberry Pi firmware based 7" touchscreen
+=====================================
+
+Required properties:
+ - compatible: "raspberrypi,firmware-ts"
+
+Optional properties:
+ - firmware: Reference to RPi's firmware device node
+ - touchscreen-size-x: See touchscreen.txt
+ - touchscreen-size-y: See touchscreen.txt
+ - touchscreen-inverted-x: See touchscreen.txt
+ - touchscreen-inverted-y: See touchscreen.txt
+ - touchscreen-swapped-x-y: See touchscreen.txt
+
+Example:
+
+firmware: firmware-rpi {
+       compatible = "raspberrypi,bcm2835-firmware";
+       mboxes = <&mailbox>;
+
+       ts: touchscreen {
+               compatible = "raspberrypi,firmware-ts";
+               touchscreen-size-x = <800>;
+               touchscreen-size-y = <480>;
+       };
+};
index 0e72183..3660341 100644 (file)
@@ -4,10 +4,14 @@ Required properties:
 - compatible : "olpc,ap-sp"
 - reg : base address and length of SoC's WTM registers
 - interrupts : SP-AP interrupt
+- clocks : phandle + clock-specifier for the clock that drives the WTM
+- clock-names:  should be "sp"
 
 Example:
        ap-sp@d4290000 {
                compatible = "olpc,ap-sp";
                reg = <0xd4290000 0x1000>;
                interrupts = <40>;
+               clocks = <&soc_clocks MMP2_CLK_SP>;
+               clock-names = "sp";
        }
index d083b86..61fefc0 100644 (file)
@@ -53,6 +53,7 @@
 #define APMU_DISP1     0x110
 #define APMU_CCIC0     0x50
 #define APMU_CCIC1     0xf4
+#define APMU_SP                0x68
 #define MPMU_UART_PLL  0x14
 
 struct mmp2_clk_unit {
@@ -209,6 +210,8 @@ static struct mmp_clk_mix_config ccic1_mix_config = {
        .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32),
 };
 
+static DEFINE_SPINLOCK(sp_lock);
+
 static struct mmp_param_mux_clk apmu_mux_clks[] = {
        {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock},
        {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock},
@@ -239,6 +242,7 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
        {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
+       {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock},
 };
 
 static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
index 8567ee4..ae3b045 100644 (file)
@@ -100,7 +100,7 @@ static int __init ske_keypad_chip_init(struct ske_keypad *keypad)
        while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
                cpu_relax();
 
-       if (!timeout)
+       if (timeout == -1)
                return -EINVAL;
 
        /*
index 2849bb6..6091f04 100644 (file)
@@ -177,9 +177,9 @@ static int drv2667_set_waveform_freq(struct drv2667_data *haptics)
                error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf);
                if (error) {
                        dev_err(&haptics->client->dev,
-                                       "Failed to set the page: %d\n", error);
-                               return -EIO;
-                       }
+                               "Failed to set the page: %d\n", error);
+                       return -EIO;
+               }
        }
 
        return error;
index 30ec77a..d748897 100644 (file)
@@ -240,8 +240,10 @@ static int rotary_encoder_probe(struct platform_device *pdev)
 
        encoder->gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN);
        if (IS_ERR(encoder->gpios)) {
-               dev_err(dev, "unable to get gpios\n");
-               return PTR_ERR(encoder->gpios);
+               err = PTR_ERR(encoder->gpios);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev, "unable to get gpios: %d\n", err);
+               return err;
        }
        if (encoder->gpios->ndescs < 2) {
                dev_err(dev, "not enough gpios found\n");
index a94b649..f322a17 100644 (file)
@@ -1336,6 +1336,7 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
 static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0000", 0 },
        { "ELAN0100", 0 },
+       { "ELAN0501", 0 },
        { "ELAN0600", 0 },
        { "ELAN0602", 0 },
        { "ELAN0605", 0 },
index d90d9f1..c9c7224 100644 (file)
@@ -254,7 +254,6 @@ config SERIO_APBPS2
 
 config SERIO_OLPC_APSP
        tristate "OLPC AP-SP input support"
-       depends on OLPC || COMPILE_TEST
        help
          Say Y here if you want support for the keyboard and touchpad included
          in the OLPC XO-1.75 and XO-4 laptops.
index 8e9a420..b360847 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 
 /*
  * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller.
@@ -74,6 +75,7 @@ struct olpc_apsp {
        struct serio *kbio;
        struct serio *padio;
        void __iomem *base;
+       struct clk *clk;
        int open_count;
        int irq;
 };
@@ -145,8 +147,21 @@ static int olpc_apsp_open(struct serio *port)
 {
        struct olpc_apsp *priv = port->port_data;
        unsigned int tmp;
+       unsigned long l;
+       int error;
 
        if (priv->open_count++ == 0) {
+               error = clk_prepare_enable(priv->clk);
+               if (error)
+                       return error;
+
+               l = readl(priv->base + COMMAND_FIFO_STATUS);
+               if (!(l & CMD_STS_MASK)) {
+                       dev_err(priv->dev, "SP cannot accept commands.\n");
+                       clk_disable_unprepare(priv->clk);
+                       return -EIO;
+               }
+
                /* Enable interrupt 0 by clearing its bit */
                tmp = readl(priv->base + PJ_INTERRUPT_MASK);
                writel(tmp & ~INT_0, priv->base + PJ_INTERRUPT_MASK);
@@ -164,6 +179,8 @@ static void olpc_apsp_close(struct serio *port)
                /* Disable interrupt 0 */
                tmp = readl(priv->base + PJ_INTERRUPT_MASK);
                writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
+
+               clk_disable_unprepare(priv->clk);
        }
 }
 
@@ -172,15 +189,12 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        struct serio *kb_serio, *pad_serio;
        struct olpc_apsp *priv;
        struct resource *res;
-       struct device_node *np;
-       unsigned long l;
        int error;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(struct olpc_apsp), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       np = pdev->dev.of_node;
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->base)) {
@@ -192,11 +206,9 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (priv->irq < 0)
                return priv->irq;
 
-       l = readl(priv->base + COMMAND_FIFO_STATUS);
-       if (!(l & CMD_STS_MASK)) {
-               dev_err(&pdev->dev, "SP cannot accept commands.\n");
-               return -EIO;
-       }
+       priv->clk = devm_clk_get(&pdev->dev, "sp");
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
 
        /* KEYBOARD */
        kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
index 2a80675..af6027c 100644 (file)
@@ -696,6 +696,18 @@ config TOUCHSCREEN_EDT_FT5X06
          To compile this driver as a module, choose M here: the
          module will be called edt-ft5x06.
 
+config TOUCHSCREEN_RASPBERRYPI_FW
+       tristate "Raspberry Pi's firmware base touch screen support"
+       depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+       help
+         Say Y here if you have the official Raspberry Pi 7 inch screen on
+         your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called raspberrypi-ts.
+
 config TOUCHSCREEN_MIGOR
        tristate "Renesas MIGO-R touchscreen"
        depends on (SH_MIGOR || COMPILE_TEST) && I2C
index 5911a41..fcc7605 100644 (file)
@@ -109,3 +109,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZET6223)   += zet6223.o
 obj-$(CONFIG_TOUCHSCREEN_ZFORCE)       += zforce_ts.o
 obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW)       += raspberrypi-ts.o
index 6bad23e..6fa714c 100644 (file)
 #include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 
 #include <linux/input/touchscreen.h>
-#include <linux/platform_data/ad7879.h>
 #include <linux/module.h>
 #include "ad7879.h"
 
@@ -290,7 +289,7 @@ static int ad7879_open(struct input_dev *input)
        return 0;
 }
 
-static void ad7879_close(struct input_devinput)
+static void ad7879_close(struct input_dev *input)
 {
        struct ad7879 *ts = input_get_drvdata(input);
 
@@ -452,47 +451,36 @@ static void ad7879_gpio_set_value(struct gpio_chip *chip,
        mutex_unlock(&ts->mutex);
 }
 
-static int ad7879_gpio_add(struct ad7879 *ts,
-                          const struct ad7879_platform_data *pdata)
+static int ad7879_gpio_add(struct ad7879 *ts)
 {
-       bool gpio_export;
-       int gpio_base;
        int ret = 0;
 
-       if (pdata) {
-               gpio_export = pdata->gpio_export;
-               gpio_base = pdata->gpio_base;
-       } else {
-               gpio_export = device_property_read_bool(ts->dev,
-                                                       "gpio-controller");
-               gpio_base = -1;
-       }
-
        mutex_init(&ts->mutex);
 
-       if (gpio_export) {
-               ts->gc.direction_input = ad7879_gpio_direction_input;
-               ts->gc.direction_output = ad7879_gpio_direction_output;
-               ts->gc.get = ad7879_gpio_get_value;
-               ts->gc.set = ad7879_gpio_set_value;
-               ts->gc.can_sleep = 1;
-               ts->gc.base = gpio_base;
-               ts->gc.ngpio = 1;
-               ts->gc.label = "AD7879-GPIO";
-               ts->gc.owner = THIS_MODULE;
-               ts->gc.parent = ts->dev;
-
-               ret = devm_gpiochip_add_data(ts->dev, &ts->gc, ts);
-               if (ret)
-                       dev_err(ts->dev, "failed to register gpio %d\n",
-                               ts->gc.base);
-       }
+       /* Do not create a chip unless flagged for it */
+       if (!device_property_read_bool(ts->dev, "gpio-controller"))
+               return 0;
+
+       ts->gc.direction_input = ad7879_gpio_direction_input;
+       ts->gc.direction_output = ad7879_gpio_direction_output;
+       ts->gc.get = ad7879_gpio_get_value;
+       ts->gc.set = ad7879_gpio_set_value;
+       ts->gc.can_sleep = 1;
+       ts->gc.base = -1;
+       ts->gc.ngpio = 1;
+       ts->gc.label = "AD7879-GPIO";
+       ts->gc.owner = THIS_MODULE;
+       ts->gc.parent = ts->dev;
+
+       ret = devm_gpiochip_add_data(ts->dev, &ts->gc, ts);
+       if (ret)
+               dev_err(ts->dev, "failed to register gpio %d\n",
+                       ts->gc.base);
 
        return ret;
 }
 #else
-static int ad7879_gpio_add(struct ad7879 *ts,
-                          const struct ad7879_platform_data *pdata)
+static int ad7879_gpio_add(struct ad7879 *ts)
 {
        return 0;
 }
@@ -527,7 +515,6 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts)
 int ad7879_probe(struct device *dev, struct regmap *regmap,
                 int irq, u16 bustype, u8 devid)
 {
-       struct ad7879_platform_data *pdata = dev_get_platdata(dev);
        struct ad7879 *ts;
        struct input_dev *input_dev;
        int err;
@@ -542,22 +529,9 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
        if (!ts)
                return -ENOMEM;
 
-       if (pdata) {
-               /* Platform data use swapped axis (backward compatibility) */
-               ts->swap_xy = !pdata->swap_xy;
-
-               ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
-
-               ts->first_conversion_delay = pdata->first_conversion_delay;
-               ts->acquisition_time = pdata->acquisition_time;
-               ts->averaging = pdata->averaging;
-               ts->pen_down_acc_interval = pdata->pen_down_acc_interval;
-               ts->median = pdata->median;
-       } else {
-               err = ad7879_parse_dt(dev, ts);
-               if (err)
-                       return err;
-       }
+       err = ad7879_parse_dt(dev, ts);
+       if (err)
+               return err;
 
        input_dev = devm_input_allocate_device(dev);
        if (!input_dev) {
@@ -585,28 +559,13 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
 
        input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
 
-       if (pdata) {
-               input_set_abs_params(input_dev, ABS_X,
-                               pdata->x_min ? : 0,
-                               pdata->x_max ? : MAX_12BIT,
-                               0, 0);
-               input_set_abs_params(input_dev, ABS_Y,
-                               pdata->y_min ? : 0,
-                               pdata->y_max ? : MAX_12BIT,
-                               0, 0);
-               input_set_abs_params(input_dev, ABS_PRESSURE,
-                               pdata->pressure_min,
-                               pdata->pressure_max ? : ~0,
-                               0, 0);
-       } else {
-               input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
-               input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
-               input_set_capability(input_dev, EV_ABS, ABS_PRESSURE);
-               touchscreen_parse_properties(input_dev, false, NULL);
-               if (!input_abs_get_max(input_dev, ABS_PRESSURE)) {
-                       dev_err(dev, "Touchscreen pressure is not specified\n");
-                       return -EINVAL;
-               }
+       input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
+       input_set_capability(input_dev, EV_ABS, ABS_PRESSURE);
+       touchscreen_parse_properties(input_dev, false, NULL);
+       if (!input_abs_get_max(input_dev, ABS_PRESSURE)) {
+               dev_err(dev, "Touchscreen pressure is not specified\n");
+               return -EINVAL;
        }
 
        err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET);
@@ -655,7 +614,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap,
        if (err)
                return err;
 
-       err = ad7879_gpio_add(ts, pdata);
+       err = ad7879_gpio_add(ts);
        if (err)
                return err;
 
index d3aacd5..5c63d25 100644 (file)
@@ -1585,10 +1585,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
        /* T7 config may have changed */
        mxt_init_t7_power_cfg(data);
 
-release_raw:
-       kfree(cfg.raw);
 release_mem:
        kfree(cfg.mem);
+release_raw:
+       kfree(cfg.raw);
        return ret;
 }
 
index 0ed34ff..28fa1b3 100644 (file)
@@ -51,7 +51,7 @@ struct ektf2127_ts {
        struct touchscreen_properties prop;
 };
 
-static void ektf2127_parse_coordinates(const u8buf, unsigned int touch_count,
+static void ektf2127_parse_coordinates(const u8 *buf, unsigned int touch_count,
                                       struct input_mt_pos *touches)
 {
        int index = 0;
index 054c253..56cf1a1 100644 (file)
@@ -53,7 +53,7 @@ struct gunze {
        char phys[32];
 };
 
-static void gunze_process_packet(struct gunzegunze)
+static void gunze_process_packet(struct gunze *gunze)
 {
        struct input_dev *dev = gunze->dev;
 
@@ -72,7 +72,7 @@ static void gunze_process_packet(struct gunze* gunze)
 static irqreturn_t gunze_interrupt(struct serio *serio,
                unsigned char data, unsigned int flags)
 {
-       struct gunzegunze = serio_get_drvdata(serio);
+       struct gunze *gunze = serio_get_drvdata(serio);
 
        if (data == '\r') {
                gunze_process_packet(gunze);
index b9bc562..13bd0bf 100644 (file)
@@ -79,7 +79,7 @@ static void inexio_process_data(struct inexio *pinexio)
 static irqreturn_t inexio_interrupt(struct serio *serio,
                unsigned char data, unsigned int flags)
 {
-       struct inexiopinexio = serio_get_drvdata(serio);
+       struct inexio *pinexio = serio_get_drvdata(serio);
 
        pinexio->data[pinexio->idx] = data;
 
@@ -97,7 +97,7 @@ static irqreturn_t inexio_interrupt(struct serio *serio,
 
 static void inexio_disconnect(struct serio *serio)
 {
-       struct inexiopinexio = serio_get_drvdata(serio);
+       struct inexio *pinexio = serio_get_drvdata(serio);
 
        input_get_device(pinexio->dev);
        input_unregister_device(pinexio->dev);
index a3707fa..8278a90 100644 (file)
@@ -90,7 +90,7 @@ static void mtouch_process_response(struct mtouch *mtouch)
 static irqreturn_t mtouch_interrupt(struct serio *serio,
                unsigned char data, unsigned int flags)
 {
-       struct mtouchmtouch = serio_get_drvdata(serio);
+       struct mtouch *mtouch = serio_get_drvdata(serio);
 
        mtouch->data[mtouch->idx] = data;
 
@@ -110,7 +110,7 @@ static irqreturn_t mtouch_interrupt(struct serio *serio,
 
 static void mtouch_disconnect(struct serio *serio)
 {
-       struct mtouchmtouch = serio_get_drvdata(serio);
+       struct mtouch *mtouch = serio_get_drvdata(serio);
 
        input_get_device(mtouch->dev);
        input_unregister_device(mtouch->dev);
diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c
new file mode 100644 (file)
index 0000000..f456c11
--- /dev/null
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Raspberry Pi firmware based touchscreen driver
+ *
+ * Copyright (C) 2015, 2017 Raspberry Pi
+ * Copyright (C) 2018 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input-polldev.h>
+#include <linux/input/touchscreen.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define RPI_TS_DEFAULT_WIDTH   800
+#define RPI_TS_DEFAULT_HEIGHT  480
+
+#define RPI_TS_MAX_SUPPORTED_POINTS    10
+
+#define RPI_TS_FTS_TOUCH_DOWN          0
+#define RPI_TS_FTS_TOUCH_CONTACT       2
+
+#define RPI_TS_POLL_INTERVAL           17      /* 60fps */
+
+#define RPI_TS_NPOINTS_REG_INVALIDATE  99
+
+struct rpi_ts {
+       struct platform_device *pdev;
+       struct input_polled_dev *poll_dev;
+       struct touchscreen_properties prop;
+
+       void __iomem *fw_regs_va;
+       dma_addr_t fw_regs_phys;
+
+       int known_ids;
+};
+
+struct rpi_ts_regs {
+       u8 device_mode;
+       u8 gesture_id;
+       u8 num_points;
+       struct rpi_ts_touch {
+               u8 xh;
+               u8 xl;
+               u8 yh;
+               u8 yl;
+               u8 pressure; /* Not supported */
+               u8 area;     /* Not supported */
+       } point[RPI_TS_MAX_SUPPORTED_POINTS];
+};
+
+static void rpi_ts_poll(struct input_polled_dev *dev)
+{
+       struct input_dev *input = dev->input;
+       struct rpi_ts *ts = dev->private;
+       struct rpi_ts_regs regs;
+       int modified_ids = 0;
+       long released_ids;
+       int event_type;
+       int touchid;
+       int x, y;
+       int i;
+
+       memcpy_fromio(&regs, ts->fw_regs_va, sizeof(regs));
+       /*
+        * We poll the memory based register copy of the touchscreen chip using
+        * the number of points register to know whether the copy has been
+        * updated (we write 99 to the memory copy, the GPU will write between
+        * 0 - 10 points)
+        */
+       iowrite8(RPI_TS_NPOINTS_REG_INVALIDATE,
+                ts->fw_regs_va + offsetof(struct rpi_ts_regs, num_points));
+
+       if (regs.num_points == RPI_TS_NPOINTS_REG_INVALIDATE ||
+           (regs.num_points == 0 && ts->known_ids == 0))
+               return;
+
+       for (i = 0; i < regs.num_points; i++) {
+               x = (((int)regs.point[i].xh & 0xf) << 8) + regs.point[i].xl;
+               y = (((int)regs.point[i].yh & 0xf) << 8) + regs.point[i].yl;
+               touchid = (regs.point[i].yh >> 4) & 0xf;
+               event_type = (regs.point[i].xh >> 6) & 0x03;
+
+               modified_ids |= BIT(touchid);
+
+               if (event_type == RPI_TS_FTS_TOUCH_DOWN ||
+                   event_type == RPI_TS_FTS_TOUCH_CONTACT) {
+                       input_mt_slot(input, touchid);
+                       input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
+                       touchscreen_report_pos(input, &ts->prop, x, y, true);
+               }
+       }
+
+       released_ids = ts->known_ids & ~modified_ids;
+       for_each_set_bit(i, &released_ids, RPI_TS_MAX_SUPPORTED_POINTS) {
+               input_mt_slot(input, i);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, 0);
+               modified_ids &= ~(BIT(i));
+       }
+       ts->known_ids = modified_ids;
+
+       input_mt_sync_frame(input);
+       input_sync(input);
+}
+
+static void rpi_ts_dma_cleanup(void *data)
+{
+       struct rpi_ts *ts = data;
+       struct device *dev = &ts->pdev->dev;
+
+       dma_free_coherent(dev, PAGE_SIZE, ts->fw_regs_va, ts->fw_regs_phys);
+}
+
+static int rpi_ts_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct input_polled_dev *poll_dev;
+       struct device_node *fw_node;
+       struct rpi_firmware *fw;
+       struct input_dev *input;
+       struct rpi_ts *ts;
+       u32 touchbuf;
+       int error;
+
+       fw_node = of_get_parent(np);
+       if (!fw_node) {
+               dev_err(dev, "Missing firmware node\n");
+               return -ENOENT;
+       }
+
+       fw = rpi_firmware_get(fw_node);
+       of_node_put(fw_node);
+       if (!fw)
+               return -EPROBE_DEFER;
+
+       ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+       ts->pdev = pdev;
+
+       ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
+                                            GFP_KERNEL);
+       if (!ts->fw_regs_va) {
+               dev_err(dev, "failed to dma_alloc_coherent\n");
+               return -ENOMEM;
+       }
+
+       error = devm_add_action_or_reset(dev, rpi_ts_dma_cleanup, ts);
+       if (error) {
+               dev_err(dev, "failed to devm_add_action_or_reset, %d\n", error);
+               return error;
+       }
+
+
+       touchbuf = (u32)ts->fw_regs_phys;
+       error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
+                                     &touchbuf, sizeof(touchbuf));
+
+       if (error || touchbuf != 0) {
+               dev_warn(dev, "Failed to set touchbuf, %d\n", error);
+               return error;
+       }
+
+       poll_dev = devm_input_allocate_polled_device(dev);
+       if (!poll_dev) {
+               dev_err(dev, "Failed to allocate input device\n");
+               return -ENOMEM;
+       }
+       ts->poll_dev = poll_dev;
+       input = poll_dev->input;
+
+       input->name = "raspberrypi-ts";
+       input->id.bustype = BUS_HOST;
+       poll_dev->poll_interval = RPI_TS_POLL_INTERVAL;
+       poll_dev->poll = rpi_ts_poll;
+       poll_dev->private = ts;
+
+       input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+                            RPI_TS_DEFAULT_WIDTH, 0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+                            RPI_TS_DEFAULT_HEIGHT, 0, 0);
+       touchscreen_parse_properties(input, true, &ts->prop);
+
+       error = input_mt_init_slots(input, RPI_TS_MAX_SUPPORTED_POINTS,
+                                   INPUT_MT_DIRECT);
+       if (error) {
+               dev_err(dev, "could not init mt slots, %d\n", error);
+               return error;
+       }
+
+       error = input_register_polled_device(poll_dev);
+       if (error) {
+               dev_err(dev, "could not register input device, %d\n", error);
+               return error;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id rpi_ts_match[] = {
+       { .compatible = "raspberrypi,firmware-ts", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, rpi_ts_match);
+
+static struct platform_driver rpi_ts_driver = {
+       .driver = {
+               .name   = "raspberrypi-ts",
+               .of_match_table = rpi_ts_match,
+       },
+       .probe          = rpi_ts_probe,
+};
+module_platform_driver(rpi_ts_driver);
+
+MODULE_AUTHOR("Gordon Hollingworth");
+MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
+MODULE_DESCRIPTION("Raspberry Pi firmware based touchscreen driver");
+MODULE_LICENSE("GPL v2");
index 228a5e2..7b24fc7 100644 (file)
@@ -71,6 +71,7 @@
 #define MMP2_CLK_CCIC1_MIX             117
 #define MMP2_CLK_CCIC1_PHY             118
 #define MMP2_CLK_CCIC1_SPHY            119
+#define MMP2_CLK_SP                    120
 
 #define MMP2_NR_CLKS                   200
 #endif
diff --git a/include/linux/platform_data/ad7879.h b/include/linux/platform_data/ad7879.h
deleted file mode 100644 (file)
index 6655cc8..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* linux/platform_data/ad7879.h */
-
-/* Touchscreen characteristics vary between boards and models.  The
- * platform_data for the device's "struct device" holds this information.
- *
- * It's OK if the min/max values are zero.
- */
-struct ad7879_platform_data {
-       u16     model;                  /* 7879 */
-       u16     x_plate_ohms;
-       u16     x_min, x_max;
-       u16     y_min, y_max;
-       u16     pressure_min, pressure_max;
-
-       bool    swap_xy;                /* swap x and y axes */
-
-       /* [0..255] 0=OFF Starts at 1=550us and goes
-        * all the way to 9.440ms in steps of 35us.
-        */
-       u8      pen_down_acc_interval;
-       /* [0..15] Starts at 0=128us and goes all the
-        * way to 4.096ms in steps of 128us.
-        */
-       u8      first_conversion_delay;
-       /* [0..3] 0 = 2us, 1 = 4us, 2 = 8us, 3 = 16us */
-       u8      acquisition_time;
-       /* [0..3] Average X middle samples 0 = 2, 1 = 4, 2 = 8, 3 = 16 */
-       u8      averaging;
-       /* [0..3] Perform X measurements 0 = OFF,
-        * 1 = 4, 2 = 8, 3 = 16 (median > averaging)
-        */
-       u8      median;
-       /* 1 = AUX/VBAT/GPIO export GPIO to gpiolib
-        * requires CONFIG_GPIOLIB
-        */
-       bool    gpio_export;
-       /* identifies the first GPIO number handled by this chip;
-        * or, if negative, requests dynamic ID allocation.
-        */
-       s32     gpio_base;
-};