diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clk/mmp/clk-of-mmp2.c | 4 | ||||
| -rw-r--r-- | drivers/input/joystick/xpad.c | 3 | ||||
| -rw-r--r-- | drivers/input/keyboard/nomadik-ske-keypad.c | 2 | ||||
| -rw-r--r-- | drivers/input/misc/drv2667.c | 6 | ||||
| -rw-r--r-- | drivers/input/misc/rotary_encoder.c | 6 | ||||
| -rw-r--r-- | drivers/input/mouse/elan_i2c_core.c | 1 | ||||
| -rw-r--r-- | drivers/input/serio/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/input/serio/olpc_apsp.c | 28 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ad7879.c | 109 | ||||
| -rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 4 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ektf2127.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/gunze.c | 4 | ||||
| -rw-r--r-- | drivers/input/touchscreen/inexio.c | 4 | ||||
| -rw-r--r-- | drivers/input/touchscreen/mtouch.c | 4 | ||||
| -rw-r--r-- | drivers/input/touchscreen/raspberrypi-ts.c | 227 |
17 files changed, 319 insertions, 99 deletions
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index d083b860f083..61fefc046ec5 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #define APMU_DISP1 0x110 | 53 | #define APMU_DISP1 0x110 |
| 54 | #define APMU_CCIC0 0x50 | 54 | #define APMU_CCIC0 0x50 |
| 55 | #define APMU_CCIC1 0xf4 | 55 | #define APMU_CCIC1 0xf4 |
| 56 | #define APMU_SP 0x68 | ||
| 56 | #define MPMU_UART_PLL 0x14 | 57 | #define MPMU_UART_PLL 0x14 |
| 57 | 58 | ||
| 58 | struct mmp2_clk_unit { | 59 | struct mmp2_clk_unit { |
| @@ -209,6 +210,8 @@ static struct mmp_clk_mix_config ccic1_mix_config = { | |||
| 209 | .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32), | 210 | .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32), |
| 210 | }; | 211 | }; |
| 211 | 212 | ||
| 213 | static DEFINE_SPINLOCK(sp_lock); | ||
| 214 | |||
| 212 | static struct mmp_param_mux_clk apmu_mux_clks[] = { | 215 | static struct mmp_param_mux_clk apmu_mux_clks[] = { |
| 213 | {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}, | 216 | {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}, |
| 214 | {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}, | 217 | {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[] = { | |||
| 239 | {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock}, | 242 | {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock}, |
| 240 | {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock}, | 243 | {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock}, |
| 241 | {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock}, | 244 | {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock}, |
| 245 | {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock}, | ||
| 242 | }; | 246 | }; |
| 243 | 247 | ||
| 244 | static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit) | 248 | static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit) |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index cfc8b94527b9..aa4e431cbcd3 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
| @@ -252,6 +252,8 @@ static const struct xpad_device { | |||
| 252 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, | 252 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, |
| 253 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, | 253 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, |
| 254 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, | 254 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, |
| 255 | { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, | ||
| 256 | { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, | ||
| 255 | { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, | 257 | { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, |
| 256 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 258 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
| 257 | { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, | 259 | { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, |
| @@ -428,6 +430,7 @@ static const struct usb_device_id xpad_table[] = { | |||
| 428 | XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ | 430 | XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ |
| 429 | XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ | 431 | XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ |
| 430 | XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ | 432 | XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ |
| 433 | XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */ | ||
| 431 | XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ | 434 | XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ |
| 432 | XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ | 435 | XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ |
| 433 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | 436 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ |
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 8567ee47761e..ae3b04557074 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c | |||
| @@ -100,7 +100,7 @@ static int __init ske_keypad_chip_init(struct ske_keypad *keypad) | |||
| 100 | while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--) | 100 | while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--) |
| 101 | cpu_relax(); | 101 | cpu_relax(); |
| 102 | 102 | ||
| 103 | if (!timeout) | 103 | if (timeout == -1) |
| 104 | return -EINVAL; | 104 | return -EINVAL; |
| 105 | 105 | ||
| 106 | /* | 106 | /* |
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c index 2849bb6906a8..6091f0490e8f 100644 --- a/drivers/input/misc/drv2667.c +++ b/drivers/input/misc/drv2667.c | |||
| @@ -177,9 +177,9 @@ static int drv2667_set_waveform_freq(struct drv2667_data *haptics) | |||
| 177 | error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf); | 177 | error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf); |
| 178 | if (error) { | 178 | if (error) { |
| 179 | dev_err(&haptics->client->dev, | 179 | dev_err(&haptics->client->dev, |
| 180 | "Failed to set the page: %d\n", error); | 180 | "Failed to set the page: %d\n", error); |
| 181 | return -EIO; | 181 | return -EIO; |
| 182 | } | 182 | } |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | return error; | 185 | return error; |
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 30ec77ad32c6..d748897bf5e9 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
| @@ -240,8 +240,10 @@ static int rotary_encoder_probe(struct platform_device *pdev) | |||
| 240 | 240 | ||
| 241 | encoder->gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); | 241 | encoder->gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); |
| 242 | if (IS_ERR(encoder->gpios)) { | 242 | if (IS_ERR(encoder->gpios)) { |
| 243 | dev_err(dev, "unable to get gpios\n"); | 243 | err = PTR_ERR(encoder->gpios); |
| 244 | return PTR_ERR(encoder->gpios); | 244 | if (err != -EPROBE_DEFER) |
| 245 | dev_err(dev, "unable to get gpios: %d\n", err); | ||
| 246 | return err; | ||
| 245 | } | 247 | } |
| 246 | if (encoder->gpios->ndescs < 2) { | 248 | if (encoder->gpios->ndescs < 2) { |
| 247 | dev_err(dev, "not enough gpios found\n"); | 249 | dev_err(dev, "not enough gpios found\n"); |
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index a94b6494e71a..f322a1768fbb 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c | |||
| @@ -1336,6 +1336,7 @@ MODULE_DEVICE_TABLE(i2c, elan_id); | |||
| 1336 | static const struct acpi_device_id elan_acpi_id[] = { | 1336 | static const struct acpi_device_id elan_acpi_id[] = { |
| 1337 | { "ELAN0000", 0 }, | 1337 | { "ELAN0000", 0 }, |
| 1338 | { "ELAN0100", 0 }, | 1338 | { "ELAN0100", 0 }, |
| 1339 | { "ELAN0501", 0 }, | ||
| 1339 | { "ELAN0600", 0 }, | 1340 | { "ELAN0600", 0 }, |
| 1340 | { "ELAN0602", 0 }, | 1341 | { "ELAN0602", 0 }, |
| 1341 | { "ELAN0605", 0 }, | 1342 | { "ELAN0605", 0 }, |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index d90d9f1098ff..c9c7224d5ae0 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
| @@ -254,7 +254,6 @@ config SERIO_APBPS2 | |||
| 254 | 254 | ||
| 255 | config SERIO_OLPC_APSP | 255 | config SERIO_OLPC_APSP |
| 256 | tristate "OLPC AP-SP input support" | 256 | tristate "OLPC AP-SP input support" |
| 257 | depends on OLPC || COMPILE_TEST | ||
| 258 | help | 257 | help |
| 259 | Say Y here if you want support for the keyboard and touchpad included | 258 | Say Y here if you want support for the keyboard and touchpad included |
| 260 | in the OLPC XO-1.75 and XO-4 laptops. | 259 | in the OLPC XO-1.75 and XO-4 laptops. |
diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c index 8e9a4209fcad..b36084710f69 100644 --- a/drivers/input/serio/olpc_apsp.c +++ b/drivers/input/serio/olpc_apsp.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <linux/clk.h> | ||
| 26 | 27 | ||
| 27 | /* | 28 | /* |
| 28 | * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller. | 29 | * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller. |
| @@ -74,6 +75,7 @@ struct olpc_apsp { | |||
| 74 | struct serio *kbio; | 75 | struct serio *kbio; |
| 75 | struct serio *padio; | 76 | struct serio *padio; |
| 76 | void __iomem *base; | 77 | void __iomem *base; |
| 78 | struct clk *clk; | ||
| 77 | int open_count; | 79 | int open_count; |
| 78 | int irq; | 80 | int irq; |
| 79 | }; | 81 | }; |
| @@ -145,8 +147,21 @@ static int olpc_apsp_open(struct serio *port) | |||
| 145 | { | 147 | { |
| 146 | struct olpc_apsp *priv = port->port_data; | 148 | struct olpc_apsp *priv = port->port_data; |
| 147 | unsigned int tmp; | 149 | unsigned int tmp; |
| 150 | unsigned long l; | ||
| 151 | int error; | ||
| 148 | 152 | ||
| 149 | if (priv->open_count++ == 0) { | 153 | if (priv->open_count++ == 0) { |
| 154 | error = clk_prepare_enable(priv->clk); | ||
| 155 | if (error) | ||
| 156 | return error; | ||
| 157 | |||
| 158 | l = readl(priv->base + COMMAND_FIFO_STATUS); | ||
| 159 | if (!(l & CMD_STS_MASK)) { | ||
| 160 | dev_err(priv->dev, "SP cannot accept commands.\n"); | ||
| 161 | clk_disable_unprepare(priv->clk); | ||
| 162 | return -EIO; | ||
| 163 | } | ||
| 164 | |||
| 150 | /* Enable interrupt 0 by clearing its bit */ | 165 | /* Enable interrupt 0 by clearing its bit */ |
| 151 | tmp = readl(priv->base + PJ_INTERRUPT_MASK); | 166 | tmp = readl(priv->base + PJ_INTERRUPT_MASK); |
| 152 | writel(tmp & ~INT_0, priv->base + PJ_INTERRUPT_MASK); | 167 | writel(tmp & ~INT_0, priv->base + PJ_INTERRUPT_MASK); |
| @@ -164,6 +179,8 @@ static void olpc_apsp_close(struct serio *port) | |||
| 164 | /* Disable interrupt 0 */ | 179 | /* Disable interrupt 0 */ |
| 165 | tmp = readl(priv->base + PJ_INTERRUPT_MASK); | 180 | tmp = readl(priv->base + PJ_INTERRUPT_MASK); |
| 166 | writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK); | 181 | writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK); |
| 182 | |||
| 183 | clk_disable_unprepare(priv->clk); | ||
| 167 | } | 184 | } |
| 168 | } | 185 | } |
| 169 | 186 | ||
| @@ -172,15 +189,12 @@ static int olpc_apsp_probe(struct platform_device *pdev) | |||
| 172 | struct serio *kb_serio, *pad_serio; | 189 | struct serio *kb_serio, *pad_serio; |
| 173 | struct olpc_apsp *priv; | 190 | struct olpc_apsp *priv; |
| 174 | struct resource *res; | 191 | struct resource *res; |
| 175 | struct device_node *np; | ||
| 176 | unsigned long l; | ||
| 177 | int error; | 192 | int error; |
| 178 | 193 | ||
| 179 | priv = devm_kzalloc(&pdev->dev, sizeof(struct olpc_apsp), GFP_KERNEL); | 194 | priv = devm_kzalloc(&pdev->dev, sizeof(struct olpc_apsp), GFP_KERNEL); |
| 180 | if (!priv) | 195 | if (!priv) |
| 181 | return -ENOMEM; | 196 | return -ENOMEM; |
| 182 | 197 | ||
| 183 | np = pdev->dev.of_node; | ||
| 184 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 198 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 185 | priv->base = devm_ioremap_resource(&pdev->dev, res); | 199 | priv->base = devm_ioremap_resource(&pdev->dev, res); |
| 186 | if (IS_ERR(priv->base)) { | 200 | if (IS_ERR(priv->base)) { |
| @@ -192,11 +206,9 @@ static int olpc_apsp_probe(struct platform_device *pdev) | |||
| 192 | if (priv->irq < 0) | 206 | if (priv->irq < 0) |
| 193 | return priv->irq; | 207 | return priv->irq; |
| 194 | 208 | ||
| 195 | l = readl(priv->base + COMMAND_FIFO_STATUS); | 209 | priv->clk = devm_clk_get(&pdev->dev, "sp"); |
| 196 | if (!(l & CMD_STS_MASK)) { | 210 | if (IS_ERR(priv->clk)) |
| 197 | dev_err(&pdev->dev, "SP cannot accept commands.\n"); | 211 | return PTR_ERR(priv->clk); |
| 198 | return -EIO; | ||
| 199 | } | ||
| 200 | 212 | ||
| 201 | /* KEYBOARD */ | 213 | /* KEYBOARD */ |
| 202 | kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 214 | kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 2a80675cfd94..068dbbc610fc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -696,6 +696,18 @@ config TOUCHSCREEN_EDT_FT5X06 | |||
| 696 | To compile this driver as a module, choose M here: the | 696 | To compile this driver as a module, choose M here: the |
| 697 | module will be called edt-ft5x06. | 697 | module will be called edt-ft5x06. |
| 698 | 698 | ||
| 699 | config TOUCHSCREEN_RASPBERRYPI_FW | ||
| 700 | tristate "Raspberry Pi's firmware base touch screen support" | ||
| 701 | depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST) | ||
| 702 | help | ||
| 703 | Say Y here if you have the official Raspberry Pi 7 inch screen on | ||
| 704 | your system. | ||
| 705 | |||
| 706 | If unsure, say N. | ||
| 707 | |||
| 708 | To compile this driver as a module, choose M here: the | ||
| 709 | module will be called raspberrypi-ts. | ||
| 710 | |||
| 699 | config TOUCHSCREEN_MIGOR | 711 | config TOUCHSCREEN_MIGOR |
| 700 | tristate "Renesas MIGO-R touchscreen" | 712 | tristate "Renesas MIGO-R touchscreen" |
| 701 | depends on (SH_MIGOR || COMPILE_TEST) && I2C | 713 | depends on (SH_MIGOR || COMPILE_TEST) && I2C |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5911a4190cd2..fcc7605fba8d 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -109,3 +109,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o | |||
| 109 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o | 109 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o |
| 110 | obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o | 110 | obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o |
| 111 | obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o | 111 | obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o |
| 112 | obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW) += raspberrypi-ts.o | ||
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 6bad23ee47a1..6fa714c587b4 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
| @@ -29,10 +29,9 @@ | |||
| 29 | #include <linux/property.h> | 29 | #include <linux/property.h> |
| 30 | #include <linux/regmap.h> | 30 | #include <linux/regmap.h> |
| 31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 32 | #include <linux/gpio.h> | 32 | #include <linux/gpio/driver.h> |
| 33 | 33 | ||
| 34 | #include <linux/input/touchscreen.h> | 34 | #include <linux/input/touchscreen.h> |
| 35 | #include <linux/platform_data/ad7879.h> | ||
| 36 | #include <linux/module.h> | 35 | #include <linux/module.h> |
| 37 | #include "ad7879.h" | 36 | #include "ad7879.h" |
| 38 | 37 | ||
| @@ -290,7 +289,7 @@ static int ad7879_open(struct input_dev *input) | |||
| 290 | return 0; | 289 | return 0; |
| 291 | } | 290 | } |
| 292 | 291 | ||
| 293 | static void ad7879_close(struct input_dev* input) | 292 | static void ad7879_close(struct input_dev *input) |
| 294 | { | 293 | { |
| 295 | struct ad7879 *ts = input_get_drvdata(input); | 294 | struct ad7879 *ts = input_get_drvdata(input); |
| 296 | 295 | ||
| @@ -452,47 +451,36 @@ static void ad7879_gpio_set_value(struct gpio_chip *chip, | |||
| 452 | mutex_unlock(&ts->mutex); | 451 | mutex_unlock(&ts->mutex); |
| 453 | } | 452 | } |
| 454 | 453 | ||
| 455 | static int ad7879_gpio_add(struct ad7879 *ts, | 454 | static int ad7879_gpio_add(struct ad7879 *ts) |
| 456 | const struct ad7879_platform_data *pdata) | ||
| 457 | { | 455 | { |
| 458 | bool gpio_export; | ||
| 459 | int gpio_base; | ||
| 460 | int ret = 0; | 456 | int ret = 0; |
| 461 | 457 | ||
| 462 | if (pdata) { | ||
| 463 | gpio_export = pdata->gpio_export; | ||
| 464 | gpio_base = pdata->gpio_base; | ||
| 465 | } else { | ||
| 466 | gpio_export = device_property_read_bool(ts->dev, | ||
| 467 | "gpio-controller"); | ||
| 468 | gpio_base = -1; | ||
| 469 | } | ||
| 470 | |||
| 471 | mutex_init(&ts->mutex); | 458 | mutex_init(&ts->mutex); |
| 472 | 459 | ||
| 473 | if (gpio_export) { | 460 | /* Do not create a chip unless flagged for it */ |
| 474 | ts->gc.direction_input = ad7879_gpio_direction_input; | 461 | if (!device_property_read_bool(ts->dev, "gpio-controller")) |
| 475 | ts->gc.direction_output = ad7879_gpio_direction_output; | 462 | return 0; |
| 476 | ts->gc.get = ad7879_gpio_get_value; | 463 | |
| 477 | ts->gc.set = ad7879_gpio_set_value; | 464 | ts->gc.direction_input = ad7879_gpio_direction_input; |
| 478 | ts->gc.can_sleep = 1; | 465 | ts->gc.direction_output = ad7879_gpio_direction_output; |
| 479 | ts->gc.base = gpio_base; | 466 | ts->gc.get = ad7879_gpio_get_value; |
| 480 | ts->gc.ngpio = 1; | 467 | ts->gc.set = ad7879_gpio_set_value; |
| 481 | ts->gc.label = "AD7879-GPIO"; | 468 | ts->gc.can_sleep = 1; |
| 482 | ts->gc.owner = THIS_MODULE; | 469 | ts->gc.base = -1; |
| 483 | ts->gc.parent = ts->dev; | 470 | ts->gc.ngpio = 1; |
| 484 | 471 | ts->gc.label = "AD7879-GPIO"; | |
| 485 | ret = devm_gpiochip_add_data(ts->dev, &ts->gc, ts); | 472 | ts->gc.owner = THIS_MODULE; |
| 486 | if (ret) | 473 | ts->gc.parent = ts->dev; |
| 487 | dev_err(ts->dev, "failed to register gpio %d\n", | 474 | |
| 488 | ts->gc.base); | 475 | ret = devm_gpiochip_add_data(ts->dev, &ts->gc, ts); |
| 489 | } | 476 | if (ret) |
| 477 | dev_err(ts->dev, "failed to register gpio %d\n", | ||
| 478 | ts->gc.base); | ||
| 490 | 479 | ||
| 491 | return ret; | 480 | return ret; |
| 492 | } | 481 | } |
| 493 | #else | 482 | #else |
| 494 | static int ad7879_gpio_add(struct ad7879 *ts, | 483 | static int ad7879_gpio_add(struct ad7879 *ts) |
| 495 | const struct ad7879_platform_data *pdata) | ||
| 496 | { | 484 | { |
| 497 | return 0; | 485 | return 0; |
| 498 | } | 486 | } |
| @@ -527,7 +515,6 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts) | |||
| 527 | int ad7879_probe(struct device *dev, struct regmap *regmap, | 515 | int ad7879_probe(struct device *dev, struct regmap *regmap, |
| 528 | int irq, u16 bustype, u8 devid) | 516 | int irq, u16 bustype, u8 devid) |
| 529 | { | 517 | { |
| 530 | struct ad7879_platform_data *pdata = dev_get_platdata(dev); | ||
| 531 | struct ad7879 *ts; | 518 | struct ad7879 *ts; |
| 532 | struct input_dev *input_dev; | 519 | struct input_dev *input_dev; |
| 533 | int err; | 520 | int err; |
| @@ -542,22 +529,9 @@ int ad7879_probe(struct device *dev, struct regmap *regmap, | |||
| 542 | if (!ts) | 529 | if (!ts) |
| 543 | return -ENOMEM; | 530 | return -ENOMEM; |
| 544 | 531 | ||
| 545 | if (pdata) { | 532 | err = ad7879_parse_dt(dev, ts); |
| 546 | /* Platform data use swapped axis (backward compatibility) */ | 533 | if (err) |
| 547 | ts->swap_xy = !pdata->swap_xy; | 534 | return err; |
| 548 | |||
| 549 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | ||
| 550 | |||
| 551 | ts->first_conversion_delay = pdata->first_conversion_delay; | ||
| 552 | ts->acquisition_time = pdata->acquisition_time; | ||
| 553 | ts->averaging = pdata->averaging; | ||
| 554 | ts->pen_down_acc_interval = pdata->pen_down_acc_interval; | ||
| 555 | ts->median = pdata->median; | ||
| 556 | } else { | ||
| 557 | err = ad7879_parse_dt(dev, ts); | ||
| 558 | if (err) | ||
| 559 | return err; | ||
| 560 | } | ||
| 561 | 535 | ||
| 562 | input_dev = devm_input_allocate_device(dev); | 536 | input_dev = devm_input_allocate_device(dev); |
| 563 | if (!input_dev) { | 537 | if (!input_dev) { |
| @@ -585,28 +559,13 @@ int ad7879_probe(struct device *dev, struct regmap *regmap, | |||
| 585 | 559 | ||
| 586 | input_set_capability(input_dev, EV_KEY, BTN_TOUCH); | 560 | input_set_capability(input_dev, EV_KEY, BTN_TOUCH); |
| 587 | 561 | ||
| 588 | if (pdata) { | 562 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); |
| 589 | input_set_abs_params(input_dev, ABS_X, | 563 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); |
| 590 | pdata->x_min ? : 0, | 564 | input_set_capability(input_dev, EV_ABS, ABS_PRESSURE); |
| 591 | pdata->x_max ? : MAX_12BIT, | 565 | touchscreen_parse_properties(input_dev, false, NULL); |
| 592 | 0, 0); | 566 | if (!input_abs_get_max(input_dev, ABS_PRESSURE)) { |
| 593 | input_set_abs_params(input_dev, ABS_Y, | 567 | dev_err(dev, "Touchscreen pressure is not specified\n"); |
| 594 | pdata->y_min ? : 0, | 568 | return -EINVAL; |
| 595 | pdata->y_max ? : MAX_12BIT, | ||
| 596 | 0, 0); | ||
| 597 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
| 598 | pdata->pressure_min, | ||
| 599 | pdata->pressure_max ? : ~0, | ||
| 600 | 0, 0); | ||
| 601 | } else { | ||
| 602 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | ||
| 603 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
| 604 | input_set_capability(input_dev, EV_ABS, ABS_PRESSURE); | ||
| 605 | touchscreen_parse_properties(input_dev, false, NULL); | ||
| 606 | if (!input_abs_get_max(input_dev, ABS_PRESSURE)) { | ||
| 607 | dev_err(dev, "Touchscreen pressure is not specified\n"); | ||
| 608 | return -EINVAL; | ||
| 609 | } | ||
| 610 | } | 569 | } |
| 611 | 570 | ||
| 612 | err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET); | 571 | err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET); |
| @@ -655,7 +614,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap, | |||
| 655 | if (err) | 614 | if (err) |
| 656 | return err; | 615 | return err; |
| 657 | 616 | ||
| 658 | err = ad7879_gpio_add(ts, pdata); | 617 | err = ad7879_gpio_add(ts); |
| 659 | if (err) | 618 | if (err) |
| 660 | return err; | 619 | return err; |
| 661 | 620 | ||
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d3aacd534e9c..5c63d25ce84e 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -1585,10 +1585,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) | |||
| 1585 | /* T7 config may have changed */ | 1585 | /* T7 config may have changed */ |
| 1586 | mxt_init_t7_power_cfg(data); | 1586 | mxt_init_t7_power_cfg(data); |
| 1587 | 1587 | ||
| 1588 | release_raw: | ||
| 1589 | kfree(cfg.raw); | ||
| 1590 | release_mem: | 1588 | release_mem: |
| 1591 | kfree(cfg.mem); | 1589 | kfree(cfg.mem); |
| 1590 | release_raw: | ||
| 1591 | kfree(cfg.raw); | ||
| 1592 | return ret; | 1592 | return ret; |
| 1593 | } | 1593 | } |
| 1594 | 1594 | ||
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c index 0ed34ff787ce..28fa1b36f7a5 100644 --- a/drivers/input/touchscreen/ektf2127.c +++ b/drivers/input/touchscreen/ektf2127.c | |||
| @@ -51,7 +51,7 @@ struct ektf2127_ts { | |||
| 51 | struct touchscreen_properties prop; | 51 | struct touchscreen_properties prop; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static void ektf2127_parse_coordinates(const u8* buf, unsigned int touch_count, | 54 | static void ektf2127_parse_coordinates(const u8 *buf, unsigned int touch_count, |
| 55 | struct input_mt_pos *touches) | 55 | struct input_mt_pos *touches) |
| 56 | { | 56 | { |
| 57 | int index = 0; | 57 | int index = 0; |
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 054c2537b392..56cf1a1ea3ea 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c | |||
| @@ -53,7 +53,7 @@ struct gunze { | |||
| 53 | char phys[32]; | 53 | char phys[32]; |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | static void gunze_process_packet(struct gunze* gunze) | 56 | static void gunze_process_packet(struct gunze *gunze) |
| 57 | { | 57 | { |
| 58 | struct input_dev *dev = gunze->dev; | 58 | struct input_dev *dev = gunze->dev; |
| 59 | 59 | ||
| @@ -72,7 +72,7 @@ static void gunze_process_packet(struct gunze* gunze) | |||
| 72 | static irqreturn_t gunze_interrupt(struct serio *serio, | 72 | static irqreturn_t gunze_interrupt(struct serio *serio, |
| 73 | unsigned char data, unsigned int flags) | 73 | unsigned char data, unsigned int flags) |
| 74 | { | 74 | { |
| 75 | struct gunze* gunze = serio_get_drvdata(serio); | 75 | struct gunze *gunze = serio_get_drvdata(serio); |
| 76 | 76 | ||
| 77 | if (data == '\r') { | 77 | if (data == '\r') { |
| 78 | gunze_process_packet(gunze); | 78 | gunze_process_packet(gunze); |
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index b9bc56233ccc..13bd0bf580a7 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c | |||
| @@ -79,7 +79,7 @@ static void inexio_process_data(struct inexio *pinexio) | |||
| 79 | static irqreturn_t inexio_interrupt(struct serio *serio, | 79 | static irqreturn_t inexio_interrupt(struct serio *serio, |
| 80 | unsigned char data, unsigned int flags) | 80 | unsigned char data, unsigned int flags) |
| 81 | { | 81 | { |
| 82 | struct inexio* pinexio = serio_get_drvdata(serio); | 82 | struct inexio *pinexio = serio_get_drvdata(serio); |
| 83 | 83 | ||
| 84 | pinexio->data[pinexio->idx] = data; | 84 | pinexio->data[pinexio->idx] = data; |
| 85 | 85 | ||
| @@ -97,7 +97,7 @@ static irqreturn_t inexio_interrupt(struct serio *serio, | |||
| 97 | 97 | ||
| 98 | static void inexio_disconnect(struct serio *serio) | 98 | static void inexio_disconnect(struct serio *serio) |
| 99 | { | 99 | { |
| 100 | struct inexio* pinexio = serio_get_drvdata(serio); | 100 | struct inexio *pinexio = serio_get_drvdata(serio); |
| 101 | 101 | ||
| 102 | input_get_device(pinexio->dev); | 102 | input_get_device(pinexio->dev); |
| 103 | input_unregister_device(pinexio->dev); | 103 | input_unregister_device(pinexio->dev); |
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index a3707fad4d1c..8278a9058640 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c | |||
| @@ -90,7 +90,7 @@ static void mtouch_process_response(struct mtouch *mtouch) | |||
| 90 | static irqreturn_t mtouch_interrupt(struct serio *serio, | 90 | static irqreturn_t mtouch_interrupt(struct serio *serio, |
| 91 | unsigned char data, unsigned int flags) | 91 | unsigned char data, unsigned int flags) |
| 92 | { | 92 | { |
| 93 | struct mtouch* mtouch = serio_get_drvdata(serio); | 93 | struct mtouch *mtouch = serio_get_drvdata(serio); |
| 94 | 94 | ||
| 95 | mtouch->data[mtouch->idx] = data; | 95 | mtouch->data[mtouch->idx] = data; |
| 96 | 96 | ||
| @@ -110,7 +110,7 @@ static irqreturn_t mtouch_interrupt(struct serio *serio, | |||
| 110 | 110 | ||
| 111 | static void mtouch_disconnect(struct serio *serio) | 111 | static void mtouch_disconnect(struct serio *serio) |
| 112 | { | 112 | { |
| 113 | struct mtouch* mtouch = serio_get_drvdata(serio); | 113 | struct mtouch *mtouch = serio_get_drvdata(serio); |
| 114 | 114 | ||
| 115 | input_get_device(mtouch->dev); | 115 | input_get_device(mtouch->dev); |
| 116 | input_unregister_device(mtouch->dev); | 116 | 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 index 000000000000..f456c1125bd6 --- /dev/null +++ b/drivers/input/touchscreen/raspberrypi-ts.c | |||
| @@ -0,0 +1,227 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Raspberry Pi firmware based touchscreen driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2015, 2017 Raspberry Pi | ||
| 6 | * Copyright (C) 2018 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/io.h> | ||
| 10 | #include <linux/of.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/device.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/bitops.h> | ||
| 15 | #include <linux/dma-mapping.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/input.h> | ||
| 18 | #include <linux/input/mt.h> | ||
| 19 | #include <linux/input-polldev.h> | ||
| 20 | #include <linux/input/touchscreen.h> | ||
| 21 | #include <soc/bcm2835/raspberrypi-firmware.h> | ||
| 22 | |||
| 23 | #define RPI_TS_DEFAULT_WIDTH 800 | ||
| 24 | #define RPI_TS_DEFAULT_HEIGHT 480 | ||
| 25 | |||
| 26 | #define RPI_TS_MAX_SUPPORTED_POINTS 10 | ||
| 27 | |||
| 28 | #define RPI_TS_FTS_TOUCH_DOWN 0 | ||
| 29 | #define RPI_TS_FTS_TOUCH_CONTACT 2 | ||
| 30 | |||
| 31 | #define RPI_TS_POLL_INTERVAL 17 /* 60fps */ | ||
| 32 | |||
| 33 | #define RPI_TS_NPOINTS_REG_INVALIDATE 99 | ||
| 34 | |||
| 35 | struct rpi_ts { | ||
| 36 | struct platform_device *pdev; | ||
| 37 | struct input_polled_dev *poll_dev; | ||
| 38 | struct touchscreen_properties prop; | ||
| 39 | |||
| 40 | void __iomem *fw_regs_va; | ||
| 41 | dma_addr_t fw_regs_phys; | ||
| 42 | |||
| 43 | int known_ids; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct rpi_ts_regs { | ||
| 47 | u8 device_mode; | ||
| 48 | u8 gesture_id; | ||
| 49 | u8 num_points; | ||
| 50 | struct rpi_ts_touch { | ||
| 51 | u8 xh; | ||
| 52 | u8 xl; | ||
| 53 | u8 yh; | ||
| 54 | u8 yl; | ||
| 55 | u8 pressure; /* Not supported */ | ||
| 56 | u8 area; /* Not supported */ | ||
| 57 | } point[RPI_TS_MAX_SUPPORTED_POINTS]; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static void rpi_ts_poll(struct input_polled_dev *dev) | ||
| 61 | { | ||
| 62 | struct input_dev *input = dev->input; | ||
| 63 | struct rpi_ts *ts = dev->private; | ||
| 64 | struct rpi_ts_regs regs; | ||
| 65 | int modified_ids = 0; | ||
| 66 | long released_ids; | ||
| 67 | int event_type; | ||
| 68 | int touchid; | ||
| 69 | int x, y; | ||
| 70 | int i; | ||
| 71 | |||
| 72 | memcpy_fromio(®s, ts->fw_regs_va, sizeof(regs)); | ||
| 73 | /* | ||
| 74 | * We poll the memory based register copy of the touchscreen chip using | ||
| 75 | * the number of points register to know whether the copy has been | ||
| 76 | * updated (we write 99 to the memory copy, the GPU will write between | ||
| 77 | * 0 - 10 points) | ||
| 78 | */ | ||
| 79 | iowrite8(RPI_TS_NPOINTS_REG_INVALIDATE, | ||
| 80 | ts->fw_regs_va + offsetof(struct rpi_ts_regs, num_points)); | ||
| 81 | |||
| 82 | if (regs.num_points == RPI_TS_NPOINTS_REG_INVALIDATE || | ||
| 83 | (regs.num_points == 0 && ts->known_ids == 0)) | ||
| 84 | return; | ||
| 85 | |||
| 86 | for (i = 0; i < regs.num_points; i++) { | ||
| 87 | x = (((int)regs.point[i].xh & 0xf) << 8) + regs.point[i].xl; | ||
| 88 | y = (((int)regs.point[i].yh & 0xf) << 8) + regs.point[i].yl; | ||
| 89 | touchid = (regs.point[i].yh >> 4) & 0xf; | ||
| 90 | event_type = (regs.point[i].xh >> 6) & 0x03; | ||
| 91 | |||
| 92 | modified_ids |= BIT(touchid); | ||
| 93 | |||
| 94 | if (event_type == RPI_TS_FTS_TOUCH_DOWN || | ||
| 95 | event_type == RPI_TS_FTS_TOUCH_CONTACT) { | ||
| 96 | input_mt_slot(input, touchid); | ||
| 97 | input_mt_report_slot_state(input, MT_TOOL_FINGER, 1); | ||
| 98 | touchscreen_report_pos(input, &ts->prop, x, y, true); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | released_ids = ts->known_ids & ~modified_ids; | ||
| 103 | for_each_set_bit(i, &released_ids, RPI_TS_MAX_SUPPORTED_POINTS) { | ||
| 104 | input_mt_slot(input, i); | ||
| 105 | input_mt_report_slot_state(input, MT_TOOL_FINGER, 0); | ||
| 106 | modified_ids &= ~(BIT(i)); | ||
| 107 | } | ||
| 108 | ts->known_ids = modified_ids; | ||
| 109 | |||
| 110 | input_mt_sync_frame(input); | ||
| 111 | input_sync(input); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void rpi_ts_dma_cleanup(void *data) | ||
| 115 | { | ||
| 116 | struct rpi_ts *ts = data; | ||
| 117 | struct device *dev = &ts->pdev->dev; | ||
| 118 | |||
| 119 | dma_free_coherent(dev, PAGE_SIZE, ts->fw_regs_va, ts->fw_regs_phys); | ||
| 120 | } | ||
| 121 | |||
| 122 | static int rpi_ts_probe(struct platform_device *pdev) | ||
| 123 | { | ||
| 124 | struct device *dev = &pdev->dev; | ||
| 125 | struct device_node *np = dev->of_node; | ||
| 126 | struct input_polled_dev *poll_dev; | ||
| 127 | struct device_node *fw_node; | ||
| 128 | struct rpi_firmware *fw; | ||
| 129 | struct input_dev *input; | ||
| 130 | struct rpi_ts *ts; | ||
| 131 | u32 touchbuf; | ||
| 132 | int error; | ||
| 133 | |||
| 134 | fw_node = of_get_parent(np); | ||
| 135 | if (!fw_node) { | ||
| 136 | dev_err(dev, "Missing firmware node\n"); | ||
| 137 | return -ENOENT; | ||
| 138 | } | ||
| 139 | |||
| 140 | fw = rpi_firmware_get(fw_node); | ||
| 141 | of_node_put(fw_node); | ||
| 142 | if (!fw) | ||
| 143 | return -EPROBE_DEFER; | ||
| 144 | |||
| 145 | ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); | ||
| 146 | if (!ts) | ||
| 147 | return -ENOMEM; | ||
| 148 | ts->pdev = pdev; | ||
| 149 | |||
| 150 | ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys, | ||
| 151 | GFP_KERNEL); | ||
| 152 | if (!ts->fw_regs_va) { | ||
| 153 | dev_err(dev, "failed to dma_alloc_coherent\n"); | ||
| 154 | return -ENOMEM; | ||
| 155 | } | ||
| 156 | |||
| 157 | error = devm_add_action_or_reset(dev, rpi_ts_dma_cleanup, ts); | ||
| 158 | if (error) { | ||
| 159 | dev_err(dev, "failed to devm_add_action_or_reset, %d\n", error); | ||
| 160 | return error; | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | touchbuf = (u32)ts->fw_regs_phys; | ||
| 165 | error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, | ||
| 166 | &touchbuf, sizeof(touchbuf)); | ||
| 167 | |||
| 168 | if (error || touchbuf != 0) { | ||
| 169 | dev_warn(dev, "Failed to set touchbuf, %d\n", error); | ||
| 170 | return error; | ||
| 171 | } | ||
| 172 | |||
| 173 | poll_dev = devm_input_allocate_polled_device(dev); | ||
| 174 | if (!poll_dev) { | ||
| 175 | dev_err(dev, "Failed to allocate input device\n"); | ||
| 176 | return -ENOMEM; | ||
| 177 | } | ||
| 178 | ts->poll_dev = poll_dev; | ||
| 179 | input = poll_dev->input; | ||
| 180 | |||
| 181 | input->name = "raspberrypi-ts"; | ||
| 182 | input->id.bustype = BUS_HOST; | ||
| 183 | poll_dev->poll_interval = RPI_TS_POLL_INTERVAL; | ||
| 184 | poll_dev->poll = rpi_ts_poll; | ||
| 185 | poll_dev->private = ts; | ||
| 186 | |||
| 187 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
| 188 | RPI_TS_DEFAULT_WIDTH, 0, 0); | ||
| 189 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
| 190 | RPI_TS_DEFAULT_HEIGHT, 0, 0); | ||
| 191 | touchscreen_parse_properties(input, true, &ts->prop); | ||
| 192 | |||
| 193 | error = input_mt_init_slots(input, RPI_TS_MAX_SUPPORTED_POINTS, | ||
| 194 | INPUT_MT_DIRECT); | ||
| 195 | if (error) { | ||
| 196 | dev_err(dev, "could not init mt slots, %d\n", error); | ||
| 197 | return error; | ||
| 198 | } | ||
| 199 | |||
| 200 | error = input_register_polled_device(poll_dev); | ||
| 201 | if (error) { | ||
| 202 | dev_err(dev, "could not register input device, %d\n", error); | ||
| 203 | return error; | ||
| 204 | } | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static const struct of_device_id rpi_ts_match[] = { | ||
| 210 | { .compatible = "raspberrypi,firmware-ts", }, | ||
| 211 | {}, | ||
| 212 | }; | ||
| 213 | MODULE_DEVICE_TABLE(of, rpi_ts_match); | ||
| 214 | |||
| 215 | static struct platform_driver rpi_ts_driver = { | ||
| 216 | .driver = { | ||
| 217 | .name = "raspberrypi-ts", | ||
| 218 | .of_match_table = rpi_ts_match, | ||
| 219 | }, | ||
| 220 | .probe = rpi_ts_probe, | ||
| 221 | }; | ||
| 222 | module_platform_driver(rpi_ts_driver); | ||
| 223 | |||
| 224 | MODULE_AUTHOR("Gordon Hollingworth"); | ||
| 225 | MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>"); | ||
| 226 | MODULE_DESCRIPTION("Raspberry Pi firmware based touchscreen driver"); | ||
| 227 | MODULE_LICENSE("GPL v2"); | ||
