Merge tag 'v4.20' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 14 Jan 2019 06:35:32 +0000 (22:35 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 14 Jan 2019 06:35:32 +0000 (22:35 -0800)
Merge with mainline to bring in the new APIs.

22 files changed:
Documentation/devicetree/bindings/input/cypress,tm2-touchkey.txt
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/keyboard/tm2-touchkey.c
drivers/input/misc/drv2667.c
drivers/input/misc/rotary_encoder.c
drivers/input/misc/soc_button_array.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]

index 0c252d9306dab31dfbe748e3c855215602c66de2..ef2ae729718f8d005565b532d0c5c1df4a88c6a5 100644 (file)
@@ -1,13 +1,19 @@
 Samsung tm2-touchkey
 
 Required properties:
-- compatible: must be "cypress,tm2-touchkey"
+- compatible:
+    * "cypress,tm2-touchkey" - for the touchkey found on the tm2 board
+    * "cypress,midas-touchkey" - for the touchkey found on midas boards
+    * "cypress,aries-touchkey" - for the touchkey found on aries boards
 - reg: I2C address of the chip.
 - interrupts: interrupt to which the chip is connected (see interrupt
        binding[0]).
 - vcc-supply : internal regulator output. 1.8V
 - vdd-supply : power supply for IC 3.3V
 
+Optional properties:
+- linux,keycodes: array of keycodes (max 4), default KEY_PHONE and KEY_BACK
+
 [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 
 Example:
@@ -21,5 +27,6 @@ Example:
                        interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
                        vcc-supply=<&ldo32_reg>;
                        vdd-supply=<&ldo33_reg>;
+                       linux,keycodes = <KEY_PHONE KEY_BACK>;
                };
        };
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 0e72183f52bc9dc5926b34f414941780e70847cc..36603419d6f8e7858692af125f51726db85c5905 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 d083b860f08333ad1caf8082664efdeaf1e0099d..61fefc046ec5ad8fd1de8df585e7c47d50be474b 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 8567ee47761e111b31f7c8270bdc6414de6668a1..ae3b04557074010bc708c48db877c486f9d1cd0a 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 abc266e40e1710e034d05077ebbe7dc33ce42903..7dbef96559d2bf6683bdf4de1e84db1542022e8b 100644 (file)
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
 
 #define TM2_TOUCHKEY_DEV_NAME          "tm2-touchkey"
-#define TM2_TOUCHKEY_KEYCODE_REG       0x03
-#define TM2_TOUCHKEY_BASE_REG          0x00
+
+#define ARIES_TOUCHKEY_CMD_LED_ON      0x1
+#define ARIES_TOUCHKEY_CMD_LED_OFF     0x2
 #define TM2_TOUCHKEY_CMD_LED_ON                0x10
 #define TM2_TOUCHKEY_CMD_LED_OFF       0x20
 #define TM2_TOUCHKEY_BIT_PRESS_EV      BIT(3)
 #define TM2_TOUCHKEY_LED_VOLTAGE_MIN   2500000
 #define TM2_TOUCHKEY_LED_VOLTAGE_MAX   3300000
 
-enum {
-       TM2_TOUCHKEY_KEY_MENU = 0x1,
-       TM2_TOUCHKEY_KEY_BACK,
+struct touchkey_variant {
+       u8 keycode_reg;
+       u8 base_reg;
+       u8 cmd_led_on;
+       u8 cmd_led_off;
+       bool no_reg;
+       bool fixed_regulator;
 };
 
 struct tm2_touchkey_data {
@@ -46,6 +52,30 @@ struct tm2_touchkey_data {
        struct led_classdev led_dev;
        struct regulator *vdd;
        struct regulator_bulk_data regulators[2];
+       const struct touchkey_variant *variant;
+       u32 keycodes[4];
+       int num_keycodes;
+};
+
+static const struct touchkey_variant tm2_touchkey_variant = {
+       .keycode_reg = 0x03,
+       .base_reg = 0x00,
+       .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON,
+       .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF,
+};
+
+static const struct touchkey_variant midas_touchkey_variant = {
+       .keycode_reg = 0x00,
+       .base_reg = 0x00,
+       .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON,
+       .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF,
+};
+
+static struct touchkey_variant aries_touchkey_variant = {
+       .no_reg = true,
+       .fixed_regulator = true,
+       .cmd_led_on = ARIES_TOUCHKEY_CMD_LED_ON,
+       .cmd_led_off = ARIES_TOUCHKEY_CMD_LED_OFF,
 };
 
 static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
@@ -58,15 +88,20 @@ static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
 
        if (brightness == LED_OFF) {
                volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN;
-               data = TM2_TOUCHKEY_CMD_LED_OFF;
+               data = touchkey->variant->cmd_led_off;
        } else {
                volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX;
-               data = TM2_TOUCHKEY_CMD_LED_ON;
+               data = touchkey->variant->cmd_led_on;
        }
 
-       regulator_set_voltage(touchkey->vdd, volt, volt);
-       i2c_smbus_write_byte_data(touchkey->client,
-                                 TM2_TOUCHKEY_BASE_REG, data);
+       if (!touchkey->variant->fixed_regulator)
+               regulator_set_voltage(touchkey->vdd, volt, volt);
+
+       if (touchkey->variant->no_reg)
+               i2c_smbus_write_byte(touchkey->client, data);
+       else
+               i2c_smbus_write_byte_data(touchkey->client,
+                                         touchkey->variant->base_reg, data);
 }
 
 static int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey)
@@ -96,49 +131,57 @@ static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
 {
        struct tm2_touchkey_data *touchkey = devid;
        int data;
-       int key;
-
-       data = i2c_smbus_read_byte_data(touchkey->client,
-                                       TM2_TOUCHKEY_KEYCODE_REG);
+       int index;
+       int i;
+
+       if (touchkey->variant->no_reg)
+               data = i2c_smbus_read_byte(touchkey->client);
+       else
+               data = i2c_smbus_read_byte_data(touchkey->client,
+                                               touchkey->variant->keycode_reg);
        if (data < 0) {
                dev_err(&touchkey->client->dev,
                        "failed to read i2c data: %d\n", data);
                goto out;
        }
 
-       switch (data & TM2_TOUCHKEY_BIT_KEYCODE) {
-       case TM2_TOUCHKEY_KEY_MENU:
-               key = KEY_PHONE;
-               break;
-
-       case TM2_TOUCHKEY_KEY_BACK:
-               key = KEY_BACK;
-               break;
-
-       default:
+       index = (data & TM2_TOUCHKEY_BIT_KEYCODE) - 1;
+       if (index < 0 || index >= touchkey->num_keycodes) {
                dev_warn(&touchkey->client->dev,
-                        "unhandled keycode, data %#02x\n", data);
+                        "invalid keycode index %d\n", index);
                goto out;
        }
 
        if (data & TM2_TOUCHKEY_BIT_PRESS_EV) {
-               input_report_key(touchkey->input_dev, KEY_PHONE, 0);
-               input_report_key(touchkey->input_dev, KEY_BACK, 0);
+               for (i = 0; i < touchkey->num_keycodes; i++)
+                       input_report_key(touchkey->input_dev,
+                                        touchkey->keycodes[i], 0);
        } else {
-               input_report_key(touchkey->input_dev, key, 1);
+               input_report_key(touchkey->input_dev,
+                                touchkey->keycodes[index], 1);
        }
 
        input_sync(touchkey->input_dev);
 
 out:
+       if (touchkey->variant->fixed_regulator &&
+                               data & TM2_TOUCHKEY_BIT_PRESS_EV) {
+               /* touch turns backlight on, so make sure we're in sync */
+               if (touchkey->led_dev.brightness == LED_OFF)
+                       tm2_touchkey_led_brightness_set(&touchkey->led_dev,
+                                                       LED_OFF);
+       }
+
        return IRQ_HANDLED;
 }
 
 static int tm2_touchkey_probe(struct i2c_client *client,
                              const struct i2c_device_id *id)
 {
+       struct device_node *np = client->dev.of_node;
        struct tm2_touchkey_data *touchkey;
        int error;
+       int i;
 
        if (!i2c_check_functionality(client->adapter,
                        I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -153,6 +196,8 @@ static int tm2_touchkey_probe(struct i2c_client *client,
        touchkey->client = client;
        i2c_set_clientdata(client, touchkey);
 
+       touchkey->variant = of_device_get_match_data(&client->dev);
+
        touchkey->regulators[0].supply = "vcc";
        touchkey->regulators[1].supply = "vdd";
        error = devm_regulator_bulk_get(&client->dev,
@@ -166,6 +211,16 @@ static int tm2_touchkey_probe(struct i2c_client *client,
        /* Save VDD for easy access */
        touchkey->vdd = touchkey->regulators[1].consumer;
 
+       touchkey->num_keycodes = of_property_read_variable_u32_array(np,
+                                       "linux,keycodes", touchkey->keycodes, 0,
+                                       ARRAY_SIZE(touchkey->keycodes));
+       if (touchkey->num_keycodes <= 0) {
+               /* default keycodes */
+               touchkey->keycodes[0] = KEY_PHONE;
+               touchkey->keycodes[1] = KEY_BACK;
+               touchkey->num_keycodes = 2;
+       }
+
        error = tm2_touchkey_power_enable(touchkey);
        if (error) {
                dev_err(&client->dev, "failed to power up device: %d\n", error);
@@ -190,8 +245,9 @@ static int tm2_touchkey_probe(struct i2c_client *client,
        touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME;
        touchkey->input_dev->id.bustype = BUS_I2C;
 
-       input_set_capability(touchkey->input_dev, EV_KEY, KEY_PHONE);
-       input_set_capability(touchkey->input_dev, EV_KEY, KEY_BACK);
+       for (i = 0; i < touchkey->num_keycodes; i++)
+               input_set_capability(touchkey->input_dev, EV_KEY,
+                                    touchkey->keycodes[i]);
 
        error = input_register_device(touchkey->input_dev);
        if (error) {
@@ -212,7 +268,7 @@ static int tm2_touchkey_probe(struct i2c_client *client,
 
        /* led device */
        touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
-       touchkey->led_dev.brightness = LED_FULL;
+       touchkey->led_dev.brightness = LED_ON;
        touchkey->led_dev.max_brightness = LED_ON;
        touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set;
 
@@ -223,6 +279,9 @@ static int tm2_touchkey_probe(struct i2c_client *client,
                return error;
        }
 
+       if (touchkey->variant->fixed_regulator)
+               tm2_touchkey_led_brightness_set(&touchkey->led_dev, LED_ON);
+
        return 0;
 }
 
@@ -262,7 +321,16 @@ static const struct i2c_device_id tm2_touchkey_id_table[] = {
 MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
 
 static const struct of_device_id tm2_touchkey_of_match[] = {
-       { .compatible = "cypress,tm2-touchkey", },
+       {
+               .compatible = "cypress,tm2-touchkey",
+               .data = &tm2_touchkey_variant,
+       }, {
+               .compatible = "cypress,midas-touchkey",
+               .data = &midas_touchkey_variant,
+       }, {
+               .compatible = "cypress,aries-touchkey",
+               .data = &aries_touchkey_variant,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match);
index 2849bb6906a8f799dae30a022937a47740595a28..6091f0490e8f6fbfac38181184263d97ce7e2c43 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 30ec77ad32c6efa6a56637246e342bad5b7e93b1..d748897bf5e92f46399fd3ad84237f53a2ceca70 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 23520df7650f5bc9261c3b58cac22a8dfc27423f..bb458beecb43326f0136fc212a6caa7094b238a1 100644 (file)
@@ -185,6 +185,10 @@ static int soc_button_parse_btn_desc(struct device *dev,
                info->name = "power";
                info->event_code = KEY_POWER;
                info->wakeup = true;
+       } else if (upage == 0x01 && usage == 0xca) {
+               info->name = "rotation lock switch";
+               info->event_type = EV_SW;
+               info->event_code = SW_ROTATE_LOCK;
        } else if (upage == 0x07 && usage == 0xe3) {
                info->name = "home";
                info->event_code = KEY_LEFTMETA;
@@ -373,7 +377,7 @@ static struct soc_button_info soc_button_PNP0C40[] = {
        { "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
        { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
        { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false },
-       { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false },
+       { "rotation_lock", 4, EV_KEY, KEY_ROTATE_LOCK_TOGGLE, false, false },
        { }
 };
 
index d90d9f1098ff8ccba4c35d032812f6a62019baa3..c9c7224d5ae08517489c1d8ee8775c2630170514 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 8e9a4209fcada1bb580bd4a95f742316d8b2d886..b36084710f696626b3f9a595f22c357169a30fdf 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 2a80675cfd9470f4a9bddd2c6ef1222428acbade..af6027cc7bbfae2687c1524ee6265c53f6feb39b 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 5911a4190cd2c3a263b5bab721b1987dfacc509a..fcc7605fba8dba99e88d6b319b0ab94bd538f734 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 6bad23ee47a1a6cb4db82ed36a2e4ff462e62820..3a016f43fb85698182954406ad4b5022060aeecf 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"
 
@@ -247,11 +246,14 @@ static void ad7879_timer(struct timer_list *t)
 static irqreturn_t ad7879_irq(int irq, void *handle)
 {
        struct ad7879 *ts = handle;
+       int error;
 
-       regmap_bulk_read(ts->regmap, AD7879_REG_XPLUS,
-                        ts->conversion_data, AD7879_NR_SENSE);
-
-       if (!ad7879_report(ts))
+       error = regmap_bulk_read(ts->regmap, AD7879_REG_XPLUS,
+                                ts->conversion_data, AD7879_NR_SENSE);
+       if (error)
+               dev_err_ratelimited(ts->dev, "failed to read %#02x: %d\n",
+                                   AD7879_REG_XPLUS, error);
+       else if (!ad7879_report(ts))
                mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
 
        return IRQ_HANDLED;
@@ -290,7 +292,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 +454,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 +518,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 +532,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 +562,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 +617,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 d3aacd534e9ca7fbf4e94504447e3c2a0e14170f..5c63d25ce84ebee9a6296de142c8cd6115a79701 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 0ed34ff787cead38306f364c1138223dd4a5edf4..28fa1b36f7a5a348cc8b51cd888e910102777729 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 054c2537b392a063ac1529c308d675e101fcbcd6..56cf1a1ea3ea8279540a83b7d4a76f46f0750fcb 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 b9bc56233ccce742daeecc4df42b0530fbe9328c..13bd0bf580a79a19f7f717ec1083e63772aac5bb 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 a3707fad4d1c8b4862e121c38c0ba54f9beffbc6..8278a9058640c1135e8111dfb2248232a0474545 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 228a5e234af048ce8388bb02326a16c183fb4444..7b24fc7911465381adf20c59a431f188bcc6fd3f 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;
-};