linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] drm/fsl-dcu: add TCON and Vybrid support
@ 2015-12-18  7:43 Stefan Agner
  2015-12-18  7:43 ` [PATCH 1/4] ARM: dts: vf610: add display nodes Stefan Agner
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Stefan Agner @ 2015-12-18  7:43 UTC (permalink / raw)
  To: airlied, daniel.vetter, jianwei.wang.chn
  Cc: alison.wang, mark.yao, dri-devel, linux-kernel, Stefan Agner

This patchset adds the missing pieces to make the Freescale
DCU DRM driver work on Freescale Vybrid.

Foremost, it adds support for the timing controller (TCON)
module. The module is between the Display Controller and the
actual output pins. It allows to alter the timings for RAW
TFT displays, but can also operate in a bypass mode. This
change has only support for the bypass mode.

Earlier variants of the DCU DRM driver configured the TCON
module in bypass mode, however this has been removed and
postponed. The last variant with the TCON code was v9:
https://lkml.org/lkml/2015/7/13/242

This change is an attempt to implement a proper driver.
Ideas have been taken from the sun4i Tcon driver:
https://lkml.org/lkml/2015/10/30/369

The patchset depends on my fsl-dcu fixes patchset:
https://lkml.org/lkml/2015/11/18/953

Stefan Agner (4):
  ARM: dts: vf610: add display nodes
  ARM: dts: vf610-colibri: enable display controller
  ARM: clk: vf610: add TCON ipg clock
  drm/fsl-dcu: add TCON driver

 .../devicetree/bindings/display/fsl,dcu.txt        |   4 +
 .../devicetree/bindings/display/fsl,tcon.txt       |  18 +++
 arch/arm/boot/dts/vf-colibri-eval-v3.dtsi          |  16 +++
 arch/arm/boot/dts/vf-colibri.dtsi                  |  33 +++++
 arch/arm/boot/dts/vfxxx.dtsi                       |  18 +++
 drivers/clk/imx/clk-vf610.c                        |   3 +
 drivers/gpu/drm/fsl-dcu/Makefile                   |   3 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c          |   6 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h          |   1 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  11 ++
 drivers/gpu/drm/fsl-dcu/fsl_tcon.c                 | 134 +++++++++++++++++++++
 drivers/gpu/drm/fsl-dcu/fsl_tcon.h                 |  37 ++++++
 include/dt-bindings/clock/vf610-clock.h            |   4 +-
 13 files changed, 286 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/fsl,tcon.txt
 create mode 100644 drivers/gpu/drm/fsl-dcu/fsl_tcon.c
 create mode 100644 drivers/gpu/drm/fsl-dcu/fsl_tcon.h

-- 
2.6.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] ARM: dts: vf610: add display nodes
  2015-12-18  7:43 [PATCH 0/4] drm/fsl-dcu: add TCON and Vybrid support Stefan Agner
@ 2015-12-18  7:43 ` Stefan Agner
  2015-12-18  7:43 ` [PATCH 2/4] ARM: dts: vf610-colibri: enable display controller Stefan Agner
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Agner @ 2015-12-18  7:43 UTC (permalink / raw)
  To: airlied, daniel.vetter, jianwei.wang.chn
  Cc: alison.wang, mark.yao, dri-devel, linux-kernel, Stefan Agner

Add the dcu and tcon nodes to enable the Display Controller Unit
and Timing Controller in Vybrid's SoC level device-tree file.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/boot/dts/vfxxx.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 6736bae..8972c1c 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -232,6 +232,14 @@
 							<20000000>;
 			};
 
+			tcon0: timing-controller@4003d000 {
+				compatible = "fsl,vf610-tcon";
+				reg = <0x4003d000 0x1000>;
+				clocks = <&clks VF610_CLK_TCON0>;
+				clock-names = "ipg";
+				status = "disabled";
+			};
+
 			wdoga5: wdog@4003e000 {
 				compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
 				reg = <0x4003e000 0x1000>;
@@ -337,6 +345,16 @@
 				status = "disabled";
 			};
 
+			dcu0: dcu@40058000 {
+				compatible = "fsl,vf610-dcu";
+				reg = <0x40058000 0x1200>;
+				interrupts = <30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks VF610_CLK_DCU0>;
+				clock-names = "dcu";
+				fsl,tcon = <&tcon0>;
+				status = "disabled";
+			};
+
 			i2c0: i2c@40066000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] ARM: dts: vf610-colibri: enable display controller
  2015-12-18  7:43 [PATCH 0/4] drm/fsl-dcu: add TCON and Vybrid support Stefan Agner
  2015-12-18  7:43 ` [PATCH 1/4] ARM: dts: vf610: add display nodes Stefan Agner
@ 2015-12-18  7:43 ` Stefan Agner
  2015-12-18  7:43 ` [PATCH 3/4] ARM: clk: vf610: add TCON ipg clock Stefan Agner
  2015-12-18  7:43 ` [PATCH 4/4] drm/fsl-dcu: add TCON driver Stefan Agner
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Agner @ 2015-12-18  7:43 UTC (permalink / raw)
  To: airlied, daniel.vetter, jianwei.wang.chn
  Cc: alison.wang, mark.yao, dri-devel, linux-kernel, Stefan Agner

Enable dcu node which is used by the DCU DRM driver. Assign the 5.7"
EDT panel with VGA resolution which Toradex sells often with the
evaluation board.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/boot/dts/vf-colibri-eval-v3.dtsi | 16 +++++++++++++++
 arch/arm/boot/dts/vf-colibri.dtsi         | 33 +++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
index ed65e0f..f5d4c78 100644
--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -18,6 +18,11 @@
 		clock-frequency = <16000000>;
 	};
 
+	panel: panel {
+		compatible = "edt,et057090dhu";
+		backlight = <&bl>;
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -53,6 +58,13 @@
 	status  = "okay";
 };
 
+&dcu0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_dcu0_1>;
+	fsl,panel = <&panel>;
+	status = "okay";
+};
+
 &dspi1 {
 	status = "okay";
 
@@ -100,6 +112,10 @@
 	status = "okay";
 };
 
+&tcon0 {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi
index e5949b9..c1afb4e 100644
--- a/arch/arm/boot/dts/vf-colibri.dtsi
+++ b/arch/arm/boot/dts/vf-colibri.dtsi
@@ -133,6 +133,39 @@
 			>;
 		};
 
+		pinctrl_dcu0_1: dcu0grp_1 {
+			fsl,pins = <
+				VF610_PAD_PTE0__DCU0_HSYNC	0x1902
+				VF610_PAD_PTE1__DCU0_VSYNC	0x1902
+				VF610_PAD_PTE2__DCU0_PCLK	0x1902
+				VF610_PAD_PTE4__DCU0_DE		0x1902
+				VF610_PAD_PTE5__DCU0_R0		0x1902
+				VF610_PAD_PTE6__DCU0_R1		0x1902
+				VF610_PAD_PTE7__DCU0_R2		0x1902
+				VF610_PAD_PTE8__DCU0_R3		0x1902
+				VF610_PAD_PTE9__DCU0_R4		0x1902
+				VF610_PAD_PTE10__DCU0_R5	0x1902
+				VF610_PAD_PTE11__DCU0_R6	0x1902
+				VF610_PAD_PTE12__DCU0_R7	0x1902
+				VF610_PAD_PTE13__DCU0_G0	0x1902
+				VF610_PAD_PTE14__DCU0_G1	0x1902
+				VF610_PAD_PTE15__DCU0_G2	0x1902
+				VF610_PAD_PTE16__DCU0_G3	0x1902
+				VF610_PAD_PTE17__DCU0_G4	0x1902
+				VF610_PAD_PTE18__DCU0_G5	0x1902
+				VF610_PAD_PTE19__DCU0_G6	0x1902
+				VF610_PAD_PTE20__DCU0_G7	0x1902
+				VF610_PAD_PTE21__DCU0_B0	0x1902
+				VF610_PAD_PTE22__DCU0_B1	0x1902
+				VF610_PAD_PTE23__DCU0_B2	0x1902
+				VF610_PAD_PTE24__DCU0_B3	0x1902
+				VF610_PAD_PTE25__DCU0_B4	0x1902
+				VF610_PAD_PTE26__DCU0_B5	0x1902
+				VF610_PAD_PTE27__DCU0_B6	0x1902
+				VF610_PAD_PTE28__DCU0_B7	0x1902
+			>;
+		};
+
 		pinctrl_dspi1: dspi1grp {
 			fsl,pins = <
 				VF610_PAD_PTD5__DSPI1_CS0		0x33e2
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] ARM: clk: vf610: add TCON ipg clock
  2015-12-18  7:43 [PATCH 0/4] drm/fsl-dcu: add TCON and Vybrid support Stefan Agner
  2015-12-18  7:43 ` [PATCH 1/4] ARM: dts: vf610: add display nodes Stefan Agner
  2015-12-18  7:43 ` [PATCH 2/4] ARM: dts: vf610-colibri: enable display controller Stefan Agner
@ 2015-12-18  7:43 ` Stefan Agner
  2015-12-18  7:43 ` [PATCH 4/4] drm/fsl-dcu: add TCON driver Stefan Agner
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Agner @ 2015-12-18  7:43 UTC (permalink / raw)
  To: airlied, daniel.vetter, jianwei.wang.chn
  Cc: alison.wang, mark.yao, dri-devel, linux-kernel, Stefan Agner

Add the ipg (bus) clock for the TCON modules (Timing Controller). This
module is required by the new DCU DRM driver, since the display signals
pass through TCON.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 drivers/clk/imx/clk-vf610.c             | 3 +++
 include/dt-bindings/clock/vf610-clock.h | 4 +++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
index d1b1c95..cb86245 100644
--- a/drivers/clk/imx/clk-vf610.c
+++ b/drivers/clk/imx/clk-vf610.c
@@ -327,6 +327,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 	clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3);
 	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8));
 
+	clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13));
+	clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13));
+
 	clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4);
 	clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30);
 	clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", CCM_CSCDR2, 24, 4);
diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h
index 56c16aa..fbe17cc 100644
--- a/include/dt-bindings/clock/vf610-clock.h
+++ b/include/dt-bindings/clock/vf610-clock.h
@@ -195,6 +195,8 @@
 #define VF610_CLK_SNVS			182
 #define VF610_CLK_DAP			183
 #define VF610_CLK_OCOTP         184
-#define VF610_CLK_END			185
+#define VF610_CLK_TCON0			185
+#define VF610_CLK_TCON1			186
+#define VF610_CLK_END			187
 
 #endif /* __DT_BINDINGS_CLOCK_VF610_H */
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] drm/fsl-dcu: add TCON driver
  2015-12-18  7:43 [PATCH 0/4] drm/fsl-dcu: add TCON and Vybrid support Stefan Agner
                   ` (2 preceding siblings ...)
  2015-12-18  7:43 ` [PATCH 3/4] ARM: clk: vf610: add TCON ipg clock Stefan Agner
@ 2015-12-18  7:43 ` Stefan Agner
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Agner @ 2015-12-18  7:43 UTC (permalink / raw)
  To: airlied, daniel.vetter, jianwei.wang.chn
  Cc: alison.wang, mark.yao, dri-devel, linux-kernel, Stefan Agner

Add driver for the TCON (timing controller) module. The TCON module
is a separate module attached after the DCU (display controller
unit). Each DCU instance has its own, directly connected TCON
instance. The DCU's RGB and timing signals are passing through
the TCON module. TCON can provide timing signals for raw TFT panels
or operate in a bypass mode which leaves all signals unaltered.

The driver currently only supports the bypass mode.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 .../devicetree/bindings/display/fsl,dcu.txt        |   4 +
 .../devicetree/bindings/display/fsl,tcon.txt       |  18 +++
 drivers/gpu/drm/fsl-dcu/Makefile                   |   3 +-
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c          |   6 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h          |   1 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  11 ++
 drivers/gpu/drm/fsl-dcu/fsl_tcon.c                 | 134 +++++++++++++++++++++
 drivers/gpu/drm/fsl-dcu/fsl_tcon.h                 |  37 ++++++
 8 files changed, 213 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/display/fsl,tcon.txt
 create mode 100644 drivers/gpu/drm/fsl-dcu/fsl_tcon.c
 create mode 100644 drivers/gpu/drm/fsl-dcu/fsl_tcon.h

diff --git a/Documentation/devicetree/bindings/display/fsl,dcu.txt b/Documentation/devicetree/bindings/display/fsl,dcu.txt
index ebf1be9..8153c9a 100644
--- a/Documentation/devicetree/bindings/display/fsl,dcu.txt
+++ b/Documentation/devicetree/bindings/display/fsl,dcu.txt
@@ -11,6 +11,9 @@ Required properties:
 - big-endian		Boolean property, LS1021A DCU registers are big-endian.
 - fsl,panel:		The phandle to panel node.
 
+Optional properties:
+- fsl,tcon:		The phandle to the timing controller node.
+
 Examples:
 dcu: dcu@2ce0000 {
 	compatible = "fsl,ls1021a-dcu";
@@ -19,4 +22,5 @@ dcu: dcu@2ce0000 {
 	clock-names = "dcu";
 	big-endian;
 	fsl,panel = <&panel>;
+	fsl,tcon = <&tcon>;
 };
diff --git a/Documentation/devicetree/bindings/display/fsl,tcon.txt b/Documentation/devicetree/bindings/display/fsl,tcon.txt
new file mode 100644
index 0000000..2e1015e
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/fsl,tcon.txt
@@ -0,0 +1,18 @@
+Device Tree bindings for Freescale TCON Driver
+
+Required properties:
+- compatible:		Should be one of
+	* "fsl,vf610-tcon".
+
+- reg:			Address and length of the register set for dcu.
+- clocks:		From common clock binding: handle to tcon ipg clock.
+- clock-names:		From common clock binding: Shall be "ipg".
+
+Examples:
+timing-controller@4003d000 {
+	compatible = "fsl,vf610-tcon";
+	reg = <0x4003d000 0x1000>;
+	clocks = <&clks VF610_CLK_TCON0>;
+	clock-names = "ipg";
+	status = "okay";
+};
diff --git a/drivers/gpu/drm/fsl-dcu/Makefile b/drivers/gpu/drm/fsl-dcu/Makefile
index 6ea1523..b35a292 100644
--- a/drivers/gpu/drm/fsl-dcu/Makefile
+++ b/drivers/gpu/drm/fsl-dcu/Makefile
@@ -3,5 +3,6 @@ fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
 		 fsl_dcu_drm_rgb.o \
 		 fsl_dcu_drm_plane.o \
 		 fsl_dcu_drm_crtc.o \
-		 fsl_dcu_drm_fbdev.o
+		 fsl_dcu_drm_fbdev.o \
+		 fsl_tcon.o
 obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index e01c813..679cde8 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -27,6 +27,7 @@
 
 #include "fsl_dcu_drm_crtc.h"
 #include "fsl_dcu_drm_drv.h"
+#include "fsl_tcon.h"
 
 static bool fsl_dcu_drm_is_volatile_reg(struct device *dev, unsigned int reg)
 {
@@ -218,6 +219,7 @@ static int fsl_dcu_drm_pm_suspend(struct device *dev)
 	drm_kms_helper_poll_disable(fsl_dev->drm);
 	regcache_cache_only(fsl_dev->regmap, true);
 	regcache_mark_dirty(fsl_dev->regmap);
+	fsl_tcon_suspend(fsl_dev->tcon);
 	clk_disable(fsl_dev->clk);
 	clk_unprepare(fsl_dev->clk);
 
@@ -244,6 +246,8 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
 		return ret;
 	}
 
+	fsl_tcon_resume(fsl_dev->tcon);
+
 	drm_kms_helper_poll_enable(fsl_dev->drm);
 	regcache_cache_only(fsl_dev->regmap, false);
 	regcache_sync(fsl_dev->regmap);
@@ -338,6 +342,8 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
 		return PTR_ERR(fsl_dev->regmap);
 	}
 
+	fsl_dev->tcon = fsl_tcon_init(dev);
+
 	id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node);
 	if (!id)
 		return -ENODEV;
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
index 2a724f3..a8919f6 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
@@ -183,6 +183,7 @@ struct fsl_dcu_drm_device {
 	struct regmap *regmap;
 	int irq;
 	struct clk *clk;
+	struct fsl_tcon *tcon;
 	/*protects hardware register*/
 	spinlock_t irq_lock;
 	struct drm_device *drm;
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index fe8ab5d..65a2df0 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -17,6 +17,7 @@
 #include <drm/drm_panel.h>
 
 #include "fsl_dcu_drm_drv.h"
+#include "fsl_tcon.h"
 
 static int
 fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
@@ -28,10 +29,20 @@ fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
 
 static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
 {
+	struct drm_device *dev = encoder->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+	if (fsl_dev->tcon)
+		fsl_tcon_disable(fsl_dev->tcon);
 }
 
 static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder)
 {
+	struct drm_device *dev = encoder->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+	if (fsl_dev->tcon)
+		fsl_tcon_enable(fsl_dev->tcon);
 }
 
 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_tcon.c b/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
new file mode 100644
index 0000000..de3c58b
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 Toradex AG
+ *
+ * Stefan Agner <stefan@agner.ch>
+ *
+ * Freescale TCON device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "fsl_tcon.h"
+
+void fsl_tcon_disable(struct fsl_tcon *tcon)
+{
+	regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
+			   FSL_TCON_CTRL1_TCON_BYPASS, 0);
+
+	tcon->enabled = false;
+}
+
+void fsl_tcon_enable(struct fsl_tcon *tcon)
+{
+	regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
+			   FSL_TCON_CTRL1_TCON_BYPASS,
+			   FSL_TCON_CTRL1_TCON_BYPASS);
+
+	tcon->enabled = true;
+}
+
+void fsl_tcon_suspend(struct fsl_tcon *tcon)
+{
+	regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
+			   FSL_TCON_CTRL1_TCON_BYPASS, 0);
+
+	clk_disable_unprepare(tcon->ipg_clk);
+}
+
+void fsl_tcon_resume(struct fsl_tcon *tcon)
+{
+	clk_prepare_enable(tcon->ipg_clk);
+
+	if (!tcon->enabled)
+		return;
+
+	regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
+			   FSL_TCON_CTRL1_TCON_BYPASS,
+			   FSL_TCON_CTRL1_TCON_BYPASS);
+}
+
+static struct regmap_config fsl_tcon_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+
+	.name = "tcon",
+};
+
+static int fsl_tcon_init_regmap(struct device *dev,
+				struct fsl_tcon *tcon,
+				struct device_node *np)
+{
+	struct resource res;
+	void __iomem *regs;
+	int ret;
+
+	ret = of_address_to_resource(np, 0, &res);
+	regs = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(regs)) {
+		dev_err(dev, "Couldn't map the TCON registers\n");
+		return PTR_ERR(regs);
+	}
+
+	tcon->regs = devm_regmap_init_mmio(dev, regs,
+					   &fsl_tcon_regmap_config);
+	if (IS_ERR(tcon->regs)) {
+		dev_err(dev, "Couldn't create the TCON regmap\n");
+		return PTR_ERR(tcon->regs);
+	}
+
+	return 0;
+}
+
+struct fsl_tcon *fsl_tcon_init(struct device *dev)
+{
+	struct fsl_tcon *tcon;
+	struct device_node *np;
+	int ret;
+
+	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
+	if (!tcon)
+		return NULL;
+
+	np = of_parse_phandle(dev->of_node, "fsl,tcon", 0);
+	if (!np) {
+		dev_warn(dev, "Couldn't find the tcon node\n");
+		return NULL;
+	}
+
+	ret = fsl_tcon_init_regmap(dev, tcon, np);
+	if (ret)
+		goto err_node_put;
+
+	tcon->ipg_clk = of_clk_get_by_name(np, "ipg");
+	if (IS_ERR(tcon->ipg_clk)) {
+		dev_err(dev, "Couldn't get the TCON bus clock\n");
+		goto err_free_regmap;
+	}
+
+	clk_prepare_enable(tcon->ipg_clk);
+
+	return tcon;
+
+err_free_regmap:
+err_node_put:
+	of_node_put(np);
+	return NULL;
+}
+
+void fsl_tcon_free(struct fsl_tcon *tcon)
+{
+	clk_disable_unprepare(tcon->ipg_clk);
+	clk_put(tcon->ipg_clk);
+}
+
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_tcon.h b/drivers/gpu/drm/fsl-dcu/fsl_tcon.h
new file mode 100644
index 0000000..199e6a1
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_tcon.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Toradex AG
+ *
+ * Stefan Agner <stefan@agner.ch>
+ *
+ * Freescale TCON device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_TCON_H__
+#define __FSL_TCON_H__
+
+#include <linux/bitops.h>
+
+#define FSL_TCON_CTRL1			0x0
+#define FSL_TCON_CTRL1_TCON_BYPASS	BIT(29)
+
+struct fsl_tcon {
+	struct regmap		*regs;
+	struct clk		*ipg_clk;
+
+	bool			enabled;
+};
+
+struct fsl_tcon *fsl_tcon_init(struct device *dev);
+void fsl_tcon_free(struct fsl_tcon *tcon);
+
+void fsl_tcon_disable(struct fsl_tcon *tcon);
+void fsl_tcon_enable(struct fsl_tcon *tcon);
+void fsl_tcon_suspend(struct fsl_tcon *tcon);
+void fsl_tcon_resume(struct fsl_tcon *tcon);
+
+#endif /* __FSL_TCON_H__ */
-- 
2.6.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-12-18  7:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-18  7:43 [PATCH 0/4] drm/fsl-dcu: add TCON and Vybrid support Stefan Agner
2015-12-18  7:43 ` [PATCH 1/4] ARM: dts: vf610: add display nodes Stefan Agner
2015-12-18  7:43 ` [PATCH 2/4] ARM: dts: vf610-colibri: enable display controller Stefan Agner
2015-12-18  7:43 ` [PATCH 3/4] ARM: clk: vf610: add TCON ipg clock Stefan Agner
2015-12-18  7:43 ` [PATCH 4/4] drm/fsl-dcu: add TCON driver Stefan Agner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).