* [PATCH v2 1/6] mfd: fsl imx25 Touchscreen ADC driver
From: Denis Carikli @ 2014-06-13 15:21 UTC (permalink / raw)
To: Shawn Guo, Samuel Ortiz, Dmitry Torokhov, Jonathan Cameron
Cc: Eric Bénard, Sascha Hauer, linux-arm-kernel, Lee Jones,
linux-input, linux-iio, Fabio Estevam, Lars-Peter Clausen,
Markus Pargmann, Denis Carikli
In-Reply-To: <1402672899-6995-1-git-send-email-denis@eukrea.com>
From: Markus Pargmann <mpa@pengutronix.de>
This is the core driver for imx25 touchscreen/adc driver. The module
has one shared ADC and two different conversion queues which use the
ADC. The two queues are identical. Both can be used for general purpose
ADC but one is meant to be used for touchscreens.
This driver is the core which manages the central components and
registers of the TSC/ADC unit. It manages the IRQs and forwards them to
the correct components.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Denis Carikli <denis@eukrea.com>
---
.../devicetree/bindings/mfd/fsl-imx25-tsadc.txt | 46 ++++
drivers/mfd/Kconfig | 9 +
drivers/mfd/Makefile | 2 +
drivers/mfd/fsl-imx25-tsadc.c | 232 ++++++++++++++++++++
include/linux/mfd/imx25-tsadc.h | 138 ++++++++++++
5 files changed, 427 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt
create mode 100644 drivers/mfd/fsl-imx25-tsadc.c
create mode 100644 include/linux/mfd/imx25-tsadc.h
diff --git a/Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt b/Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt
new file mode 100644
index 0000000..a857af0e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt
@@ -0,0 +1,46 @@
+Freescale mx25 ADC/TSC multifunction device
+
+This device combines two general purpose conversion queues one used for general
+ADC and the other used for touchscreens.
+
+Required properties:
+ - compatible: Should be "fsl,imx25-tsadc".
+ - reg: Memory range of the device.
+ - interrupts: Interrupt for this device as described in
+ interrupts/interrupts.txt
+ - clocks: An 'ipg' clock defined as described in clocks/clock.txt
+ - interrupt-controller: This device is an interrupt controller. It controls
+ the interrupts of both conversion queues.
+ - #interrupt-cells: Should be '<1>'.
+ - #address-cells: Should be '<1>'.
+ - #size-cells: Should be '<1>'.
+ - ranges
+
+This device includes two conversion queues which can be added as subnodes.
+The first queue is for the touchscreen, the second for general purpose ADC.
+
+Example:
+ tscadc: tscadc@50030000 {
+ compatible = "fsl,imx25-tsadc";
+ reg = <0x50030000 0xc>;
+ interrupts = <46>;
+ clocks = <&clks 119>;
+ clock-names = "ipg";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ tsc: tcq@50030400 {
+ compatible = "fsl,imx25-tcq";
+ reg = <0x50030400 0x60>;
+ ...
+ };
+
+ adc: gcq@50030800 {
+ compatible = "fsl,imx25-gcq";
+ reg = <0x50030800 0x60>;
+ ...
+ };
+ };
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ee8204c..73f4e66 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -183,6 +183,15 @@ config MFD_DA9063
Additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_MX25_TSADC
+ tristate "Freescale i.MX25 integrated Touchscreen and ADC unit"
+ depends on ARCH_MXC
+ select REGMAP_MMIO
+ help
+ Enable support for the integrated Touchscreen and ADC unit of the
+ i.MX25 processors. They consist of a conversion queue for general
+ purpose ADC and a queue for Touchscreens.
+
config MFD_MC13XXX
tristate
depends on (SPI_MASTER || I2C)
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8afedba..7ff1013 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
obj-$(CONFIG_TWL6040_CORE) += twl6040.o
+obj-$(CONFIG_MFD_MX25_TSADC) += fsl-imx25-tsadc.o
+
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c
new file mode 100644
index 0000000..10332c2
--- /dev/null
+++ b/drivers/mfd/fsl-imx25-tsadc.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2014 Markus Pargmann, Pengutronix <mpa@pengutronix.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/mfd/imx25-tsadc.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+struct mx25_tsadc_priv {
+ struct regmap *regs;
+ struct irq_domain *domain;
+ struct clk *clk;
+};
+
+static struct regmap_config mx25_tsadc = {
+ .fast_io = true,
+ .max_register = 0x8,
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+struct regmap *mx25_tsadc_get_regmap(struct device *dev)
+{
+ struct platform_device *pdev;
+ struct mx25_tsadc_priv *priv;
+
+ if (!dev)
+ return NULL;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ priv = platform_get_drvdata(pdev);
+ if (IS_ERR_OR_NULL(priv->regs))
+ return NULL;
+
+ return priv->regs;
+}
+EXPORT_SYMBOL(mx25_tsadc_get_regmap);
+
+struct clk *mx25_tsadc_get_ipg(struct device *dev)
+{
+ struct platform_device *pdev;
+ struct mx25_tsadc_priv *priv;
+
+ if (!dev)
+ return NULL;
+
+ pdev = container_of(dev, struct platform_device, dev);
+ priv = platform_get_drvdata(pdev);
+ if (IS_ERR_OR_NULL(priv->clk))
+ return NULL;
+
+ return priv->clk;
+}
+EXPORT_SYMBOL(mx25_tsadc_get_ipg);
+
+static void mx25_tsadc_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ struct mx25_tsadc_priv *priv = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_get_chip(irq);
+ u32 status;
+
+ chained_irq_enter(chip, desc);
+
+ regmap_read(priv->regs, MX25_TSC_TGSR, &status);
+
+ if (status & MX25_TGSR_GCQ_INT)
+ generic_handle_irq(irq_find_mapping(priv->domain, 1));
+
+ if (status & MX25_TGSR_TCQ_INT)
+ generic_handle_irq(irq_find_mapping(priv->domain, 0));
+
+ chained_irq_exit(chip, desc);
+}
+
+static void mx25_tsadc_nop(struct irq_data *d)
+{
+}
+
+static int mx25_tsadc_set_wake_nop(struct irq_data *d, unsigned int state)
+{
+ return 0;
+}
+
+static struct irq_chip mx25_tsadc_irq_chip = {
+ .name = "mx25-tsadc",
+ .irq_ack = mx25_tsadc_nop,
+ .irq_mask = mx25_tsadc_nop,
+ .irq_unmask = mx25_tsadc_nop,
+ .irq_set_wake = mx25_tsadc_set_wake_nop,
+};
+
+static int mx25_tsadc_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct mx25_tsadc_priv *priv = d->host_data;
+
+ irq_set_chip_data(irq, priv);
+ irq_set_chip_and_handler(irq, &mx25_tsadc_irq_chip,
+ handle_level_irq);
+
+
+ set_irq_flags(irq, IRQF_VALID);
+
+ return 0;
+}
+
+static struct irq_domain_ops mx25_tsadc_domain_ops = {
+ .map = mx25_tsadc_domain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static int mx25_tsadc_setup_irq(struct platform_device *pdev,
+ struct mx25_tsadc_priv *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ int irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "Failed to get irq\n");
+ return irq;
+ }
+
+ priv->domain = irq_domain_add_simple(np, 2, 0, &mx25_tsadc_domain_ops,
+ priv);
+ if (!priv->domain) {
+ dev_err(dev, "Failed to add irq domain\n");
+ return -ENOMEM;
+ }
+
+ irq_set_chained_handler(irq, mx25_tsadc_irq_handler);
+ irq_set_handler_data(irq, priv);
+
+ return 0;
+}
+
+static int mx25_tsadc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct mx25_tsadc_priv *priv;
+ struct resource *iores;
+ int ret;
+ void __iomem *iomem;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iomem = devm_ioremap_resource(dev, iores);
+ if (IS_ERR(iomem)) {
+ dev_err(dev, "Failed to remap iomem\n");
+ return PTR_ERR(iomem);
+ }
+
+ priv->regs = regmap_init_mmio(dev, iomem, &mx25_tsadc);
+ if (IS_ERR(priv->regs)) {
+ dev_err(dev, "Failed to initialize regmap\n");
+ return PTR_ERR(priv->regs);
+ }
+
+ priv->clk = devm_clk_get(dev, "ipg");
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "Failed to get ipg clock\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ /* Enable clock and reset the component */
+ regmap_update_bits(priv->regs, MX25_TSC_TGCR, MX25_TGCR_CLK_EN,
+ MX25_TGCR_CLK_EN);
+ regmap_update_bits(priv->regs, MX25_TSC_TGCR, MX25_TGCR_TSC_RST,
+ MX25_TGCR_TSC_RST);
+
+ /* Setup powersaving mode, but enable internal reference voltage */
+ regmap_update_bits(priv->regs, MX25_TSC_TGCR, MX25_TGCR_POWERMODE_MASK,
+ MX25_TGCR_POWERMODE_SAVE);
+ regmap_update_bits(priv->regs, MX25_TSC_TGCR, MX25_TGCR_INTREFEN,
+ MX25_TGCR_INTREFEN);
+
+ ret = mx25_tsadc_setup_irq(pdev, priv);
+ if (ret) {
+ dev_err(dev, "Failed to setup irqs\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ of_platform_populate(np, NULL, NULL, dev);
+
+ dev_info(dev, "i.MX25 Touchscreen and ADC core driver loaded\n");
+
+ return 0;
+}
+
+static const struct of_device_id mx25_tsadc_ids[] = {
+ { .compatible = "fsl,imx25-tsadc", },
+ { /* Sentinel */ }
+};
+
+static struct platform_driver mx25_tsadc_driver = {
+ .driver = {
+ .name = "mx25-tsadc",
+ .owner = THIS_MODULE,
+ .of_match_table = mx25_tsadc_ids,
+ },
+ .probe = mx25_tsadc_probe,
+};
+module_platform_driver(mx25_tsadc_driver);
+
+MODULE_DESCRIPTION("MFD for ADC/TSC for Freescale mx25");
+MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mx25-tsadc");
diff --git a/include/linux/mfd/imx25-tsadc.h b/include/linux/mfd/imx25-tsadc.h
new file mode 100644
index 0000000..6fba341
--- /dev/null
+++ b/include/linux/mfd/imx25-tsadc.h
@@ -0,0 +1,138 @@
+#ifndef _LINUX_INCLUDE_INPUT_IMX25_TSADC_H_
+#define _LINUX_INCLUDE_INPUT_IMX25_TSADC_H_
+
+struct regmap;
+struct device;
+struct clk;
+
+struct regmap *mx25_tsadc_get_regmap(struct device *dev);
+struct clk *mx25_tsadc_get_ipg(struct device *dev);
+
+#define MX25_TSC_TGCR 0x00
+#define MX25_TSC_TGSR 0x04
+#define MX25_TSC_TICR 0x08
+
+/* The same register layout for TC and GC queue */
+#define MX25_ADCQ_FIFO 0x00
+#define MX25_ADCQ_CR 0x04
+#define MX25_ADCQ_SR 0x08
+#define MX25_ADCQ_MR 0x0c
+#define MX25_ADCQ_ITEM_7_0 0x20
+#define MX25_ADCQ_ITEM_15_8 0x24
+#define MX25_ADCQ_CFG(n) (0x40 + ((n) * 0x4))
+
+/* Register values */
+/* Queue Config register */
+#define MX25_ADCQ_MR_MASK 0xffffffff
+
+/* TGCR */
+#define MX25_TGCR_PDBTIME(x) ((x) << 25)
+#define MX25_TGCR_PDBTIME_MASK MX25_TGCR_PDBTIME(0x7f)
+#define MX25_TGCR_PDBEN (1 << 24)
+#define MX25_TGCR_PDEN (1 << 23)
+#define MX25_TGCR_ADCCLKCFG(x) ((x) << 16)
+#define MX25_TGCR_GET_ADCCLK(x) (((x) >> 16) & 0x1f)
+#define MX25_TGCR_INTREFEN (1 << 10)
+#define MX25_TGCR_POWERMODE_MASK (3 << 8)
+#define MX25_TGCR_POWERMODE_SAVE (1 << 8)
+#define MX25_TGCR_POWERMODE_ON (2 << 8)
+#define MX25_TGCR_STLC (1 << 5)
+#define MX25_TGCR_SLPC (1 << 4)
+#define MX25_TGCR_FUNC_RST (1 << 2)
+#define MX25_TGCR_TSC_RST (1 << 1)
+#define MX25_TGCR_CLK_EN (1 << 0)
+
+/* TGSR */
+#define MX25_TGSR_SLP_INT (1 << 2)
+#define MX25_TGSR_GCQ_INT (1 << 1)
+#define MX25_TGSR_TCQ_INT (1 << 0)
+
+/* ADCQ_ITEM_* */
+#define _MX25_ADCQ_ITEM(item, x) ((x) << ((item) * 4))
+#define MX25_ADCQ_ITEM(item, x) ((item) >= 8 ? \
+ _MX25_ADCQ_ITEM((item) - 8, (x)) : _MX25_ADCQ_ITEM((item), (x)))
+
+/* ADCQ_FIFO (TCQFIFO and GCQFIFO) */
+#define MX25_ADCQ_FIFO_DATA(x) (((x) >> 4) & 0xfff)
+#define MX25_ADCQ_FIFO_ID(x) ((x) & 0xf)
+
+/* ADCQ_CR (TCQR and GCQR) */
+#define MX25_ADCQ_CR_PDCFG_LEVEL (1 << 19)
+#define MX25_ADCQ_CR_PDMSK (1 << 18)
+#define MX25_ADCQ_CR_FRST (1 << 17)
+#define MX25_ADCQ_CR_QRST (1 << 16)
+#define MX25_ADCQ_CR_RWAIT_MASK (0xf << 12)
+#define MX25_ADCQ_CR_RWAIT(x) ((x) << 12)
+#define MX25_ADCQ_CR_WMRK_MASK (0xf << 8)
+#define MX25_ADCQ_CR_WMRK(x) ((x) << 8)
+#define MX25_ADCQ_CR_LITEMID_MASK (0xf << 4)
+#define MX25_ADCQ_CR_LITEMID(x) ((x) << 4)
+#define MX25_ADCQ_CR_RPT (1 << 3)
+#define MX25_ADCQ_CR_FQS (1 << 2)
+#define MX25_ADCQ_CR_QSM_MASK 0x3
+#define MX25_ADCQ_CR_QSM_PD 0x1
+#define MX25_ADCQ_CR_QSM_FQS 0x2
+#define MX25_ADCQ_CR_QSM_FQS_PD 0x3
+
+/* ADCQ_SR (TCQSR and GCQSR) */
+#define MX25_ADCQ_SR_FDRY (1 << 15)
+#define MX25_ADCQ_SR_FULL (1 << 14)
+#define MX25_ADCQ_SR_EMPT (1 << 13)
+#define MX25_ADCQ_SR_FDN(x) (((x) >> 8) & 0x1f)
+#define MX25_ADCQ_SR_FRR (1 << 6)
+#define MX25_ADCQ_SR_FUR (1 << 5)
+#define MX25_ADCQ_SR_FOR (1 << 4)
+#define MX25_ADCQ_SR_EOQ (1 << 1)
+#define MX25_ADCQ_SR_PD (1 << 0)
+
+/* ADCQ_MR (TCQMR and GCQMR) */
+#define MX25_ADCQ_MR_FDRY_DMA (1 << 31)
+#define MX25_ADCQ_MR_FER_DMA (1 << 22)
+#define MX25_ADCQ_MR_FUR_DMA (1 << 21)
+#define MX25_ADCQ_MR_FOR_DMA (1 << 20)
+#define MX25_ADCQ_MR_EOQ_DMA (1 << 17)
+#define MX25_ADCQ_MR_PD_DMA (1 << 16)
+#define MX25_ADCQ_MR_FDRY_IRQ (1 << 15)
+#define MX25_ADCQ_MR_FER_IRQ (1 << 6)
+#define MX25_ADCQ_MR_FUR_IRQ (1 << 5)
+#define MX25_ADCQ_MR_FOR_IRQ (1 << 4)
+#define MX25_ADCQ_MR_EOQ_IRQ (1 << 1)
+#define MX25_ADCQ_MR_PD_IRQ (1 << 0)
+
+/* ADCQ_CFG (TICR, TCC0-7,GCC0-7) */
+#define MX25_ADCQ_CFG_SETTLING_TIME(x) ((x) << 24)
+#define MX25_ADCQ_CFG_IGS (1 << 20)
+#define MX25_ADCQ_CFG_NOS_MASK (0xf << 16)
+#define MX25_ADCQ_CFG_NOS(x) (((x) - 1) << 16)
+#define MX25_ADCQ_CFG_WIPER (1 << 15)
+#define MX25_ADCQ_CFG_YNLR (1 << 14)
+#define MX25_ADCQ_CFG_YPLL_HIGH 0
+#define MX25_ADCQ_CFG_YPLL_OFF (1 << 12)
+#define MX25_ADCQ_CFG_YPLL_LOW (3 << 12)
+#define MX25_ADCQ_CFG_XNUR_HIGH 0
+#define MX25_ADCQ_CFG_XNUR_OFF (1 << 10)
+#define MX25_ADCQ_CFG_XNUR_LOW (3 << 10)
+#define MX25_ADCQ_CFG_XPUL_OFF (1 << 9)
+#define MX25_ADCQ_CFG_XPUL_HIGH 0
+#define MX25_ADCQ_CFG_REFP_YP 0
+#define MX25_ADCQ_CFG_REFP_XP (1 << 7)
+#define MX25_ADCQ_CFG_REFP_EXT (2 << 7)
+#define MX25_ADCQ_CFG_REFP_INT (3 << 7)
+#define MX25_ADCQ_CFG_REFP_MASK (3 << 7)
+#define MX25_ADCQ_CFG_IN_XP 0
+#define MX25_ADCQ_CFG_IN_YP (1 << 4)
+#define MX25_ADCQ_CFG_IN_XN (2 << 4)
+#define MX25_ADCQ_CFG_IN_YN (3 << 4)
+#define MX25_ADCQ_CFG_IN_WIPER (4 << 4)
+#define MX25_ADCQ_CFG_IN_AUX0 (5 << 4)
+#define MX25_ADCQ_CFG_IN_AUX1 (6 << 4)
+#define MX25_ADCQ_CFG_IN_AUX2 (7 << 4)
+#define MX25_ADCQ_CFG_REFN_XN 0
+#define MX25_ADCQ_CFG_REFN_YN (1 << 2)
+#define MX25_ADCQ_CFG_REFN_NGND (2 << 2)
+#define MX25_ADCQ_CFG_REFN_NGND2 (3 << 2)
+#define MX25_ADCQ_CFG_REFN_MASK (3 << 2)
+#define MX25_ADCQ_CFG_PENIACK (1 << 1)
+
+
+#endif /* _LINUX_INCLUDE_INPUT_IMX25_TSADC_H_ */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 6/6] ARM: imx_v4_v5_defconfig: Add I.MX25 Touchscreen controller support.
From: Denis Carikli @ 2014-06-13 15:21 UTC (permalink / raw)
To: Shawn Guo, Samuel Ortiz, Dmitry Torokhov, Jonathan Cameron
Cc: Eric Bénard, Sascha Hauer, linux-arm-kernel, Lee Jones,
linux-input, linux-iio, Fabio Estevam, Lars-Peter Clausen,
Markus Pargmann, Denis Carikli
In-Reply-To: <1402672899-6995-1-git-send-email-denis@eukrea.com>
Signed-off-by: Denis Carikli <denis@eukrea.com>
---
arch/arm/configs/imx_v4_v5_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 397f43c..b6b3674 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -98,6 +98,7 @@ CONFIG_KEYBOARD_IMX=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_MX25=y
CONFIG_TOUCHSCREEN_MC13783=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=m
@@ -118,6 +119,7 @@ CONFIG_HWMON=m
CONFIG_SENSORS_MC13783_ADC=m
CONFIG_WATCHDOG=y
CONFIG_IMX2_WDT=y
+CONFIG_MFD_MX25_TSADC=y
CONFIG_MFD_MC13XXX_SPI=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 5/6] ARM: dts: imx25: mbimxsd25: Add touchscreen support.
From: Denis Carikli @ 2014-06-13 15:21 UTC (permalink / raw)
To: Shawn Guo, Samuel Ortiz, Dmitry Torokhov, Jonathan Cameron
Cc: Eric Bénard, Sascha Hauer, linux-arm-kernel, Lee Jones,
linux-input, linux-iio, Fabio Estevam, Lars-Peter Clausen,
Markus Pargmann, Denis Carikli
In-Reply-To: <1402672899-6995-1-git-send-email-denis@eukrea.com>
Signed-off-by: Denis Carikli <denis@eukrea.com>
---
.../imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
index 9797280..047918d 100644
--- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
@@ -70,3 +70,16 @@
lcd-supply = <®_lcd_3v3>;
status = "okay";
};
+
+&tscadc {
+ status = "okay";
+
+ tsc: tcq@50030400 {
+ compatible = "fsl,imx25-tcq";
+ reg = <0x50030400 0x60>;
+ interrupt-parent = <&tscadc>;
+ interrupts = <0>;
+ fsl,wires = <4>;
+ fsl,pen-debounce = <100>;
+ };
+};
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH v2 5/6] ARM: dts: imx25: mbimxsd25: Add touchscreen support.
From: Fabio Estevam @ 2014-06-13 17:10 UTC (permalink / raw)
To: Denis Carikli
Cc: Shawn Guo, Samuel Ortiz, Dmitry Torokhov, Jonathan Cameron,
Eric Bénard, Sascha Hauer,
linux-arm-kernel@lists.infradead.org, Lee Jones, linux-input,
linux-iio, Lars-Peter Clausen, Markus Pargmann
In-Reply-To: <1402672899-6995-6-git-send-email-denis@eukrea.com>
Hi Denis,
On Fri, Jun 13, 2014 at 12:21 PM, Denis Carikli <denis@eukrea.com> wrote:
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> .../imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
> index 9797280..047918d 100644
> --- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
> +++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
> @@ -70,3 +70,16 @@
> lcd-supply = <®_lcd_3v3>;
> status = "okay";
> };
> +
> +&tscadc {
> + status = "okay";
> +
> + tsc: tcq@50030400 {
> + compatible = "fsl,imx25-tcq";
> + reg = <0x50030400 0x60>;
> + interrupt-parent = <&tscadc>;
> + interrupts = <0>;
> + fsl,wires = <4>;
> + fsl,pen-debounce = <100>;
What about just keeping only inside the dts:
&tsadc {
status = "okay";
}
Then the rest could go to the imx25.dtsi.
fsl,wires and fsl,pen-debounce could be overwritten by board dts if needed.
^ permalink raw reply
* Re: [PATCH v5] leds: USB: HID: Add support for MSI GT683R led panels
From: Janne Kanniainen @ 2014-06-13 17:19 UTC (permalink / raw)
To: Johan Hovold
Cc: Jiri Kosina, Bryan Wu, linux-kernel, linux-leds, linux-usb,
linux-input
In-Reply-To: <20140613075411.GG10940@localhost>
> Ok, so you decided to continue setting mode on every LED brightness
> update. That should be fine, but you never answered my question about
> whether it is necessary?
I decided to do it that way because official driver did it as well. I
can check if it is necessary.
> You're almost done. One last update? :)
Yeah, I hope so :)
^ permalink raw reply
* Re: [PATCH v2 3/6] iio: adc: fsl,imx25-gcq driver
From: Peter Meerwald @ 2014-06-13 17:25 UTC (permalink / raw)
To: Denis Carikli
Cc: Shawn Guo, Samuel Ortiz, Dmitry Torokhov, Jonathan Cameron,
Eric Bénard, Sascha Hauer,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Lee Jones,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA, Fabio Estevam,
Lars-Peter Clausen, Markus Pargmann
In-Reply-To: <1402672899-6995-4-git-send-email-denis-fO0SIAKYzcbQT0dZR+AlfA@public.gmane.org>
> This is a conversion queue driver for the mx25 SoC. It uses the central
> ADC which is used by two seperate independent queues. This driver
> prepares different conversion configurations for each possible input.
> For a conversion it creates a conversionqueue of one item with the
> correct configuration for the chosen channel. It then executes the queue
> once and disables the conversion queue afterwards.
comments inline
> Signed-off-by: Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Signed-off-by: Denis Carikli <denis-fO0SIAKYzcbQT0dZR+AlfA@public.gmane.org>
> ---
> .../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 54 ++++
> drivers/iio/adc/Kconfig | 7 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/fsl-imx25-gcq.c | 338 ++++++++++++++++++++
> 4 files changed, 400 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt
> create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt b/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt
> new file mode 100644
> index 0000000..333fc55
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt
> @@ -0,0 +1,54 @@
> +Freescale i.MX25 ADC GCQ device
> +
> +This is a generic conversion queue device that can convert any of the analog
> +inputs using the ADC unit of the i.MX25.
> +
> +Required properties:
> + - compatible: Should be "fsl,imx25-gcq".
> + - reg: Should be the register range of the module.
> + - interrupts: Should be the interrupt number of the module. Typically this is <1>.
> + - interrupt-parent: phandle to the tsadc module of the i.MX25.
> + - #address-cells: Should be <1> (setting for the subnodes)
> + - #size-cells: Should be <0> (setting for the subnodes)
> +
> +Optionally you can define subnodes which define the positive and negative
> +reference voltage for one of the analog inputs.
> +
> +Required properties for subnodes:
> + - reg: Should be the number of the analog input.
> + 0: xp
> + 1: yp
> + 2: xn
> + 3: yn
> + 4: wiper
> + 5: inaux0
> + 6: inaux1
> + 7: inaux2
> + - fsl,adc-refp: Positive reference input
> + 0: yp
> + 1: xp
> + 2: External reference
> + 3: Internal reference
> + - fsl,adc-refn: Negative reference input
> + 0: xn
> + 1: yn
> + 2: ngnd_adc
> + 3: ngnd_adc
> +
> +
> +Example:
> +
> + adc: adc@50030800 {
> + compatible = "fsl,imx25-gcq";
> + reg = <0x50030800 0x60>;
> + interrupt-parent = <&tscadc>;
> + interrupts = <1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + inaux@5 {
> + reg = <5>;
> + fsl,adc-refp = <3>;
> + fsl,adc-refn = <3>;
> + };
> + };
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index a80d236..58efb8d 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -125,6 +125,13 @@ config EXYNOS_ADC
> of SoCs for drivers such as the touchscreen and hwmon to use to share
> this resource.
>
> +config FSL_MX25_ADC
> + tristate "Freescale MX25 ADC driver"
> + depends on MFD_MX25_TSADC
> + help
> + Generic Conversion Queue driver used for general purpose ADC in the
> + MX25. This driver supports single measurements using the MX25 ADC.
> +
> config LP8788_ADC
> tristate "LP8788 ADC driver"
> depends on MFD_LP8788
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 9d60f2d..2767fd6 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
> obj-$(CONFIG_AD799X) += ad799x.o
> obj-$(CONFIG_AT91_ADC) += at91_adc.o
> obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
> +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
> obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
> obj-$(CONFIG_MAX1363) += max1363.o
> obj-$(CONFIG_MCP320X) += mcp320x.o
> diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
> new file mode 100644
> index 0000000..1ae697c
> --- /dev/null
> +++ b/drivers/iio/adc/fsl-imx25-gcq.c
> @@ -0,0 +1,338 @@
> +/*
> + * Copyright 2014 Markus Pargmann, Pengutronix <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + *
> + * This is the driver for the imx25 GCQ (Generic Conversion Queue)
> + * connected to the imx25 ADC.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/iio/iio.h>
> +#include <linux/mfd/imx25-tsadc.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000))
> +
> +enum mx25_gcq_cfgs {
> + MX25_CFG_XP = 0,
> + MX25_CFG_YP,
> + MX25_CFG_XN,
> + MX25_CFG_YN,
> + MX25_CFG_WIPER,
> + MX25_CFG_INAUX0,
> + MX25_CFG_INAUX1,
> + MX25_CFG_INAUX2,
> + MX25_NUM_CFGS,
> +};
> +
> +struct mx25_gcq_priv {
> + struct regmap *regs;
> + struct completion completed;
> + unsigned int settling_time;
> + struct clk *clk;
> + int irq;
> +};
> +
> +#define MX25_IIO_CHAN(chan, id) {\
prefix should be MX25_GCQ_
> + .type = IIO_VOLTAGE,\
> + .indexed = 1,\
> + .channel = chan,\
> + .address = chan,\
don't set .address and use .channel instead
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .datasheet_name = id, \
> + }
> +
> +static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS] = {
> + MX25_IIO_CHAN(0, "xp"),
> + MX25_IIO_CHAN(1, "yp"),
> + MX25_IIO_CHAN(2, "xn"),
> + MX25_IIO_CHAN(3, "yn"),
> + MX25_IIO_CHAN(4, "wiper"),
> + MX25_IIO_CHAN(5, "inaux0"),
> + MX25_IIO_CHAN(6, "inaux1"),
> + MX25_IIO_CHAN(7, "inaux2"),
> +};
> +
> +static void mx25_gcq_disable_eoq(struct mx25_gcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ,
> + MX25_ADCQ_MR_EOQ_IRQ);
> +}
> +
> +static void mx25_gcq_enable_eoq(struct mx25_gcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ, 0);
> +}
> +
> +static irqreturn_t mx25_gcq_irq(int irq, void *data)
> +{
> + struct mx25_gcq_priv *priv = data;
> + u32 stats;
> +
> + regmap_read(priv->regs, MX25_ADCQ_SR, &stats);
> +
> + if (stats & MX25_ADCQ_SR_EOQ) {
> + mx25_gcq_disable_eoq(priv);
> + complete(&priv->completed);
> + }
> +
> + /* Disable conversion queue run */
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
> +
> + /* Acknowledge all possible irqs */
> + regmap_write(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR |
> + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_EOQ |
> + MX25_ADCQ_SR_PD);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int mx25_gcq_read_raw(struct iio_dev *idev,
> + struct iio_chan_spec const *chan, int *val, int *val2,
> + long mask)
> +{
> + struct mx25_gcq_priv *priv = iio_priv(idev);
> + unsigned long timeout;
this should be long, not unsigned long; see return of
wait_for_completion_interruptible_timeout()
> + u32 data;
> + int ret;
> +
> + if (mask != IIO_CHAN_INFO_RAW)
> + return -EINVAL;
> +
> + mutex_lock(&idev->mlock);
> +
> + /* Setup the configuration we want to use */
> + regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0,
> + MX25_ADCQ_ITEM(0, chan->address));
chan->channel
> +
> + mx25_gcq_enable_eoq(priv);
> +
> + /* Trigger queue for one run */
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS,
> + MX25_ADCQ_CR_FQS);
> +
> + timeout = wait_for_completion_interruptible_timeout(&priv->completed,
> + MX25_GCQ_TIMEOUT);
> + if (timeout < 0) {
> + dev_err(&idev->dev, "ADC wait for measurement failed\n");
> + ret = timeout;
> + goto out;
> + } else if (timeout == 0) {
> + dev_err(&idev->dev, "ADC timed out\n");
> + ret = -ETIMEDOUT;
> + goto out;
> + }
> +
> + regmap_read(priv->regs, MX25_ADCQ_FIFO, &data);
this ignores the return value
> + *val = MX25_ADCQ_FIFO_DATA(data);
> +
> + ret = IIO_VAL_INT;
> +
> +out:
> + mutex_unlock(&idev->mlock);
> +
> + return ret;
> +}
> +
> +static const struct iio_info mx25_gcq_iio_info = {
> + .read_raw = mx25_gcq_read_raw,
> +};
> +
> +static const struct regmap_config mx25_gcq_regconfig = {
> + .max_register = 0x5c,
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
> + struct mx25_gcq_priv *priv)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct device_node *child;
> + struct device *dev = &pdev->dev;
> + int ret;
> + int i;
> +
> + /* Setup all configurations registers with a default conversion
> + * configuration for each input */
multi-line comment style
> + for (i = 0; i != MX25_NUM_CFGS; ++i)
> + regmap_write(priv->regs, MX25_ADCQ_CFG(i),
> + MX25_ADCQ_CFG_YPLL_OFF |
> + MX25_ADCQ_CFG_XNUR_OFF |
> + MX25_ADCQ_CFG_XPUL_OFF |
> + MX25_ADCQ_CFG_REFP_INT |
> + (i << 4) |
> + MX25_ADCQ_CFG_REFN_NGND2);
> +
> + for_each_child_of_node(np, child) {
> + u32 reg;
> + u32 refn;
> + u32 refp;
> +
> + ret = of_property_read_u32(child, "reg", ®);
> + if (ret) {
> + dev_err(dev, "Failed to get reg property\n");
> + return ret;
> + }
> + if (reg > MX25_NUM_CFGS) {
>= probably
> + dev_err(dev, "reg value is greater than the number of available configuration registers\n");
> + return -EINVAL;
> + }
> +
> + ret = of_property_read_u32(child, "fsl,adc-refn", &refn);
> + if (ret) {
> + dev_err(dev, "Failed to get fsl,adc-refn property\n");
> + return ret;
> + }
> + if (refn < 0 || refn > 3) {
> + dev_err(dev, "Invalid fsl,adc-refn property value %d\n",
> + refn);
> + return -EINVAL
> + }
> +
> + ret = of_property_read_u32(child, "fsl,adc-refp", &refp);
> + if (ret) {
> + dev_err(dev, "Failed to get fsl,adc-refp property\n");
> + return ret;
> + }
> + if (refp < 0 || refp > 3) {
> + dev_err(dev, "Invalid fsl,adc-refp property value %d\n",
> + refp);
> + return -EINVAL;
> + }
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_CFG(reg),
> + MX25_ADCQ_CFG_REFP_MASK |
> + MX25_ADCQ_CFG_REFN_MASK,
> + (refp << 7) | (refn << 2));
> + }
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR,
> + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST,
> + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST);
> +
> + regmap_write(priv->regs, MX25_ADCQ_CR,
> + MX25_ADCQ_CR_PDMSK |
> + MX25_ADCQ_CR_QSM_FQS);
> +
> + return 0;
> +}
> +
> +static int mx25_gcq_probe(struct platform_device *pdev)
> +{
> + struct iio_dev *idev;
> + struct mx25_gcq_priv *priv;
> + struct resource *res;
> + struct device *dev = &pdev->dev;
> + int ret;
> + void __iomem *mem;
> +
> + idev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
> + if (!idev)
> + return -ENOMEM;
> +
> + priv = iio_priv(idev);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mem = devm_ioremap_resource(dev, res);
> + if (!mem)
> + return -ENOMEM;
> +
> + priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_gcq_regconfig);
> + if (IS_ERR(priv->regs)) {
> + dev_err(dev, "Failed to initialize regmap\n");
> + return PTR_ERR(priv->regs);
> + }
> +
> + init_completion(&priv->completed);
> +
> + ret = mx25_gcq_setup_cfgs(pdev, priv);
> + if (ret)
> + goto err_irq_free;
> +
> + priv->clk = mx25_tsadc_get_ipg(pdev->dev.parent);
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + dev_err(dev, "Failed to enable clock\n");
> + return ret;
> + }
> +
> + priv->irq = platform_get_irq(pdev, 0);
> + if (priv->irq <= 0) {
> + dev_err(dev, "Failed to get IRQ\n");
> + err = priv->irq;
> + goto err_clk_unprepare;
> + }
> +
> + ret = request_irq(priv->irq, mx25_gcq_irq, NULL, pdev->name,
> + priv);
> + if (ret) {
> + dev_err(dev, "Failed requesting IRQ\n");
> + goto err_clk_unprepare;
> + }
> +
> + idev->dev.parent = &pdev->dev;
> + idev->channels = mx25_gcq_channels;
> + idev->num_channels = ARRAY_SIZE(mx25_gcq_channels);
> + idev->info = &mx25_gcq_iio_info;
> +
> + ret = iio_device_register(idev);
> + if (ret) {
> + dev_err(dev, "Failed to register iio device\n");
> + goto err_irq_free;
> + }
> +
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +err_irq_free:
> + free_irq(priv->irq, (void *)priv);
> +
> +err_clk_unprepare:
> + clk_disable_unprepare(priv->clk);
> +
> + return ret;
> +}
> +
> +static int mx25_gcq_remove(struct platform_device *pdev)
> +{
> + struct mx25_gcq_priv *priv = platform_get_drvdata(pdev);
> + struct iio_dev *idev = iio_priv_to_dev(pdev);
> +
> + iio_device_unregister(idev);
> + free_irq(priv->irq, (void *)priv);
> + clk_disable_unprepare(priv->clk);
> +
> + return 0;
> +}
> +
> +static struct of_device_id mx25_gcq_ids[] = {
> + { .compatible = "fsl,imx25-gcq", },
> + { /* Senitel */ }
Sentinel
> +};
> +
> +static struct platform_driver mx25_gcq_driver = {
> + .driver = {
> + .name = "mx25-gcq",
> + .owner = THIS_MODULE,
> + .of_match_table = mx25_gcq_ids,
> + },
> + .probe = mx25_gcq_probe,
> + .remove = mx25_gcq_remove,
> +};
> +module_platform_driver(mx25_gcq_driver);
> +
> +MODULE_DESCRIPTION("ADC driver for Freescale mx25");
> +MODULE_AUTHOR("Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
>
--
Peter Meerwald
+43-664-2444418 (mobile)
^ permalink raw reply
* [PATCH] Input - wacom: remove phys field in struct wacom
From: Benjamin Tissoires @ 2014-06-13 20:29 UTC (permalink / raw)
To: Dmitry Torokhov, Ping Cheng, Jason Gerecke; +Cc: linux-input, linux-kernel
This field is not used, remove it.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom.h | 1 -
drivers/input/tablet/wacom_sys.c | 2 --
2 files changed, 3 deletions(-)
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 9ebf0ed..70b1e71 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -114,7 +114,6 @@ struct wacom {
struct mutex lock;
struct work_struct work;
bool open;
- char phys[32];
struct wacom_led {
u8 select[2]; /* status led selector (0..3) */
u8 llv; /* status led brightness no button (1..127) */
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2c613cd..94096fd 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1323,8 +1323,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->intf = intf;
mutex_init(&wacom->lock);
INIT_WORK(&wacom->work, wacom_wireless_work);
- usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
- strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
endpoint = &intf->cur_altsetting->endpoint[0].desc;
--
1.9.0
^ permalink raw reply related
* [PATCH] Input - wacom: put a flag when the led are initialized
From: Benjamin Tissoires @ 2014-06-13 20:29 UTC (permalink / raw)
To: Dmitry Torokhov, Ping Cheng, Jason Gerecke; +Cc: linux-input, linux-kernel
This solves a bug with the wireless receiver:
- at plug, the wireless receiver does not know which Wacom device it is
connected to, so it does not actually creates all the LEDs
- when the tablet connects, wacom->wacom_wac.features.type is set to the
proper device so that wacom_wac can understand the packets
- when the receiver is unplugged, it detects that a LED should have been
created (based on wacom->wacom_wac.features.type) and tries to remove
it: crash when removing the sysfs group.
Side effect, we can now safely call several times wacom_destroy_leds().
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/tablet/wacom.h | 1 +
drivers/input/tablet/wacom_sys.c | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 70b1e71..f13ad31 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -120,6 +120,7 @@ struct wacom {
u8 hlv; /* status led brightness button pressed (1..127) */
u8 img_lum; /* OLED matrix display brightness */
} led;
+ bool led_initialized;
struct power_supply battery;
};
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 94096fd..7087b33 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1016,12 +1016,18 @@ static int wacom_initialize_leds(struct wacom *wacom)
return error;
}
wacom_led_control(wacom);
+ wacom->led_initialized = true;
return 0;
}
static void wacom_destroy_leds(struct wacom *wacom)
{
+ if (!wacom->led_initialized)
+ return;
+
+ wacom->led_initialized = false;
+
switch (wacom->wacom_wac.features.type) {
case INTUOS4S:
case INTUOS4:
--
1.9.0
^ permalink raw reply related
* [PATCH] Revert "Input: wacom - testing result shows get_report is unnecessary."
From: Benjamin Tissoires @ 2014-06-13 20:32 UTC (permalink / raw)
To: Dmitry Torokhov, Aristeu Rozanski, Ping Cheng, Jason Gerecke
Cc: linux-input, linux-kernel
This reverts commit 1b2faaf7e219fc2905d75afcd4c815e5d39eda80.
The Intuos4 series presents a bug in which it hangs if it receives
a set feature command while switching to the enhanced mode.
This bug is triggered when plugging an Intuos 4 while having
a gnome user session up and running.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
Hi Aris,
actually, you bisected the bug, so can I consider that I have your signed-off-by?
Cheers,
Benjamin
drivers/input/tablet/wacom_sys.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 7087b33..319a3ff 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -536,6 +536,9 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
+ if (error >= 0)
+ error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
+ report_id, rep_data, length, 1);
} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
kfree(rep_data);
--
1.9.0
^ permalink raw reply related
* Re: [PATCH] Input - wacom: remove phys field in struct wacom
From: Dmitry Torokhov @ 2014-06-13 20:35 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: Ping Cheng, Jason Gerecke, linux-input, linux-kernel
In-Reply-To: <1402691344-26196-1-git-send-email-benjamin.tissoires@redhat.com>
On Fri, Jun 13, 2014 at 04:29:04PM -0400, Benjamin Tissoires wrote:
> This field is not used, remove it.
We must have lost the assignment, but it should be assigned to phys of
corresponding input device.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
> drivers/input/tablet/wacom.h | 1 -
> drivers/input/tablet/wacom_sys.c | 2 --
> 2 files changed, 3 deletions(-)
>
> diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
> index 9ebf0ed..70b1e71 100644
> --- a/drivers/input/tablet/wacom.h
> +++ b/drivers/input/tablet/wacom.h
> @@ -114,7 +114,6 @@ struct wacom {
> struct mutex lock;
> struct work_struct work;
> bool open;
> - char phys[32];
> struct wacom_led {
> u8 select[2]; /* status led selector (0..3) */
> u8 llv; /* status led brightness no button (1..127) */
> diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
> index 2c613cd..94096fd 100644
> --- a/drivers/input/tablet/wacom_sys.c
> +++ b/drivers/input/tablet/wacom_sys.c
> @@ -1323,8 +1323,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
> wacom->intf = intf;
> mutex_init(&wacom->lock);
> INIT_WORK(&wacom->work, wacom_wireless_work);
> - usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
> - strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
>
> endpoint = &intf->cur_altsetting->endpoint[0].desc;
>
> --
> 1.9.0
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input - wacom: remove phys field in struct wacom
From: Benjamin Tissoires @ 2014-06-13 20:48 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Ping Cheng, Jason Gerecke, linux-input, linux-kernel
In-Reply-To: <20140613203545.GA31651@core.coreip.homeip.net>
On Jun 13 2014 or thereabouts, Dmitry Torokhov wrote:
> On Fri, Jun 13, 2014 at 04:29:04PM -0400, Benjamin Tissoires wrote:
> > This field is not used, remove it.
>
> We must have lost the assignment, but it should be assigned to phys of
> corresponding input device.
hehe. Even in 2007, when the files moved under drivers/input/tablet,
there is no mention of assigning input_dev->phys :)
I can send a patch to fix the other way around if you prefer (add
input_dev->phys).
Cheers,
Benjamin
>
> >
> > Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> > ---
> > drivers/input/tablet/wacom.h | 1 -
> > drivers/input/tablet/wacom_sys.c | 2 --
> > 2 files changed, 3 deletions(-)
> >
> > diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
> > index 9ebf0ed..70b1e71 100644
> > --- a/drivers/input/tablet/wacom.h
> > +++ b/drivers/input/tablet/wacom.h
> > @@ -114,7 +114,6 @@ struct wacom {
> > struct mutex lock;
> > struct work_struct work;
> > bool open;
> > - char phys[32];
> > struct wacom_led {
> > u8 select[2]; /* status led selector (0..3) */
> > u8 llv; /* status led brightness no button (1..127) */
> > diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
> > index 2c613cd..94096fd 100644
> > --- a/drivers/input/tablet/wacom_sys.c
> > +++ b/drivers/input/tablet/wacom_sys.c
> > @@ -1323,8 +1323,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
> > wacom->intf = intf;
> > mutex_init(&wacom->lock);
> > INIT_WORK(&wacom->work, wacom_wireless_work);
> > - usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
> > - strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
> >
> > endpoint = &intf->cur_altsetting->endpoint[0].desc;
> >
> > --
> > 1.9.0
> >
>
> --
> Dmitry
^ permalink raw reply
* Re: [PATCH] Revert "Input: wacom - testing result shows get_report is unnecessary."
From: Aristeu Rozanski @ 2014-06-13 20:50 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Dmitry Torokhov, Ping Cheng, Jason Gerecke, linux-input,
linux-kernel
In-Reply-To: <1402691538-26392-1-git-send-email-benjamin.tissoires@redhat.com>
On Fri, Jun 13, 2014 at 04:32:18PM -0400, Benjamin Tissoires wrote:
> This reverts commit 1b2faaf7e219fc2905d75afcd4c815e5d39eda80.
>
> The Intuos4 series presents a bug in which it hangs if it receives
> a set feature command while switching to the enhanced mode.
> This bug is triggered when plugging an Intuos 4 while having
> a gnome user session up and running.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>
> Hi Aris,
>
> actually, you bisected the bug, so can I consider that I have your signed-off-by?
Yes, my apologies, I ended up losing track of this and didn't send
earlier.
Signed-off-by: Aristeu Rozanski <aris@redhat.com>
> drivers/input/tablet/wacom_sys.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
> index 7087b33..319a3ff 100644
> --- a/drivers/input/tablet/wacom_sys.c
> +++ b/drivers/input/tablet/wacom_sys.c
> @@ -536,6 +536,9 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
>
> error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
> report_id, rep_data, length, 1);
> + if (error >= 0)
> + error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
> + report_id, rep_data, length, 1);
> } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
>
> kfree(rep_data);
> --
> 1.9.0
>
--
Aristeu
^ permalink raw reply
* Re: [PATCH] Input - wacom: remove phys field in struct wacom
From: Benjamin Tissoires @ 2014-06-13 20:55 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Ping Cheng, Jason Gerecke, linux-input, linux-kernel
In-Reply-To: <20140613204826.GA30355@mail.corp.redhat.com>
On Jun 13 2014 or thereabouts, Benjamin Tissoires wrote:
> On Jun 13 2014 or thereabouts, Dmitry Torokhov wrote:
> > On Fri, Jun 13, 2014 at 04:29:04PM -0400, Benjamin Tissoires wrote:
> > > This field is not used, remove it.
> >
> > We must have lost the assignment, but it should be assigned to phys of
> > corresponding input device.
>
> hehe. Even in 2007, when the files moved under drivers/input/tablet,
> there is no mention of assigning input_dev->phys :)
>
> I can send a patch to fix the other way around if you prefer (add
> input_dev->phys).
>
Actually, I found the culprit:
$ git describe c5b7c7c395a34f12cdf246d66c1feeff2933d584
v2.6.14-21-gc5b7c7c
---> Thu Sep 15 02:01:47 2005
I should have wait one more year to fix it :)
No one complain about it for nearly 10 years, so I am not sure it will
help assigning the ->phys field of input_dev.
It's your call, Dmitry.
Cheers,
Benjamin
^ permalink raw reply
* [PATCH v3 0/2] Input: Support in the elantech driver of the trackpoint present on for instance Lenovo L530
From: Ulrik De Bie @ 2014-06-13 21:21 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: stable, linux-input, Hans de Goede, David Herrmann,
ulrik.debie-os
In-Reply-To: <20140613205547.GA5244@lantern>
Patch 1 adds support for trackpoint on elantech driver for v3 models.
Patch 2 adds a psmouse_reset when the elantech probes fails. Patch 2 depends on Patch 1.
Changes since v2:
* psmouse_reset change is now moved to a separate patch
* comments/white spaces/newlines cleanup
* Unexpected trackpoint message warning now only printed once
* removed some unnecessary casts
* Deleted etd->trackpoint_present and use instead etd->tp_dev to indicate the
presence of a trackpoint
* Propagate the error when elantech_init fails
Changes since v1:
* New patch now with reference to 3.14rc1
* Added etd->trackpoint_present to indicate presence of trackpoint (based
on MSB of etd->capabilities[0])
* trackpoint will only be registered now when MSB of etd->capabilities[0] is
set; got confirmation that this is the indicator of trackpoint
* Added input_unregister_device/input_free_device in elantech_disconnect()
* Fixed a bug in cleaning up when elantech_init fails
* Rename commit to be more specific (now also applicable to future elantech
v3 models with trackpoint)
* input device name 'TPPS/2 IBM TrackPoint' changed to
'Elantech PS/2 TrackPoint', this patch is not ibm/lenovo specific!
* dev2 renamed to tp_dev to indicate that this is the trackpoint device
* etd->phys renamed to etd->tp_phys
* Added Lenovo 530 and Fujitsu H730 to the laptop list because those are now
also known.
* Added psmouse_reset at the end of elantech_init when it fails
* Added warning when trackpoint packets are received with no trackpoint detected
The patches are also available from:
https://github.com/ulrikdb/linux/commit/f8570efe466fb835b76f11fdbaf277fea9999a42
https://github.com/ulrikdb/linux/commit/69ab8ef8cf96237a90b393607727d080930d4469
Ulrik De Bie (2):
elantech: Add support for trackpoint found on some v3 models
elantech: Call psmouse_reset when elantech probe fails
drivers/input/mouse/elantech.c | 120 +++++++++++++++++++++++++++++++++++++++--
drivers/input/mouse/elantech.h | 3 ++
2 files changed, 119 insertions(+), 4 deletions(-)
--
2.0.0
^ permalink raw reply
* [PATCH v3 1/2] elantech: Add support for trackpoint found on some v3 models
From: Ulrik De Bie @ 2014-06-13 21:21 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: stable, linux-input, Hans de Goede, David Herrmann,
ulrik.debie-os
In-Reply-To: <1402694473-11518-1-git-send-email-ulrik.debie-os@e2big.org>
Some elantech v3 touchpad equipped laptops also have a trackpoint, before
this commit, these give sync errors. With this patch, the trackpoint is
provided as another input device: 'Elantech PS/2 TrackPoint'
The patch will also output messages that do not follow the expected pattern.
In the mean time I've seen 2 unknown packets occasionally:
0x04 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x00
I don't know what those are for, but they can be safely ignored.
Currently all packets that are not known to v3 touchpad and where
packet[3] (the fourth byte) lowest nibble is 6 are now recognized as
PACKET_TRACKPOINT and processed by the new elantech_report_trackpoint.
This has been verified to work on a laptop Lenovo L530 where the
touchpad/trackpoint combined identify themselves as:
psmouse serio1: elantech: assuming hardware version 3 (with firmware version 0x350f02)
psmouse serio1: elantech: Synaptics capabilities query result 0xb9, 0x15, 0x0c.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
---
drivers/input/mouse/elantech.c | 119 +++++++++++++++++++++++++++++++++++++++--
drivers/input/mouse/elantech.h | 3 ++
2 files changed, 118 insertions(+), 4 deletions(-)
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index ee2a04d..0eb185b 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -403,6 +403,71 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
input_sync(dev);
}
+static void elantech_report_trackpoint(struct psmouse *psmouse,
+ int packet_type)
+{
+ /*
+ * byte 0: 0 0 ~sx ~sy 0 M R L
+ * byte 1: sx 0 0 0 0 0 0 0
+ * byte 2: sy 0 0 0 0 0 0 0
+ * byte 3: 0 0 sy sx 0 1 1 0
+ * byte 4: x7 x6 x5 x4 x3 x2 x1 x0
+ * byte 5: y7 y6 y5 y4 y3 y2 y1 y0
+ *
+ * x and y are written in two's complement spread
+ * over 9 bits with sx/sy the relative top bit and
+ * x7..x0 and y7..y0 the lower bits.
+ * The sign of y is opposite to what the input driver
+ * expects for a relative movement
+ */
+
+ struct elantech_data *etd = psmouse->private;
+ struct input_dev *tp_dev = etd->tp_dev;
+ unsigned char *packet = psmouse->packet;
+ int x, y;
+ u32 t;
+
+ if (!tp_dev) {
+ static bool __section(.data.unlikely) __warned;
+
+ if (!__warned) {
+ __warned = true;
+ psmouse_err(psmouse, "Unexpected trackpoint message\n");
+ if (etd->debug == 1)
+ elantech_packet_dump(psmouse);
+ }
+
+ return;
+ }
+
+ input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
+ input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
+ input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
+
+ x = ((packet[1] & 0x80) ? 0U : 0xFFFFFF00U) | packet[4];
+ y = -(int)(((packet[2] & 0x80) ? 0U : 0xFFFFFF00U) | packet[5]);
+
+ input_report_rel(tp_dev, REL_X, x);
+ input_report_rel(tp_dev, REL_Y, y);
+
+ t = (((u32)packet[0] & 0xF8) << 24) | ((u32)packet[1] << 16)
+ | (u32)packet[2] << 8 | (u32)packet[3];
+ switch (t) {
+ case 0x00808036U:
+ case 0x10008026U:
+ case 0x20800016U:
+ case 0x30000006U:
+ break;
+ default:
+ /* Dump unexpected packet sequences if debug=1 (default) */
+ if (etd->debug == 1)
+ elantech_packet_dump(psmouse);
+ break;
+ }
+
+ input_sync(tp_dev);
+}
+
/*
* Interpret complete data packets and report absolute mode input events for
* hardware version 3. (12 byte packets for two fingers)
@@ -715,6 +780,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
return PACKET_V3_TAIL;
+ if ((packet[3] & 0x0f) == 0x06)
+ return PACKET_TRACKPOINT;
}
return PACKET_UNKNOWN;
@@ -798,7 +865,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
if (packet_type == PACKET_UNKNOWN)
return PSMOUSE_BAD_DATA;
- elantech_report_absolute_v3(psmouse, packet_type);
+ if (packet_type == PACKET_TRACKPOINT)
+ elantech_report_trackpoint(psmouse, packet_type);
+ else
+ elantech_report_absolute_v3(psmouse, packet_type);
break;
case 4:
@@ -1018,8 +1088,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
* Asus UX31 0x361f00 20, 15, 0e clickpad
* Asus UX32VD 0x361f02 00, 15, 0e clickpad
* Avatar AVIU-145A2 0x361f00 ? clickpad
+ * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
* Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
* Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
+ * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*)
* Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
* Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
* Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
@@ -1029,6 +1101,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
* Samsung RF710 0x450f00 ? 2 hw buttons
* System76 Pangolin 0x250f01 ? 2 hw buttons
* (*) + 3 trackpoint buttons
+ * (**) + 0 trackpoint buttons
+ * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps
*/
static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
{
@@ -1324,6 +1398,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
*/
static void elantech_disconnect(struct psmouse *psmouse)
{
+ struct elantech_data *etd = psmouse->private;
+
+ if (etd->tp_dev)
+ input_unregister_device(etd->tp_dev);
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
&elantech_attr_group);
kfree(psmouse->private);
@@ -1438,8 +1516,10 @@ static int elantech_set_properties(struct elantech_data *etd)
int elantech_init(struct psmouse *psmouse)
{
struct elantech_data *etd;
- int i, error;
+ int i;
+ int error = -EINVAL;
unsigned char param[3];
+ struct input_dev *tp_dev;
psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
if (!etd)
@@ -1498,14 +1578,45 @@ int elantech_init(struct psmouse *psmouse)
goto init_fail;
}
+ /* The MSB indicates the presence of the trackpoint */
+ if ((etd->capabilities[0] & 0x80) == 0x80) {
+ tp_dev = input_allocate_device();
+ if (!tp_dev)
+ goto init_fail_tp_alloc;
+
+ etd->tp_dev = tp_dev;
+ snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1",
+ psmouse->ps2dev.serio->phys);
+ tp_dev->phys = etd->tp_phys;
+ tp_dev->name = "Elantech PS/2 TrackPoint";
+ tp_dev->id.bustype = BUS_I8042;
+ tp_dev->id.vendor = 0x0002;
+ tp_dev->id.product = PSMOUSE_ELANTECH;
+ tp_dev->id.version = 0x0000;
+ tp_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+ tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ tp_dev->relbit[BIT_WORD(REL_X)] =
+ BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
+ BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+ BIT_MASK(BTN_RIGHT);
+ error = input_register_device(etd->tp_dev);
+ if (error < 0)
+ goto init_fail_tp_reg;
+ }
+
psmouse->protocol_handler = elantech_process_byte;
psmouse->disconnect = elantech_disconnect;
psmouse->reconnect = elantech_reconnect;
psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
return 0;
-
+ init_fail_tp_reg:
+ input_free_device(tp_dev);
+ init_fail_tp_alloc:
+ sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
+ &elantech_attr_group);
init_fail:
kfree(etd);
- return -1;
+ return error;
}
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index 9e0e2a1..e410336 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -94,6 +94,7 @@
#define PACKET_V4_HEAD 0x05
#define PACKET_V4_MOTION 0x06
#define PACKET_V4_STATUS 0x07
+#define PACKET_TRACKPOINT 0x08
/*
* track up to 5 fingers for v4 hardware
@@ -114,6 +115,8 @@ struct finger_pos {
};
struct elantech_data {
+ struct input_dev *tp_dev; /* Relative device for trackpoint */
+ char tp_phys[32];
unsigned char reg_07;
unsigned char reg_10;
unsigned char reg_11;
--
2.0.0
^ permalink raw reply related
* [PATCH v3 2/2] elantech: Call psmouse_reset when elantech probe fails
From: Ulrik De Bie @ 2014-06-13 21:21 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: stable, linux-input, Hans de Goede, David Herrmann,
ulrik.debie-os
In-Reply-To: <1402694473-11518-1-git-send-email-ulrik.debie-os@e2big.org>
Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
---
drivers/input/mouse/elantech.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 0eb185b..fa150d9 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1617,6 +1617,7 @@ int elantech_init(struct psmouse *psmouse)
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
&elantech_attr_group);
init_fail:
+ psmouse_reset(psmouse);
kfree(etd);
return error;
}
--
2.0.0
^ permalink raw reply related
* Re: [PATCH v2 2/2] Add support for Compact (Bluetooth|USB) keyboard with Trackpoint
From: Antonio Ospite @ 2014-06-13 21:45 UTC (permalink / raw)
To: Jamie Lentin; +Cc: Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <alpine.DEB.2.02.1406112253440.4059@marmot.wormnet.eu>
On Thu, 12 Jun 2014 09:56:41 +0100 (BST)
Jamie Lentin <jm@lentin.co.uk> wrote:
> On Wed, 11 Jun 2014, Antonio Ospite wrote:
>
[...]
> >> +static int tpcompactkbd_input_mapping(struct hid_device *hdev,
> >
> > Maybe name these functions like tpkbd_input_mapping_compact()?
> >
> > This way the namespace is more consistent, and follows the logic of
> > patch 1/2 more closely.
> >
> > Use this scheme at least for functions which have a _tp() counterpart.
>
> Previously the tpkbd driver had various functions marked "_tp" to indicate
> that it's for the "mouse" half of the keyboard as the kernel sees it,
> however it does nothing special with the keyboard half. I was intending
> (somewhat sloppily) to repurpose this into having versions of each
> function for each keyboard, and a common function to switch between them.
> Should make it fairly easy to add extra keyboards in the future.
>
> The problem, as ever, is choosing decent names for them. It should
> probably be either:-
>
> * tpkbd_input_mapping_usbkbd
> * tpkbd_input_mapping_compactkbd
> ...and tpkbd_input_mapping switches between them
>
> or rename the driver to hid-lenovo and do:-
>
I am OK with a rename. Most files in drivers/hid are per-vendor after
all. Jiri?
> * lenovo_input_mapping_tpkbd
> * lenovo_input_mapping_compacttp
I think you meant lenovo_input_mapping_compactkbd ? :)
> ...and lenovo_input_mapping switches between them
>
> The latter seems a bit too invasive, but I'm not sure how obvious with the
> former that it'd be that the "Compact USB keyboard" is in-fact a
> compactkbd not a usbkbd. The former is probably what I'll go for unless
> you have any thoughts.
>
[...]
Ciao,
Antonio
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* Re: [PATCH] input: touchscreen: ti_am335x_tsc: warn about incorrect spelling
From: Felipe Balbi @ 2014-06-14 0:23 UTC (permalink / raw)
To: Felipe Balbi, Andrew Morton
Cc: Mark Rutland, Sebastian Andrzej Siewior, dmitry.torokhov,
rob.herring, Pawel.Moll, swarren, ijc+devicetree, bcousson,
Tony Lindgren, devicetree, Linux OMAP Mailing List, linux-input
In-Reply-To: <1384788541-16338-1-git-send-email-balbi@ti.com>
[-- Attachment #1: Type: text/plain, Size: 1485 bytes --]
Hi,
Here's another patch which has been pending for months.
On Mon, Nov 18, 2013 at 09:29:01AM -0600, Felipe Balbi wrote:
> In the hopes that people run new kernels on
> their devices, let's add a warning message
> asking users to have their DTS file fixed.
>
> The goal is that by Linux 4.0 we will be
> able to remove support for the bogus version
> of our touchscreen's DTS.
>
> Suggested-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> ---
>
> Here you go, I've added your Suggested-by Mark,
> if you wish I can remove or change to something
> else.
>
> cheers
>
> drivers/input/touchscreen/ti_am335x_tsc.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
> index b61df9d..91302cd 100644
> --- a/drivers/input/touchscreen/ti_am335x_tsc.c
> +++ b/drivers/input/touchscreen/ti_am335x_tsc.c
> @@ -354,9 +354,12 @@ static int titsc_parse_dt(struct platform_device *pdev,
> */
> err = of_property_read_u32(node, "ti,coordinate-readouts",
> &ts_dev->coordinate_readouts);
> - if (err < 0)
> + if (err < 0) {
> + dev_warn(&pdev->dev, "please use 'ti,coordinate-readouts' instead\n");
> err = of_property_read_u32(node, "ti,coordiante-readouts",
> &ts_dev->coordinate_readouts);
> + }
> +
> if (err < 0)
> return err;
>
> --
> 1.8.4.GIT
>
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH] Input - wacom: put a flag when the led are initialized
From: Ping Cheng @ 2014-06-14 0:28 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Dmitry Torokhov, Jason Gerecke, linux-input,
linux-kernel@vger.kernel.org
In-Reply-To: <1402691372-26282-1-git-send-email-benjamin.tissoires@redhat.com>
Hi Benjamin,
On Fri, Jun 13, 2014 at 1:29 PM, Benjamin Tissoires
<benjamin.tissoires@redhat.com> wrote:
> This solves a bug with the wireless receiver:
Your patch does get rid of the crash. But, it does not fix it at the
root cause.
> - at plug, the wireless receiver does not know which Wacom device it is
> connected to, so it does not actually creates all the LEDs
This is the root cause - LEDs are not created for wireless devices.
Neither here, nor later when a real device is connected.
> - when the tablet connects, wacom->wacom_wac.features.type is set to the
> proper device so that wacom_wac can understand the packets
LEDs are not created for any wireless devices since we don't call
wacom_initialize_leds() when real tablets are connected.
> - when the receiver is unplugged, it detects that a LED should have been
> created (based on wacom->wacom_wac.features.type) and tries to remove
> it: crash when removing the sysfs group.
When receiver is unplugged, it remembers the last tablet that
connected to it. If that tablet supports LEDs, wacom_destroy_leds() is
called. But, no LEDs were initialized. That's why it crashes.
> Side effect, we can now safely call several times wacom_destroy_leds().
led_initialized will never be true if we keep wacom_initialize_leds()
inside probe().
To make initialize_leds() and desctroy_leds() work for wireless
devices, we need to move them to wacom_wireless_work() where we know
what type of tablet is connected/disconnected.
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Thank you for your support. But, sorry
NAKed-by: Ping Cheng <pingc@wacom.com>
Ping
> ---
> drivers/input/tablet/wacom.h | 1 +
> drivers/input/tablet/wacom_sys.c | 6 ++++++
> 2 files changed, 7 insertions(+)
>
> diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
> index 70b1e71..f13ad31 100644
> --- a/drivers/input/tablet/wacom.h
> +++ b/drivers/input/tablet/wacom.h
> @@ -120,6 +120,7 @@ struct wacom {
> u8 hlv; /* status led brightness button pressed (1..127) */
> u8 img_lum; /* OLED matrix display brightness */
> } led;
> + bool led_initialized;
> struct power_supply battery;
> };
>
> diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
> index 94096fd..7087b33 100644
> --- a/drivers/input/tablet/wacom_sys.c
> +++ b/drivers/input/tablet/wacom_sys.c
> @@ -1016,12 +1016,18 @@ static int wacom_initialize_leds(struct wacom *wacom)
> return error;
> }
> wacom_led_control(wacom);
> + wacom->led_initialized = true;
>
> return 0;
> }
>
> static void wacom_destroy_leds(struct wacom *wacom)
> {
> + if (!wacom->led_initialized)
> + return;
> +
> + wacom->led_initialized = false;
> +
> switch (wacom->wacom_wac.features.type) {
> case INTUOS4S:
> case INTUOS4:
> --
> 1.9.0
>
^ permalink raw reply
* Re: [PATCH v2 2/2] Add support for Compact (Bluetooth|USB) keyboard with Trackpoint
From: Jiri Kosina @ 2014-06-14 5:33 UTC (permalink / raw)
To: Antonio Ospite; +Cc: Jamie Lentin, linux-input, linux-kernel
In-Reply-To: <20140613234538.c960b52757f554699f2dbd1f@ao2.it>
On Fri, 13 Jun 2014, Antonio Ospite wrote:
> > Previously the tpkbd driver had various functions marked "_tp" to indicate
> > that it's for the "mouse" half of the keyboard as the kernel sees it,
> > however it does nothing special with the keyboard half. I was intending
> > (somewhat sloppily) to repurpose this into having versions of each
> > function for each keyboard, and a common function to switch between them.
> > Should make it fairly easy to add extra keyboards in the future.
> >
> > The problem, as ever, is choosing decent names for them. It should
> > probably be either:-
> >
> > * tpkbd_input_mapping_usbkbd
> > * tpkbd_input_mapping_compactkbd
> > ...and tpkbd_input_mapping switches between them
> >
> > or rename the driver to hid-lenovo and do:-
> >
>
> I am OK with a rename. Most files in drivers/hid are per-vendor after
> all. Jiri?
Fine by me; the module doesn't take any parameters, so we are not risking
introducing regression for people who'd have put parameter settings in
modprobe.conf or some such.
So please go ahead with the rename.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH v2 3/6] iio: adc: fsl,imx25-gcq driver
From: Hartmut Knaack @ 2014-06-14 19:27 UTC (permalink / raw)
To: Denis Carikli, Shawn Guo, Samuel Ortiz, Dmitry Torokhov,
Jonathan Cameron
Cc: Eric Bénard, Sascha Hauer, linux-arm-kernel, Lee Jones,
linux-input, linux-iio, Fabio Estevam, Lars-Peter Clausen,
Markus Pargmann
In-Reply-To: <1402672899-6995-4-git-send-email-denis@eukrea.com>
Denis Carikli schrieb:
> From: Markus Pargmann <mpa@pengutronix.de>
>
> This is a conversion queue driver for the mx25 SoC. It uses the central
> ADC which is used by two seperate independent queues. This driver
> prepares different conversion configurations for each possible input.
> For a conversion it creates a conversionqueue of one item with the
> correct configuration for the chosen channel. It then executes the queue
> once and disables the conversion queue afterwards.
>
> The reference voltages are configurable through devicetree subnodes,
> depending on the connections of the ADC inputs.
It has become pretty common to call instances of iio_dev indio_dev, thus making reviews a bit easier. Another comment inline.
> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> .../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 54 ++++
> drivers/iio/adc/Kconfig | 7 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/fsl-imx25-gcq.c | 338 ++++++++++++++++++++
> 4 files changed, 400 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt
> create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt b/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt
> new file mode 100644
> index 0000000..333fc55
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt
> @@ -0,0 +1,54 @@
> +Freescale i.MX25 ADC GCQ device
> +
> +This is a generic conversion queue device that can convert any of the analog
> +inputs using the ADC unit of the i.MX25.
> +
> +Required properties:
> + - compatible: Should be "fsl,imx25-gcq".
> + - reg: Should be the register range of the module.
> + - interrupts: Should be the interrupt number of the module. Typically this is <1>.
> + - interrupt-parent: phandle to the tsadc module of the i.MX25.
> + - #address-cells: Should be <1> (setting for the subnodes)
> + - #size-cells: Should be <0> (setting for the subnodes)
> +
> +Optionally you can define subnodes which define the positive and negative
> +reference voltage for one of the analog inputs.
> +
> +Required properties for subnodes:
> + - reg: Should be the number of the analog input.
> + 0: xp
> + 1: yp
> + 2: xn
> + 3: yn
> + 4: wiper
> + 5: inaux0
> + 6: inaux1
> + 7: inaux2
> + - fsl,adc-refp: Positive reference input
> + 0: yp
> + 1: xp
> + 2: External reference
> + 3: Internal reference
> + - fsl,adc-refn: Negative reference input
> + 0: xn
> + 1: yn
> + 2: ngnd_adc
> + 3: ngnd_adc
> +
> +
> +Example:
> +
> + adc: adc@50030800 {
> + compatible = "fsl,imx25-gcq";
> + reg = <0x50030800 0x60>;
> + interrupt-parent = <&tscadc>;
> + interrupts = <1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + inaux@5 {
> + reg = <5>;
> + fsl,adc-refp = <3>;
> + fsl,adc-refn = <3>;
> + };
> + };
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index a80d236..58efb8d 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -125,6 +125,13 @@ config EXYNOS_ADC
> of SoCs for drivers such as the touchscreen and hwmon to use to share
> this resource.
>
> +config FSL_MX25_ADC
> + tristate "Freescale MX25 ADC driver"
> + depends on MFD_MX25_TSADC
> + help
> + Generic Conversion Queue driver used for general purpose ADC in the
> + MX25. This driver supports single measurements using the MX25 ADC.
> +
> config LP8788_ADC
> tristate "LP8788 ADC driver"
> depends on MFD_LP8788
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 9d60f2d..2767fd6 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
> obj-$(CONFIG_AD799X) += ad799x.o
> obj-$(CONFIG_AT91_ADC) += at91_adc.o
> obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
> +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
> obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
> obj-$(CONFIG_MAX1363) += max1363.o
> obj-$(CONFIG_MCP320X) += mcp320x.o
> diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
> new file mode 100644
> index 0000000..1ae697c
> --- /dev/null
> +++ b/drivers/iio/adc/fsl-imx25-gcq.c
> @@ -0,0 +1,338 @@
> +/*
> + * Copyright 2014 Markus Pargmann, Pengutronix <mpa@pengutronix.de>
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + *
> + * This is the driver for the imx25 GCQ (Generic Conversion Queue)
> + * connected to the imx25 ADC.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/iio/iio.h>
> +#include <linux/mfd/imx25-tsadc.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000))
> +
> +enum mx25_gcq_cfgs {
> + MX25_CFG_XP = 0,
> + MX25_CFG_YP,
> + MX25_CFG_XN,
> + MX25_CFG_YN,
> + MX25_CFG_WIPER,
> + MX25_CFG_INAUX0,
> + MX25_CFG_INAUX1,
> + MX25_CFG_INAUX2,
> + MX25_NUM_CFGS,
> +};
> +
> +struct mx25_gcq_priv {
> + struct regmap *regs;
> + struct completion completed;
> + unsigned int settling_time;
> + struct clk *clk;
> + int irq;
> +};
> +
> +#define MX25_IIO_CHAN(chan, id) {\
> + .type = IIO_VOLTAGE,\
> + .indexed = 1,\
> + .channel = chan,\
> + .address = chan,\
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .datasheet_name = id, \
> + }
> +
> +static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS] = {
> + MX25_IIO_CHAN(0, "xp"),
> + MX25_IIO_CHAN(1, "yp"),
> + MX25_IIO_CHAN(2, "xn"),
> + MX25_IIO_CHAN(3, "yn"),
> + MX25_IIO_CHAN(4, "wiper"),
> + MX25_IIO_CHAN(5, "inaux0"),
> + MX25_IIO_CHAN(6, "inaux1"),
> + MX25_IIO_CHAN(7, "inaux2"),
> +};
> +
> +static void mx25_gcq_disable_eoq(struct mx25_gcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ,
> + MX25_ADCQ_MR_EOQ_IRQ);
> +}
> +
> +static void mx25_gcq_enable_eoq(struct mx25_gcq_priv *priv)
> +{
> + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ, 0);
> +}
> +
> +static irqreturn_t mx25_gcq_irq(int irq, void *data)
> +{
> + struct mx25_gcq_priv *priv = data;
> + u32 stats;
> +
> + regmap_read(priv->regs, MX25_ADCQ_SR, &stats);
> +
> + if (stats & MX25_ADCQ_SR_EOQ) {
> + mx25_gcq_disable_eoq(priv);
> + complete(&priv->completed);
> + }
> +
> + /* Disable conversion queue run */
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0);
> +
> + /* Acknowledge all possible irqs */
> + regmap_write(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR |
> + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_EOQ |
> + MX25_ADCQ_SR_PD);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int mx25_gcq_read_raw(struct iio_dev *idev,
> + struct iio_chan_spec const *chan, int *val, int *val2,
> + long mask)
> +{
> + struct mx25_gcq_priv *priv = iio_priv(idev);
> + unsigned long timeout;
> + u32 data;
> + int ret;
> +
> + if (mask != IIO_CHAN_INFO_RAW)
> + return -EINVAL;
> +
> + mutex_lock(&idev->mlock);
> +
> + /* Setup the configuration we want to use */
> + regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0,
> + MX25_ADCQ_ITEM(0, chan->address));
> +
> + mx25_gcq_enable_eoq(priv);
> +
> + /* Trigger queue for one run */
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS,
> + MX25_ADCQ_CR_FQS);
> +
> + timeout = wait_for_completion_interruptible_timeout(&priv->completed,
> + MX25_GCQ_TIMEOUT);
> + if (timeout < 0) {
> + dev_err(&idev->dev, "ADC wait for measurement failed\n");
> + ret = timeout;
> + goto out;
> + } else if (timeout == 0) {
> + dev_err(&idev->dev, "ADC timed out\n");
> + ret = -ETIMEDOUT;
> + goto out;
> + }
> +
> + regmap_read(priv->regs, MX25_ADCQ_FIFO, &data);
> + *val = MX25_ADCQ_FIFO_DATA(data);
> +
> + ret = IIO_VAL_INT;
> +
> +out:
> + mutex_unlock(&idev->mlock);
> +
> + return ret;
> +}
> +
> +static const struct iio_info mx25_gcq_iio_info = {
> + .read_raw = mx25_gcq_read_raw,
> +};
> +
> +static const struct regmap_config mx25_gcq_regconfig = {
> + .max_register = 0x5c,
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
> + struct mx25_gcq_priv *priv)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct device_node *child;
> + struct device *dev = &pdev->dev;
> + int ret;
> + int i;
> +
> + /* Setup all configurations registers with a default conversion
> + * configuration for each input */
> + for (i = 0; i != MX25_NUM_CFGS; ++i)
Since you count up, check if i is smaller than MX25_NUM_CFGS.
> + regmap_write(priv->regs, MX25_ADCQ_CFG(i),
> + MX25_ADCQ_CFG_YPLL_OFF |
> + MX25_ADCQ_CFG_XNUR_OFF |
> + MX25_ADCQ_CFG_XPUL_OFF |
> + MX25_ADCQ_CFG_REFP_INT |
> + (i << 4) |
> + MX25_ADCQ_CFG_REFN_NGND2);
> +
> + for_each_child_of_node(np, child) {
> + u32 reg;
> + u32 refn;
> + u32 refp;
> +
> + ret = of_property_read_u32(child, "reg", ®);
> + if (ret) {
> + dev_err(dev, "Failed to get reg property\n");
> + return ret;
> + }
> + if (reg > MX25_NUM_CFGS) {
> + dev_err(dev, "reg value is greater than the number of available configuration registers\n");
> + return -EINVAL;
> + }
> +
> + ret = of_property_read_u32(child, "fsl,adc-refn", &refn);
> + if (ret) {
> + dev_err(dev, "Failed to get fsl,adc-refn property\n");
> + return ret;
> + }
> + if (refn < 0 || refn > 3) {
> + dev_err(dev, "Invalid fsl,adc-refn property value %d\n",
> + refn);
> + return -EINVAL
> + }
> +
> + ret = of_property_read_u32(child, "fsl,adc-refp", &refp);
> + if (ret) {
> + dev_err(dev, "Failed to get fsl,adc-refp property\n");
> + return ret;
> + }
> + if (refp < 0 || refp > 3) {
> + dev_err(dev, "Invalid fsl,adc-refp property value %d\n",
> + refp);
> + return -EINVAL;
> + }
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_CFG(reg),
> + MX25_ADCQ_CFG_REFP_MASK |
> + MX25_ADCQ_CFG_REFN_MASK,
> + (refp << 7) | (refn << 2));
> + }
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR,
> + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST,
> + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST);
> +
> + regmap_write(priv->regs, MX25_ADCQ_CR,
> + MX25_ADCQ_CR_PDMSK |
> + MX25_ADCQ_CR_QSM_FQS);
> +
> + return 0;
> +}
> +
> +static int mx25_gcq_probe(struct platform_device *pdev)
> +{
> + struct iio_dev *idev;
> + struct mx25_gcq_priv *priv;
> + struct resource *res;
> + struct device *dev = &pdev->dev;
> + int ret;
> + void __iomem *mem;
> +
> + idev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
> + if (!idev)
> + return -ENOMEM;
> +
> + priv = iio_priv(idev);
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mem = devm_ioremap_resource(dev, res);
> + if (!mem)
> + return -ENOMEM;
> +
> + priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_gcq_regconfig);
> + if (IS_ERR(priv->regs)) {
> + dev_err(dev, "Failed to initialize regmap\n");
> + return PTR_ERR(priv->regs);
> + }
> +
> + init_completion(&priv->completed);
> +
> + ret = mx25_gcq_setup_cfgs(pdev, priv);
> + if (ret)
> + goto err_irq_free;
> +
> + priv->clk = mx25_tsadc_get_ipg(pdev->dev.parent);
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + dev_err(dev, "Failed to enable clock\n");
> + return ret;
> + }
> +
> + priv->irq = platform_get_irq(pdev, 0);
> + if (priv->irq <= 0) {
> + dev_err(dev, "Failed to get IRQ\n");
> + err = priv->irq;
> + goto err_clk_unprepare;
> + }
> +
> + ret = request_irq(priv->irq, mx25_gcq_irq, NULL, pdev->name,
> + priv);
> + if (ret) {
> + dev_err(dev, "Failed requesting IRQ\n");
> + goto err_clk_unprepare;
> + }
> +
> + idev->dev.parent = &pdev->dev;
> + idev->channels = mx25_gcq_channels;
> + idev->num_channels = ARRAY_SIZE(mx25_gcq_channels);
> + idev->info = &mx25_gcq_iio_info;
> +
> + ret = iio_device_register(idev);
> + if (ret) {
> + dev_err(dev, "Failed to register iio device\n");
> + goto err_irq_free;
> + }
> +
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +err_irq_free:
> + free_irq(priv->irq, (void *)priv);
> +
> +err_clk_unprepare:
> + clk_disable_unprepare(priv->clk);
> +
> + return ret;
> +}
> +
> +static int mx25_gcq_remove(struct platform_device *pdev)
> +{
> + struct mx25_gcq_priv *priv = platform_get_drvdata(pdev);
> + struct iio_dev *idev = iio_priv_to_dev(pdev);
> +
> + iio_device_unregister(idev);
> + free_irq(priv->irq, (void *)priv);
> + clk_disable_unprepare(priv->clk);
> +
> + return 0;
> +}
> +
> +static struct of_device_id mx25_gcq_ids[] = {
> + { .compatible = "fsl,imx25-gcq", },
> + { /* Senitel */ }
> +};
> +
> +static struct platform_driver mx25_gcq_driver = {
> + .driver = {
> + .name = "mx25-gcq",
> + .owner = THIS_MODULE,
> + .of_match_table = mx25_gcq_ids,
> + },
> + .probe = mx25_gcq_probe,
> + .remove = mx25_gcq_remove,
> +};
> +module_platform_driver(mx25_gcq_driver);
> +
> +MODULE_DESCRIPTION("ADC driver for Freescale mx25");
> +MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
> +MODULE_LICENSE("GPL v2");
^ permalink raw reply
* Re: [PATCH v5] leds: USB: HID: Add support for MSI GT683R led panels
From: Pavel Machek @ 2014-06-14 22:42 UTC (permalink / raw)
To: Janne Kanniainen
Cc: jkosina, johan, cooloney, linux-kernel, linux-leds, linux-usb,
linux-input
In-Reply-To: <1402605252-9620-1-git-send-email-janne.kanniainen@gmail.com>
On Thu 2014-06-12 23:34:12, Janne Kanniainen wrote:
> This driver adds support for USB controlled led panels that exists in
> MSI GT683R laptop
Hi!
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
> @@ -0,0 +1,10 @@
> +What: /sys/class/hidraw/<hidraw>/device/state
> +Date: Jun 2014
> +KernelVersion: 3.15
> +Contact: Janne Kanniainen <janne.kanniainen@gmail.com>
> +Description:
> + Set the mode of LEDs
> +
> + 0 - normal
> + 1 - audio
> + 2 - breathing
THat's some strange interface. Don't we normally use led triggers for this?
And the mode of the LED should really be in /sys/class/leds, not in hidraw somewhere...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: [PATCH v5] leds: USB: HID: Add support for MSI GT683R led panels
From: Janne Kanniainen @ 2014-06-14 23:23 UTC (permalink / raw)
To: Pavel Machek
Cc: Jiri Kosina, Johan Hovold, Bryan Wu, linux-kernel, linux-leds,
linux-usb, linux-input
In-Reply-To: <20140614224222.GE1389@xo-6d-61-c0.localdomain>
> Hi!
Hi.
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-class-hid-driver-gt683r
>> @@ -0,0 +1,10 @@
>> +What: /sys/class/hidraw/<hidraw>/device/state
>> +Date: Jun 2014
>> +KernelVersion: 3.15
>> +Contact: Janne Kanniainen <janne.kanniainen@gmail.com>
>> +Description:
>> + Set the mode of LEDs
>> +
>> + 0 - normal
>> + 1 - audio
>> + 2 - breathing
>
> THat's some strange interface. Don't we normally use led triggers for this?
I can implement it that way, if you all think that it is correct way.
What do Jiri and Johan thinks of it?
> And the mode of the LED should really be in /sys/class/leds, not in hidraw somewhere...
The problem is that all panels can only be in one mode at the time.
For example front panel can't be in breathing mode while side panel is
in normal mode.
Janne
^ permalink raw reply
* Re: [PATCH] input: touchscreen: ti_am335x_tsc: warn about incorrect spelling
From: Dmitry Torokhov @ 2014-06-15 7:16 UTC (permalink / raw)
To: Felipe Balbi
Cc: Andrew Morton, Mark Rutland, Sebastian Andrzej Siewior,
rob.herring, Pawel.Moll, swarren, ijc+devicetree, bcousson,
Tony Lindgren, devicetree, Linux OMAP Mailing List, linux-input
In-Reply-To: <20140614002355.GB24821@saruman.home>
On Fri, Jun 13, 2014 at 07:23:55PM -0500, Felipe Balbi wrote:
> Hi,
>
> Here's another patch which has been pending for months.
Sorry, lost track of this one, applied.
>
> On Mon, Nov 18, 2013 at 09:29:01AM -0600, Felipe Balbi wrote:
> > In the hopes that people run new kernels on
> > their devices, let's add a warning message
> > asking users to have their DTS file fixed.
> >
> > The goal is that by Linux 4.0 we will be
> > able to remove support for the bogus version
> > of our touchscreen's DTS.
> >
> > Suggested-by: Mark Rutland <mark.rutland@arm.com>
> > Signed-off-by: Felipe Balbi <balbi@ti.com>
> > ---
> >
> > Here you go, I've added your Suggested-by Mark,
> > if you wish I can remove or change to something
> > else.
> >
> > cheers
> >
> > drivers/input/touchscreen/ti_am335x_tsc.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
> > index b61df9d..91302cd 100644
> > --- a/drivers/input/touchscreen/ti_am335x_tsc.c
> > +++ b/drivers/input/touchscreen/ti_am335x_tsc.c
> > @@ -354,9 +354,12 @@ static int titsc_parse_dt(struct platform_device *pdev,
> > */
> > err = of_property_read_u32(node, "ti,coordinate-readouts",
> > &ts_dev->coordinate_readouts);
> > - if (err < 0)
> > + if (err < 0) {
> > + dev_warn(&pdev->dev, "please use 'ti,coordinate-readouts' instead\n");
> > err = of_property_read_u32(node, "ti,coordiante-readouts",
> > &ts_dev->coordinate_readouts);
> > + }
> > +
> > if (err < 0)
> > return err;
> >
> > --
> > 1.8.4.GIT
> >
>
> --
> balbi
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2 2/6] input: touchscreen: imx25 tcq driver
From: Dmitry Torokhov @ 2014-06-15 7:27 UTC (permalink / raw)
To: Denis Carikli
Cc: Shawn Guo, Samuel Ortiz, Jonathan Cameron, Eric Bénard,
Sascha Hauer, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Lee Jones, linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA, Fabio Estevam,
Lars-Peter Clausen, Markus Pargmann
In-Reply-To: <1402672899-6995-3-git-send-email-denis-fO0SIAKYzcbQT0dZR+AlfA@public.gmane.org>
Hi Denis,
On Fri, Jun 13, 2014 at 05:21:35PM +0200, Denis Carikli wrote:
> +
> + if (ret == 0 && samples != 0) {
> + /*
> + * only if both touch measures are below a treshold,
> + * the position is valid
> + */
> + if (touch_pre < priv->pen_threshold &&
> + touch_post < priv->pen_threshold) {
> + /* valid samples, generate a report */
> + x_pos /= priv->sample_count;
> + y_pos /= priv->sample_count;
> + input_report_abs(priv->idev, ABS_X, x_pos);
> + input_report_abs(priv->idev, ABS_Y, y_pos);
> + input_report_key(priv->idev, BTN_TOUCH,
> + 0xfff - ((touch_pre + touch_post) / 2));
I still do not understand this calculation. input_report_key()
converts the last argument to a boolean, so the only time it would
report BTN_TOUCH UP here if (touch_pre + touch_post) / 2 is exactly
0xfff. Given that default threshold is 500 this won't ever happen.
Why isn't it simply:
input_report_key(priv->idev, BTN_TOUCH, 1);
?
...
> +
> +static irqreturn_t mx25_tcq_irq_thread(int irq, void *dev_id)
> +{
> + struct mx25_tcq_priv *priv = (struct mx25_tcq_priv *) dev_id;
No need to cast.
> + u32 sample_buf[TSC_MAX_SAMPLES];
> + int samples = 0;
> +
> + /* read all samples */
> + while (1) {
> + u32 stats;
> +
> + regmap_read(priv->regs, MX25_ADCQ_SR, &stats);
> + if (stats & MX25_ADCQ_SR_EMPT)
> + break;
> +
> + if (samples < TSC_MAX_SAMPLES) {
> + regmap_read(priv->regs, MX25_ADCQ_FIFO,
> + &sample_buf[samples]);
> + ++samples;
> + } else {
> + u32 discarded;
> + /* discard samples */
> + regmap_read(priv->regs, MX25_ADCQ_FIFO, &discarded);
> + }
> + }
> +
> + mx25_tcq_create_event_for_4wire(priv, sample_buf, samples);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t mx25_tcq_irq(int irq, void *dev_id)
> +{
> + struct mx25_tcq_priv *priv = (struct mx25_tcq_priv *)dev_id;
Same here.
> + u32 stat;
> + int ret = IRQ_HANDLED;
> +
> + regmap_read(priv->regs, MX25_ADCQ_SR, &stat);
> +
> + if (stat & (MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR))
> + mx25_tcq_fifo_reset(priv);
> +
> + if (stat & MX25_ADCQ_SR_PD) {
> + mx25_tcq_disable_touch_irq(priv);
> + mx25_tcq_force_queue_start(priv);
> + mx25_tcq_enable_fifo_irq(priv);
> + }
> +
> + if (stat & MX25_ADCQ_SR_FDRY) {
> + mx25_tcq_disable_fifo_irq(priv);
> + ret = IRQ_WAKE_THREAD;
> + }
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR |
> + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD |
> + MX25_ADCQ_SR_EOQ,
> + MX25_ADCQ_SR_FRR |
> + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD |
> + MX25_ADCQ_SR_EOQ);
> +
> + return ret;
> +}
> +
> +/* configure the statemachine for a 4-wire touchscreen */
> +static int mx25_tcq_init(struct mx25_tcq_priv *priv)
> +{
> + u32 tgcr;
> + unsigned int ipg_div;
> + unsigned int adc_period;
> + unsigned int debounce_cnt;
> + unsigned int settling_time;
> + int itemct;
> + int ret;
> +
> + regmap_read(priv->core_regs, MX25_TSC_TGCR, &tgcr);
> + ipg_div = max_t(unsigned int, 4, MX25_TGCR_GET_ADCCLK(tgcr));
> + adc_period = clk_get_rate(priv->clk) / (ipg_div * 2 + 2);
> + debounce_cnt = DIV_ROUND_UP(priv->pen_debounce, adc_period * 8) - 1;
> + settling_time = DIV_ROUND_UP(priv->settling_time, adc_period);
> +
> +
> + /* Reset */
> + regmap_write(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QRST |
> + MX25_ADCQ_CR_FRST);
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QRST |
> + MX25_ADCQ_CR_FRST, 0);
> +
> + /* up to 128 * 8 ADC clocks are possible */
> + if (debounce_cnt > 127)
> + debounce_cnt = 127;
> +
> + ret = imx25_setup_queue_4wire(priv, 0x0, &itemct);
> + if (ret)
> + return ret;
> +
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_LITEMID_MASK |
> + MX25_ADCQ_CR_WMRK_MASK,
> + MX25_ADCQ_CR_LITEMID(itemct - 1) |
> + MX25_ADCQ_CR_WMRK(priv->expected_samples - 1));
> +
> + /* setup debounce count */
> + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR,
> + MX25_TGCR_PDBTIME_MASK,
> + MX25_TGCR_PDBTIME(debounce_cnt));
> +
> + /* enable debounce */
> + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDBEN,
> + MX25_TGCR_PDBEN);
> + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDEN,
> + MX25_TGCR_PDEN);
> +
> + /* enable the engine on demand */
> + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QSM_FQS,
> + MX25_ADCQ_CR_QSM_FQS);
> +
> + mx25_tcq_re_enable_touch_detection(priv);
> +
> + return 0;
> +}
> +
> +static int mx25_tcq_parse_dt(struct platform_device *pdev,
> + struct mx25_tcq_priv *priv)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + u32 wires;
> + int ret;
> +
> + /* Setup defaults */
> + priv->pen_threshold = 500;
> + priv->sample_count = 3;
> + priv->pen_debounce = 1000000;
> + priv->settling_time = 250000;
> +
> + ret = of_property_read_u32(np, "fsl,wires", &wires);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to find fsl,wires properties\n");
> + return ret;
> + }
> +
> + if (wires == 4) {
> + priv->mode = MX25_TS_4WIRE;
> + } else {
> + dev_err(&pdev->dev, "%u-wire mode not supported\n", wires);
> + return -EINVAL;
> + }
> +
> + /* These are optional, we don't care about the return values */
> + of_property_read_u32(np, "fsl,pen-threshold", &priv->pen_threshold);
> + of_property_read_u32(np, "fsl,settling-time", &priv->settling_time);
> + of_property_read_u32(np, "fsl,pen-debounce", &priv->pen_debounce);
> +
> + return 0;
> +}
> +
> +static int mx25_tcq_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct input_dev *idev;
> + struct mx25_tcq_priv *priv;
> + struct resource *res;
> + void __iomem *mem;
> + int ret;
> + int irq;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mem = devm_ioremap_resource(dev, res);
> + if (!mem)
> + return -ENOMEM;
> +
> + ret = mx25_tcq_parse_dt(pdev, priv);
> + if (ret)
> + return ret;
> +
> + priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_tcq_regconfig);
> + if (IS_ERR(priv->regs)) {
> + dev_err(dev, "Failed to initialize regmap\n");
> + return PTR_ERR(priv->regs);
> + }
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq <= 0) {
> + dev_err(dev, "Failed to get IRQ\n");
> + return irq;
> + }
> +
> + idev = devm_input_allocate_device(dev);
> + if (!idev) {
> + dev_err(dev, "Failed to allocate input device\n");
> + return -ENOMEM;
> + }
> +
> + idev->name = mx25_tcq_name;
> + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> + idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> + input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
> + input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
> +
> + idev->id.bustype = BUS_HOST;
> +
> + ret = input_register_device(idev);
> + if (ret) {
> + dev_err(dev, "Failed to register input device\n");
> + return ret;
> + }
> +
> + priv->idev = idev;
> +
> + priv->core_regs = mx25_tsadc_get_regmap(pdev->dev.parent);
> + priv->clk = mx25_tsadc_get_ipg(pdev->dev.parent);
> +
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + dev_err(dev, "Failed to enable ipg clock\n");
> + return ret;
> + }
> +
> + ret = devm_request_threaded_irq(dev, irq, mx25_tcq_irq,
> + mx25_tcq_irq_thread, IRQF_ONESHOT, pdev->name, priv);
> + if (ret) {
> + dev_err(dev, "Failed requesting IRQ\n");
You are leaving clock enabled here.
> + return ret;
> + }
> +
> + ret = mx25_tcq_init(priv);
> + if (ret) {
> + dev_err(dev, "Failed to init tcq\n");
> + goto error_tcq_init;
> + }
> +
> + platform_set_drvdata(pdev, priv);
> +
> + return 0;
> +
> +error_tcq_init:
> + clk_disable_unprepare(priv->clk);
> + return ret;
> +}
> +
> +static int mx25_tcq_remove(struct platform_device *pdev)
> +{
> + struct mx25_tcq_priv *priv = platform_get_drvdata(pdev);
> +
> + clk_disable_unprepare(priv->clk);
> +
> + return 0;
> +}
> +
> +static struct platform_driver mx25_tcq_driver = {
> + .driver = {
> + .name = "mx25-tcq",
> + .owner = THIS_MODULE,
> + .of_match_table = mx25_tcq_ids,
> + },
> + .probe = mx25_tcq_probe,
> + .remove = mx25_tcq_remove,
> +};
> +module_platform_driver(mx25_tcq_driver);
> +
> +MODULE_DESCRIPTION("TS input driver for Freescale mx25");
> +MODULE_AUTHOR("Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>
Thanks.
--
Dmitry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox