diff mbox

[PATCH/RFC,383/390] drm/rcar-du: Centralize DU device core resource management

Message ID 1364525119-31791-384-git-send-email-horms+renesas@verge.net.au (mailing list archive)
State New, archived
Headers show

Commit Message

Simon Horman March 29, 2013, 2:45 a.m. UTC
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Create reference-counted get/put handlers for the DU device. The get()
operation enables the device clock and initializes core registers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
(cherry picked from commit 72737f07538e138532050311873e1891f1976ef3)

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c |   11 ++-----
 drivers/gpu/drm/rcar-du/rcar_du_drv.c  |   53 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_drv.h  |    4 +++
 3 files changed, 59 insertions(+), 9 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index aa7da6e..0e5eab1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -232,14 +232,7 @@  static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 	if (WARN_ON(rcrtc->plane->format == NULL))
 		return;
 
-	/* Enable clocks before accessing the hardware. */
-	clk_prepare_enable(rcdu->clock);
-
-	/* Enable extended features */
-	rcar_du_write(rcdu, DEFR, DEFR_CODE | DEFR_DEFE);
-	rcar_du_write(rcdu, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
-	rcar_du_write(rcdu, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
-	rcar_du_write(rcdu, DEFR4, DEFR4_CODE);
+	rcar_du_get(rcdu);
 
 	/* Set display off and background to black */
 	rcar_du_crtc_write(rcrtc, DOOR, DOOR_RGB(0, 0, 0));
@@ -297,7 +290,7 @@  static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 
 	rcar_du_start_stop(rcdu, false);
 
-	clk_disable_unprepare(rcdu->clock);
+	rcar_du_put(rcdu);
 
 	rcrtc->started = false;
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 2236fa6..1facacc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -26,6 +26,59 @@ 
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
 #include "rcar_du_kms.h"
+#include "rcar_du_regs.h"
+
+/* -----------------------------------------------------------------------------
+ * Core device operations
+ */
+
+/*
+ * rcar_du_get - Acquire a reference to the DU
+ *
+ * Acquiring a reference enables the device clock and setup core registers. A
+ * reference must be held before accessing any hardware registers.
+ *
+ * This function must be called with the DRM mode_config lock held.
+ *
+ * Return 0 in case of success or a negative error code otherwise.
+ */
+int rcar_du_get(struct rcar_du_device *rcdu)
+{
+	int ret;
+
+	if (rcdu->use_count)
+		goto done;
+
+	/* Enable clocks before accessing the hardware. */
+	ret = clk_prepare_enable(rcdu->clock);
+	if (ret < 0)
+		return ret;
+
+	/* Enable extended features */
+	rcar_du_write(rcdu, DEFR, DEFR_CODE | DEFR_DEFE);
+	rcar_du_write(rcdu, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
+	rcar_du_write(rcdu, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
+	rcar_du_write(rcdu, DEFR4, DEFR4_CODE);
+
+done:
+	rcdu->use_count++;
+	return 0;
+}
+
+/*
+ * rcar_du_put - Release a reference to the DU
+ *
+ * Releasing the last reference disables the device clock.
+ *
+ * This function must be called with the DRM mode_config lock held.
+ */
+void rcar_du_put(struct rcar_du_device *rcdu)
+{
+	if (--rcdu->use_count)
+		return;
+
+	clk_disable_unprepare(rcdu->clock);
+}
 
 /* -----------------------------------------------------------------------------
  * DRM operations
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index a0bc870..73faf77 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -31,6 +31,7 @@  struct rcar_du_device {
 
 	void __iomem *mmio;
 	struct clk *clock;
+	unsigned int use_count;
 
 	struct drm_device *ddev;
 
@@ -48,6 +49,9 @@  struct rcar_du_device {
 	} planes;
 };
 
+int rcar_du_get(struct rcar_du_device *rcdu);
+void rcar_du_put(struct rcar_du_device *rcdu);
+
 static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
 {
 	return ioread32(rcdu->mmio + reg);