Devicetree
 help / color / mirror / Atom feed
* [PATCH 1/2 v4] video: fbdev: imxfb: support AUS mode
From: Martin Kaiser @ 2017-04-21 10:29 UTC (permalink / raw)
  To: linux-fbdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Bartlomiej Zolnierkiewicz, Sascha Hauer,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Martin Kaiser
In-Reply-To: <1488193030-13064-1-git-send-email-martin-XxZfDwE/svGeZLLa646FqQ@public.gmane.org>

Some displays require setting AUS mode in the LDCD AUS Mode Control
Register to work with the imxfb driver. Like the value of the Panel
Configuration Register, the AUS mode setting depends on the display
mode.

Allow setting AUS mode from the device tree by adding a boolean
property. Make this property optional to keep the DT ABI stable.
AUS mode can be set only on imx21 and compatible chipsets.

Signed-off-by: Martin Kaiser <martin-XxZfDwE/svGeZLLa646FqQ@public.gmane.org>
---
v4:
   rename the DT property to fsl,aus-mode

v3:
   use a boolean DT property instead of the register value
   separate patches for DT binding and code changes

v2:
   re-sending DT bindings and code changes as one patch

 drivers/video/fbdev/imxfb.c               | 17 +++++++++++++++++
 include/linux/platform_data/video-imxfb.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index 1b0faad..c166e07 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -117,6 +117,9 @@
 
 #define IMXFB_LSCR1_DEFAULT 0x00120300
 
+#define LCDC_LAUSCR	0x80
+#define LAUSCR_AUS_MODE	(1<<31)
+
 /* Used fb-mode. Can be set on kernel command line, therefore file-static. */
 static const char *fb_mode;
 
@@ -158,6 +161,7 @@ struct imxfb_info {
 	dma_addr_t		dbar2;
 
 	u_int			pcr;
+	u_int			lauscr;
 	u_int			pwmr;
 	u_int			lscr1;
 	u_int			dmacr;
@@ -422,6 +426,11 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 	pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
 
 	fbi->pcr = pcr;
+	/*
+	 * The LCDC AUS Mode Control Register does not exist on imx1.
+	 */
+	if (!is_imx1_fb(fbi) && imxfb_mode->aus_mode)
+		fbi->lauscr = LAUSCR_AUS_MODE;
 
 	/*
 	 * Copy the RGB parameters for this display
@@ -638,6 +647,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
 	if (fbi->dmacr)
 		writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
 
+	if (fbi->lauscr)
+		writel(fbi->lauscr, fbi->regs + LCDC_LAUSCR);
+
 	return 0;
 }
 
@@ -734,6 +746,11 @@ static int imxfb_of_read_mode(struct device *dev, struct device_node *np,
 	imxfb_mode->bpp = bpp;
 	imxfb_mode->pcr = pcr;
 
+	/*
+	 * fsl,aus-mode is optional
+	 */
+	imxfb_mode->aus_mode = of_property_read_bool(np, "fsl,aus-mode");
+
 	return 0;
 }
 
diff --git a/include/linux/platform_data/video-imxfb.h b/include/linux/platform_data/video-imxfb.h
index a5c0a71..cf9348b 100644
--- a/include/linux/platform_data/video-imxfb.h
+++ b/include/linux/platform_data/video-imxfb.h
@@ -50,6 +50,7 @@
 struct imx_fb_videomode {
 	struct fb_videomode mode;
 	u32 pcr;
+	bool aus_mode;
 	unsigned char	bpp;
 };
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH v2 3/5] MAINTAINERS: add Atmel PTC entries
From: Ludovic Desroches @ 2017-04-21  9:56 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ludovic Desroches
In-Reply-To: <20170421083924.15096-4-ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>

On Fri, Apr 21, 2017 at 10:39:22AM +0200, Ludovic Desroches wrote:
> Add entries for the Atmel PTC Subsystem.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> ---
>  MAINTAINERS | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 860dacb..e1b8b0e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2323,6 +2323,13 @@ F:	Documentation/devicetree/bindings/input/atmel,maxtouch.txt
>  F:	drivers/input/touchscreen/atmel_mxt_ts.c
>  F:	include/linux/platform_data/atmel_mxt_ts.h
>  
> +ATMEL PTC SUBSYSTEM DRIVER
> +M:	Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
> +L:	linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> +S:	Supported
> +F:	drivers/input/misc/atmel_ptc.c
> +F:	include/uapi/linux/atmel_ptc.h

I'll remove it in v3.

> +
>  ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
>  M:	Bradley Grove <linuxdrivers-hoWRoavIt3ZWk0Htik3J/w@public.gmane.org>
>  L:	linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> -- 
> 2.9.0
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/2 v3 resend] video: fbdev: imxfb: support AUS mode
From: Bartlomiej Zolnierkiewicz @ 2017-04-21  9:33 UTC (permalink / raw)
  To: Martin Kaiser
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Sascha Hauer,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1492760753-8374-1-git-send-email-martin-XxZfDwE/svGeZLLa646FqQ@public.gmane.org>


Hi,

On Friday, April 21, 2017 09:45:52 AM Martin Kaiser wrote:
> Some displays require setting AUS mode in the LDCD AUS Mode Control
> Register to work with the imxfb driver. Like the value of the Panel
> Configuration Register, the AUS mode setting depends on the display
> mode.
> 
> Allow setting AUS mode from the device tree by adding a boolean
> property. Make this property optional to keep the DT ABI stable.
> AUS mode can be set only on imx21 and compatible chipsets.
> 
> Signed-off-by: Martin Kaiser <martin-XxZfDwE/svGeZLLa646FqQ@public.gmane.org>
> ---
> re-sending v3, rebased against current linux-next
> it seems this got lost along the way, there was a bit of confusion
> whether to split this in two patches or not

It hadn't been lost, I've been waiting on v4, please see:

https://lkml.org/lkml/2017/3/15/709

[ Rob has requested rename of the property to "fsl,aus-mode". ]

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 1/4] gpio: mvebu: Add limited PWM support
From: Thomas Petazzoni @ 2017-04-21  9:19 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Mark Rutland, Alexandre Courbot, Jason Cooper, linux-pwm,
	Linus Walleij, Russell King, Rob Herring, linux-kernel,
	Gregory Clement, devicetree, Thierry Reding, linux-gpio,
	Ralph Sennhauser, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20170412151932.GE7023@lunn.ch>

Hello,

On Wed, 12 Apr 2017 17:19:32 +0200, Andrew Lunn wrote:

> Yep. It was a compromise. By adding a new binding for the GPIO driver,
> this might be possible. But it did not seem worth such a major change.
> 
> The prime use of this feature is for controlling a fan. So far, i've
> not seen any hardware with more than one fan, i.e. needs more than one
> PWM. Nor have i seen any hardware with the GPIO for the fan being on
> the third bank. A hardware manufacture could add multiple fans, but i
> doubt it, they make noise and fail. And if a manufacture does place a
> fan on the third bank, it can still be controlled as a plain GPIO fan,
> as we have been doing for the last few years.

Right.

> So i personally think it is an O.K. compromise.

I clearly don't want to block this, but I believe this is a very good
illustration of why stable DT bindings simply don't work. We are
realizing here that having each GPIO bank represented as a separate DT
node doesn't work, because this blinking functionality is not per GPIO
bank, but global to all GPIO banks.

I am totally fine with compromise, and having things simple first, and
extend them later if needed. But this stable DT binding rule makes this
quite impossible: what is a compromise today might put you in big
troubles tomorrow.

Anyway, it's fine for me, I don't think it's worth the effort making a
much more complicated solution/change.

Best regards,

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v2 5/5] ARM: at91/defconfig: add PTC driver to sama5_defconfig
From: Ludovic Desroches @ 2017-04-21  8:39 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ludovic Desroches
In-Reply-To: <20170421083924.15096-1-ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>

Add Peripheral Touch Controller driver to sama5_defconfig.

Signed-off-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
---
 arch/arm/configs/sama5_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 777c9e9..7480665 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -116,6 +116,8 @@ CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_ATMEL_PTC=m
 # CONFIG_SERIO is not set
 CONFIG_LEGACY_PTY_COUNT=4
 CONFIG_SERIAL_ATMEL=y
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v2 4/5] ARM: dts: at91: sama5d2: add PTC subsystem device
From: Ludovic Desroches @ 2017-04-21  8:39 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	nicolas.ferre-UWL1GkI3JZL3oGB3hsPCZA,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ludovic Desroches
In-Reply-To: <20170421083924.15096-1-ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>

Add the Atmel Peripheral Touch Controller subsystem.

Signed-off-by: Ludovic Desroches <ludovic.desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
---
 arch/arm/boot/dts/sama5d2.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 8067c71..fa4ed56 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -762,6 +762,12 @@
 						atmel,clk-output-range = <0 83000000>;
 					};
 
+					ptc_clk: ptc_clk {
+						#clock-cells = <0>;
+						reg = <58>;
+						atmel,clk-output-range = <0 83000000>;
+					};
+
 					classd_clk: classd_clk {
 						#clock-cells = <0>;
 						reg = <59>;
@@ -1310,6 +1316,16 @@
 				reg = <0xfc05c000 0x20>;
 			};
 
+			ptc@fc060000 {
+				compatible = "atmel,sama5d2-ptc";
+				reg = <0x00800000 0x10000
+				       0xfc060000 0xcf>;
+				interrupts = <58 IRQ_TYPE_LEVEL_HIGH 7>;
+				clocks = <&ptc_clk>, <&main>, <&clk32k>;
+				clock-names = "ptc_clk", "ptc_int_osc", "slow_clk";
+				status = "disabled";
+			};
+
 			chipid@fc069000 {
 				compatible = "atmel,sama5d2-chipid";
 				reg = <0xfc069000 0x8>;
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v2 3/5] MAINTAINERS: add Atmel PTC entries
From: Ludovic Desroches @ 2017-04-21  8:39 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, devicetree
  Cc: dmitry.torokhov, nicolas.ferre, alexandre.belloni, linux-kernel,
	Ludovic Desroches
In-Reply-To: <20170421083924.15096-1-ludovic.desroches@microchip.com>

Add entries for the Atmel PTC Subsystem.

Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 860dacb..e1b8b0e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2323,6 +2323,13 @@ F:	Documentation/devicetree/bindings/input/atmel,maxtouch.txt
 F:	drivers/input/touchscreen/atmel_mxt_ts.c
 F:	include/linux/platform_data/atmel_mxt_ts.h
 
+ATMEL PTC SUBSYSTEM DRIVER
+M:	Ludovic Desroches <ludovic.desroches@microchip.com>
+L:	linux-input@vger.kernel.org
+S:	Supported
+F:	drivers/input/misc/atmel_ptc.c
+F:	include/uapi/linux/atmel_ptc.h
+
 ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
 M:	Bradley Grove <linuxdrivers@attotech.com>
 L:	linux-scsi@vger.kernel.org
-- 
2.9.0


^ permalink raw reply related

* [PATCH v2 2/5] input: misc: introduce Atmel PTC driver
From: Ludovic Desroches @ 2017-04-21  8:39 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, devicetree
  Cc: dmitry.torokhov, nicolas.ferre, alexandre.belloni, linux-kernel,
	Ludovic Desroches
In-Reply-To: <20170421083924.15096-1-ludovic.desroches@microchip.com>

The Atmel Peripheral Touch Controller subsystem offers built-in hardware
for capacitive touch measurement on sensors that function as buttons,
sliders and wheels.

Two files are loaded when probing the driver:
- a firmware for the Pico Power Processor that computes raw data from
  the ADC front end to provide high level information as button touch or
  untouch, slider position, etc.
- a configuration file that describe the topology and the parameters of
  the sensors.

Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
 drivers/input/misc/Kconfig     |  12 +
 drivers/input/misc/Makefile    |   1 +
 drivers/input/misc/atmel_ptc.c | 723 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 736 insertions(+)
 create mode 100644 drivers/input/misc/atmel_ptc.c

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 79d0be9..5e27378 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -96,6 +96,18 @@ config INPUT_ATMEL_CAPTOUCH
 	  To compile this driver as a module, choose M here: the
 	  module will be called atmel_captouch.
 
+config INPUT_ATMEL_PTC
+	tristate "Atmel PTC Driver"
+	depends on OF || COMPILE_TEST
+	depends on SOC_SAMA5D2
+	help
+	  Say Y to enable support for the Atmel PTC Subsystem.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel_ptc.
+	  If you compile it as a built-in driver, you have to build the
+	  firmware into the kernel or to use an initrd.
+
 config INPUT_BMA150
 	tristate "BMA150/SMB380 acceleration sensor support"
 	depends on I2C
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index b10523f..9470ec7 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_INPUT_ARIZONA_HAPTICS)	+= arizona-haptics.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)		+= ati_remote2.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH)	+= atmel_captouch.o
+obj-$(CONFIG_INPUT_ATMEL_PTC)		+= atmel_ptc.o
 obj-$(CONFIG_INPUT_BFIN_ROTARY)		+= bfin_rotary.o
 obj-$(CONFIG_INPUT_BMA150)		+= bma150.o
 obj-$(CONFIG_INPUT_CM109)		+= cm109.o
diff --git a/drivers/input/misc/atmel_ptc.c b/drivers/input/misc/atmel_ptc.c
new file mode 100644
index 0000000..612eaed
--- /dev/null
+++ b/drivers/input/misc/atmel_ptc.c
@@ -0,0 +1,723 @@
+/*
+ * Atmel PTC subsystem driver for SAMA5D2 devices and compatible.
+ *
+ * Copyright (C) 2017 Microchip,
+ *               2017 Ludovic Desroches <ludovic.desroches@microchip.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/cdev.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#define ATMEL_PTC_MAX_NODES	64
+#define ATMEL_PTC_MAX_SCROLLERS	4
+
+/* ----- PPP ----- */
+#define ATMEL_PPP_FIRMWARE_NAME	"atmel_ptc.bin"
+
+#define ATMEL_PPP_CONFIG	0x20
+#define ATMEL_PPP_CTRL		0x24
+#define ATMEL_PPP_CMD		0x28
+#define		ATMEL_PPP_CMD_STOP		0x1
+#define		ATMEL_PPP_CMD_RESET		0x2
+#define		ATMEL_PPP_CMD_RESTART		0x3
+#define		ATMEL_PPP_CMD_ABORT		0x4
+#define		ATMEL_PPP_CMD_RUN		0x5
+#define		ATMEL_PPP_CMD_RUN_LOCKED	0x6
+#define		ATMEL_PPP_CMD_RUN_OCD		0x7
+#define		ATMEL_PPP_CMD_UNLOCK		0x8
+#define		ATMEL_PPP_CMD_NMI		0x9
+#define		ATMEL_PPP_CMD_HOST_OCD_RESUME	0xB
+#define ATMEL_PPP_ISR		0x33
+#define		ATMEL_PPP_IRQ_MASK	GENMASK(7, 4)
+#define		ATMEL_PPP_IRQ0		BIT(4)
+#define		ATMEL_PPP_IRQ1		BIT(5)
+#define		ATMEL_PPP_IRQ2		BIT(6)
+#define		ATMEL_PPP_IRQ3		BIT(7)
+#define		ATMEL_PPP_NOTIFY_MASK	GENMASK(3, 0)
+#define		ATMEL_PPP_NOTIFY0	BIT(0)
+#define		ATMEL_PPP_NOTIFY1	BIT(1)
+#define		ATMEL_PPP_NOTIFY2	BIT(2)
+#define		ATMEL_PPP_NOTIFY3	BIT(3)
+#define ATMEL_PPP_IDR		0x34
+#define ATMEL_PPP_IER		0x35
+
+#define atmel_ppp_readb(ptc, reg)	readb_relaxed(ptc->ppp_regs + reg)
+#define atmel_ppp_writeb(ptc, reg, val)	writeb_relaxed(val, ptc->ppp_regs + reg)
+#define atmel_ppp_readl(ptc, reg)	readl_relaxed(ptc->ppp_regs + reg)
+#define atmel_ppp_writel(ptc, reg, val)	writel_relaxed(val, ptc->ppp_regs + reg)
+
+/* ----- QTM ----- */
+#define ATMEL_QTM_CONF_NAME		"atmel_ptc.conf"
+
+#define ATMEL_QTM_MB_OFFSET			0x4000
+#define ATMEL_QTM_MB_SIZE			0x1000
+
+#define ATMEL_QTM_MB_CMD_OFFSET			0x0
+#define		ATMEL_QTM_CMD_FIRM_VERSION		8
+#define		ATMEL_QTM_CMD_INIT			18
+#define		ATMEL_QTM_CMD_RUN			19
+#define		ATMEL_QTM_CMD_STOP			21
+#define		ATMEL_QTM_CMD_SET_ACQ_MODE_TIMER	24
+#define ATMEL_QTM_MB_NODE_GROUP_CONFIG_OFFSET	0x100
+#define ATMEL_QTM_MB_SCROLLER_CONFIG_OFFSET	0x81a
+#define		ATMEL_QTM_SCROLLER_TYPE_SLIDER		0x0
+#define		ATMEL_QTM_SCROLLER_TYPE_WHEEL		0x1
+#define ATMEL_QTM_MB_SCROLLER_DATA_OFFSET	0x842
+#define ATMEL_QTM_MB_TOUCH_EVENTS_OFFSET	0x880
+
+#define atmel_qtm_get_scroller_config(buf, id) \
+	memcpy(buf, \
+	       ptc->qtm_mb + ATMEL_QTM_MB_SCROLLER_CONFIG_OFFSET \
+	       + (id) * sizeof(struct atmel_qtm_scroller_config), \
+	       sizeof(struct atmel_qtm_scroller_config))
+
+#define atmel_qtm_get_scroller_data(buf, id) \
+	memcpy(buf, \
+	       ptc->qtm_mb + ATMEL_QTM_MB_SCROLLER_DATA_OFFSET \
+	       + (id) * sizeof(struct atmel_qtm_scroller_data), \
+	       sizeof(struct atmel_qtm_scroller_data))
+
+#define get_scroller_resolution(scroller_config) \
+	(1 << (scroller_config.resol_deadband >> 4))
+
+struct atmel_qtm_cmd {
+	u16	id;
+	u16	addr;
+	u32	data;
+} __packed;
+
+struct atmel_qtm_node_group_config {
+	u16	count;
+	u8	ptc_type;
+	u8	freq_option;
+	u8	calib_option;
+	u8	unused;
+} __packed;
+
+struct atmel_qtm_scroller_config {
+	u8	type;
+	u8	unused;
+	u16	key_start;
+	u8	key_count;
+	u8	resol_deadband;
+	u8	position_hysteresis;
+	u8	unused2;
+	u16	contact_min_threshold;
+} __packed;
+
+struct atmel_qtm_scroller_data {
+	u8	status;
+	u8	right_hyst;
+	u8	left_hyst;
+	u8	unused;
+	u16	raw_position;
+	u16	position;
+	u16	contact_size;
+} __packed;
+
+struct atmel_qtm_touch_events {
+	u32	key_event_id[2];
+	u32	key_enable_state[2];
+	u32	scroller_event_id;
+	u32	scroller_event_state;
+} __packed;
+
+struct atmel_ptc {
+	void __iomem		*ppp_regs;
+	void __iomem		*firmware;
+	int			irq;
+	u8			imr;
+	void __iomem		*qtm_mb;
+	struct clk		*clk_per;
+	struct clk		*clk_int_osc;
+	struct clk		*clk_slow;
+	struct device		*dev;
+	struct completion	ppp_ack;
+	unsigned int		button_keycode[ATMEL_PTC_MAX_NODES];
+	struct input_dev	*buttons_input;
+	struct input_dev	*scroller_input[ATMEL_PTC_MAX_SCROLLERS];
+	bool			buttons_registered;
+	bool			scroller_registered[ATMEL_PTC_MAX_SCROLLERS];
+	u32			button_event[ATMEL_PTC_MAX_NODES / 32];
+	u32			button_state[ATMEL_PTC_MAX_NODES / 32];
+	u32			scroller_event;
+	u32			scroller_state;
+};
+
+static void atmel_ppp_irq_enable(struct atmel_ptc *ptc, u8 mask)
+{
+	ptc->imr |= mask;
+	atmel_ppp_writeb(ptc, ATMEL_PPP_IER, mask & ATMEL_PPP_IRQ_MASK);
+}
+
+static void atmel_ppp_irq_disable(struct atmel_ptc *ptc, u8 mask)
+{
+	ptc->imr &= ~mask;
+	atmel_ppp_writeb(ptc, ATMEL_PPP_IDR, mask & ATMEL_PPP_IRQ_MASK);
+}
+
+static void atmel_ppp_notify(struct atmel_ptc *ptc, u8 mask)
+{
+	if (mask & ATMEL_PPP_NOTIFY_MASK) {
+		u8 notify = atmel_ppp_readb(ptc, ATMEL_PPP_ISR)
+			| (mask & ATMEL_PPP_NOTIFY_MASK);
+
+		atmel_ppp_writeb(ptc, ATMEL_PPP_ISR, notify);
+	}
+}
+
+static void atmel_ppp_irq_pending_clr(struct atmel_ptc *ptc, u8 mask)
+{
+	if (mask & ATMEL_PPP_IRQ_MASK) {
+		u8 irq = atmel_ppp_readb(ptc, ATMEL_PPP_ISR) & ~mask;
+
+		atmel_ppp_writeb(ptc, ATMEL_PPP_ISR, irq);
+	}
+}
+
+static void atmel_ppp_cmd_send(struct atmel_ptc *ptc, u32 cmd)
+{
+	atmel_ppp_writel(ptc, ATMEL_PPP_CMD, cmd);
+}
+
+static void atmel_ppp_irq_scroller_event(struct atmel_ptc *ptc)
+{
+	int i;
+
+	if (!ptc->scroller_event)
+		return;
+
+	for (i = 0; i < ATMEL_PTC_MAX_SCROLLERS; i++) {
+		u32 mask = 1 << i;
+		struct atmel_qtm_scroller_data scroller_data;
+		struct atmel_qtm_scroller_config scroller_config;
+
+		if (!(ptc->scroller_event & mask))
+			continue;
+
+		atmel_qtm_get_scroller_data(&scroller_data, i);
+		atmel_qtm_get_scroller_config(&scroller_config, i);
+
+		if (scroller_config.type == ATMEL_QTM_SCROLLER_TYPE_WHEEL)
+			input_report_abs(ptc->scroller_input[i],
+					 ABS_WHEEL, scroller_data.position);
+		else
+			input_report_abs(ptc->scroller_input[i],
+					 ABS_X, scroller_data.position);
+
+		input_report_key(ptc->scroller_input[i], BTN_TOUCH,
+				 scroller_data.status & 0x1);
+		input_sync(ptc->scroller_input[i]);
+	}
+}
+
+static void atmel_ppp_irq_button_event(struct atmel_ptc *ptc)
+{
+	int i, j;
+
+	for (i = 0; i < ATMEL_PTC_MAX_NODES / 32; i++) {
+		if (!ptc->button_event[i])
+			continue;
+
+		for (j = 0; j < 32; j++) {
+			u32 mask = 1 << j;
+			u32 state = ptc->button_state[i] & mask;
+			unsigned int key_id = i * 32 + j;
+
+			if (!(ptc->button_event[i] & mask))
+				continue;
+
+			input_report_key(ptc->buttons_input,
+					 ptc->button_keycode[key_id], !!state);
+			input_sync(ptc->buttons_input);
+		}
+	}
+}
+
+static void atmel_ppp_irq_touch_event(struct atmel_ptc *ptc)
+{
+	atmel_ppp_irq_scroller_event(ptc);
+	atmel_ppp_irq_button_event(ptc);
+}
+
+static irqreturn_t atmel_ppp_irq_handler(int irq, void *data)
+{
+	struct atmel_ptc *ptc = data;
+	u32 isr = atmel_ppp_readb(ptc, ATMEL_PPP_ISR) & ptc->imr;
+
+	/* QTM CMD acknowledgment */
+	if (isr & ATMEL_PPP_IRQ0) {
+		atmel_ppp_irq_disable(ptc, ATMEL_PPP_IRQ0);
+		atmel_ppp_irq_pending_clr(ptc, ATMEL_PPP_IRQ0);
+		complete(&ptc->ppp_ack);
+	}
+	/* QTM touch event */
+	if (isr & ATMEL_PPP_IRQ1) {
+		struct atmel_qtm_touch_events touch_events;
+		int i;
+
+		memcpy(&touch_events,
+		       ptc->qtm_mb + ATMEL_QTM_MB_TOUCH_EVENTS_OFFSET,
+		       sizeof(touch_events));
+
+		for (i = 0; i < ATMEL_PTC_MAX_NODES / 32; i++) {
+			ptc->button_event[i] = touch_events.key_event_id[i];
+			ptc->button_state[i] = touch_events.key_enable_state[i];
+		}
+		ptc->scroller_event = touch_events.scroller_event_id;
+		ptc->scroller_state = touch_events.scroller_event_state;
+
+		atmel_ppp_irq_pending_clr(ptc, ATMEL_PPP_IRQ1);
+
+		atmel_ppp_irq_touch_event(ptc);
+	}
+	/* Debug event */
+	if (isr & ATMEL_PPP_IRQ2)
+		atmel_ppp_irq_pending_clr(ptc, ATMEL_PPP_IRQ2);
+
+	return IRQ_HANDLED;
+}
+
+void atmel_qtm_cmd_send(struct atmel_ptc *ptc, struct atmel_qtm_cmd *cmd)
+{
+	int i, ret;
+
+	dev_dbg(ptc->dev, "%s: cmd=0x%x, addr=0x%x, data=0x%x\n",
+		__func__, cmd->id, cmd->addr, cmd->data);
+
+	memcpy(ptc->qtm_mb, cmd, sizeof(*cmd));
+
+	/* Once command performed, we'll get an IRQ. */
+	atmel_ppp_irq_enable(ptc, ATMEL_PPP_IRQ0);
+	/* Notify PPP that we have sent a command. */
+	atmel_ppp_notify(ptc, ATMEL_PPP_NOTIFY0);
+	/* Wait for IRQ from PPP. */
+	wait_for_completion(&ptc->ppp_ack);
+
+	/*
+	 * Register input devices only when QTM is started since we need some
+	 * information from the QTM configuration.
+	 */
+	if (cmd->id == ATMEL_QTM_CMD_RUN) {
+		if (ptc->buttons_input && !ptc->buttons_registered) {
+			ret = input_register_device(ptc->buttons_input);
+			if (ret)
+				dev_err(ptc->dev, "can't register input button device.\n");
+			else
+				ptc->buttons_registered = true;
+		}
+
+		for (i = 0; i < ATMEL_PTC_MAX_SCROLLERS; i++) {
+			struct input_dev *scroller = ptc->scroller_input[i];
+			struct atmel_qtm_scroller_config scroller_config;
+
+			if (!scroller || ptc->scroller_registered[i])
+				continue;
+
+			atmel_qtm_get_scroller_config(&scroller_config, i);
+
+			if (scroller_config.type ==
+			    ATMEL_QTM_SCROLLER_TYPE_SLIDER) {
+				unsigned int max = get_scroller_resolution(scroller_config);
+
+				input_set_abs_params(scroller, 0, 0, max, 0, 0);
+			}
+			ret = input_register_device(scroller);
+			if (ret)
+				dev_err(ptc->dev, "can't register input scroller device.\n");
+			else
+				ptc->scroller_registered[i] = true;
+		}
+	}
+
+	memcpy(cmd, ptc->qtm_mb, sizeof(*cmd));
+}
+
+static inline struct atmel_ptc *kobj_to_atmel_ptc(struct kobject *kobj)
+{
+	struct device *dev = kobj_to_dev(kobj);
+
+	return dev->driver_data;
+}
+
+static ssize_t atmel_qtm_mb_read(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *attr,
+				 char *buf, loff_t off, size_t count)
+{
+	struct atmel_ptc *ptc = kobj_to_atmel_ptc(kobj);
+	char *qtm_mb = (char *)ptc->qtm_mb;
+
+	dev_dbg(ptc->dev, "%s: off=0x%llx, count=%zu\n", __func__, off, count);
+
+	memcpy(buf, qtm_mb + off, count);
+
+	return count;
+}
+
+static ssize_t atmel_qtm_mb_write(struct file *filp, struct kobject *kobj,
+				  struct bin_attribute *attr,
+				  char *buf, loff_t off, size_t count)
+{
+	struct atmel_ptc *ptc = kobj_to_atmel_ptc(kobj);
+	char *qtm_mb = (char *)ptc->qtm_mb;
+
+	dev_dbg(ptc->dev, "%s: off=0x%llx, count=%zu\n", __func__, off, count);
+
+	if (off == 0 && count == sizeof(struct atmel_qtm_cmd))
+		atmel_qtm_cmd_send(ptc, (struct atmel_qtm_cmd *)buf);
+	else
+		memcpy(qtm_mb + off, buf, count);
+
+	return count;
+}
+
+static struct bin_attribute atmel_ptc_qtm_mb_attr = {
+	.attr = {
+		.name = "qtm_mb",
+		.mode = 0644,
+	},
+	.size = ATMEL_QTM_MB_SIZE,
+	.read = atmel_qtm_mb_read,
+	.write = atmel_qtm_mb_write,
+};
+
+/*
+ * From QTM MB configuration, we can't retrieve all the information needed
+ * to setup correctly input devices: buttons key codes and slider axis are
+ * missing.
+ */
+static int atmel_ptc_of_parse(struct atmel_ptc *ptc)
+{
+	struct device_node *sensor;
+	bool first_button = true;
+
+	/* Parse sensors. */
+	for_each_child_of_node(ptc->dev->of_node, sensor) {
+		if (!strcmp(sensor->name, "button")) {
+			u32 key_id, keycode;
+			struct input_dev *buttons = ptc->buttons_input;
+
+			if (of_property_read_u32(sensor, "reg", &key_id)) {
+				dev_err(ptc->dev, "reg is missing (%s)\n",
+					sensor->full_name);
+				return -EINVAL;
+			}
+
+			if (of_property_read_u32(sensor, "linux,keycode", &keycode)) {
+				dev_err(ptc->dev, "linux,keycode is missing (%s)\n",
+					sensor->full_name);
+				return -EINVAL;
+			}
+			ptc->button_keycode[key_id] = keycode;
+
+			/* All buttons are put together in a keyboard device. */
+			if (first_button) {
+				buttons = devm_input_allocate_device(ptc->dev);
+				if (!buttons)
+					return -ENOMEM;
+				buttons->name = "atmel_ptc_buttons";
+				buttons->dev.parent = ptc->dev;
+				buttons->keycode = ptc->button_keycode;
+				buttons->keycodesize = sizeof(ptc->button_keycode[0]);
+				buttons->keycodemax = ATMEL_PTC_MAX_NODES;
+				ptc->buttons_input = buttons;
+				first_button = false;
+			}
+
+			input_set_capability(buttons, EV_KEY, keycode);
+		} else if (!strcmp(sensor->name, "slider") ||
+			   !strcmp(sensor->name, "wheel")) {
+			u32 scroller_id;
+			struct input_dev *scroller;
+
+			if (of_property_read_u32(sensor, "reg", &scroller_id)) {
+				dev_err(ptc->dev, "reg is missing (%s)\n",
+					sensor->full_name);
+				return -EINVAL;
+			}
+
+			if (scroller_id > ATMEL_PTC_MAX_SCROLLERS - 1) {
+				dev_err(ptc->dev, "wrong scroller id (%s)\n",
+					sensor->full_name);
+				return -EINVAL;
+			}
+
+			scroller = devm_input_allocate_device(ptc->dev);
+			if (!scroller)
+				return -ENOMEM;
+
+			scroller->dev.parent = ptc->dev;
+			ptc->scroller_input[scroller_id] = scroller;
+
+			if (!strcmp(sensor->name, "slider")) {
+				scroller->name = "atmel_ptc_slider";
+				input_set_capability(scroller, EV_ABS, ABS_X);
+				input_set_capability(scroller, EV_KEY, BTN_TOUCH);
+			} else {
+				scroller->name = "atmel_ptc_wheel";
+				input_set_capability(scroller, EV_ABS, ABS_WHEEL);
+				input_set_capability(scroller, EV_KEY, BTN_TOUCH);
+			}
+		} else {
+			dev_err(ptc->dev, "%s is not supported\n", sensor->name);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void atmel_qtm_conf_callback(const struct firmware *conf, void *context)
+{
+	struct atmel_ptc *ptc = context;
+	struct atmel_qtm_cmd qtm_cmd;
+	char *dst;
+	struct atmel_qtm_node_group_config node_group_config;
+
+	if (!conf) {
+		dev_err(ptc->dev, "cannot load QTM configuration, it has to be set manually.\n");
+		return;
+	}
+
+	atmel_ppp_irq_enable(ptc, ATMEL_PPP_IRQ1);
+	atmel_ppp_irq_disable(ptc, ATMEL_PPP_IRQ2 | ATMEL_PPP_IRQ3);
+
+	qtm_cmd.id = ATMEL_QTM_CMD_STOP;
+	atmel_qtm_cmd_send(ptc, &qtm_cmd);
+
+	/* Load QTM configuration. */
+	dst = (char *)ptc->qtm_mb + ATMEL_QTM_MB_NODE_GROUP_CONFIG_OFFSET;
+	/* memcpy doesn't work for an unknown reason. */
+	_memcpy_toio(dst, conf->data, conf->size);
+	release_firmware(conf);
+
+	if (atmel_ptc_of_parse(ptc))
+		dev_err(ptc->dev, "ptc_of_parse failed\n");
+
+	memcpy(&node_group_config,
+	       ptc->qtm_mb + ATMEL_QTM_MB_NODE_GROUP_CONFIG_OFFSET,
+	       sizeof(node_group_config));
+
+	/* Start QTM. */
+	qtm_cmd.id = ATMEL_QTM_CMD_INIT;
+	qtm_cmd.data = node_group_config.count;
+	atmel_qtm_cmd_send(ptc, &qtm_cmd);
+	qtm_cmd.id = ATMEL_QTM_CMD_SET_ACQ_MODE_TIMER;
+	qtm_cmd.data = 20;
+	atmel_qtm_cmd_send(ptc, &qtm_cmd);
+	qtm_cmd.id = ATMEL_QTM_CMD_RUN;
+	qtm_cmd.data = node_group_config.count;
+	atmel_qtm_cmd_send(ptc, &qtm_cmd);
+}
+
+static void atmel_ppp_fw_callback(const struct firmware *fw, void *context)
+{
+	struct atmel_ptc *ptc = context;
+	int ret;
+	struct atmel_qtm_cmd cmd;
+
+	if (!fw || !fw->size) {
+		dev_err(ptc->dev, "cannot load firmware.\n");
+		release_firmware(fw);
+		device_release_driver(ptc->dev);
+		return;
+	}
+
+	/* Command sequence to start from a clean state. */
+	atmel_ppp_cmd_send(ptc, ATMEL_PPP_CMD_ABORT);
+	atmel_ppp_irq_pending_clr(ptc, ATMEL_PPP_IRQ_MASK);
+	atmel_ppp_cmd_send(ptc, ATMEL_PPP_CMD_RESET);
+
+	memcpy(ptc->firmware, fw->data, fw->size);
+	release_firmware(fw);
+
+	atmel_ppp_cmd_send(ptc, ATMEL_PPP_CMD_RUN);
+
+	cmd.id = ATMEL_QTM_CMD_FIRM_VERSION;
+	atmel_qtm_cmd_send(ptc, &cmd);
+	dev_info(ptc->dev, "firmware version: %u\n", cmd.data);
+
+	/* PPP is running, it's time to load the QTM configuration. */
+	ret = request_firmware_nowait(THIS_MODULE, 1, ATMEL_QTM_CONF_NAME, ptc->dev,
+				      GFP_KERNEL, ptc, atmel_qtm_conf_callback);
+	if (ret)
+		dev_err(ptc->dev, "QTM configuration loading failed.\n");
+}
+
+static int atmel_ptc_probe(struct platform_device *pdev)
+{
+	struct atmel_ptc *ptc;
+	struct resource	*res;
+	void *shared_memory;
+	int ret;
+
+	ptc = devm_kzalloc(&pdev->dev, sizeof(*ptc), GFP_KERNEL);
+	if (!ptc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ptc);
+	ptc->dev = &pdev->dev;
+	ptc->dev->driver_data = ptc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	shared_memory = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(shared_memory))
+		return PTR_ERR(shared_memory);
+
+	ptc->firmware = shared_memory;
+	ptc->qtm_mb = shared_memory + ATMEL_QTM_MB_OFFSET;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+
+	ptc->ppp_regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ptc->ppp_regs))
+		return PTR_ERR(ptc->ppp_regs);
+
+	ptc->irq = platform_get_irq(pdev, 0);
+	if (ptc->irq <= 0) {
+		if (!ptc->irq)
+			ptc->irq = -ENXIO;
+
+		return ptc->irq;
+	}
+
+	ptc->clk_per = devm_clk_get(&pdev->dev, "ptc_clk");
+	if (IS_ERR(ptc->clk_per))
+		return PTR_ERR(ptc->clk_per);
+
+	ptc->clk_int_osc = devm_clk_get(&pdev->dev, "ptc_int_osc");
+	if (IS_ERR(ptc->clk_int_osc))
+		return PTR_ERR(ptc->clk_int_osc);
+
+	ptc->clk_slow = devm_clk_get(&pdev->dev, "slow_clk");
+	if (IS_ERR(ptc->clk_slow))
+		return PTR_ERR(ptc->clk_slow);
+
+	ret = devm_request_irq(&pdev->dev, ptc->irq, atmel_ppp_irq_handler, 0,
+			       pdev->dev.driver->name, ptc);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(ptc->clk_int_osc);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(ptc->clk_per);
+	if (ret)
+		goto disable_clk_int_osc;
+
+	ret = clk_prepare_enable(ptc->clk_slow);
+	if (ret)
+		goto disable_clk_per;
+
+	/* Needed to avoid unexpected behaviors. */
+	memset(ptc->firmware, 0, ATMEL_QTM_MB_OFFSET + sizeof(*ptc->qtm_mb));
+	ptc->imr = 0;
+	init_completion(&ptc->ppp_ack);
+
+	/*
+	 * Expose a file to give an access to the QTM mailbox to a user space
+	 * application in order to configure it or to send commands.
+	 */
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, &atmel_ptc_qtm_mb_attr);
+	if (ret)
+		goto disable_clk_slow;
+
+	ret = request_firmware_nowait(THIS_MODULE, 1, ATMEL_PPP_FIRMWARE_NAME,
+				      ptc->dev, GFP_KERNEL, ptc,
+				      atmel_ppp_fw_callback);
+	if (ret) {
+		dev_err(&pdev->dev, "firmware loading failed\n");
+		ret = -EPROBE_DEFER;
+		goto remove_qtm_mb;
+	}
+
+	return 0;
+
+remove_qtm_mb:
+	sysfs_remove_bin_file(&pdev->dev.kobj, &atmel_ptc_qtm_mb_attr);
+disable_clk_slow:
+	clk_disable_unprepare(ptc->clk_slow);
+disable_clk_per:
+	clk_disable_unprepare(ptc->clk_per);
+disable_clk_int_osc:
+	clk_disable_unprepare(ptc->clk_int_osc);
+
+	return ret;
+}
+
+static int atmel_ptc_remove(struct platform_device *pdev)
+{
+	struct atmel_ptc *ptc = platform_get_drvdata(pdev);
+	int i;
+
+	if (ptc->buttons_registered)
+		input_unregister_device(ptc->buttons_input);
+
+	for (i = 0; i < ATMEL_PTC_MAX_SCROLLERS; i++) {
+		struct input_dev *scroller = ptc->scroller_input[i];
+
+		if (!scroller || !ptc->scroller_registered[i])
+			continue;
+		input_unregister_device(scroller);
+	}
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, &atmel_ptc_qtm_mb_attr);
+	clk_disable_unprepare(ptc->clk_slow);
+	clk_disable_unprepare(ptc->clk_per);
+	clk_disable_unprepare(ptc->clk_int_osc);
+
+	return 0;
+}
+
+static const struct of_device_id atmel_ptc_dt_match[] = {
+	{
+		.compatible = "atmel,sama5d2-ptc",
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, atmel_ptc_dt_match);
+
+static struct platform_driver atmel_ptc_driver = {
+	.probe = atmel_ptc_probe,
+	.remove = atmel_ptc_remove,
+	.driver = {
+		.name = "atmel_ptc",
+		.of_match_table = atmel_ptc_dt_match,
+	},
+};
+module_platform_driver(atmel_ptc_driver)
+
+MODULE_AUTHOR("Ludovic Desroches <ludovic.desroches@microchip.com>");
+MODULE_DESCRIPTION("Atmel PTC subsystem");
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(ATMEL_PPP_FIRMWARE_NAME);
+MODULE_FIRMWARE(ATMEL_QTM_CONF_NAME);
-- 
2.9.0

^ permalink raw reply related

* [PATCH v2 1/5] dt-bindings: input: Add Atmel PTC subsystem bindings
From: Ludovic Desroches @ 2017-04-21  8:39 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, devicetree
  Cc: Ludovic Desroches, dmitry.torokhov, alexandre.belloni,
	linux-kernel
In-Reply-To: <20170421083924.15096-1-ludovic.desroches@microchip.com>

Add description of the Atmel PTC subsystem bindings.

Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/input/atmel,ptc.txt        | 67 ++++++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/atmel,ptc.txt

diff --git a/Documentation/devicetree/bindings/input/atmel,ptc.txt b/Documentation/devicetree/bindings/input/atmel,ptc.txt
new file mode 100644
index 0000000..a183fd5
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/atmel,ptc.txt
@@ -0,0 +1,67 @@
+Atmel PTC Subsystem
+
+The Atmel Peripheral Touch Controller subsystem offers built-in hardware
+for capacitive touch measurement on sensors that function as buttons, sliders
+and wheels.
+
+1) PTC Subsystem node
+
+Required properties:
+- compatible: 		Must be "atmel,sama5d2-ptc"
+- reg: 			Address, length of the shared memory and ppp registers location
+			and length.
+- clocks: 		Phandlers to the clocks.
+- clock-names: 		Must be "ptc_clk", "ptc_int_osc", "slow_clk".
+- #address-cells:	Must be one. The cell is the button or scroller id.
+- #size-cells: 		Must be zero.
+
+Example:
+	ptc@fc060000 {
+		compatible = "atmel,sama5d2-ptc";
+		reg = <0x00800000 0x10000
+		       0xfc060000 0xcf>;
+		interrupts = <58 IRQ_TYPE_LEVEL_HIGH 7>;
+		clocks = <&ptc_clk>, <&main>, <&clk32k>;
+		clock-names = "ptc_clk", "ptc_int_osc", "slow_clk";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		[ child node definitions... ]
+	};
+
+2) Scroller / buttons subnodes
+
+Subnodes describe the kind of sensors the customer want to use. They have to be
+named according to their function: button, slider or wheel.
+
+2.1) Scroller subnodes
+
+Required properties:
+- reg:	Id of the scroller, each id must be different.
+
+Example:
+	slider@0 {
+		reg = <0>;
+	};
+
+	wheel@1 {
+		reg = <1>;
+	};
+
+2.2) Button subnodes
+
+Required properties:
+- reg:			Id of node used for the button, each id must be
+			different.
+- linux,keycode: 	Key code of the button.
+
+Example:
+		button@8 {
+			reg = <8>;
+			linux,keycode = <2>;
+		};
+
+		button@9 {
+			reg = <9>;
+			linux,keycode = <3>;
+		};
-- 
2.9.0

^ permalink raw reply related

* [PATCH v2 0/5] Introduce the Atmel PTC subsystem
From: Ludovic Desroches @ 2017-04-21  8:39 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, devicetree
  Cc: dmitry.torokhov, nicolas.ferre, alexandre.belloni, linux-kernel,
	Ludovic Desroches

Hi,

The Atmel Peripheral touch controller subsystem offers built-in hardware for
capacitive touch measurement on sensors that function as buttons, sliders and
wheels. It is available on SAMA5D2.

A firmware and a configuration file describing the topology and the parameters
of the sensor are loaded when probing the driver.

Changes:
- v2:
  - reorder patches to get the bindings documentation in first
  - remove the header from the uapi since it may change in the future. Declare
  only the few structures needed in the driver.
  - add this driver to the sama5_defconfig

Ludovic Desroches (5):
  dt-bindings: input: Add Atmel PTC subsystem bindings
  input: misc: introduce Atmel PTC driver
  MAINTAINERS: add Atmel PTC entries
  ARM: dts: at91: sama5d2: add PTC subsystem device
  ARM: at91/defconfig: add PTC driver to sama5_defconfig

 .../devicetree/bindings/input/atmel,ptc.txt        |  67 ++
 MAINTAINERS                                        |   7 +
 arch/arm/boot/dts/sama5d2.dtsi                     |  16 +
 arch/arm/configs/sama5_defconfig                   |   2 +
 drivers/input/misc/Kconfig                         |  12 +
 drivers/input/misc/Makefile                        |   1 +
 drivers/input/misc/atmel_ptc.c                     | 723 +++++++++++++++++++++
 7 files changed, 828 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/atmel,ptc.txt
 create mode 100644 drivers/input/misc/atmel_ptc.c

-- 
2.9.0

^ permalink raw reply

* [PATCH v2 9/9] ARM: dts: sun6i: Enable tcon0 by default
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

tcon0 contains a muxing register used to mux tcon output to downstream
hdmi or mipi dsi encoders. tcon0 must be available for the mux to be
configured.

Whether the display subsystem is enabled or not is now solely controlled
by the display-engine node.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 1 -
 arch/arm/boot/dts/sun6i-a31.dtsi            | 1 -
 2 files changed, 2 deletions(-)

diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
index b4c87a23e3f8..55607208468b 100644
--- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
+++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
@@ -319,7 +319,6 @@
 &tcon0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&lcd0_rgb888_pins>;
-	status = "okay";
 };
 
 &tcon0_out {
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index dfcf64515d7f..d0cede5aaeb5 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -264,7 +264,6 @@
 				      "tcon-ch0",
 				      "tcon-ch1";
 			clock-output-names = "tcon0-pixel-clock";
-			status = "disabled";
 
 			ports {
 				#address-cells = <1>;
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 8/9] ARM: dts: sun6i: Add second display pipeline device nodes
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

The Allwinner A31/A31s SoCs have 2 display pipelines, as in 2 display
frontends, backends, and tcons each. The relationship between the
backends and tcons are 1:1, but the frontends can feed either backend.

Add device nodes and of graph nodes describing this relationship.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 arch/arm/boot/dts/sun6i-a31.dtsi | 168 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 167 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 9c999d3788f6..dfcf64515d7f 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -232,7 +232,7 @@
 
 	de: display-engine {
 		compatible = "allwinner,sun6i-a31-display-engine";
-		allwinner,pipelines = <&fe0>;
+		allwinner,pipelines = <&fe0>, <&fe1>;
 		status = "disabled";
 	};
 
@@ -289,6 +289,43 @@
 			};
 		};
 
+		tcon1: lcd-controller@01c0d000 {
+			compatible = "allwinner,sun6i-a31-tcon";
+			reg = <0x01c0d000 0x1000>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&ccu RST_AHB1_LCD1>;
+			reset-names = "lcd";
+			clocks = <&ccu CLK_AHB1_LCD1>,
+				 <&ccu CLK_LCD1_CH0>,
+				 <&ccu CLK_LCD1_CH1>;
+			clock-names = "ahb",
+				      "tcon-ch0",
+				      "tcon-ch1";
+			clock-output-names = "tcon1-pixel-clock";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon1_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon1_in_drc1: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&drc1_out_tcon1>;
+					};
+				};
+
+				tcon1_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
@@ -896,6 +933,130 @@
 						reg = <0>;
 						remote-endpoint = <&be0_in_fe0>;
 					};
+
+					fe0_out_be1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&be1_in_fe0>;
+					};
+				};
+			};
+		};
+
+		fe1: display-frontend@01e20000 {
+			compatible = "allwinner,sun6i-a31-display-frontend";
+			reg = <0x01e20000 0x20000>;
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_AHB1_FE1>, <&ccu CLK_FE1>,
+				 <&ccu CLK_DRAM_FE1>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_AHB1_FE1>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				fe1_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					fe1_out_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_in_fe1>;
+					};
+
+					fe1_out_be1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&be1_in_fe1>;
+					};
+				};
+			};
+		};
+
+		be1: display-backend@01e40000 {
+			compatible = "allwinner,sun6i-a31-display-backend";
+			reg = <0x01e40000 0x10000>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_AHB1_BE1>, <&ccu CLK_BE1>,
+				 <&ccu CLK_DRAM_BE1>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_AHB1_BE1>;
+
+			assigned-clocks = <&ccu CLK_BE1>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				be1_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					be1_in_fe0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&fe0_out_be1>;
+					};
+
+					be1_in_fe1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&fe1_out_be1>;
+					};
+				};
+
+				be1_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					be1_out_drc1: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&drc1_in_be1>;
+					};
+				};
+			};
+		};
+
+		drc1: drc@01e50000 {
+			compatible = "allwinner,sun6i-a31-drc";
+			reg = <0x01e50000 0x10000>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_AHB1_DRC1>, <&ccu CLK_IEP_DRC1>,
+				 <&ccu CLK_DRAM_DRC1>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_AHB1_DRC1>;
+
+			assigned-clocks = <&ccu CLK_IEP_DRC1>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				drc1_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					drc1_in_be1: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be1_out_drc1>;
+					};
+				};
+
+				drc1_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					drc1_out_tcon1: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon1_in_drc1>;
+					};
 				};
 			};
 		};
@@ -926,6 +1087,11 @@
 						reg = <0>;
 						remote-endpoint = <&fe0_out_be0>;
 					};
+
+					be0_in_fe1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&fe1_out_be0>;
+					};
 				};
 
 				be0_out: port@1 {
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 7/9] drm/sun4i: tcon: Copy ID from associated backend
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

The tcons and backends have a one-to-one relationship. Their IDs,
or indexes in the documentation, are also the same.

Copy the ID from the associated backend and save it in the tcon
structure. This will later be used when we add support for the
output data path muxes.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 1 +
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 4409e7b6c74d..8301389c411d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -540,6 +540,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	dev_set_drvdata(dev, tcon);
 	tcon->drm = drm;
 	tcon->dev = dev;
+	tcon->id = backend->id;
 	tcon->quirks = of_device_get_match_data(dev);
 
 	tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 1bda4d183eec..d37e1e2ed60e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -174,6 +174,8 @@ struct sun4i_tcon {
 	/* Associated crtc */
 	struct sun4i_crtc		*crtc;
 
+	int				id;
+
 	/* TCON list management */
 	struct list_head		list;
 };
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 6/9] drm/sun4i: tcon: Find matching display backend by device node matching
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

With Allwinner's Display Engine 1.0, each TCON's input is tied to a
specific display backend, and the 2 comprise what is known as a crtc
in DRM KMS land: The layer, framebuffer, and compositing functions are
provided by the backend, while the TCON provides the display timing
signals and vblank interrupts. This 1 to 1 relationship is represented
in the device tree. On some systems there is an intermediate DRC
component.

Pointers to both matching components must be provided when initializing
the crtc. As the backend is always registered before the associated
tcon, we can recursively search upwards through the of_graph to find
the matching backend.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 55 +++++++++++++++++++++++++++++++++++---
 1 file changed, 51 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 52f37ef9a050..4409e7b6c74d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -472,6 +472,53 @@ struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node)
 	return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
 }
 
+/*
+ * On SoCs with the old display pipeline design (Display Engine 1.0),
+ * the TCON is always tied to just one backend. Hence we can traverse
+ * the of_graph upwards to find the backend our tcon is connected to,
+ * and take its ID as our own.
+ *
+ * We can either identify backends from their compatible strings, which
+ * means maintaining a large list of them. Or, since the backend is
+ * registered and binded before the TCON, we can just go through the
+ * list of registered backends and compare the device node.
+ */
+static struct sun4i_backend *sun4i_tcon_find_backend(struct sun4i_drv *drv,
+						     struct device_node *node)
+{
+	struct device_node *port, *ep, *remote;
+	struct sun4i_backend *backend;
+
+	port = of_graph_get_port_by_id(node, 0);
+	if (!port)
+		return ERR_PTR(-EINVAL);
+
+	for_each_available_child_of_node(port, ep) {
+		remote = of_graph_get_remote_port_parent(ep);
+		if (!remote)
+			continue;
+
+		/* does this node match any registered backends? */
+		list_for_each_entry(backend, &drv->backend_list, list) {
+			if (remote == backend->node) {
+				of_node_put(remote);
+				of_node_put(port);
+				return backend;
+			}
+		}
+
+		/* keep looking through upstream ports */
+		backend = sun4i_tcon_find_backend(drv, remote);
+		if (!IS_ERR(backend)) {
+			of_node_put(remote);
+			of_node_put(port);
+			return backend;
+		}
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
 			   void *data)
 {
@@ -481,9 +528,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	struct sun4i_tcon *tcon;
 	int ret;
 
-	/* Wait for a backend to be registered */
-	if (list_empty(&drv->backend_list))
+	backend = sun4i_tcon_find_backend(drv, dev->of_node);
+	if (IS_ERR(backend)) {
+		dev_err(dev, "Couldn't find matching backend\n");
 		return -EPROBE_DEFER;
+	}
 
 	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
 	if (!tcon)
@@ -533,8 +582,6 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	backend = list_first_entry(&drv->backend_list,
-				   struct sun4i_backend, list);
 	tcon->crtc = sun4i_crtc_init(drm, backend, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 5/9] drm/sun4i: backend: Save pointer to device tree node
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

Save a pointer to the backend's underlying device tree node in its
data structure. This will be used later for downstream tcons to find
and match their respective upstream backends.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 1 +
 drivers/gpu/drm/sun4i/sun4i_backend.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 0b4222312e49..e9eca057ff35 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -352,6 +352,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
 
+	backend->node = dev->of_node;
 	backend->id = sun4i_backend_of_get_id(dev->of_node);
 	if (backend->id < 0)
 		return backend->id;
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 45b7fc110590..6327a2985fe6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -15,6 +15,7 @@
 
 #include <linux/clk.h>
 #include <linux/list.h>
+#include <linux/of.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
@@ -140,6 +141,7 @@
 #define SUN4I_BACKEND_PIPE_OFF(p)		(0x5000 + (0x400 * (p)))
 
 struct sun4i_backend {
+	struct device_node	*node;
 	struct regmap		*regs;
 
 	struct reset_control	*reset;
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 4/9] drm/sun4i: backend: Fetch backend ID from device tree
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

Some Allwinner SoCs have 2 display pipelines, as in 2 of each
components, including the frontend, backend, TCON, and any other
extras.

As the backend and TCON are always paired together and form the CRTC,
we need to know which backend or TCON we are currently probing, so we
can pair them when initializing the CRTC.

This patch figures out the backend's ID from the device tree and stores
it in the backend's data structure. It does this by looking at the "reg"
property of any remote endpoints connected to the backend's input port.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 44 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_backend.h |  2 ++
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index e17e20036aa3..0b4222312e49 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -20,6 +20,7 @@
 
 #include <linux/component.h>
 #include <linux/list.h>
+#include <linux/of_graph.h>
 #include <linux/reset.h>
 
 #include "sun4i_backend.h"
@@ -289,6 +290,45 @@ static int sun4i_backend_free_sat(struct device *dev) {
 	return 0;
 }
 
+/*
+ * The display backend can take video output from the display frontend, or
+ * the display enhancement unit on the A80, as input for one it its layers.
+ * This relationship within the display pipeline is encoded in the device
+ * tree with of_graph, and we use it here to figure out which backend, if
+ * there are 2 or more, we are currently probing. The number would be in
+ * the "reg" property of the upstream output port endpoint.
+ */
+static int sun4i_backend_of_get_id(struct device_node *node)
+{
+	struct device_node *port, *ep;
+	int ret = -EINVAL;
+
+	/* input is port 0 */
+	port = of_graph_get_port_by_id(node, 0);
+	if (!port)
+		return -EINVAL;
+
+	/* try finding an upstream endpoint */
+	for_each_available_child_of_node(port, ep) {
+		struct device_node *remote;
+		u32 reg;
+
+		remote = of_parse_phandle(ep, "remote-endpoint", 0);
+		if (!remote)
+			continue;
+
+		ret = of_property_read_u32(remote, "reg", &reg);
+		if (ret)
+			continue;
+
+		ret = reg;
+	}
+
+	of_node_put(port);
+
+	return ret;
+}
+
 static struct regmap_config sun4i_backend_regmap_config = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -312,6 +352,10 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
 
+	backend->id = sun4i_backend_of_get_id(dev->of_node);
+	if (backend->id < 0)
+		return backend->id;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
 	if (IS_ERR(regs))
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 9c8287309c65..45b7fc110590 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -151,6 +151,8 @@ struct sun4i_backend {
 	struct clk		*sat_clk;
 	struct reset_control	*sat_reset;
 
+	int			id;
+
 	/* Backend list management */
 	struct list_head	list;
 };
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 3/9] drm/sun4i: backend: Drop trailing 0 from backend in error message
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

Now that we support multiple instances of backends, the trailing 0
implying only one backend no longer makes sense.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 95a77c6a9161..e17e20036aa3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -320,7 +320,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	backend->regs = devm_regmap_init_mmio(dev, regs,
 					      &sun4i_backend_regmap_config);
 	if (IS_ERR(backend->regs)) {
-		dev_err(dev, "Couldn't create the backend0 regmap\n");
+		dev_err(dev, "Couldn't create the backend regmap\n");
 		return PTR_ERR(backend->regs);
 	}
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 2/9] drm/sun4i: Use lists to track registered display backends and TCONs
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

To support multiple display pipelines, we need to keep track of the
multiple display backends and TCONs registered with the driver.

Switch to lists to track registered components. Components are only
appended to their respective lists if the bind process was successful.
The TCON bind function now defers if a backend was not registered.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c |  6 +++++-
 drivers/gpu/drm/sun4i/sun4i_backend.h |  4 ++++
 drivers/gpu/drm/sun4i/sun4i_drv.c     |  2 ++
 drivers/gpu/drm/sun4i/sun4i_drv.h     |  4 +++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c    | 14 ++++++++++++--
 drivers/gpu/drm/sun4i/sun4i_tcon.h    |  4 ++++
 6 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index d660741ba475..95a77c6a9161 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -19,6 +19,7 @@
 #include <drm/drm_plane_helper.h>
 
 #include <linux/component.h>
+#include <linux/list.h>
 #include <linux/reset.h>
 
 #include "sun4i_backend.h"
@@ -310,7 +311,6 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	if (!backend)
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
-	drv->backend = backend;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
@@ -369,6 +369,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 		}
 	}
 
+	list_add_tail(&backend->list, &drv->backend_list);
+
 	/* Reset the registers */
 	for (i = 0x800; i < 0x1000; i += 4)
 		regmap_write(backend->regs, i, 0);
@@ -400,6 +402,8 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master,
 {
 	struct sun4i_backend *backend = dev_get_drvdata(dev);
 
+	list_del(&backend->list);
+
 	if (of_device_is_compatible(dev->of_node,
 				    "allwinner,sun8i-a33-display-backend"))
 		sun4i_backend_free_sat(dev);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 83e63cc702b4..9c8287309c65 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -14,6 +14,7 @@
 #define _SUN4I_BACKEND_H_
 
 #include <linux/clk.h>
+#include <linux/list.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
@@ -149,6 +150,9 @@ struct sun4i_backend {
 
 	struct clk		*sat_clk;
 	struct reset_control	*sat_reset;
+
+	/* Backend list management */
+	struct list_head	list;
 };
 
 void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 767bbadcc85d..89c51fd6e9af 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -101,6 +101,8 @@ static int sun4i_drv_bind(struct device *dev)
 		goto free_drm;
 	}
 	drm->dev_private = drv;
+	INIT_LIST_HEAD(&drv->backend_list);
+	INIT_LIST_HEAD(&drv->tcon_list);
 
 	ret = of_reserved_mem_device_init(dev);
 	if (ret && ret != -ENODEV) {
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..835bdb5cc0c2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -14,10 +14,12 @@
 #define _SUN4I_DRV_H_
 
 #include <linux/clk.h>
+#include <linux/list.h>
 #include <linux/regmap.h>
 
 struct sun4i_drv {
-	struct sun4i_backend	*backend;
+	struct list_head	backend_list;
+	struct list_head	tcon_list;
 	struct sun4i_tcon	*tcon;
 
 	struct drm_fbdev_cma	*fbdev;
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..52f37ef9a050 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -26,6 +26,7 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
+#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
@@ -476,14 +477,18 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = data;
 	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_backend *backend;
 	struct sun4i_tcon *tcon;
 	int ret;
 
+	/* Wait for a backend to be registered */
+	if (list_empty(&drv->backend_list))
+		return -EPROBE_DEFER;
+
 	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
 	if (!tcon)
 		return -ENOMEM;
 	dev_set_drvdata(dev, tcon);
-	drv->tcon = tcon;
 	tcon->drm = drm;
 	tcon->dev = dev;
 	tcon->quirks = of_device_get_match_data(dev);
@@ -528,7 +533,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+	backend = list_first_entry(&drv->backend_list,
+				   struct sun4i_backend, list);
+	tcon->crtc = sun4i_crtc_init(drm, backend, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
 		ret = PTR_ERR(tcon->crtc);
@@ -539,6 +546,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	if (ret < 0)
 		goto err_free_clocks;
 
+	list_add_tail(&tcon->list, &drv->tcon_list);
+
 	return 0;
 
 err_free_dotclock:
@@ -555,6 +564,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
 {
 	struct sun4i_tcon *tcon = dev_get_drvdata(dev);
 
+	list_del(&tcon->list);
 	sun4i_dclk_free(tcon);
 	sun4i_tcon_free_clocks(tcon);
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f636343a935d..1bda4d183eec 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -17,6 +17,7 @@
 #include <drm/drm_crtc.h>
 
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/reset.h>
 
 #define SUN4I_TCON_GCTL_REG			0x0
@@ -172,6 +173,9 @@ struct sun4i_tcon {
 
 	/* Associated crtc */
 	struct sun4i_crtc		*crtc;
+
+	/* TCON list management */
+	struct list_head		list;
 };
 
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 1/9] dt-bindings: display: sun4i: Add component endpoint ID numbering scheme
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20170421083857.29636-1-wens-jdAy2FN1RRM@public.gmane.org>

The Allwinner display pipeline contains many hardware components, some
of which can consume data from one of multiple upstream components.
The numbering scheme of these components must be encoded into the device
tree so the driver can figure out which component out of two or more of
the same type it is supposed to use or program.

This patch adds the constraint that local endpoint IDs must be the index
or number of the remote endpoint's hardware block, for all components
in the display pipeline up to the TCONs.

Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
 Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 57a8d0610062..7acdbf14ae1c 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -4,6 +4,16 @@ Allwinner A10 Display Pipeline
 The Allwinner A10 Display pipeline is composed of several components
 that are going to be documented below:
 
+For the input port of all components up to the TCON in the display
+pipeline, if there are multiple components, the local endpoint IDs
+must correspond to the index of the upstream block. For example, if
+the remote endpoint is Frontend 1, then the local endpoint ID must
+be 1.
+
+Conversely, for the output ports of the same group, the remote endpoint
+ID must be the index of the local hardware block. If the local backend
+is backend 1, then the remote endpoint ID must be 1.
+
 TV Encoder
 ----------
 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v2 0/9] drm/sun4i: Support multiple display pipelines
From: Chen-Yu Tsai @ 2017-04-21  8:38 UTC (permalink / raw)
  To: Maxime Ripard, David Airlie, Rob Herring, Mark Rutland
  Cc: Chen-Yu Tsai, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

Hi,

This is v2 of the series previously named "drm/sun4i: Support two
display pipelines". As the name change suggests, the driver now
supports any number of pipelines, though the hardware only has
2 or 3.

Changes since v1:

  - Add component endpoint ID numbering scheme to device tree binding.

  - Use lists to keep references to registered backends and tcons.

  - Save pointer to device node for backends.

  - Traverse the device tree of_graph starting from the tcons, going
    up towards the inputs, and matching the device nodes with the
    device nodes of registered backends, to find the one linked with
    the tcon the search started from.

  - Copy the ID for the tcon from its upstream backend, instead of
    trying, and possibly failing, to figure it out from the device
    tree.

  - Split out hunk dropping trailing 0 from a backend error message.

Patch 1 adds the component endpoint ID numbering scheme to the
device tree binding. New in v2.

Patch 2 adds lists to track registered display backends and TCONs,
instead of just one pointer per component type. Previously added
arrays of pointers in v1.

Patch 3 drops the trailing 0 from one of the backend's bind error
messages. This was previously part of the patch "drm/sun4i: Support
two display pipelines".

Patch 4 adds a function to fetch a backend's ID from the device tree.
Unchanged.

Patch 5 adds a device node field to the backend data structure and
saves a reference to the underlying device node of the backend.
New in v2.

Patch 6 makes the tcon driver find its upstream backend by traversing
the of_graph and matching device nodes against the device nodes of
registered backends.
New in v2.

Patch 7 makes the tcon driver use the ID from its associated backend.
New in v2. This is not immediately used in this series, but will be
used in similar fashion for downstream encoders to figure out IDs and
muxing

Patch 8 adds device nodes for sun6i's second display pipeline.
Unchanged.

Patch 9 enables sun6i's tcon0 by default.
Unchanged.

With this series, the sun4i drm driver now supports registering multiple
display pipelines. However the driver does not guard against setups the
hardware does not support, such as driving 2 encoders with incompatible
dot clocks from the same source clock. Muxing of downstream encoders is
not supported either, as we have no drivers for hardware that uses them.
The WiP HDMI driver will be the first.

While this series enables the second display pipeline, there's no
usable output at the moment. For the A31, the second TCON's panel
interface uses the same pins as the Ethernet controller. However
Ethernet is used on most boards.


Regards
ChenYu


Chen-Yu Tsai (9):
  dt-bindings: display: sun4i: Add component endpoint ID numbering
    scheme
  drm/sun4i: Use lists to track registered display backends and TCONs
  drm/sun4i: backend: Drop trailing 0 from backend in error message
  drm/sun4i: backend: Fetch backend ID from device tree
  drm/sun4i: backend: Save pointer to device tree node
  drm/sun4i: tcon: Find matching display backend by device node matching
  drm/sun4i: tcon: Copy ID from associated backend
  ARM: dts: sun6i: Add second display pipeline device nodes
  ARM: dts: sun6i: Enable tcon0 by default

 .../bindings/display/sunxi/sun4i-drm.txt           |  10 ++
 arch/arm/boot/dts/sun6i-a31-hummingbird.dts        |   1 -
 arch/arm/boot/dts/sun6i-a31.dtsi                   | 169 ++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_backend.c              |  53 ++++++-
 drivers/gpu/drm/sun4i/sun4i_backend.h              |   8 +
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |   2 +
 drivers/gpu/drm/sun4i/sun4i_drv.h                  |   4 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |  62 +++++++-
 drivers/gpu/drm/sun4i/sun4i_tcon.h                 |   6 +
 9 files changed, 307 insertions(+), 8 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: [PATCH v4 06/11] drm/sun4i: add support for Allwinner DE2 mixers
From: icenowy-h8G6r0blFSE @ 2017-04-21  8:18 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Maxime Ripard
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Jernej Skrabec, David Airlie,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Rob Herring, Chen-Yu Tsai,
	linux-clk-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170420083707.wdtrdlxpvocpzc7g@lukather>


于 2017年4月20日 GMT+08:00 下午4:37:07, Maxime Ripard 
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> 写到:
> On Tue, Apr 18, 2017 at 06:47:56PM +0800, Icenowy Zheng wrote:
>> >> +	/* Get the physical address of the buffer in memory */
>> >> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
>> >> +
>> >> +	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
>> >> +
>> >> +	/* Compute the start of the displayed memory */
>> >> +	bpp = fb->format->cpp[0];
>> >> +	paddr = gem->paddr + fb->offsets[0];
>> >> +	paddr += (state->src_x >> 16) * bpp;
>> >> +	paddr += (state->src_y >> 16) * fb->pitches[0];
>> >> +
>> >> +	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
>> >> +
>> >> +	paddr_u32 = (uint32_t) paddr;
>> >
>> >How does that work on 64-bits systems ?
>> 
>> The hardware is not designed to work on 64-bit systems.
>> 
>> Even 64-bit A64/H5 has also 3GiB memory limit.
> 
> That's a fragile assumption.

Yes, it's only the basical reason.

> 
>> The address cell in mixer hardware is also only 32-bit.
>> 
>> So we should just keep the force conversion here. If we then really
>> met 4GiB-capable AW SoC without changing DE2, I think we should have
>> other way to limit CMA pool inside 4GiB.
> 
> The register name looks like this is only the lower 32 bits that you
> can set here, and that there is another register for the upper 32 bits
> of that address somewhere.

Maybe... but no one can verify this as their's no currently any user
which has 4GiB+ DRAM.

I think we should keep this until Allwinner really made a 4GiB-capable
hardware.

> 
> In that case, please use the lower_32_bits and upper_32_bits helper,
> and don't cast it that way.
> 
> If it isn't the case, you should set the DMA mask (through
> dma_set_mask) so that we only allocate memory that can be accessed by
> this device.

How to do it?

> 
> Maxime

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* Re: [PATCH] media: mtk-vcodec: remove informative log
From: Tiffany Lin @ 2017-04-21  8:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: devicetree, daniel.thompson, Minghsiu Tsai, srv_heupstream,
	Wu-Cheng Li, linux-mediatek, linux-kernel, Daniel Kurtz,
	Rob Herring, Hans Verkuil, linux-arm-kernel, Matthias Brugger,
	Yingjoe Chen, Eddie Huang, Pawel Osciak, linux-media
In-Reply-To: <20170419075643.0a04af21@vento.lan>

On Wed, 2017-04-19 at 07:56 -0300, Mauro Carvalho Chehab wrote:
> Em Wed, 5 Apr 2017 19:09:59 +0800
> Tiffany Lin <tiffany.lin@mediatek.com> escreveu:
> 
> > On Wed, 2017-04-05 at 18:54 +0800, Minghsiu Tsai wrote:
> > > Driver is stable. Remove DEBUG definition from driver.
> > > 
> > > There are debug message in /var/log/messages if DEBUG is defined,
> > > such as:
> > > [MTK_V4L2] level=0 fops_vcodec_open(),170: decoder capability 0
> > > [MTK_V4L2] level=0 fops_vcodec_open(),177: 16000000.vcodec decoder [0]
> > > [MTK_V4L2] level=0 fops_vcodec_release(),200: [0] decoder
> > > 
> > > Signed-off-by: Minghsiu Tsai <minghsiu.tsai@mediatek.com>  
> > Acked-by:Tiffany Lin <Tiffany.lin@mediatek.com>
> > 
> > > ---
> > >  drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h | 1 -
> > >  1 file changed, 1 deletion(-)
> > > 
> > > diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
> > > index 7d55975..1248083 100644
> > > --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
> > > +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
> > > @@ -31,7 +31,6 @@ struct mtk_vcodec_mem {
> > >  extern int mtk_v4l2_dbg_level;
> > >  extern bool mtk_vcodec_dbg;
> > >  
> > > -#define DEBUG	1
> > >  
> > >  #if defined(DEBUG)
> > >    
> 
> After this patch, building the Kernel with W=1 now shows warnings:
> 
> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c: In function 'mtk_vcodec_dec_pw_on':
> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c:114:51: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
>    mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
>                                                    ^
> 
> I wrote a patch fixing it, as this is really a trivial issue.
> 
> Yet, after that, this one still remains:
> 
> 
> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c: In function 'mtk_vdec_pic_info_update':
> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c:284:6: warning: variable 'ret' set but not used [-Wunused-but-set-variable]
>   int ret;
>       ^~~
> 


> 
> Shouldn't be mtk_vdec_pic_info_update() returning an error code?
> 
> 
> Also, IMHO, at least errors should be shown at dmesg.
> 
Got it. We will upstream patch to fix warning and add dmesg when error.


best regards,
Tiffany

> Thanks,
> Mauro

^ permalink raw reply

* [PATCH 2/2 v3 resend] dt-bindings: display: imx: entry for AUS mode
From: Martin Kaiser @ 2017-04-21  7:45 UTC (permalink / raw)
  To: linux-fbdev
  Cc: Bartlomiej Zolnierkiewicz, Sascha Hauer, linux-kernel,
	Rob Herring, Mark Rutland, devicetree, Martin Kaiser
In-Reply-To: <1492760753-8374-1-git-send-email-martin@kaiser.cx>

Allow setting the AUS mode for a display from the device tree.
Use an optional boolean property. AUS mode can be set only on imx21
and compatible chipsets.

Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Acked-by: Rob Herring <robh@kernel.org>
---
re-sending v3, rebased against current linux-next
it seems this got lost along the way, there was a bit of confusion
whether to split this in two patches or not

v3:
   use a boolean DT property instead of the register value
   separate patches for DT binding and code changes

v2:
   re-sending DT bindings and code changes as one patch

 Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt b/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
index 7a5c0e2..cacae0e 100644
--- a/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
@@ -13,6 +13,8 @@ Required nodes:
 	Additional, the display node has to define properties:
 	- bits-per-pixel: Bits per pixel
 	- fsl,pcr: LCDC PCR value
+	A display node may optionally define
+	- fsl,aus_mode: boolean to enable AUS mode (only for imx21)
 
 Optional properties:
 - lcd-supply: Regulator for LCD supply voltage.
-- 
2.1.4

^ permalink raw reply related

* [PATCH 1/2 v3 resend] video: fbdev: imxfb: support AUS mode
From: Martin Kaiser @ 2017-04-21  7:45 UTC (permalink / raw)
  To: linux-fbdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Bartlomiej Zolnierkiewicz, Sascha Hauer,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Martin Kaiser
In-Reply-To: <1488193030-13064-1-git-send-email-martin-XxZfDwE/svGeZLLa646FqQ@public.gmane.org>

Some displays require setting AUS mode in the LDCD AUS Mode Control
Register to work with the imxfb driver. Like the value of the Panel
Configuration Register, the AUS mode setting depends on the display
mode.

Allow setting AUS mode from the device tree by adding a boolean
property. Make this property optional to keep the DT ABI stable.
AUS mode can be set only on imx21 and compatible chipsets.

Signed-off-by: Martin Kaiser <martin-XxZfDwE/svGeZLLa646FqQ@public.gmane.org>
---
re-sending v3, rebased against current linux-next
it seems this got lost along the way, there was a bit of confusion
whether to split this in two patches or not

v3:
   use a boolean DT property instead of the register value
   separate patches for DT binding and code changes

v2:
   re-sending DT bindings and code changes as one patch

 drivers/video/fbdev/imxfb.c               | 17 +++++++++++++++++
 include/linux/platform_data/video-imxfb.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index 1b0faad..463fbf2 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -117,6 +117,9 @@
 
 #define IMXFB_LSCR1_DEFAULT 0x00120300
 
+#define LCDC_LAUSCR	0x80
+#define LAUSCR_AUS_MODE	(1<<31)
+
 /* Used fb-mode. Can be set on kernel command line, therefore file-static. */
 static const char *fb_mode;
 
@@ -158,6 +161,7 @@ struct imxfb_info {
 	dma_addr_t		dbar2;
 
 	u_int			pcr;
+	u_int			lauscr;
 	u_int			pwmr;
 	u_int			lscr1;
 	u_int			dmacr;
@@ -422,6 +426,11 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 	pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
 
 	fbi->pcr = pcr;
+	/*
+	 * The LCDC AUS Mode Control Register does not exist on imx1.
+	 */
+	if (!is_imx1_fb(fbi) && imxfb_mode->aus_mode)
+		fbi->lauscr = LAUSCR_AUS_MODE;
 
 	/*
 	 * Copy the RGB parameters for this display
@@ -638,6 +647,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
 	if (fbi->dmacr)
 		writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
 
+	if (fbi->lauscr)
+		writel(fbi->lauscr, fbi->regs + LCDC_LAUSCR);
+
 	return 0;
 }
 
@@ -734,6 +746,11 @@ static int imxfb_of_read_mode(struct device *dev, struct device_node *np,
 	imxfb_mode->bpp = bpp;
 	imxfb_mode->pcr = pcr;
 
+	/*
+	 * fsl,aus_mode is optional
+	 */
+	imxfb_mode->aus_mode = of_property_read_bool(np, "fsl,aus_mode");
+
 	return 0;
 }
 
diff --git a/include/linux/platform_data/video-imxfb.h b/include/linux/platform_data/video-imxfb.h
index a5c0a71..cf9348b 100644
--- a/include/linux/platform_data/video-imxfb.h
+++ b/include/linux/platform_data/video-imxfb.h
@@ -50,6 +50,7 @@
 struct imx_fb_videomode {
 	struct fb_videomode mode;
 	u32 pcr;
+	bool aus_mode;
 	unsigned char	bpp;
 };
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH v6 0/6] add support for AXP20X and AXP22X battery power supply driver
From: Maxime Ripard @ 2017-04-21  7:43 UTC (permalink / raw)
  To: Quentin Schulz
  Cc: sre-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, wens-jdAy2FN1RRM,
	linux-I+IVW8TIWO2tmTQ+vhA3Yw, linux-pm-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, icenowy-ymACFijhrKM,
	liam-RYWXG+zxWwBdeoIcmNTgJF6hYfS7NtTn,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170418073421.31351-1-quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 6108 bytes --]

On Tue, Apr 18, 2017 at 09:34:15AM +0200, Quentin Schulz wrote:
> This is a series for AXP20X and AXP22X battery power supply without the
> support for changing constant charge current from the DT. The patches for
> supporting the constant charge current from DT are ready and will be sent
> once the battery framework required to make this work has been merged.
> 
> v6:
>   - removed mention to fixed battery in DT-binding documentation,
> 
> Quote from v4 cover letter:
> 
> The X-Powers AXP20X and AXP22X PMICs have multiple ADCs. They expose
> information and data of the various power supplies they support such as
> ACIN, battery and VBUS. For example, they expose the current battery
> voltage, charge or discharge, as well as ACIN and VBUS current voltages
> and currents, internal PMIC temperature and ADC on 2 different GPIOs
> when in the right mode (for the AXP209 only).
> 
> The ACIN power supply driver is added by this patch. The AXP20X and
> AXP22X can both read the status and the "usability" of the power supply
> but only the AXP209 will be able to tell the current current and voltage
> of the power supply by reading ADC channels. It is simply not supported
> by the AXP22X PMICs.
> 
> The battery power supply driver is also added by this patch. The AXP20X
> and AXP22X share most of their behaviour but have slight variations. The
> allowed target voltages for battery charging are not the same, the
> AXP22X PMIC are able to tell if the battery percentage computed by the
> PMIC is trustworthy and they have different formulas for computing max
> current for battery power supply. The driver is able to give the current
> voltage and current of the battery (be it charging or discharging), the
> maximal and minimal voltage and maximal current allowed for the battery,
> whether the battery is present and usable and its capacity. It will get
> the battery current current and voltage by reading the ADC channels. The
> PMIC allows maximal voltages (4.36V for AXP20X and 4.22V and 4.24V for
> AXP22X) that should not be used with Lithium-based batteries and since
> this PMIC is supposed to be used with Lithium-based batteries, they have
> been disabled. The values returned by the ADC driver are multipled by
> 1000 to scale from the mV returned by the ADC to the uV expected by the
> power supply framework.
> 
> This series of patch adds DT bindings for ACIN power supply, ADC and
> battery power supply drivers for AXP20X and AXP22X PMICs and their
> documentation. It also enables the supported power supplies for the
> Nextthing Co. CHIP and Sinlinx SinA33 boards.
> 
> The different drivers are also added to the MFD cells of the AXP20X and
> AXP22X cells and the writeable and volatile regs updated to work with
> the newly added drivers.
> 
> This series of patch is based on a previous upstreaming attempt done by
> Bruno Prémont few months ago. It differs in three points: the ADC
> driver does not tell the battery temperature (TS_IN) as I do not have a
> board to test it with, it does not tell the instantaneous battery power
> as it returns crazy values for me and finally no support for OCV curves
> for the battery.
> 
> You can test these patches from this repo and branch:
> https://github.com/QSchulz/linux/tree/axp2xx_adc_batt_ac_v4
> 
> v4:
>  - added the ability to set maximum constant charge current from sysfs,
>  - added a warning when setting a higher than current maximum constant charge
>  current,
>  - set default to minimum possible value for current and maximum constant charge
>  current when no battery DT is present or invalid battery DT,
>  - fixed a forgotten custom formula to compute maximum constant charge current
>  for AXP22X,
>  - automatically lower the current constant charge current when it is higher
>  than the maximum constant charge current about to be set,
> 
> v3:
>  - Removed DT property for constant charge current in favor of the WIP
>  battery framework as requested by Sebastian Reichel,
>  - Using a simple if condition instead of a switch in the ADC driver,
>  - Fixed error handling in ADC driver's probe,
>  - Fixed missing call to iio_map_array_unregister in the ADC driver's
>  remove,
>  - Removed ADC driver's DT node and documentation,
>  - Merged IIO channel mapping patches into the original ADC driver
>  patch,
>  - Removed `adding V-OFF to writeable reg' patch as it's already in
>  writeable reg range,
> 
> v2:
>  - Some registers' name have been changed to better reflect their
>  purpose,
>  - Make VBUS power supply driver use IIO channels when AXP ADC driver is
>  enabled, but fall back on previous behavior when disabled. This is made
>  to avoid the ADC driver overwritting registers for VBUS power supply
>  ADC when removed,
>  - Removed useless adding of data registers to volatile registers,
>  - Reordered IIO channels, now grouped by same part of the PMIC (e.g.
>  voltage and current of the battery have the same index in different
>  IIO types),
>  - Added structures for specific data instead of matching on IDs,
>  - Switched from DT IIO channels mapping to iio_map structures IIO
>  channels mapping,
> 
> Quentin
> 
> Quentin Schulz (6):
>   dt-bindings: power: supply: add AXP20X/AXP22X battery DT binding
>   power: supply: add battery driver for AXP20X and AXP22X PMICs
>   ARM: dtsi: axp209: add battery power supply subnode
>   ARM: dtsi: axp22x: add battery power supply subnode
>   ARM: dts: sun8i: sina33: enable battery power supply subnode
>   ARM: sun5i: chip: enable battery power supply subnode

Applied the last 4 patches.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox