All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/27] OMAP DSS runtime PM adaptation
@ 2011-06-03 10:00 ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Hi,

This patch set implements runtime PM adaptation for OMAP DSS driver.

The bulk of the code is in the "OMAP: DSS2: Use PM runtime & HWMOD support"
patch, which is a bit too large for comfort, but I haven't found out ways to
split it up.

All DSS HW modules now handle enabling and disabling of the HW block
independently via pm_runtime calls. Some DSS modules also require other DSS
modules, and for that we have functions like dispc_runtime_get/put() which can
be used to enable that module.

Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
problem is that on OMAP4 we have to enable an optional clock before calling
pm_runtime_get(), and similarly we need to keep the optional clock enabled
until after pm_runtime_put() has been called.

This causes some extra complications. For example, we can't use runtime_resume
callback to enable the opt clocks, as they are required before calling
pm_runtime_get().

Previously DSS driver did reset the HW every time before taking it into use.
This can no longer be done, as HWMOD framework handles the reset. While the
driver works without resetting the HW, an error could render the HW inoperable
and currently the driver may not be able to recover. So these patches may make
the driver more unreliable on error cases.

If a way to reset the HWMOD is added to the HWMOD framework, DSS driver can
take it into use and the above mentioned problem should go away.

Tested on OMAP4 Blaze, OMAP3 Overo, OMAP2420 N800. (However, N800 needs extra
patches to get it and DSS2 running, can be found from n800 branch in my tree).

These patches can be found from:

git://gitorious.org/linux-omap-dss2/linux.git pmruntime

 Tomi

Tomi Valkeinen (27):
  OMAP: change get_context_loss_count ret value to int
  OMAP: DSS2: Taal: Make driver more fault tolerant
  OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
  OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
  OMAP: DSS2: Clean up probe for DSS & DSI
  OMAP: DSS2: Init dispc first before other components
  OMAP: DSS2: Remove clk optimization at dss init
  OMAP: DSS2: rewrite use of context_loss_count
  OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss
    count
  OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
  OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK
  OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2
  OMAP: DSS2: Remove core_dump_clocks
  OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
  OMAP4: HWMOD: Modify DSS opt clocks
  OMAP3: HWMOD: Add DSS opt clocks
  OMAP2420: HWMOD: Add DSS opt clocks
  OMAP2430: HWMOD: Add DSS opt clocks
  OMAP: DSS2: Use PM runtime & HWMOD support
  OMAP4: HWMOD: Remove unneeded DSS opt clocks
  OMAP: DSS2: Remove unused opt_clock_available
  OMAP: DSS2: DISPC: remove finegrained clk enables/disables
  OMAP: DSS2: Remove unused code from display.c
  OMAP: DSS2: Remove ctx loss count from dss.c
  OMAP4: CLKDEV: Remove omapdss clock aliases
  OMAP: DSS2: DISPC: Fix context save/restore
  OMAP: DSS2: DSS: Fix context save/restore

 arch/arm/mach-omap2/clock44xx_data.c          |   10 +-
 arch/arm/mach-omap2/display.c                 |   26 +-
 arch/arm/mach-omap2/omap_hwmod.c              |    2 +-
 arch/arm/mach-omap2/omap_hwmod_2420_data.c    |   19 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c    |   19 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |   37 ++-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c    |   43 ++-
 arch/arm/mach-omap2/powerdomain.c             |   14 +-
 arch/arm/mach-omap2/powerdomain.h             |    2 +-
 arch/arm/plat-omap/include/plat/omap-pm.h     |    4 +-
 arch/arm/plat-omap/include/plat/omap_device.h |    2 +-
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    2 +-
 arch/arm/plat-omap/omap-pm-noop.c             |   24 +-
 arch/arm/plat-omap/omap_device.c              |    2 +-
 drivers/video/omap2/displays/panel-taal.c     |   33 +-
 drivers/video/omap2/dss/Kconfig               |   12 -
 drivers/video/omap2/dss/core.c                |   15 +-
 drivers/video/omap2/dss/dispc.c               |  496 ++++++++++++----------
 drivers/video/omap2/dss/dpi.c                 |   73 ++--
 drivers/video/omap2/dss/dsi.c                 |  284 ++++++++-----
 drivers/video/omap2/dss/dss.c                 |  564 ++++++-------------------
 drivers/video/omap2/dss/dss.h                 |   34 +-
 drivers/video/omap2/dss/dss_features.c        |   13 +-
 drivers/video/omap2/dss/dss_features.h        |    4 +
 drivers/video/omap2/dss/hdmi.c                |  149 +++++--
 drivers/video/omap2/dss/manager.c             |    8 +-
 drivers/video/omap2/dss/overlay.c             |   27 +-
 drivers/video/omap2/dss/rfbi.c                |   97 ++++-
 drivers/video/omap2/dss/sdi.c                 |   40 ++-
 drivers/video/omap2/dss/venc.c                |  171 +++++++-
 include/video/omapdss.h                       |    4 +-
 31 files changed, 1207 insertions(+), 1023 deletions(-)

-- 
1.7.4.1


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

* [PATCH 00/27] OMAP DSS runtime PM adaptation
@ 2011-06-03 10:00 ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Hi,

This patch set implements runtime PM adaptation for OMAP DSS driver.

The bulk of the code is in the "OMAP: DSS2: Use PM runtime & HWMOD support"
patch, which is a bit too large for comfort, but I haven't found out ways to
split it up.

All DSS HW modules now handle enabling and disabling of the HW block
independently via pm_runtime calls. Some DSS modules also require other DSS
modules, and for that we have functions like dispc_runtime_get/put() which can
be used to enable that module.

Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
problem is that on OMAP4 we have to enable an optional clock before calling
pm_runtime_get(), and similarly we need to keep the optional clock enabled
until after pm_runtime_put() has been called.

This causes some extra complications. For example, we can't use runtime_resume
callback to enable the opt clocks, as they are required before calling
pm_runtime_get().

Previously DSS driver did reset the HW every time before taking it into use.
This can no longer be done, as HWMOD framework handles the reset. While the
driver works without resetting the HW, an error could render the HW inoperable
and currently the driver may not be able to recover. So these patches may make
the driver more unreliable on error cases.

If a way to reset the HWMOD is added to the HWMOD framework, DSS driver can
take it into use and the above mentioned problem should go away.

Tested on OMAP4 Blaze, OMAP3 Overo, OMAP2420 N800. (However, N800 needs extra
patches to get it and DSS2 running, can be found from n800 branch in my tree).

These patches can be found from:

git://gitorious.org/linux-omap-dss2/linux.git pmruntime

 Tomi

Tomi Valkeinen (27):
  OMAP: change get_context_loss_count ret value to int
  OMAP: DSS2: Taal: Make driver more fault tolerant
  OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
  OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
  OMAP: DSS2: Clean up probe for DSS & DSI
  OMAP: DSS2: Init dispc first before other components
  OMAP: DSS2: Remove clk optimization at dss init
  OMAP: DSS2: rewrite use of context_loss_count
  OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss
    count
  OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
  OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK
  OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2
  OMAP: DSS2: Remove core_dump_clocks
  OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
  OMAP4: HWMOD: Modify DSS opt clocks
  OMAP3: HWMOD: Add DSS opt clocks
  OMAP2420: HWMOD: Add DSS opt clocks
  OMAP2430: HWMOD: Add DSS opt clocks
  OMAP: DSS2: Use PM runtime & HWMOD support
  OMAP4: HWMOD: Remove unneeded DSS opt clocks
  OMAP: DSS2: Remove unused opt_clock_available
  OMAP: DSS2: DISPC: remove finegrained clk enables/disables
  OMAP: DSS2: Remove unused code from display.c
  OMAP: DSS2: Remove ctx loss count from dss.c
  OMAP4: CLKDEV: Remove omapdss clock aliases
  OMAP: DSS2: DISPC: Fix context save/restore
  OMAP: DSS2: DSS: Fix context save/restore

 arch/arm/mach-omap2/clock44xx_data.c          |   10 +-
 arch/arm/mach-omap2/display.c                 |   26 +-
 arch/arm/mach-omap2/omap_hwmod.c              |    2 +-
 arch/arm/mach-omap2/omap_hwmod_2420_data.c    |   19 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c    |   19 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |   37 ++-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c    |   43 ++-
 arch/arm/mach-omap2/powerdomain.c             |   14 +-
 arch/arm/mach-omap2/powerdomain.h             |    2 +-
 arch/arm/plat-omap/include/plat/omap-pm.h     |    4 +-
 arch/arm/plat-omap/include/plat/omap_device.h |    2 +-
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    2 +-
 arch/arm/plat-omap/omap-pm-noop.c             |   24 +-
 arch/arm/plat-omap/omap_device.c              |    2 +-
 drivers/video/omap2/displays/panel-taal.c     |   33 +-
 drivers/video/omap2/dss/Kconfig               |   12 -
 drivers/video/omap2/dss/core.c                |   15 +-
 drivers/video/omap2/dss/dispc.c               |  496 ++++++++++++----------
 drivers/video/omap2/dss/dpi.c                 |   73 ++--
 drivers/video/omap2/dss/dsi.c                 |  284 ++++++++-----
 drivers/video/omap2/dss/dss.c                 |  564 ++++++-------------------
 drivers/video/omap2/dss/dss.h                 |   34 +-
 drivers/video/omap2/dss/dss_features.c        |   13 +-
 drivers/video/omap2/dss/dss_features.h        |    4 +
 drivers/video/omap2/dss/hdmi.c                |  149 +++++--
 drivers/video/omap2/dss/manager.c             |    8 +-
 drivers/video/omap2/dss/overlay.c             |   27 +-
 drivers/video/omap2/dss/rfbi.c                |   97 ++++-
 drivers/video/omap2/dss/sdi.c                 |   40 ++-
 drivers/video/omap2/dss/venc.c                |  171 +++++++-
 include/video/omapdss.h                       |    4 +-
 31 files changed, 1207 insertions(+), 1023 deletions(-)

-- 
1.7.4.1


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

* [PATCH 01/27] OMAP: change get_context_loss_count ret value to int
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

get_context_loss_count functions return context loss count as u32, and
zero means an error. However, zero is also returned when context has
never been lost and could also be returned when the context loss count
has wrapped and goes to zero.

Change the functions to return an int, with negative value meaning an
error.

OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the
hsmmc code handles the returned value as an int, with negative value
meaning an error, this patch actually fixes hsmmc code also.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c              |    2 +-
 arch/arm/mach-omap2/powerdomain.c             |   14 ++++++++++----
 arch/arm/mach-omap2/powerdomain.h             |    2 +-
 arch/arm/plat-omap/include/plat/omap-pm.h     |    4 ++--
 arch/arm/plat-omap/include/plat/omap_device.h |    2 +-
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    2 +-
 arch/arm/plat-omap/omap-pm-noop.c             |   24 +++++++++++++++++-------
 arch/arm/plat-omap/omap_device.c              |    2 +-
 8 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e034294..4f0d554 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2332,7 +2332,7 @@ ohsps_unlock:
  * Returns the context loss count of the powerdomain assocated with @oh
  * upon success, or zero if no powerdomain exists for @oh.
  */
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
 	struct powerdomain *pwrdm;
 	int ret = 0;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9af0847..9d53a34 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -935,16 +935,16 @@ int pwrdm_post_transition(void)
  * @pwrdm: struct powerdomain * to wait for
  *
  * Context loss count is the sum of powerdomain off-mode counter, the
- * logic off counter and the per-bank memory off counter.  Returns 0
+ * logic off counter and the per-bank memory off counter.  Returns negative
  * (and WARNs) upon error, otherwise, returns the context loss count.
  */
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 {
 	int i, count;
 
 	if (!pwrdm) {
 		WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
-		return 0;
+		return -ENODEV;
 	}
 
 	count = pwrdm->state_counter[PWRDM_POWER_OFF];
@@ -953,7 +953,13 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 	for (i = 0; i < pwrdm->banks; i++)
 		count += pwrdm->ret_mem_off_counter[i];
 
-	pr_debug("powerdomain: %s: context loss count = %u\n",
+	/*
+	 * Context loss count has to be a non-negative value. Clear the sign
+	 * bit to get a value range from 0 to INT_MAX.
+	 */
+	count &= INT_MAX;
+
+	pr_debug("powerdomain: %s: context loss count = %d\n",
 		 pwrdm->name, count);
 
 	return count;
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index d23d979..012827f 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -207,7 +207,7 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
 extern void omap2xxx_powerdomains_init(void);
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index c0a7520..68df031 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -350,9 +350,9 @@ unsigned long omap_pm_cpu_get_freq(void);
  * driver must restore device context.   If the number of context losses
  * exceeds the maximum positive integer, the function will wrap to 0 and
  * continue counting.  Returns the number of context losses for this device,
- * or zero upon error.
+ * or negative value upon error.
  */
-u32 omap_pm_get_dev_context_loss_count(struct device *dev);
+int omap_pm_get_dev_context_loss_count(struct device *dev);
 
 void omap_pm_enable_off_mode(void);
 void omap_pm_disable_off_mode(void);
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349f..70d31d0 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -107,7 +107,7 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od);
 int omap_device_align_pm_lat(struct platform_device *pdev,
 			     u32 new_wakeup_lat_limit);
 struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
 
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c..8658e2d 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -598,7 +598,7 @@ int omap_hwmod_for_each_by_class(const char *classname,
 				 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index b0471bb2..3dc3801 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -27,7 +27,7 @@
 #include <plat/omap_device.h>
 
 static bool off_mode_enabled;
-static u32 dummy_context_loss_counter;
+static int dummy_context_loss_counter;
 
 /*
  * Device-driver-originated constraints (via board-*.c files)
@@ -311,22 +311,32 @@ void omap_pm_disable_off_mode(void)
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	u32 count;
+	int count;
 
 	if (WARN_ON(!dev))
-		return 0;
+		return -ENODEV;
 
 	if (dev->parent = &omap_device_parent) {
 		count = omap_device_get_context_loss_count(pdev);
 	} else {
 		WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
 			  dev_name(dev));
-		if (off_mode_enabled)
-			dummy_context_loss_counter++;
+
 		count = dummy_context_loss_counter;
+
+		if (off_mode_enabled) {
+			count++;
+			/*
+			 * Context loss count has to be a non-negative value.
+			 * Clear the sign bit to get a value range from 0 to
+			 * INT_MAX.
+			 */
+			count &= INT_MAX;
+			dummy_context_loss_counter = count;
+		}
 	}
 
 	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
@@ -337,7 +347,7 @@ u32 omap_pm_get_dev_context_loss_count(struct device *dev)
 
 #else
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	return dummy_context_loss_counter;
 }
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 9bbda9a..9753f71 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -310,7 +310,7 @@ static void _add_optional_clock_clkdev(struct omap_device *od,
  * return the context loss counter for that hwmod, otherwise return
  * zero.
  */
-u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+int omap_device_get_context_loss_count(struct platform_device *pdev)
 {
 	struct omap_device *od;
 	u32 ret = 0;
-- 
1.7.4.1


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

* [PATCH 01/27] OMAP: change get_context_loss_count ret value to int
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

get_context_loss_count functions return context loss count as u32, and
zero means an error. However, zero is also returned when context has
never been lost and could also be returned when the context loss count
has wrapped and goes to zero.

Change the functions to return an int, with negative value meaning an
error.

OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the
hsmmc code handles the returned value as an int, with negative value
meaning an error, this patch actually fixes hsmmc code also.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c              |    2 +-
 arch/arm/mach-omap2/powerdomain.c             |   14 ++++++++++----
 arch/arm/mach-omap2/powerdomain.h             |    2 +-
 arch/arm/plat-omap/include/plat/omap-pm.h     |    4 ++--
 arch/arm/plat-omap/include/plat/omap_device.h |    2 +-
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    2 +-
 arch/arm/plat-omap/omap-pm-noop.c             |   24 +++++++++++++++++-------
 arch/arm/plat-omap/omap_device.c              |    2 +-
 8 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e034294..4f0d554 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2332,7 +2332,7 @@ ohsps_unlock:
  * Returns the context loss count of the powerdomain assocated with @oh
  * upon success, or zero if no powerdomain exists for @oh.
  */
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
 	struct powerdomain *pwrdm;
 	int ret = 0;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9af0847..9d53a34 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -935,16 +935,16 @@ int pwrdm_post_transition(void)
  * @pwrdm: struct powerdomain * to wait for
  *
  * Context loss count is the sum of powerdomain off-mode counter, the
- * logic off counter and the per-bank memory off counter.  Returns 0
+ * logic off counter and the per-bank memory off counter.  Returns negative
  * (and WARNs) upon error, otherwise, returns the context loss count.
  */
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 {
 	int i, count;
 
 	if (!pwrdm) {
 		WARN(1, "powerdomain: %s: pwrdm is null\n", __func__);
-		return 0;
+		return -ENODEV;
 	}
 
 	count = pwrdm->state_counter[PWRDM_POWER_OFF];
@@ -953,7 +953,13 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 	for (i = 0; i < pwrdm->banks; i++)
 		count += pwrdm->ret_mem_off_counter[i];
 
-	pr_debug("powerdomain: %s: context loss count = %u\n",
+	/*
+	 * Context loss count has to be a non-negative value. Clear the sign
+	 * bit to get a value range from 0 to INT_MAX.
+	 */
+	count &= INT_MAX;
+
+	pr_debug("powerdomain: %s: context loss count = %d\n",
 		 pwrdm->name, count);
 
 	return count;
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index d23d979..012827f 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -207,7 +207,7 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
-u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
 extern void omap2xxx_powerdomains_init(void);
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index c0a7520..68df031 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -350,9 +350,9 @@ unsigned long omap_pm_cpu_get_freq(void);
  * driver must restore device context.   If the number of context losses
  * exceeds the maximum positive integer, the function will wrap to 0 and
  * continue counting.  Returns the number of context losses for this device,
- * or zero upon error.
+ * or negative value upon error.
  */
-u32 omap_pm_get_dev_context_loss_count(struct device *dev);
+int omap_pm_get_dev_context_loss_count(struct device *dev);
 
 void omap_pm_enable_off_mode(void);
 void omap_pm_disable_off_mode(void);
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index e4c349f..70d31d0 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -107,7 +107,7 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od);
 int omap_device_align_pm_lat(struct platform_device *pdev,
 			     u32 new_wakeup_lat_limit);
 struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
-u32 omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
 
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c..8658e2d 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -598,7 +598,7 @@ int omap_hwmod_for_each_by_class(const char *classname,
 				 void *user);
 
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
-u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
+int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index b0471bb2..3dc3801 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -27,7 +27,7 @@
 #include <plat/omap_device.h>
 
 static bool off_mode_enabled;
-static u32 dummy_context_loss_counter;
+static int dummy_context_loss_counter;
 
 /*
  * Device-driver-originated constraints (via board-*.c files)
@@ -311,22 +311,32 @@ void omap_pm_disable_off_mode(void)
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	u32 count;
+	int count;
 
 	if (WARN_ON(!dev))
-		return 0;
+		return -ENODEV;
 
 	if (dev->parent == &omap_device_parent) {
 		count = omap_device_get_context_loss_count(pdev);
 	} else {
 		WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
 			  dev_name(dev));
-		if (off_mode_enabled)
-			dummy_context_loss_counter++;
+
 		count = dummy_context_loss_counter;
+
+		if (off_mode_enabled) {
+			count++;
+			/*
+			 * Context loss count has to be a non-negative value.
+			 * Clear the sign bit to get a value range from 0 to
+			 * INT_MAX.
+			 */
+			count &= INT_MAX;
+			dummy_context_loss_counter = count;
+		}
 	}
 
 	pr_debug("OMAP PM: context loss count for dev %s = %d\n",
@@ -337,7 +347,7 @@ u32 omap_pm_get_dev_context_loss_count(struct device *dev)
 
 #else
 
-u32 omap_pm_get_dev_context_loss_count(struct device *dev)
+int omap_pm_get_dev_context_loss_count(struct device *dev)
 {
 	return dummy_context_loss_counter;
 }
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 9bbda9a..9753f71 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -310,7 +310,7 @@ static void _add_optional_clock_clkdev(struct omap_device *od,
  * return the context loss counter for that hwmod, otherwise return
  * zero.
  */
-u32 omap_device_get_context_loss_count(struct platform_device *pdev)
+int omap_device_get_context_loss_count(struct platform_device *pdev)
 {
 	struct omap_device *od;
 	u32 ret = 0;
-- 
1.7.4.1


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

* [PATCH 02/27] OMAP: DSS2: Taal: Make driver more fault tolerant
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

If ULPS exit fails, and the following reset fails also, Taal driver was
left in state where it thinks DSI is enabled while it really isn't,
leading to crash.

This patch checks the return value of taal_panel_reset, and if that
fails, ulps_enabled is left true, causing the driver to retry ulps exit
later.

Also the return value of taal_wake_up is checked at taal_disable, and if
wake up fails, we'll skip the power_off. This could leave the panel into
a not-quite-valid state, but there's nothing we can do about it in that
situation.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |   33 ++++++++++++++++++----------
 1 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index fdd5d4ae..b82bcc1 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -504,14 +504,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
 		return 0;
 
 	r = omapdss_dsi_display_enable(dssdev);
-	if (r)
-		goto err;
+	if (r) {
+		dev_err(&dssdev->dev, "failed to enable DSI\n");
+		goto err1;
+	}
 
 	omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
 
 	r = _taal_enable_te(dssdev, true);
-	if (r)
-		goto err;
+	if (r) {
+		dev_err(&dssdev->dev, "failed to re-enable TE");
+		goto err2;
+	}
 
 	enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
 
@@ -521,13 +525,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
 
 	return 0;
 
-err:
-	dev_err(&dssdev->dev, "exit ULPS failed");
-	r = taal_panel_reset(dssdev);
-
-	enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
-	td->ulps_enabled = false;
+err2:
+	dev_err(&dssdev->dev, "failed to exit ULPS");
 
+	r = taal_panel_reset(dssdev);
+	if (!r) {
+		enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+		td->ulps_enabled = false;
+	}
+err1:
 	taal_queue_ulps_work(dssdev);
 
 	return r;
@@ -1317,8 +1323,11 @@ static void taal_disable(struct omap_dss_device *dssdev)
 	dsi_bus_lock(dssdev);
 
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
-		taal_wake_up(dssdev);
-		taal_power_off(dssdev);
+		int r;
+
+		r = taal_wake_up(dssdev);
+		if (!r)
+			taal_power_off(dssdev);
 	}
 
 	dsi_bus_unlock(dssdev);
-- 
1.7.4.1


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

* [PATCH 02/27] OMAP: DSS2: Taal: Make driver more fault tolerant
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

If ULPS exit fails, and the following reset fails also, Taal driver was
left in state where it thinks DSI is enabled while it really isn't,
leading to crash.

This patch checks the return value of taal_panel_reset, and if that
fails, ulps_enabled is left true, causing the driver to retry ulps exit
later.

Also the return value of taal_wake_up is checked at taal_disable, and if
wake up fails, we'll skip the power_off. This could leave the panel into
a not-quite-valid state, but there's nothing we can do about it in that
situation.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |   33 ++++++++++++++++++----------
 1 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index fdd5d4ae..b82bcc1 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -504,14 +504,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
 		return 0;
 
 	r = omapdss_dsi_display_enable(dssdev);
-	if (r)
-		goto err;
+	if (r) {
+		dev_err(&dssdev->dev, "failed to enable DSI\n");
+		goto err1;
+	}
 
 	omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
 
 	r = _taal_enable_te(dssdev, true);
-	if (r)
-		goto err;
+	if (r) {
+		dev_err(&dssdev->dev, "failed to re-enable TE");
+		goto err2;
+	}
 
 	enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
 
@@ -521,13 +525,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
 
 	return 0;
 
-err:
-	dev_err(&dssdev->dev, "exit ULPS failed");
-	r = taal_panel_reset(dssdev);
-
-	enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
-	td->ulps_enabled = false;
+err2:
+	dev_err(&dssdev->dev, "failed to exit ULPS");
 
+	r = taal_panel_reset(dssdev);
+	if (!r) {
+		enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+		td->ulps_enabled = false;
+	}
+err1:
 	taal_queue_ulps_work(dssdev);
 
 	return r;
@@ -1317,8 +1323,11 @@ static void taal_disable(struct omap_dss_device *dssdev)
 	dsi_bus_lock(dssdev);
 
 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-		taal_wake_up(dssdev);
-		taal_power_off(dssdev);
+		int r;
+
+		r = taal_wake_up(dssdev);
+		if (!r)
+			taal_power_off(dssdev);
 	}
 
 	dsi_bus_unlock(dssdev);
-- 
1.7.4.1


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

* [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause
any problems currently, as DSI HW is reset when it is enabled. However,
if the reset is not done, operation fails if the bits are still set.

So reset the bits after entering ULPS to ensure operation even without
HW reset.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 69c2d4f..4496d09 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 	dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
 			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
 
+	/* Reset LANEx_ULPS_SIG2 */
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
+		7, 5);
+
 	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
 
 	dsi_if_enable(dsidev, false);
-- 
1.7.4.1


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

* [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause
any problems currently, as DSI HW is reset when it is enabled. However,
if the reset is not done, operation fails if the bits are still set.

So reset the bits after entering ULPS to ensure operation even without
HW reset.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 69c2d4f..4496d09 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 	dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
 			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
 
+	/* Reset LANEx_ULPS_SIG2 */
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
+		7, 5);
+
 	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
 
 	dsi_if_enable(dsidev, false);
-- 
1.7.4.1


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

* [PATCH 04/27] OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Get and put for dpll4_m4_ck was handled in dss_init/dss_exit. Move the
code to dss_get/put_clocks(), which is a better place to handle it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   52 ++++++++++++++++++++--------------------
 1 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index d0b3f81..3eed8a2 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -669,7 +669,6 @@ static int dss_init(void)
 	int r;
 	u32 rev;
 	struct resource *dss_mem;
-	struct clk *dpll4_m4_ck;
 
 	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
 	if (!dss_mem) {
@@ -715,26 +714,6 @@ static int dss_init(void)
 	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
 	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
 #endif
-	if (cpu_is_omap34xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
-			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
-			goto fail1;
-		}
-	} else if (cpu_is_omap44xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
-			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
-			goto fail1;
-		}
-	} else { /* omap24xx */
-		dpll4_m4_ck = NULL;
-	}
-
-	dss.dpll4_m4_ck = dpll4_m4_ck;
-
 	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
 	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
@@ -749,17 +728,12 @@ static int dss_init(void)
 
 	return 0;
 
-fail1:
-	iounmap(dss.base);
 fail0:
 	return r;
 }
 
 static void dss_exit(void)
 {
-	if (dss.dpll4_m4_ck)
-		clk_put(dss.dpll4_m4_ck);
-
 	iounmap(dss.base);
 }
 
@@ -845,6 +819,7 @@ static int dss_get_clock(struct clk **clock, const char *clk_name)
 static int dss_get_clocks(void)
 {
 	int r;
+	struct clk *dpll4_m4_ck;
 	struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
 
 	dss.dss_ick = NULL;
@@ -884,6 +859,27 @@ static int dss_get_clocks(void)
 			goto err;
 	}
 
+	if (cpu_is_omap34xx()) {
+		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+		if (IS_ERR(dpll4_m4_ck)) {
+			DSSERR("Failed to get dpll4_m4_ck\n");
+			r = PTR_ERR(dpll4_m4_ck);
+			goto err;
+		}
+	} else if (cpu_is_omap44xx()) {
+		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
+		if (IS_ERR(dpll4_m4_ck)) {
+			DSSERR("Failed to get dpll4_m4_ck\n");
+			r = PTR_ERR(dpll4_m4_ck);
+			goto err;
+		}
+	} else { /* omap24xx */
+		dpll4_m4_ck = NULL;
+	}
+
+	dss.dpll4_m4_ck = dpll4_m4_ck;
+
+
 	return 0;
 
 err:
@@ -897,12 +893,16 @@ err:
 		clk_put(dss.dss_tv_fck);
 	if (dss.dss_video_fck)
 		clk_put(dss.dss_video_fck);
+	if (dss.dpll4_m4_ck)
+		clk_put(dss.dpll4_m4_ck);
 
 	return r;
 }
 
 static void dss_put_clocks(void)
 {
+	if (dss.dpll4_m4_ck)
+		clk_put(dss.dpll4_m4_ck);
 	if (dss.dss_video_fck)
 		clk_put(dss.dss_video_fck);
 	if (dss.dss_tv_fck)
-- 
1.7.4.1


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

* [PATCH 04/27] OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Get and put for dpll4_m4_ck was handled in dss_init/dss_exit. Move the
code to dss_get/put_clocks(), which is a better place to handle it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   52 ++++++++++++++++++++--------------------
 1 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index d0b3f81..3eed8a2 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -669,7 +669,6 @@ static int dss_init(void)
 	int r;
 	u32 rev;
 	struct resource *dss_mem;
-	struct clk *dpll4_m4_ck;
 
 	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
 	if (!dss_mem) {
@@ -715,26 +714,6 @@ static int dss_init(void)
 	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
 	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
 #endif
-	if (cpu_is_omap34xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
-			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
-			goto fail1;
-		}
-	} else if (cpu_is_omap44xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
-			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
-			goto fail1;
-		}
-	} else { /* omap24xx */
-		dpll4_m4_ck = NULL;
-	}
-
-	dss.dpll4_m4_ck = dpll4_m4_ck;
-
 	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
 	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
@@ -749,17 +728,12 @@ static int dss_init(void)
 
 	return 0;
 
-fail1:
-	iounmap(dss.base);
 fail0:
 	return r;
 }
 
 static void dss_exit(void)
 {
-	if (dss.dpll4_m4_ck)
-		clk_put(dss.dpll4_m4_ck);
-
 	iounmap(dss.base);
 }
 
@@ -845,6 +819,7 @@ static int dss_get_clock(struct clk **clock, const char *clk_name)
 static int dss_get_clocks(void)
 {
 	int r;
+	struct clk *dpll4_m4_ck;
 	struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
 
 	dss.dss_ick = NULL;
@@ -884,6 +859,27 @@ static int dss_get_clocks(void)
 			goto err;
 	}
 
+	if (cpu_is_omap34xx()) {
+		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+		if (IS_ERR(dpll4_m4_ck)) {
+			DSSERR("Failed to get dpll4_m4_ck\n");
+			r = PTR_ERR(dpll4_m4_ck);
+			goto err;
+		}
+	} else if (cpu_is_omap44xx()) {
+		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
+		if (IS_ERR(dpll4_m4_ck)) {
+			DSSERR("Failed to get dpll4_m4_ck\n");
+			r = PTR_ERR(dpll4_m4_ck);
+			goto err;
+		}
+	} else { /* omap24xx */
+		dpll4_m4_ck = NULL;
+	}
+
+	dss.dpll4_m4_ck = dpll4_m4_ck;
+
+
 	return 0;
 
 err:
@@ -897,12 +893,16 @@ err:
 		clk_put(dss.dss_tv_fck);
 	if (dss.dss_video_fck)
 		clk_put(dss.dss_video_fck);
+	if (dss.dpll4_m4_ck)
+		clk_put(dss.dpll4_m4_ck);
 
 	return r;
 }
 
 static void dss_put_clocks(void)
 {
+	if (dss.dpll4_m4_ck)
+		clk_put(dss.dpll4_m4_ck);
 	if (dss.dss_video_fck)
 		clk_put(dss.dss_video_fck);
 	if (dss.dss_tv_fck)
-- 
1.7.4.1


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

* [PATCH 05/27] OMAP: DSS2: Clean up probe for DSS & DSI
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Both dss.c and dsi.c had a probe function, which was almost a dummy one,
calling dss_init() and dsi_init().

Remove the init functions by moving the initialization code into probe
functions.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   30 ++-------
 drivers/video/omap2/dss/dss.c |  145 ++++++++++++++++++-----------------------
 2 files changed, 69 insertions(+), 106 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 4496d09..0609885 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4450,7 +4450,8 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
 	dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
-static int dsi_init(struct platform_device *dsidev)
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *dsidev)
 {
 	struct omap_display_platform_data *dss_plat_data;
 	struct omap_dss_board_info *board_info;
@@ -4547,10 +4548,12 @@ err0:
 	return r;
 }
 
-static void dsi_exit(struct platform_device *dsidev)
+static int omap_dsi1hw_remove(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
+	WARN_ON(dsi->scp_clk_refcount > 0);
+
 	if (dsi->vdds_dsi_reg != NULL) {
 		if (dsi->vdds_dsi_enabled) {
 			regulator_disable(dsi->vdds_dsi_reg);
@@ -4566,29 +4569,6 @@ static void dsi_exit(struct platform_device *dsidev)
 
 	kfree(dsi);
 
-	DSSDBG("omap_dsi_exit\n");
-}
-
-/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
-{
-	int r;
-
-	r = dsi_init(dsidev);
-	if (r) {
-		DSSERR("Failed to initialize DSI\n");
-		goto err_dsi;
-	}
-err_dsi:
-	return r;
-}
-
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	dsi_exit(dsidev);
-	WARN_ON(dsi->scp_clk_refcount > 0);
 	return 0;
 }
 
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 3eed8a2..f5f9fcb 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -664,79 +664,6 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
 	REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15);	/* VENC_HDMI_SWITCH */
 }
 
-static int dss_init(void)
-{
-	int r;
-	u32 rev;
-	struct resource *dss_mem;
-
-	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
-	if (!dss_mem) {
-		DSSERR("can't get IORESOURCE_MEM DSS\n");
-		r = -EINVAL;
-		goto fail0;
-	}
-	dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
-	if (!dss.base) {
-		DSSERR("can't ioremap DSS\n");
-		r = -ENOMEM;
-		goto fail0;
-	}
-
-	/* disable LCD and DIGIT output. This seems to fix the synclost
-	 * problem that we get, if the bootloader starts the DSS and
-	 * the kernel resets it */
-	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
-
-#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
-	/* We need to wait here a bit, otherwise we sometimes start to
-	 * get synclost errors, and after that only power cycle will
-	 * restore DSS functionality. I have no idea why this happens.
-	 * And we have to wait _before_ resetting the DSS, but after
-	 * enabling clocks.
-	 *
-	 * This bug was at least present on OMAP3430. It's unknown
-	 * if it happens on OMAP2 or OMAP3630.
-	 */
-	msleep(50);
-#endif
-
-	_omap_dss_reset();
-
-	/* autoidle */
-	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
-
-	/* Select DPLL */
-	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
-
-#ifdef CONFIG_OMAP2_DSS_VENC
-	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
-	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
-	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
-#endif
-	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
-	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-
-	dss_save_context();
-
-	rev = dss_read_reg(DSS_REVISION);
-	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
-			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-	return 0;
-
-fail0:
-	return r;
-}
-
-static void dss_exit(void)
-{
-	iounmap(dss.base);
-}
-
 /* CONTEXT */
 static int dss_get_ctx_id(void)
 {
@@ -1094,10 +1021,25 @@ void dss_debug_dump_clocks(struct seq_file *s)
 /* DSS HW IP initialisation */
 static int omap_dsshw_probe(struct platform_device *pdev)
 {
+	struct resource *dss_mem;
+	u32 rev;
 	int r;
 
 	dss.pdev = pdev;
 
+	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+	if (!dss_mem) {
+		DSSERR("can't get IORESOURCE_MEM DSS\n");
+		r = -EINVAL;
+		goto err_ioremap;
+	}
+	dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
+	if (!dss.base) {
+		DSSERR("can't ioremap DSS\n");
+		r = -ENOMEM;
+		goto err_ioremap;
+	}
+
 	r = dss_get_clocks();
 	if (r)
 		goto err_clocks;
@@ -1107,11 +1049,42 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	dss.ctx_id = dss_get_ctx_id();
 	DSSDBG("initial ctx id %u\n", dss.ctx_id);
 
-	r = dss_init();
-	if (r) {
-		DSSERR("Failed to initialize DSS\n");
-		goto err_dss;
-	}
+	/* disable LCD and DIGIT output. This seems to fix the synclost
+	 * problem that we get, if the bootloader starts the DSS and
+	 * the kernel resets it */
+	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+
+#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
+	/* We need to wait here a bit, otherwise we sometimes start to
+	 * get synclost errors, and after that only power cycle will
+	 * restore DSS functionality. I have no idea why this happens.
+	 * And we have to wait _before_ resetting the DSS, but after
+	 * enabling clocks.
+	 *
+	 * This bug was at least present on OMAP3430. It's unknown
+	 * if it happens on OMAP2 or OMAP3630.
+	 */
+	msleep(50);
+#endif
+
+	_omap_dss_reset();
+
+	/* autoidle */
+	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+
+	/* Select DPLL */
+	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
+	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
+	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
+#endif
+	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
 	r = dpi_init();
 	if (r) {
@@ -1125,23 +1098,32 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 		goto err_sdi;
 	}
 
+	dss_save_context();
+
+	rev = dss_read_reg(DSS_REVISION);
+	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
 	dss_clk_disable_all_no_ctx();
+
 	return 0;
 err_sdi:
 	dpi_exit();
 err_dpi:
-	dss_exit();
-err_dss:
 	dss_clk_disable_all_no_ctx();
 	dss_put_clocks();
 err_clocks:
+	iounmap(dss.base);
+err_ioremap:
 	return r;
 }
 
 static int omap_dsshw_remove(struct platform_device *pdev)
 {
+	dpi_exit();
+	sdi_exit();
 
-	dss_exit();
+	iounmap(dss.base);
 
 	/*
 	 * As part of hwmod changes, DSS is not the only controller of dss
@@ -1152,6 +1134,7 @@ static int omap_dsshw_remove(struct platform_device *pdev)
 	WARN_ON(dss.num_clks_enabled > 0);
 
 	dss_put_clocks();
+
 	return 0;
 }
 
-- 
1.7.4.1


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

* [PATCH 05/27] OMAP: DSS2: Clean up probe for DSS & DSI
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Both dss.c and dsi.c had a probe function, which was almost a dummy one,
calling dss_init() and dsi_init().

Remove the init functions by moving the initialization code into probe
functions.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   30 ++-------
 drivers/video/omap2/dss/dss.c |  145 ++++++++++++++++++-----------------------
 2 files changed, 69 insertions(+), 106 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 4496d09..0609885 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4450,7 +4450,8 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
 	dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
-static int dsi_init(struct platform_device *dsidev)
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *dsidev)
 {
 	struct omap_display_platform_data *dss_plat_data;
 	struct omap_dss_board_info *board_info;
@@ -4547,10 +4548,12 @@ err0:
 	return r;
 }
 
-static void dsi_exit(struct platform_device *dsidev)
+static int omap_dsi1hw_remove(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
+	WARN_ON(dsi->scp_clk_refcount > 0);
+
 	if (dsi->vdds_dsi_reg != NULL) {
 		if (dsi->vdds_dsi_enabled) {
 			regulator_disable(dsi->vdds_dsi_reg);
@@ -4566,29 +4569,6 @@ static void dsi_exit(struct platform_device *dsidev)
 
 	kfree(dsi);
 
-	DSSDBG("omap_dsi_exit\n");
-}
-
-/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
-{
-	int r;
-
-	r = dsi_init(dsidev);
-	if (r) {
-		DSSERR("Failed to initialize DSI\n");
-		goto err_dsi;
-	}
-err_dsi:
-	return r;
-}
-
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
-{
-	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
-	dsi_exit(dsidev);
-	WARN_ON(dsi->scp_clk_refcount > 0);
 	return 0;
 }
 
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 3eed8a2..f5f9fcb 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -664,79 +664,6 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
 	REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15);	/* VENC_HDMI_SWITCH */
 }
 
-static int dss_init(void)
-{
-	int r;
-	u32 rev;
-	struct resource *dss_mem;
-
-	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
-	if (!dss_mem) {
-		DSSERR("can't get IORESOURCE_MEM DSS\n");
-		r = -EINVAL;
-		goto fail0;
-	}
-	dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
-	if (!dss.base) {
-		DSSERR("can't ioremap DSS\n");
-		r = -ENOMEM;
-		goto fail0;
-	}
-
-	/* disable LCD and DIGIT output. This seems to fix the synclost
-	 * problem that we get, if the bootloader starts the DSS and
-	 * the kernel resets it */
-	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
-
-#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
-	/* We need to wait here a bit, otherwise we sometimes start to
-	 * get synclost errors, and after that only power cycle will
-	 * restore DSS functionality. I have no idea why this happens.
-	 * And we have to wait _before_ resetting the DSS, but after
-	 * enabling clocks.
-	 *
-	 * This bug was at least present on OMAP3430. It's unknown
-	 * if it happens on OMAP2 or OMAP3630.
-	 */
-	msleep(50);
-#endif
-
-	_omap_dss_reset();
-
-	/* autoidle */
-	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
-
-	/* Select DPLL */
-	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
-
-#ifdef CONFIG_OMAP2_DSS_VENC
-	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
-	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
-	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
-#endif
-	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
-	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-
-	dss_save_context();
-
-	rev = dss_read_reg(DSS_REVISION);
-	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
-			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
-	return 0;
-
-fail0:
-	return r;
-}
-
-static void dss_exit(void)
-{
-	iounmap(dss.base);
-}
-
 /* CONTEXT */
 static int dss_get_ctx_id(void)
 {
@@ -1094,10 +1021,25 @@ void dss_debug_dump_clocks(struct seq_file *s)
 /* DSS HW IP initialisation */
 static int omap_dsshw_probe(struct platform_device *pdev)
 {
+	struct resource *dss_mem;
+	u32 rev;
 	int r;
 
 	dss.pdev = pdev;
 
+	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+	if (!dss_mem) {
+		DSSERR("can't get IORESOURCE_MEM DSS\n");
+		r = -EINVAL;
+		goto err_ioremap;
+	}
+	dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
+	if (!dss.base) {
+		DSSERR("can't ioremap DSS\n");
+		r = -ENOMEM;
+		goto err_ioremap;
+	}
+
 	r = dss_get_clocks();
 	if (r)
 		goto err_clocks;
@@ -1107,11 +1049,42 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	dss.ctx_id = dss_get_ctx_id();
 	DSSDBG("initial ctx id %u\n", dss.ctx_id);
 
-	r = dss_init();
-	if (r) {
-		DSSERR("Failed to initialize DSS\n");
-		goto err_dss;
-	}
+	/* disable LCD and DIGIT output. This seems to fix the synclost
+	 * problem that we get, if the bootloader starts the DSS and
+	 * the kernel resets it */
+	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+
+#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
+	/* We need to wait here a bit, otherwise we sometimes start to
+	 * get synclost errors, and after that only power cycle will
+	 * restore DSS functionality. I have no idea why this happens.
+	 * And we have to wait _before_ resetting the DSS, but after
+	 * enabling clocks.
+	 *
+	 * This bug was at least present on OMAP3430. It's unknown
+	 * if it happens on OMAP2 or OMAP3630.
+	 */
+	msleep(50);
+#endif
+
+	_omap_dss_reset();
+
+	/* autoidle */
+	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+
+	/* Select DPLL */
+	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
+	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
+	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
+#endif
+	dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+	dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+	dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
 	r = dpi_init();
 	if (r) {
@@ -1125,23 +1098,32 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 		goto err_sdi;
 	}
 
+	dss_save_context();
+
+	rev = dss_read_reg(DSS_REVISION);
+	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
 	dss_clk_disable_all_no_ctx();
+
 	return 0;
 err_sdi:
 	dpi_exit();
 err_dpi:
-	dss_exit();
-err_dss:
 	dss_clk_disable_all_no_ctx();
 	dss_put_clocks();
 err_clocks:
+	iounmap(dss.base);
+err_ioremap:
 	return r;
 }
 
 static int omap_dsshw_remove(struct platform_device *pdev)
 {
+	dpi_exit();
+	sdi_exit();
 
-	dss_exit();
+	iounmap(dss.base);
 
 	/*
 	 * As part of hwmod changes, DSS is not the only controller of dss
@@ -1152,6 +1134,7 @@ static int omap_dsshw_remove(struct platform_device *pdev)
 	WARN_ON(dss.num_clks_enabled > 0);
 
 	dss_put_clocks();
+
 	return 0;
 }
 
-- 
1.7.4.1


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

* [PATCH 06/27] OMAP: DSS2: Init dispc first before other components
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The initialization order of the DSS modules is important when pm_runtime
support is implemented. Currently RFBI is initialized before DISPC,
which will cause problems with pm_runtime as RFBI uses DISPC.

Change the init order so that DISPC is before RFBI.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/core.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 3da4267..02187df 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -185,6 +185,11 @@ static int omap_dss_probe(struct platform_device *pdev)
 
 	/* keep clocks enabled to prevent context saves/restores during init */
 	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	r = dispc_init_platform_driver();
+	if (r) {
+		DSSERR("Failed to initialize dispc platform driver\n");
+		goto err_dispc;
+	}
 
 	r = rfbi_init_platform_driver();
 	if (r) {
@@ -192,12 +197,6 @@ static int omap_dss_probe(struct platform_device *pdev)
 		goto err_rfbi;
 	}
 
-	r = dispc_init_platform_driver();
-	if (r) {
-		DSSERR("Failed to initialize dispc platform driver\n");
-		goto err_dispc;
-	}
-
 	r = venc_init_platform_driver();
 	if (r) {
 		DSSERR("Failed to initialize venc platform driver\n");
-- 
1.7.4.1


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

* [PATCH 06/27] OMAP: DSS2: Init dispc first before other components
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The initialization order of the DSS modules is important when pm_runtime
support is implemented. Currently RFBI is initialized before DISPC,
which will cause problems with pm_runtime as RFBI uses DISPC.

Change the init order so that DISPC is before RFBI.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/core.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 3da4267..02187df 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -185,6 +185,11 @@ static int omap_dss_probe(struct platform_device *pdev)
 
 	/* keep clocks enabled to prevent context saves/restores during init */
 	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	r = dispc_init_platform_driver();
+	if (r) {
+		DSSERR("Failed to initialize dispc platform driver\n");
+		goto err_dispc;
+	}
 
 	r = rfbi_init_platform_driver();
 	if (r) {
@@ -192,12 +197,6 @@ static int omap_dss_probe(struct platform_device *pdev)
 		goto err_rfbi;
 	}
 
-	r = dispc_init_platform_driver();
-	if (r) {
-		DSSERR("Failed to initialize dispc platform driver\n");
-		goto err_dispc;
-	}
-
 	r = venc_init_platform_driver();
 	if (r) {
 		DSSERR("Failed to initialize venc platform driver\n");
-- 
1.7.4.1


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

* [PATCH 07/27] OMAP: DSS2: Remove clk optimization at dss init
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

DSS enables core clocks for the duration of initialization to avoid
unnecessary context saves and restores.

With PM runtime the clocks cannot be handled in this way, outside the
dss module drivers. Thus we need to remove the optimization.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/core.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 02187df..f0bae6d 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -183,8 +183,6 @@ static int omap_dss_probe(struct platform_device *pdev)
 		goto err_dss;
 	}
 
-	/* keep clocks enabled to prevent context saves/restores during init */
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 	r = dispc_init_platform_driver();
 	if (r) {
 		DSSERR("Failed to initialize dispc platform driver\n");
@@ -237,8 +235,6 @@ static int omap_dss_probe(struct platform_device *pdev)
 			pdata->default_device = dssdev;
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-
 	return 0;
 
 err_register:
-- 
1.7.4.1


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

* [PATCH 07/27] OMAP: DSS2: Remove clk optimization at dss init
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

DSS enables core clocks for the duration of initialization to avoid
unnecessary context saves and restores.

With PM runtime the clocks cannot be handled in this way, outside the
dss module drivers. Thus we need to remove the optimization.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/core.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 02187df..f0bae6d 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -183,8 +183,6 @@ static int omap_dss_probe(struct platform_device *pdev)
 		goto err_dss;
 	}
 
-	/* keep clocks enabled to prevent context saves/restores during init */
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 	r = dispc_init_platform_driver();
 	if (r) {
 		DSSERR("Failed to initialize dispc platform driver\n");
@@ -237,8 +235,6 @@ static int omap_dss_probe(struct platform_device *pdev)
 			pdata->default_device = dssdev;
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-
 	return 0;
 
 err_register:
-- 
1.7.4.1


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

* [PATCH 08/27] OMAP: DSS2: rewrite use of context_loss_count
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The function to get device's context loss count has changed from

omap_pm_get_last_off_on_transaction_id() to
omap_pm_get_dev_context_loss_count()

Change name of the function pointer in omapdss.h accordingly, and use
the term "context loss count" instead of "context id" in the code.

Restructure the context loss count functions to handle errors properly,
and ensure that context is always considered lost if an error happens.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |    2 +-
 drivers/video/omap2/dss/dss.c |   71 +++++++++++++++++++++++++++--------------
 drivers/video/omap2/dss/dss.h |    1 -
 include/video/omapdss.h       |    2 +-
 4 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 543fcb8..084a51b 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -117,7 +117,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	}
 
 	pdata.board_data = board_data;
-	pdata.board_data->get_last_off_on_transaction_id = NULL;
+	pdata.board_data->get_context_loss_count = NULL;
 	pdata.opt_clock_available = opt_clock_available;
 
 	for (i = 0; i < oh_count; i++) {
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index f5f9fcb..b63e290 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -60,7 +60,7 @@ struct dss_reg {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
-	int             ctx_id;
+	int		ctx_loss_cnt;
 
 	struct clk	*dpll4_m4_ck;
 	struct clk	*dss_ick;
@@ -665,34 +665,58 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
 }
 
 /* CONTEXT */
-static int dss_get_ctx_id(void)
+static void dss_init_ctx_loss_count(void)
 {
-	struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-	int r;
+	struct device *dev = &dss.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt = 0;
 
-	if (!pdata->board_data->get_last_off_on_transaction_id)
-		return 0;
-	r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
-	if (r < 0) {
-		dev_err(&dss.pdev->dev, "getting transaction ID failed, "
-				"will force context restore\n");
-		r = -1;
-	}
-	return r;
+	/*
+	 * get_context_loss_count returns negative on error. We'll ignore the
+	 * error and store the error to ctx_loss_cnt, which will cause
+	 * dss_need_ctx_restore() call to return true.
+	 */
+
+	if (board_data->get_context_loss_count)
+		cnt = board_data->get_context_loss_count(dev);
+
+	WARN_ON(cnt < 0);
+
+	dss.ctx_loss_cnt = cnt;
+
+	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
 }
 
-int dss_need_ctx_restore(void)
+static bool dss_need_ctx_restore(void)
 {
-	int id = dss_get_ctx_id();
+	struct device *dev = &dss.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt;
 
-	if (id < 0 || id != dss.ctx_id) {
-		DSSDBG("ctx id %d -> id %d\n",
-				dss.ctx_id, id);
-		dss.ctx_id = id;
-		return 1;
-	} else {
-		return 0;
+	/*
+	 * If get_context_loss_count is not available, assume that we need
+	 * context restore always.
+	 */
+	if (!board_data->get_context_loss_count)
+		return true;
+
+	cnt = board_data->get_context_loss_count(dev);
+	if (cnt < 0) {
+		dev_err(dev, "getting context loss count failed, will force "
+				"context restore\n");
+		dss.ctx_loss_cnt = cnt;
+		return true;
 	}
+
+	if (cnt = dss.ctx_loss_cnt)
+		return false;
+
+	DSSDBG("ctx_loss_cnt %d -> %d\n", dss.ctx_loss_cnt, cnt);
+	dss.ctx_loss_cnt = cnt;
+
+	return true;
 }
 
 static void save_all_ctx(void)
@@ -1046,8 +1070,7 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 
 	dss_clk_enable_all_no_ctx();
 
-	dss.ctx_id = dss_get_ctx_id();
-	DSSDBG("initial ctx id %u\n", dss.ctx_id);
+	dss_init_ctx_loss_count();
 
 	/* disable LCD and DIGIT output. This seems to fix the synclost
 	 * problem that we get, if the bootloader starts the DSS and
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 8ab6d43..aeb611d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -226,7 +226,6 @@ void dss_restore_context(void);
 void dss_clk_enable(enum dss_clock clks);
 void dss_clk_disable(enum dss_clock clks);
 unsigned long dss_clk_get_rate(enum dss_clock clk);
-int dss_need_ctx_restore(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index bb39738..4f914a5 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -244,7 +244,7 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
 
 /* Board specific data */
 struct omap_dss_board_info {
-	int (*get_last_off_on_transaction_id)(struct device *dev);
+	int (*get_context_loss_count)(struct device *dev);
 	int num_devices;
 	struct omap_dss_device **devices;
 	struct omap_dss_device *default_device;
-- 
1.7.4.1


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

* [PATCH 08/27] OMAP: DSS2: rewrite use of context_loss_count
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The function to get device's context loss count has changed from

omap_pm_get_last_off_on_transaction_id() to
omap_pm_get_dev_context_loss_count()

Change name of the function pointer in omapdss.h accordingly, and use
the term "context loss count" instead of "context id" in the code.

Restructure the context loss count functions to handle errors properly,
and ensure that context is always considered lost if an error happens.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |    2 +-
 drivers/video/omap2/dss/dss.c |   71 +++++++++++++++++++++++++++--------------
 drivers/video/omap2/dss/dss.h |    1 -
 include/video/omapdss.h       |    2 +-
 4 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 543fcb8..084a51b 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -117,7 +117,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	}
 
 	pdata.board_data = board_data;
-	pdata.board_data->get_last_off_on_transaction_id = NULL;
+	pdata.board_data->get_context_loss_count = NULL;
 	pdata.opt_clock_available = opt_clock_available;
 
 	for (i = 0; i < oh_count; i++) {
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index f5f9fcb..b63e290 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -60,7 +60,7 @@ struct dss_reg {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
-	int             ctx_id;
+	int		ctx_loss_cnt;
 
 	struct clk	*dpll4_m4_ck;
 	struct clk	*dss_ick;
@@ -665,34 +665,58 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
 }
 
 /* CONTEXT */
-static int dss_get_ctx_id(void)
+static void dss_init_ctx_loss_count(void)
 {
-	struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-	int r;
+	struct device *dev = &dss.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt = 0;
 
-	if (!pdata->board_data->get_last_off_on_transaction_id)
-		return 0;
-	r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
-	if (r < 0) {
-		dev_err(&dss.pdev->dev, "getting transaction ID failed, "
-				"will force context restore\n");
-		r = -1;
-	}
-	return r;
+	/*
+	 * get_context_loss_count returns negative on error. We'll ignore the
+	 * error and store the error to ctx_loss_cnt, which will cause
+	 * dss_need_ctx_restore() call to return true.
+	 */
+
+	if (board_data->get_context_loss_count)
+		cnt = board_data->get_context_loss_count(dev);
+
+	WARN_ON(cnt < 0);
+
+	dss.ctx_loss_cnt = cnt;
+
+	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
 }
 
-int dss_need_ctx_restore(void)
+static bool dss_need_ctx_restore(void)
 {
-	int id = dss_get_ctx_id();
+	struct device *dev = &dss.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt;
 
-	if (id < 0 || id != dss.ctx_id) {
-		DSSDBG("ctx id %d -> id %d\n",
-				dss.ctx_id, id);
-		dss.ctx_id = id;
-		return 1;
-	} else {
-		return 0;
+	/*
+	 * If get_context_loss_count is not available, assume that we need
+	 * context restore always.
+	 */
+	if (!board_data->get_context_loss_count)
+		return true;
+
+	cnt = board_data->get_context_loss_count(dev);
+	if (cnt < 0) {
+		dev_err(dev, "getting context loss count failed, will force "
+				"context restore\n");
+		dss.ctx_loss_cnt = cnt;
+		return true;
 	}
+
+	if (cnt == dss.ctx_loss_cnt)
+		return false;
+
+	DSSDBG("ctx_loss_cnt %d -> %d\n", dss.ctx_loss_cnt, cnt);
+	dss.ctx_loss_cnt = cnt;
+
+	return true;
 }
 
 static void save_all_ctx(void)
@@ -1046,8 +1070,7 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 
 	dss_clk_enable_all_no_ctx();
 
-	dss.ctx_id = dss_get_ctx_id();
-	DSSDBG("initial ctx id %u\n", dss.ctx_id);
+	dss_init_ctx_loss_count();
 
 	/* disable LCD and DIGIT output. This seems to fix the synclost
 	 * problem that we get, if the bootloader starts the DSS and
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 8ab6d43..aeb611d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -226,7 +226,6 @@ void dss_restore_context(void);
 void dss_clk_enable(enum dss_clock clks);
 void dss_clk_disable(enum dss_clock clks);
 unsigned long dss_clk_get_rate(enum dss_clock clk);
-int dss_need_ctx_restore(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index bb39738..4f914a5 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -244,7 +244,7 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
 
 /* Board specific data */
 struct omap_dss_board_info {
-	int (*get_last_off_on_transaction_id)(struct device *dev);
+	int (*get_context_loss_count)(struct device *dev);
 	int num_devices;
 	struct omap_dss_device **devices;
 	struct omap_dss_device *default_device;
-- 
1.7.4.1


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

* [PATCH 09/27] OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Initialize get_context_loss_count in the DSS board data to
omap_pm_get_dev_context_loss_count, so that omapdss driver can use it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 084a51b..c7e19c4 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -25,6 +25,7 @@
 #include <video/omapdss.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap-pm.h>
 
 static struct platform_device omap_display_device = {
 	.name          = "omapdss",
@@ -117,7 +118,8 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	}
 
 	pdata.board_data = board_data;
-	pdata.board_data->get_context_loss_count = NULL;
+	pdata.board_data->get_context_loss_count +		omap_pm_get_dev_context_loss_count;
 	pdata.opt_clock_available = opt_clock_available;
 
 	for (i = 0; i < oh_count; i++) {
-- 
1.7.4.1


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

* [PATCH 09/27] OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Initialize get_context_loss_count in the DSS board data to
omap_pm_get_dev_context_loss_count, so that omapdss driver can use it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 084a51b..c7e19c4 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -25,6 +25,7 @@
 #include <video/omapdss.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap-pm.h>
 
 static struct platform_device omap_display_device = {
 	.name          = "omapdss",
@@ -117,7 +118,8 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	}
 
 	pdata.board_data = board_data;
-	pdata.board_data->get_context_loss_count = NULL;
+	pdata.board_data->get_context_loss_count =
+		omap_pm_get_dev_context_loss_count;
 	pdata.opt_clock_available = opt_clock_available;
 
 	for (i = 0; i < oh_count; i++) {
-- 
1.7.4.1


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

* [PATCH 10/27] OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

DSI PLL requires sys_clk to function, and DPI enables sys_clk when it
wants to use DSI PLL. However, DSI PLL code already handles enabling
sys_clk, so DPI's sys_clk code is extra.

Remove the unneeded sys_clk handling from dpi.c.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dpi.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index ff6bd30..bab55cd 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -202,15 +202,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 		goto err2;
 
 	if (dpi_use_dsi_pll(dssdev)) {
-		dss_clk_enable(DSS_CLK_SYSCK);
 		r = dsi_pll_init(dpi.dsidev, 0, 1);
 		if (r)
-			goto err3;
+			goto err2;
 	}
 
 	r = dpi_set_mode(dssdev);
 	if (r)
-		goto err4;
+		goto err3;
 
 	mdelay(2);
 
@@ -218,12 +217,9 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 	return 0;
 
-err4:
-	if (dpi_use_dsi_pll(dssdev))
-		dsi_pll_uninit(dpi.dsidev, true);
 err3:
 	if (dpi_use_dsi_pll(dssdev))
-		dss_clk_disable(DSS_CLK_SYSCK);
+		dsi_pll_uninit(dpi.dsidev, true);
 err2:
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 	if (cpu_is_omap34xx())
@@ -242,7 +238,6 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 	if (dpi_use_dsi_pll(dssdev)) {
 		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 		dsi_pll_uninit(dpi.dsidev, true);
-		dss_clk_disable(DSS_CLK_SYSCK);
 	}
 
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-- 
1.7.4.1


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

* [PATCH 10/27] OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

DSI PLL requires sys_clk to function, and DPI enables sys_clk when it
wants to use DSI PLL. However, DSI PLL code already handles enabling
sys_clk, so DPI's sys_clk code is extra.

Remove the unneeded sys_clk handling from dpi.c.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dpi.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index ff6bd30..bab55cd 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -202,15 +202,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 		goto err2;
 
 	if (dpi_use_dsi_pll(dssdev)) {
-		dss_clk_enable(DSS_CLK_SYSCK);
 		r = dsi_pll_init(dpi.dsidev, 0, 1);
 		if (r)
-			goto err3;
+			goto err2;
 	}
 
 	r = dpi_set_mode(dssdev);
 	if (r)
-		goto err4;
+		goto err3;
 
 	mdelay(2);
 
@@ -218,12 +217,9 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 	return 0;
 
-err4:
-	if (dpi_use_dsi_pll(dssdev))
-		dsi_pll_uninit(dpi.dsidev, true);
 err3:
 	if (dpi_use_dsi_pll(dssdev))
-		dss_clk_disable(DSS_CLK_SYSCK);
+		dsi_pll_uninit(dpi.dsidev, true);
 err2:
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 	if (cpu_is_omap34xx())
@@ -242,7 +238,6 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 	if (dpi_use_dsi_pll(dssdev)) {
 		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 		dsi_pll_uninit(dpi.dsidev, true);
-		dss_clk_disable(DSS_CLK_SYSCK);
 	}
 
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-- 
1.7.4.1


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

* [PATCH 11/27] OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

OMAP3430 requires an 96MHz clock to VENC's DAC, but no other OMAP needs
it.

Add a new feature, FEAT_VENC_REQUIRES_TV_DAC_CLK, which tells if the
clock is needed on this platform, and use that feature in venc.c to
decide if the clock needs enabling.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss_features.c |    3 ++-
 drivers/video/omap2/dss/dss_features.h |    1 +
 drivers/video/omap2/dss/venc.c         |   16 ++++++++++------
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 1c18888..a588380 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -286,7 +286,8 @@ static const struct omap_dss_features omap3430_dss_features = {
 		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
 		FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
 		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
-		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
+		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
+		FEAT_VENC_REQUIRES_TV_DAC_CLK,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 07b346f..3058e24 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -51,6 +51,7 @@ enum dss_feat_id {
 	FEAT_HDMI_CTS_SWMODE		= 1 << 19,
 	FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
 	FEAT_ATTR2                      = 1 << 21,
+	FEAT_VENC_REQUIRES_TV_DAC_CLK	= 1 << 22,
 };
 
 /* DSS register field id */
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 980f919..15b4431 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -38,6 +38,7 @@
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /* Venc registers */
 #define VENC_REV_ID				0x00
@@ -382,12 +383,15 @@ static void venc_reset(void)
 
 static void venc_enable_clocks(int enable)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-				DSS_CLK_VIDFCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-				DSS_CLK_VIDFCK);
+	if (enable) {
+		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
+		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
+			dss_clk_enable(DSS_CLK_VIDFCK);
+	} else {
+		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
+		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
+			dss_clk_disable(DSS_CLK_VIDFCK);
+	}
 }
 
 static const struct venc_config *venc_timings_to_config(
-- 
1.7.4.1


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

* [PATCH 11/27] OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

OMAP3430 requires an 96MHz clock to VENC's DAC, but no other OMAP needs
it.

Add a new feature, FEAT_VENC_REQUIRES_TV_DAC_CLK, which tells if the
clock is needed on this platform, and use that feature in venc.c to
decide if the clock needs enabling.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss_features.c |    3 ++-
 drivers/video/omap2/dss/dss_features.h |    1 +
 drivers/video/omap2/dss/venc.c         |   16 ++++++++++------
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 1c18888..a588380 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -286,7 +286,8 @@ static const struct omap_dss_features omap3430_dss_features = {
 		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
 		FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
 		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
-		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
+		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
+		FEAT_VENC_REQUIRES_TV_DAC_CLK,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 07b346f..3058e24 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -51,6 +51,7 @@ enum dss_feat_id {
 	FEAT_HDMI_CTS_SWMODE		= 1 << 19,
 	FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
 	FEAT_ATTR2                      = 1 << 21,
+	FEAT_VENC_REQUIRES_TV_DAC_CLK	= 1 << 22,
 };
 
 /* DSS register field id */
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 980f919..15b4431 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -38,6 +38,7 @@
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /* Venc registers */
 #define VENC_REV_ID				0x00
@@ -382,12 +383,15 @@ static void venc_reset(void)
 
 static void venc_enable_clocks(int enable)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-				DSS_CLK_VIDFCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-				DSS_CLK_VIDFCK);
+	if (enable) {
+		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
+		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
+			dss_clk_enable(DSS_CLK_VIDFCK);
+	} else {
+		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
+		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
+			dss_clk_disable(DSS_CLK_VIDFCK);
+	}
 }
 
 static const struct venc_config *venc_timings_to_config(
-- 
1.7.4.1


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

* [PATCH 12/27] OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

OMAP2 doesn't have CPR, PRELOAD nor FIR_COEF_V registers. Add new
feature definitions for those, and check the feature before accessing
those registers.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c        |  145 ++++++++++++++++++++------------
 drivers/video/omap2/dss/dss_features.c |   12 ++-
 drivers/video/omap2/dss/dss_features.h |    3 +
 drivers/video/omap2/dss/overlay.c      |    3 +
 4 files changed, 105 insertions(+), 58 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index a9eebd8..ee2052f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -159,7 +159,8 @@ void dispc_save_context(void)
 	SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
 	SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 	SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-	SR(GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+		SR(GLOBAL_ALPHA);
 	SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 	SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -189,20 +190,25 @@ void dispc_save_context(void)
 	SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 	SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-	SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-	SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-	SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	if (dss_has_feature(FEAT_CPR)) {
+		SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+		SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+		SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	}
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-		SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-		SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		if (dss_has_feature(FEAT_CPR)) {
+			SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+			SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+			SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		}
 
 		SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 		SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 		SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 	}
 
-	SR(OVL_PRELOAD(OMAP_DSS_GFX));
+	if (dss_has_feature(FEAT_PRELOAD))
+		SR(OVL_PRELOAD(OMAP_DSS_GFX));
 
 	/* VID1 */
 	SR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -227,8 +233,10 @@ void dispc_save_context(void)
 	for (i = 0; i < 5; i++)
 		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-	for (i = 0; i < 8; i++)
-		SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -249,7 +257,8 @@ void dispc_save_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-	SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+	if (dss_has_feature(FEAT_PRELOAD))
+		SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
 	/* VID2 */
 	SR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -274,8 +283,10 @@ void dispc_save_context(void)
 	for (i = 0; i < 5; i++)
 		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-	for (i = 0; i < 8; i++)
-		SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -296,7 +307,8 @@ void dispc_save_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-	SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	if (dss_has_feature(FEAT_PRELOAD))
+		SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		SR(DIVISOR);
@@ -318,7 +330,8 @@ void dispc_restore_context(void)
 	RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
 	RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 	RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-	RR(GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+		RR(GLOBAL_ALPHA);
 	RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 	RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -348,20 +361,25 @@ void dispc_restore_context(void)
 	RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 	RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-	RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-	RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-	RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	if (dss_has_feature(FEAT_CPR)) {
+		RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+		RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+		RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	}
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
 		RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 		RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 		RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-		RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-		RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-		RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		if (dss_has_feature(FEAT_CPR)) {
+			RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+			RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+			RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		}
 	}
 
-	RR(OVL_PRELOAD(OMAP_DSS_GFX));
+	if (dss_has_feature(FEAT_PRELOAD))
+		RR(OVL_PRELOAD(OMAP_DSS_GFX));
 
 	/* VID1 */
 	RR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -386,8 +404,10 @@ void dispc_restore_context(void)
 	for (i = 0; i < 5; i++)
 		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-	for (i = 0; i < 8; i++)
-		RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -408,7 +428,8 @@ void dispc_restore_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-	RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+	if (dss_has_feature(FEAT_PRELOAD))
+		RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
 	/* VID2 */
 	RR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -433,8 +454,10 @@ void dispc_restore_context(void)
 	for (i = 0; i < 5; i++)
 		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-	for (i = 0; i < 8; i++)
-		RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -455,7 +478,8 @@ void dispc_restore_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-	RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	if (dss_has_feature(FEAT_PRELOAD))
+		RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		RR(DIVISOR);
@@ -2650,7 +2674,8 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
 	DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 	DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
-	DUMPREG(DISPC_GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+		DUMPREG(DISPC_GLOBAL_ALPHA);
 	DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 	DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -2681,20 +2706,25 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 	DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-	DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-	DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-	DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	if (dss_has_feature(FEAT_CPR)) {
+		DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+		DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+		DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	}
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
 		DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 		DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 		DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-		DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
-		DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-		DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+		if (dss_has_feature(FEAT_CPR)) {
+			DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+			DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+			DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+		}
 	}
 
-	DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
+	if (dss_has_feature(FEAT_PRELOAD))
+		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
 
 	DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
 	DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
@@ -2745,14 +2775,16 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -2813,14 +2845,17 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -2859,8 +2894,10 @@ void dispc_dump_regs(struct seq_file *s)
 	if (dss_has_feature(FEAT_ATTR2))
 		DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-	DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
-	DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	if (dss_has_feature(FEAT_PRELOAD)) {
+		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
+		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	}
 
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 #undef DUMPREG
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index a588380..bd420f9 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -287,7 +287,8 @@ static const struct omap_dss_features omap3430_dss_features = {
 		FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
 		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
 		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
-		FEAT_VENC_REQUIRES_TV_DAC_CLK,
+		FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
+		FEAT_FIR_COEF_V,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
@@ -307,7 +308,8 @@ static const struct omap_dss_features omap3630_dss_features = {
 		FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
 		FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
 		FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
-		FEAT_DSI_PLL_FREQSEL,
+		FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
+		FEAT_FIR_COEF_V,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
@@ -328,7 +330,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
 		FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
 		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
 		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
-		FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+		FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
+		FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
 	.num_mgrs = 3,
 	.num_ovls = 3,
@@ -349,7 +352,8 @@ static const struct omap_dss_features omap4_dss_features = {
 		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
 		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
 		FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
-		FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+		FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
+		FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
 	.num_mgrs = 3,
 	.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 3058e24..5be8103 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -52,6 +52,9 @@ enum dss_feat_id {
 	FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
 	FEAT_ATTR2                      = 1 << 21,
 	FEAT_VENC_REQUIRES_TV_DAC_CLK	= 1 << 22,
+	FEAT_CPR			= 1 << 23,
+	FEAT_PRELOAD			= 1 << 24,
+	FEAT_FIR_COEF_V			= 1 << 25,
 };
 
 /* DSS register field id */
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 0f08025..cfbfc57 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -238,6 +238,9 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
 	u8 alpha;
 	struct omap_overlay_info info;
 
+	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+		return -ENODEV;
+
 	r = kstrtou8(buf, 0, &alpha);
 	if (r)
 		return r;
-- 
1.7.4.1


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

* [PATCH 12/27] OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

OMAP2 doesn't have CPR, PRELOAD nor FIR_COEF_V registers. Add new
feature definitions for those, and check the feature before accessing
those registers.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c        |  145 ++++++++++++++++++++------------
 drivers/video/omap2/dss/dss_features.c |   12 ++-
 drivers/video/omap2/dss/dss_features.h |    3 +
 drivers/video/omap2/dss/overlay.c      |    3 +
 4 files changed, 105 insertions(+), 58 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index a9eebd8..ee2052f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -159,7 +159,8 @@ void dispc_save_context(void)
 	SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
 	SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 	SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-	SR(GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+		SR(GLOBAL_ALPHA);
 	SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 	SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -189,20 +190,25 @@ void dispc_save_context(void)
 	SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 	SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-	SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-	SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-	SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	if (dss_has_feature(FEAT_CPR)) {
+		SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+		SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+		SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	}
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-		SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-		SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		if (dss_has_feature(FEAT_CPR)) {
+			SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+			SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+			SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		}
 
 		SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 		SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 		SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 	}
 
-	SR(OVL_PRELOAD(OMAP_DSS_GFX));
+	if (dss_has_feature(FEAT_PRELOAD))
+		SR(OVL_PRELOAD(OMAP_DSS_GFX));
 
 	/* VID1 */
 	SR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -227,8 +233,10 @@ void dispc_save_context(void)
 	for (i = 0; i < 5; i++)
 		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-	for (i = 0; i < 8; i++)
-		SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -249,7 +257,8 @@ void dispc_save_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-	SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+	if (dss_has_feature(FEAT_PRELOAD))
+		SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
 	/* VID2 */
 	SR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -274,8 +283,10 @@ void dispc_save_context(void)
 	for (i = 0; i < 5; i++)
 		SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-	for (i = 0; i < 8; i++)
-		SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -296,7 +307,8 @@ void dispc_save_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-	SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	if (dss_has_feature(FEAT_PRELOAD))
+		SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		SR(DIVISOR);
@@ -318,7 +330,8 @@ void dispc_restore_context(void)
 	RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
 	RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 	RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-	RR(GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+		RR(GLOBAL_ALPHA);
 	RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 	RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -348,20 +361,25 @@ void dispc_restore_context(void)
 	RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 	RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-	RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-	RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-	RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	if (dss_has_feature(FEAT_CPR)) {
+		RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+		RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+		RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	}
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
 		RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 		RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 		RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-		RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-		RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-		RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		if (dss_has_feature(FEAT_CPR)) {
+			RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+			RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+			RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+		}
 	}
 
-	RR(OVL_PRELOAD(OMAP_DSS_GFX));
+	if (dss_has_feature(FEAT_PRELOAD))
+		RR(OVL_PRELOAD(OMAP_DSS_GFX));
 
 	/* VID1 */
 	RR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -386,8 +404,10 @@ void dispc_restore_context(void)
 	for (i = 0; i < 5; i++)
 		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-	for (i = 0; i < 8; i++)
-		RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -408,7 +428,8 @@ void dispc_restore_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-	RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+	if (dss_has_feature(FEAT_PRELOAD))
+		RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
 	/* VID2 */
 	RR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -433,8 +454,10 @@ void dispc_restore_context(void)
 	for (i = 0; i < 5; i++)
 		RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-	for (i = 0; i < 8; i++)
-		RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		for (i = 0; i < 8; i++)
+			RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -455,7 +478,8 @@ void dispc_restore_context(void)
 	if (dss_has_feature(FEAT_ATTR2))
 		RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-	RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	if (dss_has_feature(FEAT_PRELOAD))
+		RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		RR(DIVISOR);
@@ -2650,7 +2674,8 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
 	DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
 	DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
-	DUMPREG(DISPC_GLOBAL_ALPHA);
+	if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+		DUMPREG(DISPC_GLOBAL_ALPHA);
 	DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
 	DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -2681,20 +2706,25 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
 	DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-	DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-	DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-	DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	if (dss_has_feature(FEAT_CPR)) {
+		DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+		DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+		DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+	}
 	if (dss_has_feature(FEAT_MGR_LCD2)) {
 		DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
 		DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
 		DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-		DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
-		DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-		DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+		if (dss_has_feature(FEAT_CPR)) {
+			DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+			DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+			DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+		}
 	}
 
-	DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
+	if (dss_has_feature(FEAT_PRELOAD))
+		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
 
 	DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
 	DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
@@ -2745,14 +2775,16 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -2813,14 +2845,17 @@ void dispc_dump_regs(struct seq_file *s)
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
 	DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
-	DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+
+	if (dss_has_feature(FEAT_FIR_COEF_V)) {
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
+		DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+	}
 
 	if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
 		DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -2859,8 +2894,10 @@ void dispc_dump_regs(struct seq_file *s)
 	if (dss_has_feature(FEAT_ATTR2))
 		DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-	DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
-	DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	if (dss_has_feature(FEAT_PRELOAD)) {
+		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
+		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+	}
 
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 #undef DUMPREG
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index a588380..bd420f9 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -287,7 +287,8 @@ static const struct omap_dss_features omap3430_dss_features = {
 		FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
 		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
 		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
-		FEAT_VENC_REQUIRES_TV_DAC_CLK,
+		FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
+		FEAT_FIR_COEF_V,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
@@ -307,7 +308,8 @@ static const struct omap_dss_features omap3630_dss_features = {
 		FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
 		FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
 		FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
-		FEAT_DSI_PLL_FREQSEL,
+		FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
+		FEAT_FIR_COEF_V,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
@@ -328,7 +330,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
 		FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
 		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
 		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
-		FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+		FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
+		FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
 	.num_mgrs = 3,
 	.num_ovls = 3,
@@ -349,7 +352,8 @@ static const struct omap_dss_features omap4_dss_features = {
 		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
 		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
 		FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
-		FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+		FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
+		FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
 	.num_mgrs = 3,
 	.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 3058e24..5be8103 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -52,6 +52,9 @@ enum dss_feat_id {
 	FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
 	FEAT_ATTR2                      = 1 << 21,
 	FEAT_VENC_REQUIRES_TV_DAC_CLK	= 1 << 22,
+	FEAT_CPR			= 1 << 23,
+	FEAT_PRELOAD			= 1 << 24,
+	FEAT_FIR_COEF_V			= 1 << 25,
 };
 
 /* DSS register field id */
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 0f08025..cfbfc57 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -238,6 +238,9 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
 	u8 alpha;
 	struct omap_overlay_info info;
 
+	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+		return -ENODEV;
+
 	r = kstrtou8(buf, 0, &alpha);
 	if (r)
 		return r;
-- 
1.7.4.1


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

* [PATCH 13/27] OMAP: DSS2: Remove core_dump_clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Currently dss.c does all the low level clock handling in the DSS, and
thus it contains pointers to all the clocks. This allows dss.c to dump
the clock information for all the clocks.

With pm_runtime this is no longer the case, as each submodule will
handle its clocks independently. Thus remove the core_dump_clocks
function as it cannot be used with pm_runtime.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   40 ----------------------------------------
 1 files changed, 0 insertions(+), 40 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index b63e290..951c849 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -989,50 +989,10 @@ static void dss_clk_disable_all_no_ctx(void)
 	dss_clk_disable_no_ctx(clks);
 }
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-/* CLOCKS */
-static void core_dump_clocks(struct seq_file *s)
-{
-	int i;
-	struct clk *clocks[5] = {
-		dss.dss_ick,
-		dss.dss_fck,
-		dss.dss_sys_clk,
-		dss.dss_tv_fck,
-		dss.dss_video_fck
-	};
-
-	const char *names[5] = {
-		"ick",
-		"fck",
-		"sys_clk",
-		"tv_fck",
-		"video_fck"
-	};
-
-	seq_printf(s, "- CORE -\n");
-
-	seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
-
-	for (i = 0; i < 5; i++) {
-		if (!clocks[i])
-			continue;
-		seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
-				names[i],
-				clocks[i]->name,
-				24 - strlen(names[i]) - strlen(clocks[i]->name),
-				"",
-				clk_get_rate(clocks[i]),
-				clocks[i]->usecount);
-	}
-}
-#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
-
 /* DEBUGFS */
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
-	core_dump_clocks(s);
 	dss_dump_clocks(s);
 	dispc_dump_clocks(s);
 #ifdef CONFIG_OMAP2_DSS_DSI
-- 
1.7.4.1


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

* [PATCH 13/27] OMAP: DSS2: Remove core_dump_clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Currently dss.c does all the low level clock handling in the DSS, and
thus it contains pointers to all the clocks. This allows dss.c to dump
the clock information for all the clocks.

With pm_runtime this is no longer the case, as each submodule will
handle its clocks independently. Thus remove the core_dump_clocks
function as it cannot be used with pm_runtime.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   40 ----------------------------------------
 1 files changed, 0 insertions(+), 40 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index b63e290..951c849 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -989,50 +989,10 @@ static void dss_clk_disable_all_no_ctx(void)
 	dss_clk_disable_no_ctx(clks);
 }
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-/* CLOCKS */
-static void core_dump_clocks(struct seq_file *s)
-{
-	int i;
-	struct clk *clocks[5] = {
-		dss.dss_ick,
-		dss.dss_fck,
-		dss.dss_sys_clk,
-		dss.dss_tv_fck,
-		dss.dss_video_fck
-	};
-
-	const char *names[5] = {
-		"ick",
-		"fck",
-		"sys_clk",
-		"tv_fck",
-		"video_fck"
-	};
-
-	seq_printf(s, "- CORE -\n");
-
-	seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
-
-	for (i = 0; i < 5; i++) {
-		if (!clocks[i])
-			continue;
-		seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
-				names[i],
-				clocks[i]->name,
-				24 - strlen(names[i]) - strlen(clocks[i]->name),
-				"",
-				clk_get_rate(clocks[i]),
-				clocks[i]->usecount);
-	}
-}
-#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
-
 /* DEBUGFS */
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
-	core_dump_clocks(s);
 	dss_dump_clocks(s);
 	dispc_dump_clocks(s);
 #ifdef CONFIG_OMAP2_DSS_DSI
-- 
1.7.4.1


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

* [PATCH 14/27] OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET is used to avoid an unclear bug at
DSS reset time. The pm runtime will handle reset in the future, and this
code has to be removed. Hopefully we won't see this error anymore.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/Kconfig |   12 ------------
 drivers/video/omap2/dss/dss.c   |   13 -------------
 2 files changed, 0 insertions(+), 25 deletions(-)

diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 6b3e2da..0d12524 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -117,18 +117,6 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
 	  Max FCK is 173MHz, so this doesn't work if your PCK
 	  is very high.
 
-config OMAP2_DSS_SLEEP_BEFORE_RESET
-	bool "Sleep 50ms before DSS reset"
-	default y
-	help
-	  For some unknown reason we may get SYNC_LOST errors from the display
-	  subsystem at initialization time if we don't sleep before resetting
-	  the DSS. See the source (dss.c) for more comments.
-
-	  However, 50ms is quite long time to sleep, and with some
-	  configurations the SYNC_LOST may never happen, so the sleep can
-	  be disabled here.
-
 config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
 	bool "Sleep 20ms after VENC reset"
 	default y
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 951c849..a0e933a 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -1037,19 +1037,6 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	 * the kernel resets it */
 	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
 
-#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
-	/* We need to wait here a bit, otherwise we sometimes start to
-	 * get synclost errors, and after that only power cycle will
-	 * restore DSS functionality. I have no idea why this happens.
-	 * And we have to wait _before_ resetting the DSS, but after
-	 * enabling clocks.
-	 *
-	 * This bug was at least present on OMAP3430. It's unknown
-	 * if it happens on OMAP2 or OMAP3630.
-	 */
-	msleep(50);
-#endif
-
 	_omap_dss_reset();
 
 	/* autoidle */
-- 
1.7.4.1


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

* [PATCH 14/27] OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET is used to avoid an unclear bug at
DSS reset time. The pm runtime will handle reset in the future, and this
code has to be removed. Hopefully we won't see this error anymore.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/Kconfig |   12 ------------
 drivers/video/omap2/dss/dss.c   |   13 -------------
 2 files changed, 0 insertions(+), 25 deletions(-)

diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 6b3e2da..0d12524 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -117,18 +117,6 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
 	  Max FCK is 173MHz, so this doesn't work if your PCK
 	  is very high.
 
-config OMAP2_DSS_SLEEP_BEFORE_RESET
-	bool "Sleep 50ms before DSS reset"
-	default y
-	help
-	  For some unknown reason we may get SYNC_LOST errors from the display
-	  subsystem at initialization time if we don't sleep before resetting
-	  the DSS. See the source (dss.c) for more comments.
-
-	  However, 50ms is quite long time to sleep, and with some
-	  configurations the SYNC_LOST may never happen, so the sleep can
-	  be disabled here.
-
 config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
 	bool "Sleep 20ms after VENC reset"
 	default y
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 951c849..a0e933a 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -1037,19 +1037,6 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	 * the kernel resets it */
 	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
 
-#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
-	/* We need to wait here a bit, otherwise we sometimes start to
-	 * get synclost errors, and after that only power cycle will
-	 * restore DSS functionality. I have no idea why this happens.
-	 * And we have to wait _before_ resetting the DSS, but after
-	 * enabling clocks.
-	 *
-	 * This bug was at least present on OMAP3430. It's unknown
-	 * if it happens on OMAP2 or OMAP3630.
-	 */
-	msleep(50);
-#endif
-
 	_omap_dss_reset();
 
 	/* autoidle */
-- 
1.7.4.1


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

* [PATCH 15/27] OMAP4: HWMOD: Modify DSS opt clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add missing DSS optional clocks to HWMOD data for OMAP4xxx.

Add HWMOD_CONTROL_OPT_CLKS_IN_RESET flag for dispc to fix dispc reset.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   40 ++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index abc548a..4f6ae94 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1263,9 +1263,21 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
 	&omap44xx_l4_per__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss_dss_clk" },
+	/*
+	 * The rest of the clocks are not needed by the driver,
+	 * but are needed by the hwmod to reset DSS properly.
+	 */
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_dss_dispc_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
@@ -1276,6 +1288,8 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap44xx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1354,6 +1368,11 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
 	&omap44xx_l4_per__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dsi1_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss_dss_clk" },
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap44xx_dsi_hwmod_class,
@@ -1367,6 +1386,8 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dsi1_opt_clks),
 	.slaves		= omap44xx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1514,6 +1535,11 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
 	&omap44xx_l4_per__dss_hdmi,
 };
 
+static struct omap_hwmod_opt_clk hdmi_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.name		= "dss_hdmi",
 	.class		= &omap44xx_hdmi_hwmod_class,
@@ -1527,6 +1553,8 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= hdmi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(hdmi_opt_clks),
 	.slaves		= omap44xx_dss_hdmi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1600,6 +1628,10 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
 	&omap44xx_l4_per__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_fck" },
+};
+
 static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap44xx_rfbi_hwmod_class,
@@ -1611,6 +1643,8 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap44xx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1669,6 +1703,10 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
 	&omap44xx_l4_per__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
@@ -1678,6 +1716,8 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap44xx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-- 
1.7.4.1


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

* [PATCH 15/27] OMAP4: HWMOD: Modify DSS opt clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add missing DSS optional clocks to HWMOD data for OMAP4xxx.

Add HWMOD_CONTROL_OPT_CLKS_IN_RESET flag for dispc to fix dispc reset.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   40 ++++++++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index abc548a..4f6ae94 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1263,9 +1263,21 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
 	&omap44xx_l4_per__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss_dss_clk" },
+	/*
+	 * The rest of the clocks are not needed by the driver,
+	 * but are needed by the hwmod to reset DSS properly.
+	 */
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_dss_dispc_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
@@ -1276,6 +1288,8 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap44xx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1354,6 +1368,11 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
 	&omap44xx_l4_per__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dsi1_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss_dss_clk" },
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap44xx_dsi_hwmod_class,
@@ -1367,6 +1386,8 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dsi1_opt_clks),
 	.slaves		= omap44xx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1514,6 +1535,11 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
 	&omap44xx_l4_per__dss_hdmi,
 };
 
+static struct omap_hwmod_opt_clk hdmi_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.name		= "dss_hdmi",
 	.class		= &omap44xx_hdmi_hwmod_class,
@@ -1527,6 +1553,8 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= hdmi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(hdmi_opt_clks),
 	.slaves		= omap44xx_dss_hdmi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1600,6 +1628,10 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
 	&omap44xx_l4_per__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_fck" },
+};
+
 static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap44xx_rfbi_hwmod_class,
@@ -1611,6 +1643,8 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap44xx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -1669,6 +1703,10 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
 	&omap44xx_l4_per__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+};
+
 static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
@@ -1678,6 +1716,8 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap44xx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
-- 
1.7.4.1


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

* [PATCH 16/27] OMAP3: HWMOD: Add DSS opt clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add DSS optional clocks to HWMOD data for OMAP3xxx.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   37 ++++++++++++++++++++++++++-
 1 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 909a84d..5fac4c0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1542,9 +1542,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-	{ .role = "tv_clk", .clk = "dss_tv_fck" },
-	{ .role = "video_clk", .clk = "dss_96m_fck" },
+	{ .role = "dss_clk", .clk = "dss1_alwon_fck" },
+	/*
+	 * The rest of the clocks are not needed by the driver,
+	 * but are needed by the hwmod to reset DSS properly.
+	 */
 	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
 };
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1656,6 +1662,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 	&omap3xxx_l4_core__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap3xxx_dispc_hwmod_class,
@@ -1669,6 +1679,8 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap3xxx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1720,6 +1732,11 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
 	&omap3xxx_l4_core__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dsi1_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_alwon_fck" },
+	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
@@ -1733,6 +1750,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dsi1_opt_clks),
 	.slaves		= omap3xxx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1791,6 +1810,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
 	&omap3xxx_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap3xxx_rfbi_hwmod_class,
@@ -1802,6 +1825,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap3xxx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1851,6 +1876,12 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
 	&omap3xxx_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap3xxx_venc_hwmod_class,
@@ -1862,6 +1893,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap3xxx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-- 
1.7.4.1


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

* [PATCH 16/27] OMAP3: HWMOD: Add DSS opt clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add DSS optional clocks to HWMOD data for OMAP3xxx.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   37 ++++++++++++++++++++++++++-
 1 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 909a84d..5fac4c0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1542,9 +1542,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-	{ .role = "tv_clk", .clk = "dss_tv_fck" },
-	{ .role = "video_clk", .clk = "dss_96m_fck" },
+	{ .role = "dss_clk", .clk = "dss1_alwon_fck" },
+	/*
+	 * The rest of the clocks are not needed by the driver,
+	 * but are needed by the hwmod to reset DSS properly.
+	 */
 	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
 };
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1656,6 +1662,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 	&omap3xxx_l4_core__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap3xxx_dispc_hwmod_class,
@@ -1669,6 +1679,8 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap3xxx_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1720,6 +1732,11 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
 	&omap3xxx_l4_core__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dsi1_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_alwon_fck" },
+	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
@@ -1733,6 +1750,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= dsi1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dsi1_opt_clks),
 	.slaves		= omap3xxx_dss_dsi1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1791,6 +1810,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
 	&omap3xxx_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap3xxx_rfbi_hwmod_class,
@@ -1802,6 +1825,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap3xxx_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
@@ -1851,6 +1876,12 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
 	&omap3xxx_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	/* required only on OMAP3430 */
+	{ .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap3xxx_venc_hwmod_class,
@@ -1862,6 +1893,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
 			.module_offs = OMAP3430_DSS_MOD,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap3xxx_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
-- 
1.7.4.1


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

* [PATCH 17/27] OMAP2420: HWMOD: Add DSS opt clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add DSS optional clocks to HWMOD data for OMAP2420.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index c4d0ae8..d87019d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1208,6 +1208,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -1291,6 +1292,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
 	&omap2420_l4_core__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
+};
+
 static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2420_dispc_hwmod_class,
@@ -1306,6 +1311,8 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap2420_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -1361,6 +1368,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
 	&omap2420_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2420_rfbi_hwmod_class,
@@ -1372,6 +1383,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap2420_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -1418,6 +1431,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
 	&omap2420_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+};
+
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2420_venc_hwmod_class,
@@ -1429,6 +1446,8 @@ static struct omap_hwmod omap2420_dss_venc_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap2420_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-- 
1.7.4.1


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

* [PATCH 17/27] OMAP2420: HWMOD: Add DSS opt clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add DSS optional clocks to HWMOD data for OMAP2420.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index c4d0ae8..d87019d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1208,6 +1208,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -1291,6 +1292,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
 	&omap2420_l4_core__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
+};
+
 static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2420_dispc_hwmod_class,
@@ -1306,6 +1311,8 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap2420_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -1361,6 +1368,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
 	&omap2420_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2420_rfbi_hwmod_class,
@@ -1372,6 +1383,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap2420_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -1418,6 +1431,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
 	&omap2420_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+};
+
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2420_venc_hwmod_class,
@@ -1429,6 +1446,8 @@ static struct omap_hwmod omap2420_dss_venc_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap2420_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
-- 
1.7.4.1


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

* [PATCH 18/27] OMAP2430: HWMOD: Add DSS opt clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add DSS optional clocks to HWMOD data for OMAP2430.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 9682dd5..8009945 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1302,6 +1302,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -1379,6 +1380,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
 	&omap2430_l4_core__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
+};
+
 static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2430_dispc_hwmod_class,
@@ -1394,6 +1399,8 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap2430_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -1443,6 +1450,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
 	&omap2430_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2430_rfbi_hwmod_class,
@@ -1454,6 +1465,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap2430_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -1494,6 +1507,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
 	&omap2430_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+};
+
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2430_venc_hwmod_class,
@@ -1505,6 +1522,8 @@ static struct omap_hwmod omap2430_dss_venc_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap2430_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-- 
1.7.4.1


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

* [PATCH 18/27] OMAP2430: HWMOD: Add DSS opt clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Add DSS optional clocks to HWMOD data for OMAP2430.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 9682dd5..8009945 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1302,6 +1302,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
 	{ .role = "tv_clk", .clk = "dss_54m_fck" },
 	{ .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -1379,6 +1380,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
 	&omap2430_l4_core__dss_dispc,
 };
 
+static struct omap_hwmod_opt_clk dispc_opt_clks[] = {
+	{ .role = "dss_clk", .clk = "dss1_fck" },
+};
+
 static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2430_dispc_hwmod_class,
@@ -1394,6 +1399,8 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
 		},
 	},
+	.opt_clks	= dispc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dispc_opt_clks),
 	.slaves		= omap2430_dss_dispc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -1443,6 +1450,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
 	&omap2430_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk rfbi_opt_clks[] = {
+	{ .role = "rfbi_iclk", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap2430_rfbi_hwmod_class,
@@ -1454,6 +1465,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= rfbi_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(rfbi_opt_clks),
 	.slaves		= omap2430_dss_rfbi_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -1494,6 +1507,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
 	&omap2430_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk venc_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+};
+
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap2430_venc_hwmod_class,
@@ -1505,6 +1522,8 @@ static struct omap_hwmod omap2430_dss_venc_hwmod = {
 			.module_offs = CORE_MOD,
 		},
 	},
+	.opt_clks	= venc_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(venc_opt_clks),
 	.slaves		= omap2430_dss_venc_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-- 
1.7.4.1


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

* [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Use PM runtime and HWMOD support to handle enabling and disabling of DSS
modules.

Each DSS module will have get and put functions which can be used to
enable and disable that module. The functions use pm_runtime and hwmod
opt-clocks to enable the hardware.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c   |  339 ++++++++++++++++++++++++----------
 drivers/video/omap2/dss/dpi.c     |   70 +++++---
 drivers/video/omap2/dss/dsi.c     |  250 ++++++++++++++++---------
 drivers/video/omap2/dss/dss.c     |  368 ++++++++-----------------------------
 drivers/video/omap2/dss/dss.h     |   33 ++--
 drivers/video/omap2/dss/hdmi.c    |  149 +++++++++++----
 drivers/video/omap2/dss/manager.c |    8 +-
 drivers/video/omap2/dss/overlay.c |   24 ++-
 drivers/video/omap2/dss/rfbi.c    |   97 ++++++++--
 drivers/video/omap2/dss/sdi.c     |   40 +++--
 drivers/video/omap2/dss/venc.c    |  171 +++++++++++++++---
 11 files changed, 926 insertions(+), 623 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ee2052f..57400f6 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -34,6 +34,7 @@
 #include <linux/hardirq.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/sram.h>
 #include <plat/clock.h>
@@ -93,7 +94,13 @@ struct dispc_irq_stats {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
+
+	int		ctx_loss_cnt;
+	struct mutex	runtime_lock;
+	int		runtime_count;
+
 	int irq;
+	struct clk *dss_clk;
 
 	u32	fifo_size[3];
 
@@ -140,13 +147,12 @@ static inline u32 dispc_read_reg(const u16 idx)
 #define RR(reg) \
 	dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
 
-void dispc_save_context(void)
+static void dispc_save_context(void)
 {
 	int i;
-	if (cpu_is_omap24xx())
-		return;
 
-	SR(SYSCONFIG);
+	DSSDBG("dispc_save_context\n");
+
 	SR(IRQENABLE);
 	SR(CONTROL);
 	SR(CONFIG);
@@ -314,10 +320,12 @@ void dispc_save_context(void)
 		SR(DIVISOR);
 }
 
-void dispc_restore_context(void)
+static void dispc_restore_context(void)
 {
 	int i;
-	RR(SYSCONFIG);
+
+	DSSDBG("dispc_restore_context\n");
+
 	/*RR(IRQENABLE);*/
 	/*RR(CONTROL);*/
 	RR(CONFIG);
@@ -501,14 +509,121 @@ void dispc_restore_context(void)
 #undef SR
 #undef RR
 
-static inline void enable_clocks(bool enable)
+static void dispc_init_ctx_loss_count(void)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	struct device *dev = &dispc.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt = 0;
+
+	/*
+	 * get_context_loss_count returns negative on error. We'll ignore the
+	 * error and store the error to ctx_loss_cnt, which will cause
+	 * dispc_need_ctx_restore() call to return true.
+	 */
+
+	if (board_data->get_context_loss_count)
+		cnt = board_data->get_context_loss_count(dev);
+
+	WARN_ON(cnt < 0);
+
+	dispc.ctx_loss_cnt = cnt;
+
+	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
+}
+
+static bool dispc_need_ctx_restore(void)
+{
+	struct device *dev = &dispc.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt;
+
+	/*
+	 * If get_context_loss_count is not available, assume that we need
+	 * context restore always.
+	 */
+	if (!board_data->get_context_loss_count)
+		return true;
+
+	cnt = board_data->get_context_loss_count(dev);
+	if (cnt < 0) {
+		dev_err(dev, "getting context loss count failed, will force "
+				"context restore\n");
+		dispc.ctx_loss_cnt = cnt;
+		return true;
+	}
+
+	if (cnt = dispc.ctx_loss_cnt)
+		return false;
+
+	DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt);
+	dispc.ctx_loss_cnt = cnt;
+
+	return true;
+}
+
+int dispc_runtime_get(void)
+{
+	int r;
+
+	mutex_lock(&dispc.runtime_lock);
+
+	if (dispc.runtime_count++ = 0) {
+		DSSDBG("dispc_runtime_get\n");
+
+		r = dss_runtime_get();
+		if (r)
+			goto err_dss_get;
+
+		/* XXX dispc fclk can also come from DSI PLL */
+		clk_enable(dispc.dss_clk);
+
+		r = pm_runtime_get_sync(&dispc.pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err_runtime_get;
+
+		if (dispc_need_ctx_restore())
+			dispc_restore_context();
+	}
+
+	mutex_unlock(&dispc.runtime_lock);
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(dispc.dss_clk);
+	dss_runtime_put();
+err_dss_get:
+	mutex_unlock(&dispc.runtime_lock);
+
+	return r;
 }
 
+void dispc_runtime_put(void)
+{
+	mutex_lock(&dispc.runtime_lock);
+
+	if (--dispc.runtime_count = 0) {
+		int r;
+
+		DSSDBG("dispc_runtime_put\n");
+
+		dispc_save_context();
+
+		r = pm_runtime_put_sync(&dispc.pdev->dev);
+		WARN_ON(r);
+
+		clk_disable(dispc.dss_clk);
+
+		dss_runtime_put();
+	}
+
+	mutex_unlock(&dispc.runtime_lock);
+}
+
+
 bool dispc_go_busy(enum omap_channel channel)
 {
 	int bit;
@@ -530,7 +645,7 @@ void dispc_go(enum omap_channel channel)
 	int bit;
 	bool enable_bit, go_bit;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	if (channel = OMAP_DSS_CHANNEL_LCD ||
 			channel = OMAP_DSS_CHANNEL_LCD2)
@@ -571,7 +686,7 @@ void dispc_go(enum omap_channel channel)
 	else
 		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
 end:
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -998,7 +1113,7 @@ void dispc_set_burst_size(enum omap_plane plane,
 	int shift;
 	u32 val;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	switch (plane) {
 	case OMAP_DSS_GFX:
@@ -1017,7 +1132,7 @@ void dispc_set_burst_size(enum omap_plane plane,
 	val = FLD_MOD(val, burst_size, shift+1, shift);
 	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_gamma_table(bool enable)
@@ -1054,9 +1169,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
 	else
 		bit = 10;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1064,9 +1179,9 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_digit_size(u16 width, u16 height)
@@ -1074,9 +1189,9 @@ void dispc_set_digit_size(u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void dispc_read_plane_fifo_sizes(void)
@@ -1085,7 +1200,7 @@ static void dispc_read_plane_fifo_sizes(void)
 	int plane;
 	u8 start, end;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
@@ -1095,7 +1210,7 @@ static void dispc_read_plane_fifo_sizes(void)
 		dispc.fifo_size[plane] = size;
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1110,7 +1225,7 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
 	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
 			plane,
@@ -1124,17 +1239,17 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 			FLD_VAL(high, hi_start, hi_end) |
 			FLD_VAL(low, lo_start, lo_end));
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_fifomerge(bool enable)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
 	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void _dispc_set_fir(enum omap_plane plane,
@@ -1756,9 +1871,9 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
 
 void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	_dispc_set_channel_out(plane, channel_out);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static int _dispc_setup_plane(enum omap_plane plane,
@@ -1954,7 +2069,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 	int r;
 	u32 irq;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	/* When we disable LCD output, we need to wait until frame is done.
 	 * Otherwise the DSS is still working, and turning off the clocks
@@ -1990,7 +2105,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 			DSSERR("failed to unregister FRAMEDONE isr\n");
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void _enable_digit_out(bool enable)
@@ -2003,10 +2118,10 @@ static void dispc_enable_digit_out(bool enable)
 	struct completion frame_done_completion;
 	int r;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	if (REG_GET(DISPC_CONTROL, 1, 1) = enable) {
-		enable_clocks(0);
+		dispc_runtime_put();
 		return;
 	}
 
@@ -2061,7 +2176,7 @@ static void dispc_enable_digit_out(bool enable)
 		spin_unlock_irqrestore(&dispc.irq_lock, flags);
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2092,9 +2207,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_lcd_enable_signal(bool enable)
@@ -2102,9 +2217,9 @@ void dispc_lcd_enable_signal(bool enable)
 	if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_pck_free_enable(bool enable)
@@ -2112,19 +2227,19 @@ void dispc_pck_free_enable(bool enable)
 	if (!dss_has_feature(FEAT_PCKFREEENABLE))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (channel = OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
 	else
 		REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 
@@ -2147,27 +2262,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
 		return;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (channel = OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_loadmode(enum omap_dss_load_mode mode)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 
 void dispc_set_default_color(enum omap_channel channel, u32 color)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 u32 dispc_get_default_color(enum omap_channel channel)
@@ -2178,9 +2293,9 @@ u32 dispc_get_default_color(enum omap_channel channel)
 		channel != OMAP_DSS_CHANNEL_LCD &&
 		channel != OMAP_DSS_CHANNEL_LCD2);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return l;
 }
@@ -2189,7 +2304,7 @@ void dispc_set_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type type,
 		u32 trans_key)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
@@ -2198,14 +2313,14 @@ void dispc_set_trans_key(enum omap_channel ch,
 		REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
 
 	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_get_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type *type,
 		u32 *trans_key)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (type) {
 		if (ch = OMAP_DSS_CHANNEL_LCD)
 			*type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2219,33 +2334,33 @@ void dispc_get_trans_key(enum omap_channel ch,
 
 	if (trans_key)
 		*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
@@ -2254,7 +2369,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return false;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 18, 18);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
@@ -2263,7 +2378,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 18, 18);
 	else
 		BUG();
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2273,7 +2388,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 {
 	bool enabled;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 10, 10);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
@@ -2282,7 +2397,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 10, 10);
 	else
 		BUG();
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2310,12 +2425,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 		return;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (channel = OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2347,7 +2462,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		return;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	if (channel = OMAP_DSS_CHANNEL_LCD2) {
 		l = dispc_read_reg(DISPC_CONTROL2);
@@ -2361,7 +2476,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		dispc_write_reg(DISPC_CONTROL, l);
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2414,10 +2529,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
 			FLD_VAL(vbp, 31, 20);
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
 	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 /* change name to mode? */
@@ -2460,10 +2575,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 	BUG_ON(lck_div < 1);
 	BUG_ON(pck_div < 2);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2482,7 +2597,7 @@ unsigned long dispc_fclk_rate(void)
 
 	switch (dss_get_dispc_clk_source()) {
 	case OMAP_DSS_CLK_SRC_FCK:
-		r = dss_clk_get_rate(DSS_CLK_FCK);
+		r = clk_get_rate(dispc.dss_clk);
 		break;
 	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 		dsidev = dsi_get_dsidev_from_id(0);
@@ -2512,7 +2627,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
 
 	switch (dss_get_lcd_clk_source(channel)) {
 	case OMAP_DSS_CLK_SRC_FCK:
-		r = dss_clk_get_rate(DSS_CLK_FCK);
+		r = clk_get_rate(dispc.dss_clk);
 		break;
 	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 		dsidev = dsi_get_dsidev_from_id(0);
@@ -2551,7 +2666,8 @@ void dispc_dump_clocks(struct seq_file *s)
 	enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
 	enum omap_dss_clk_source lcd_clk_src;
 
-	enable_clocks(1);
+	if (dispc_runtime_get())
+		return;
 
 	seq_printf(s, "- DISPC -\n");
 
@@ -2599,7 +2715,8 @@ void dispc_dump_clocks(struct seq_file *s)
 		seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
 				dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
 	}
-	enable_clocks(0);
+
+	dispc_runtime_put();
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2654,7 +2771,8 @@ void dispc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dispc_runtime_get())
+		return;
 
 	DUMPREG(DISPC_REVISION);
 	DUMPREG(DISPC_SYSCONFIG);
@@ -2899,7 +3017,7 @@ void dispc_dump_regs(struct seq_file *s)
 		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dispc_runtime_put();
 #undef DUMPREG
 }
 
@@ -2920,9 +3038,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
 	l |= FLD_VAL(acbi, 11, 8);
 	l |= FLD_VAL(acb, 7, 0);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_POL_FREQ(channel), l);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_pol_freq(enum omap_channel channel,
@@ -3043,7 +3161,7 @@ static void _omap_dispc_set_irqs(void)
 		mask |= isr_data->mask;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	old_mask = dispc_read_reg(DISPC_IRQENABLE);
 	/* clear the irqstatus for newly enabled irqs */
@@ -3051,7 +3169,7 @@ static void _omap_dispc_set_irqs(void)
 
 	dispc_write_reg(DISPC_IRQENABLE, mask);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3560,13 +3678,6 @@ static void _omap_dispc_initial_config(void)
 {
 	u32 l;
 
-	l = dispc_read_reg(DISPC_SYSCONFIG);
-	l = FLD_MOD(l, 2, 13, 12);	/* MIDLEMODE: smart standby */
-	l = FLD_MOD(l, 2, 4, 3);	/* SIDLEMODE: smart idle */
-	l = FLD_MOD(l, 1, 2, 2);	/* ENWAKEUP */
-	l = FLD_MOD(l, 1, 0, 0);	/* AUTOIDLE */
-	dispc_write_reg(DISPC_SYSCONFIG, l);
-
 	/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
 	if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
 		l = dispc_read_reg(DISPC_DIVISOR);
@@ -3596,9 +3707,9 @@ int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
 	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	_dispc_enable_plane(plane, enable);
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return 0;
 }
@@ -3625,7 +3736,7 @@ int dispc_setup_plane(enum omap_plane plane,
 	       ilace, color_mode,
 	       rotation, mirror, channel);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	r = _dispc_setup_plane(plane,
 			   paddr, screen_width,
@@ -3639,7 +3750,7 @@ int dispc_setup_plane(enum omap_plane plane,
 			   pre_mult_alpha,
 			   channel, puv_addr);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return r;
 }
@@ -3650,9 +3761,19 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 	u32 rev;
 	int r = 0;
 	struct resource *dispc_mem;
+	struct clk *clk;
 
 	dispc.pdev = pdev;
 
+	clk = clk_get(&pdev->dev, "dss_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get dss_clk\n");
+		r = PTR_ERR(clk);
+		goto err_get_clk;
+	}
+
+	dispc.dss_clk = clk;
+
 	spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3666,51 +3787,67 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 	if (!dispc_mem) {
 		DSSERR("can't get IORESOURCE_MEM DISPC\n");
 		r = -EINVAL;
-		goto fail0;
+		goto err_ioremap;
 	}
 	dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
 	if (!dispc.base) {
 		DSSERR("can't ioremap DISPC\n");
 		r = -ENOMEM;
-		goto fail0;
+		goto err_ioremap;
 	}
 	dispc.irq = platform_get_irq(dispc.pdev, 0);
 	if (dispc.irq < 0) {
 		DSSERR("platform_get_irq failed\n");
 		r = -ENODEV;
-		goto fail1;
+		goto err_irq;
 	}
 
 	r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
 		"OMAP DISPC", dispc.pdev);
 	if (r < 0) {
 		DSSERR("request_irq failed\n");
-		goto fail1;
+		goto err_irq;
 	}
 
-	enable_clocks(1);
+	dispc_init_ctx_loss_count();
+
+	mutex_init(&dispc.runtime_lock);
+
+	pm_runtime_enable(&pdev->dev);
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_runtime_get;
 
 	_omap_dispc_initial_config();
 
 	_omap_dispc_initialize_irq();
 
-	dispc_save_context();
-
 	rev = dispc_read_reg(DISPC_REVISION);
 	dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return 0;
-fail1:
+
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
+	free_irq(dispc.irq, dispc.pdev);
+err_irq:
 	iounmap(dispc.base);
-fail0:
+err_ioremap:
+	clk_put(dispc.dss_clk);
+err_get_clk:
 	return r;
 }
 
 static int omap_dispchw_remove(struct platform_device *pdev)
 {
+	pm_runtime_disable(&pdev->dev);
+
+	clk_put(dispc.dss_clk);
+
 	free_irq(dispc.irq, dispc.pdev);
 	iounmap(dispc.base);
 	return 0;
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index bab55cd..f053b18 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -23,7 +23,6 @@
 #define DSS_SUBSYS_NAME "DPI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/errno.h>
@@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 	bool is_tft;
 	int r = 0;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-
 	dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
 			dssdev->panel.acbi, dssdev->panel.acb);
 
@@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 		r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
 				&fck, &lck_div, &pck_div);
 	if (r)
-		goto err0;
+		return r;
 
 	pck = fck / lck_div / pck_div / 1000;
 
@@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 
 	dispc_set_lcd_timings(dssdev->manager->id, t);
 
-err0:
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-	return r;
+	return 0;
 }
 
-static int dpi_basic_init(struct omap_dss_device *dssdev)
+static void dpi_basic_init(struct omap_dss_device *dssdev)
 {
 	bool is_tft;
 
@@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
 			OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
 	dispc_set_tft_data_lines(dssdev->manager->id,
 			dssdev->phy.dpi.data_lines);
-
-	return 0;
 }
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -186,30 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
-		goto err0;
+		goto err_start_dev;
 	}
 
 	if (cpu_is_omap34xx()) {
 		r = regulator_enable(dpi.vdds_dsi_reg);
 		if (r)
-			goto err1;
+			goto err_reg_enable;
 	}
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
 
-	r = dpi_basic_init(dssdev);
+	r = dispc_runtime_get();
 	if (r)
-		goto err2;
+		goto err_get_dispc;
+
+	dpi_basic_init(dssdev);
 
 	if (dpi_use_dsi_pll(dssdev)) {
+		r = dsi_runtime_get(dpi.dsidev);
+		if (r)
+			goto err_get_dsi;
+
 		r = dsi_pll_init(dpi.dsidev, 0, 1);
 		if (r)
-			goto err2;
+			goto err_dsi_pll_init;
 	}
 
 	r = dpi_set_mode(dssdev);
 	if (r)
-		goto err3;
+		goto err_set_mode;
 
 	mdelay(2);
 
@@ -217,16 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 	return 0;
 
-err3:
+err_set_mode:
 	if (dpi_use_dsi_pll(dssdev))
 		dsi_pll_uninit(dpi.dsidev, true);
-err2:
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+err_dsi_pll_init:
+	if (dpi_use_dsi_pll(dssdev))
+		dsi_runtime_put(dpi.dsidev);
+err_get_dsi:
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
 	if (cpu_is_omap34xx())
 		regulator_disable(dpi.vdds_dsi_reg);
-err1:
+err_reg_enable:
 	omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
 	return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -238,9 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 	if (dpi_use_dsi_pll(dssdev)) {
 		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 		dsi_pll_uninit(dpi.dsidev, true);
+		dsi_runtime_put(dpi.dsidev);
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dispc_runtime_put();
+	dss_runtime_put();
 
 	if (cpu_is_omap34xx())
 		regulator_disable(dpi.vdds_dsi_reg);
@@ -252,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
 void dpi_set_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
+	int r;
+
 	DSSDBG("dpi_set_timings\n");
 	dssdev->panel.timings = *timings;
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
+		r = dss_runtime_get();
+		if (r)
+			return;
+
+		r = dispc_runtime_get();
+		if (r) {
+			dss_runtime_put();
+			return;
+		}
+
 		dpi_set_mode(dssdev);
 		dispc_go(dssdev->manager->id);
+
+		dispc_runtime_put();
+		dss_runtime_put();
 	}
 }
 EXPORT_SYMBOL(dpi_set_timings);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 0609885..89c4203 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -36,6 +36,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -267,8 +268,15 @@ struct dsi_isr_tables {
 struct dsi_data {
 	struct platform_device *pdev;
 	void __iomem	*base;
+
+	struct mutex	runtime_lock;
+	int		runtime_count;
+
 	int irq;
 
+	struct clk *dss_clk;
+	struct clk *sys_clk;
+
 	void (*dsi_mux_pads)(bool enable);
 
 	struct dsi_clock_info current_cinfo;
@@ -389,15 +397,6 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
 	return __raw_readl(dsi->base + idx.idx);
 }
 
-
-void dsi_save_context(void)
-{
-}
-
-void dsi_restore_context(void)
-{
-}
-
 void dsi_bus_lock(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -1048,13 +1047,69 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
 	return e;
 }
 
-/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
-static inline void enable_clocks(bool enable)
+int dsi_runtime_get(struct platform_device *dsidev)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	int r;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	mutex_lock(&dsi->runtime_lock);
+
+	if (dsi->runtime_count++ = 0) {
+		DSSDBG("dsi_runtime_get\n");
+
+		r = dss_runtime_get();
+		if (r)
+			goto err_get_dss;
+
+		r = dispc_runtime_get();
+		if (r)
+			goto err_get_dispc;
+
+		/* XXX dsi fclk can also come from DSI PLL */
+		clk_enable(dsi->dss_clk);
+
+		r = pm_runtime_get_sync(&dsi->pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err_runtime_get;
+	}
+
+	mutex_unlock(&dsi->runtime_lock);
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(dsi->dss_clk);
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	mutex_unlock(&dsi->runtime_lock);
+
+	return r;
+}
+
+void dsi_runtime_put(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	mutex_lock(&dsi->runtime_lock);
+
+	if (--dsi->runtime_count = 0) {
+		int r;
+
+		DSSDBG("dsi_runtime_put\n");
+
+		r = pm_runtime_put_sync(&dsi->pdev->dev);
+		WARN_ON(r);
+
+		clk_disable(dsi->dss_clk);
+
+		dispc_runtime_put();
+		dss_runtime_put();
+	}
+
+	mutex_unlock(&dsi->runtime_lock);
 }
 
 /* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1064,9 +1119,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
 	if (enable)
-		dss_clk_enable(DSS_CLK_SYSCK);
+		clk_enable(dsi->sys_clk);
 	else
-		dss_clk_disable(DSS_CLK_SYSCK);
+		clk_disable(dsi->sys_clk);
 
 	if (enable && dsi->pll_locked) {
 		if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1159,10 +1214,11 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 {
 	unsigned long r;
 	int dsi_module = dsi_get_dsidev_id(dsidev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
 	if (dss_get_dsi_clk_source(dsi_module) = OMAP_DSS_CLK_SRC_FCK) {
 		/* DSI FCLK source is DSS_CLK_FCK */
-		r = dss_clk_get_rate(DSS_CLK_FCK);
+		r = clk_get_rate(dsi->dss_clk);
 	} else {
 		/* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
 		r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1271,7 +1327,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
 		return -EINVAL;
 
 	if (cinfo->use_sys_clk) {
-		cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
+		cinfo->clkin = clk_get_rate(dsi->sys_clk);
 		/* XXX it is unclear if highfreq should be used
 		 * with DSS_SYS_CLK source also */
 		cinfo->highfreq = 0;
@@ -1320,7 +1376,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
 	int match = 0;
 	unsigned long dss_sys_clk, max_dss_fck;
 
-	dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
+	dss_sys_clk = clk_get_rate(dsi->sys_clk);
 
 	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
@@ -1610,7 +1666,6 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 		dsi->vdds_dsi_reg = vdds_dsi;
 	}
 
-	enable_clocks(1);
 	dsi_enable_pll_clock(dsidev, 1);
 	/*
 	 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1662,7 +1717,6 @@ err1:
 	}
 err0:
 	dsi_disable_scp_clk(dsidev);
-	enable_clocks(0);
 	dsi_enable_pll_clock(dsidev, 0);
 	return r;
 }
@@ -1680,7 +1734,6 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
 	}
 
 	dsi_disable_scp_clk(dsidev);
-	enable_clocks(0);
 	dsi_enable_pll_clock(dsidev, 0);
 
 	DSSDBG("PLL uninit done\n");
@@ -1697,7 +1750,8 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 	dispc_clk_src = dss_get_dispc_clk_source();
 	dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
 
-	enable_clocks(1);
+	if (dsi_runtime_get(dsidev))
+		return;
 
 	seq_printf(s,	"- DSI%d PLL -\n", dsi_module + 1);
 
@@ -1740,7 +1794,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 
 	seq_printf(s,	"LP_CLK\t\t%lu\n", cinfo->lp_clk);
 
-	enable_clocks(0);
+	dsi_runtime_put(dsidev);
 }
 
 void dsi_dump_clocks(struct seq_file *s)
@@ -1882,7 +1936,8 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dsi_runtime_get(dsidev))
+		return;
 	dsi_enable_scp_clk(dsidev);
 
 	DUMPREG(DSI_REVISION);
@@ -1956,7 +2011,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
 	DUMPREG(DSI_PLL_CONFIGURATION2);
 
 	dsi_disable_scp_clk(dsidev);
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dsi_runtime_put(dsidev);
 #undef DUMPREG
 }
 
@@ -2472,28 +2527,6 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
 		dsi->dsi_mux_pads(false);
 }
 
-static int _dsi_wait_reset(struct platform_device *dsidev)
-{
-	int t = 0;
-
-	while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) = 0) {
-		if (++t > 5) {
-			DSSERR("soft reset failed\n");
-			return -ENODEV;
-		}
-		udelay(1);
-	}
-
-	return 0;
-}
-
-static int _dsi_reset(struct platform_device *dsidev)
-{
-	/* Soft reset */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
-	return _dsi_wait_reset(dsidev);
-}
-
 static void dsi_config_tx_fifo(struct platform_device *dsidev,
 		enum fifo_size size1, enum fifo_size size2,
 		enum fifo_size size3, enum fifo_size size4)
@@ -4211,22 +4244,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 	dsi_pll_uninit(dsidev, disconnect_lanes);
 }
 
-static int dsi_core_init(struct platform_device *dsidev)
-{
-	/* Autoidle */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
-
-	/* ENWAKEUP */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
-
-	/* SIDLEMODE smart-idle */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
-
-	_dsi_initialize_irq(dsidev);
-
-	return 0;
-}
-
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4242,37 +4259,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
-		goto err0;
+		goto err_start_dev;
 	}
 
-	enable_clocks(1);
-	dsi_enable_pll_clock(dsidev, 1);
-
-	r = _dsi_reset(dsidev);
+	r = dsi_runtime_get(dsidev);
 	if (r)
-		goto err1;
+		goto err_get_dsi;
 
-	dsi_core_init(dsidev);
+	dsi_enable_pll_clock(dsidev, 1);
+
+	_dsi_initialize_irq(dsidev);
 
 	r = dsi_display_init_dispc(dssdev);
 	if (r)
-		goto err1;
+		goto err_init_dispc;
 
 	r = dsi_display_init_dsi(dssdev);
 	if (r)
-		goto err2;
+		goto err_init_dsi;
 
 	mutex_unlock(&dsi->lock);
 
 	return 0;
 
-err2:
+err_init_dsi:
 	dsi_display_uninit_dispc(dssdev);
-err1:
-	enable_clocks(0);
+err_init_dispc:
 	dsi_enable_pll_clock(dsidev, 0);
+	dsi_runtime_put(dsidev);
+err_get_dsi:
 	omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
 	mutex_unlock(&dsi->lock);
 	DSSDBG("dsi_display_enable FAILED\n");
 	return r;
@@ -4295,7 +4312,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
 	dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
 
-	enable_clocks(0);
+	dsi_runtime_put(dsidev);
 	dsi_enable_pll_clock(dsidev, 0);
 
 	omap_dss_stop_device(dssdev);
@@ -4450,6 +4467,42 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
 	dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
+static int dsi_get_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct clk *clk;
+
+	clk = clk_get(&dsidev->dev, "dss_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get dss_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	dsi->dss_clk = clk;
+
+	clk = clk_get(&dsidev->dev, "sys_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get sys_clk\n");
+		clk_put(dsi->dss_clk);
+		dsi->dss_clk = NULL;
+		return PTR_ERR(clk);
+	}
+
+	dsi->sys_clk = clk;
+
+	return 0;
+}
+
+static void dsi_put_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dsi->dss_clk)
+		clk_put(dsi->dss_clk);
+	if (dsi->sys_clk)
+		clk_put(dsi->sys_clk);
+}
+
 /* DSI1 HW IP initialisation */
 static int omap_dsi1hw_probe(struct platform_device *dsidev)
 {
@@ -4463,7 +4516,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
 	if (!dsi) {
 		r = -ENOMEM;
-		goto err0;
+		goto err_alloc;
 	}
 
 	dsi->pdev = dsidev;
@@ -4486,6 +4539,14 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 	mutex_init(&dsi->lock);
 	sema_init(&dsi->bus_lock, 1);
 
+	r = dsi_get_clocks(dsidev);
+	if (r)
+		goto err_get_clk;
+
+	mutex_init(&dsi->runtime_lock);
+
+	pm_runtime_enable(&dsidev->dev);
+
 	INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
 			dsi_framedone_timeout_work_callback);
 
@@ -4498,26 +4559,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 	if (!dsi_mem) {
 		DSSERR("can't get IORESOURCE_MEM DSI\n");
 		r = -EINVAL;
-		goto err1;
+		goto err_ioremap;
 	}
 	dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
 	if (!dsi->base) {
 		DSSERR("can't ioremap DSI\n");
 		r = -ENOMEM;
-		goto err1;
+		goto err_ioremap;
 	}
 	dsi->irq = platform_get_irq(dsi->pdev, 0);
 	if (dsi->irq < 0) {
 		DSSERR("platform_get_irq failed\n");
 		r = -ENODEV;
-		goto err2;
+		goto err_get_irq;
 	}
 
 	r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
 		dev_name(&dsidev->dev), dsi->pdev);
 	if (r < 0) {
 		DSSERR("request_irq failed\n");
-		goto err2;
+		goto err_get_irq;
 	}
 
 	/* DSI VCs initialization */
@@ -4529,7 +4590,9 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 
 	dsi_calc_clock_param_ranges(dsidev);
 
-	enable_clocks(1);
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		goto err_get_dsi;
 
 	rev = dsi_read_reg(dsidev, DSI_REVISION);
 	dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4537,14 +4600,19 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 
 	dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
 
-	enable_clocks(0);
+	dsi_runtime_put(dsidev);
 
 	return 0;
-err2:
+
+err_get_dsi:
+	free_irq(dsi->irq, dsi->pdev);
+err_get_irq:
 	iounmap(dsi->base);
-err1:
+err_ioremap:
+	pm_runtime_disable(&dsidev->dev);
+err_get_clk:
 	kfree(dsi);
-err0:
+err_alloc:
 	return r;
 }
 
@@ -4554,6 +4622,10 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
 
 	WARN_ON(dsi->scp_clk_refcount > 0);
 
+	pm_runtime_disable(&dsidev->dev);
+
+	dsi_put_clocks(dsidev);
+
 	if (dsi->vdds_dsi_reg != NULL) {
 		if (dsi->vdds_dsi_enabled) {
 			regulator_disable(dsi->vdds_dsi_reg);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index a0e933a..c8d7357 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -60,15 +61,13 @@ struct dss_reg {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
+
 	int		ctx_loss_cnt;
+	struct mutex	runtime_lock;
+	int		runtime_count;
 
 	struct clk	*dpll4_m4_ck;
-	struct clk	*dss_ick;
-	struct clk	*dss_fck;
-	struct clk	*dss_sys_clk;
-	struct clk	*dss_tv_fck;
-	struct clk	*dss_video_fck;
-	unsigned	num_clks_enabled;
+	struct clk	*dss_clk;
 
 	unsigned long	cache_req_pck;
 	unsigned long	cache_prate;
@@ -88,13 +87,6 @@ static const char * const dss_generic_clk_source_names[] = {
 	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
 };
 
-static void dss_clk_enable_all_no_ctx(void);
-static void dss_clk_disable_all_no_ctx(void);
-static void dss_clk_enable_no_ctx(enum dss_clock clks);
-static void dss_clk_disable_no_ctx(enum dss_clock clks);
-
-static int _omap_dss_wait_reset(void);
-
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 {
 	__raw_writel(val, dss.base + idx.idx);
@@ -110,12 +102,10 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
 #define RR(reg) \
 	dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
 
-void dss_save_context(void)
+static void dss_save_context(void)
 {
-	if (cpu_is_omap24xx())
-		return;
+	DSSDBG("dss_save_context\n");
 
-	SR(SYSCONFIG);
 	SR(CONTROL);
 
 	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -125,12 +115,10 @@ void dss_save_context(void)
 	}
 }
 
-void dss_restore_context(void)
+static void dss_restore_context(void)
 {
-	if (_omap_dss_wait_reset())
-		DSSERR("DSS not coming out of reset after sleep\n");
+	DSSDBG("dss_restore_context\n");
 
-	RR(SYSCONFIG);
 	RR(CONTROL);
 
 	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -235,6 +223,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
 	return dss_generic_clk_source_names[clk_src];
 }
 
+
 void dss_dump_clocks(struct seq_file *s)
 {
 	unsigned long dpll4_ck_rate;
@@ -242,13 +231,14 @@ void dss_dump_clocks(struct seq_file *s)
 	const char *fclk_name, *fclk_real_name;
 	unsigned long fclk_rate;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dss_runtime_get())
+		return;
 
 	seq_printf(s, "- DSS -\n");
 
 	fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
 	fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
-	fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
+	fclk_rate = clk_get_rate(dss.dss_clk);
 
 	if (dss.dpll4_m4_ck) {
 		dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -274,14 +264,15 @@ void dss_dump_clocks(struct seq_file *s)
 				fclk_rate);
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dss_runtime_put();
 }
 
 void dss_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dss_runtime_get())
+		return;
 
 	DUMPREG(DSS_REVISION);
 	DUMPREG(DSS_SYSCONFIG);
@@ -295,7 +286,7 @@ void dss_dump_regs(struct seq_file *s)
 		DUMPREG(DSS_SDI_STATUS);
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dss_runtime_put();
 #undef DUMPREG
 }
 
@@ -438,7 +429,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 	} else {
 		if (cinfo->fck_div != 0)
 			return -EINVAL;
-		cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+		cinfo->fck = clk_get_rate(dss.dss_clk);
 	}
 
 	return 0;
@@ -468,7 +459,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
 
 int dss_get_clock_div(struct dss_clock_info *cinfo)
 {
-	cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+	cinfo->fck = clk_get_rate(dss.dss_clk);
 
 	if (dss.dpll4_m4_ck) {
 		unsigned long prate;
@@ -513,7 +504,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
 
 	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
-	fck = dss_clk_get_rate(DSS_CLK_FCK);
+	fck = clk_get_rate(dss.dss_clk);
 	if (req_pck = dss.cache_req_pck &&
 			((cpu_is_omap34xx() && prate = dss.cache_prate) ||
 			 dss.cache_dss_cinfo.fck = fck)) {
@@ -540,7 +531,7 @@ retry:
 	if (dss.dpll4_m4_ck = NULL) {
 		struct dispc_clock_info cur_dispc;
 		/* XXX can we change the clock on omap2? */
-		fck = dss_clk_get_rate(DSS_CLK_FCK);
+		fck = clk_get_rate(dss.dss_clk);
 		fck_div = 1;
 
 		dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -617,28 +608,6 @@ found:
 	return 0;
 }
 
-static int _omap_dss_wait_reset(void)
-{
-	int t = 0;
-
-	while (REG_GET(DSS_SYSSTATUS, 0, 0) = 0) {
-		if (++t > 1000) {
-			DSSERR("soft reset failed\n");
-			return -ENODEV;
-		}
-		udelay(1);
-	}
-
-	return 0;
-}
-
-static int _omap_dss_reset(void)
-{
-	/* Soft reset */
-	REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
-	return _omap_dss_wait_reset();
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
 	int l = 0;
@@ -719,131 +688,45 @@ static bool dss_need_ctx_restore(void)
 	return true;
 }
 
-static void save_all_ctx(void)
-{
-	DSSDBG("save context\n");
-
-	dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-
-	dss_save_context();
-	dispc_save_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_save_context();
-#endif
-
-	dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-}
-
-static void restore_all_ctx(void)
-{
-	DSSDBG("restore context\n");
-
-	dss_clk_enable_all_no_ctx();
-
-	dss_restore_context();
-	dispc_restore_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_restore_context();
-#endif
-
-	dss_clk_disable_all_no_ctx();
-}
-
-static int dss_get_clock(struct clk **clock, const char *clk_name)
-{
-	struct clk *clk;
-
-	clk = clk_get(&dss.pdev->dev, clk_name);
-
-	if (IS_ERR(clk)) {
-		DSSERR("can't get clock %s", clk_name);
-		return PTR_ERR(clk);
-	}
-
-	*clock = clk;
-
-	DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
-
-	return 0;
-}
-
 static int dss_get_clocks(void)
 {
+	struct clk *clk;
 	int r;
-	struct clk *dpll4_m4_ck;
-	struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-
-	dss.dss_ick = NULL;
-	dss.dss_fck = NULL;
-	dss.dss_sys_clk = NULL;
-	dss.dss_tv_fck = NULL;
-	dss.dss_video_fck = NULL;
-
-	r = dss_get_clock(&dss.dss_ick, "ick");
-	if (r)
-		goto err;
 
-	r = dss_get_clock(&dss.dss_fck, "fck");
-	if (r)
-		goto err;
-
-	if (!pdata->opt_clock_available) {
-		r = -ENODEV;
+	clk = clk_get(&dss.pdev->dev, "dss_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get clock dss_clk\n");
+		r = PTR_ERR(clk);
 		goto err;
 	}
 
-	if (pdata->opt_clock_available("sys_clk")) {
-		r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
-		if (r)
-			goto err;
-	}
-
-	if (pdata->opt_clock_available("tv_clk")) {
-		r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
-		if (r)
-			goto err;
-	}
-
-	if (pdata->opt_clock_available("video_clk")) {
-		r = dss_get_clock(&dss.dss_video_fck, "video_clk");
-		if (r)
-			goto err;
-	}
+	dss.dss_clk = clk;
 
 	if (cpu_is_omap34xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
+		clk = clk_get(NULL, "dpll4_m4_ck");
+		if (IS_ERR(clk)) {
 			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
+			r = PTR_ERR(clk);
 			goto err;
 		}
 	} else if (cpu_is_omap44xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
-			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
+		clk = clk_get(NULL, "dpll_per_m5x2_ck");
+		if (IS_ERR(clk)) {
+			DSSERR("Failed to get dpll_per_m5x2_ck\n");
+			r = PTR_ERR(clk);
 			goto err;
 		}
 	} else { /* omap24xx */
-		dpll4_m4_ck = NULL;
+		clk = NULL;
 	}
 
-	dss.dpll4_m4_ck = dpll4_m4_ck;
-
+	dss.dpll4_m4_ck = clk;
 
 	return 0;
 
 err:
-	if (dss.dss_ick)
-		clk_put(dss.dss_ick);
-	if (dss.dss_fck)
-		clk_put(dss.dss_fck);
-	if (dss.dss_sys_clk)
-		clk_put(dss.dss_sys_clk);
-	if (dss.dss_tv_fck)
-		clk_put(dss.dss_tv_fck);
-	if (dss.dss_video_fck)
-		clk_put(dss.dss_video_fck);
+	if (dss.dss_clk)
+		clk_put(dss.dss_clk);
 	if (dss.dpll4_m4_ck)
 		clk_put(dss.dpll4_m4_ck);
 
@@ -854,139 +737,57 @@ static void dss_put_clocks(void)
 {
 	if (dss.dpll4_m4_ck)
 		clk_put(dss.dpll4_m4_ck);
-	if (dss.dss_video_fck)
-		clk_put(dss.dss_video_fck);
-	if (dss.dss_tv_fck)
-		clk_put(dss.dss_tv_fck);
-	if (dss.dss_sys_clk)
-		clk_put(dss.dss_sys_clk);
-	clk_put(dss.dss_fck);
-	clk_put(dss.dss_ick);
+	clk_put(dss.dss_clk);
 }
 
-unsigned long dss_clk_get_rate(enum dss_clock clk)
+int dss_runtime_get(void)
 {
-	switch (clk) {
-	case DSS_CLK_ICK:
-		return clk_get_rate(dss.dss_ick);
-	case DSS_CLK_FCK:
-		return clk_get_rate(dss.dss_fck);
-	case DSS_CLK_SYSCK:
-		return clk_get_rate(dss.dss_sys_clk);
-	case DSS_CLK_TVFCK:
-		return clk_get_rate(dss.dss_tv_fck);
-	case DSS_CLK_VIDFCK:
-		return clk_get_rate(dss.dss_video_fck);
-	}
+	int r;
 
-	BUG();
-	return 0;
-}
+	mutex_lock(&dss.runtime_lock);
 
-static unsigned count_clk_bits(enum dss_clock clks)
-{
-	unsigned num_clks = 0;
-
-	if (clks & DSS_CLK_ICK)
-		++num_clks;
-	if (clks & DSS_CLK_FCK)
-		++num_clks;
-	if (clks & DSS_CLK_SYSCK)
-		++num_clks;
-	if (clks & DSS_CLK_TVFCK)
-		++num_clks;
-	if (clks & DSS_CLK_VIDFCK)
-		++num_clks;
-
-	return num_clks;
-}
+	if (dss.runtime_count++ = 0) {
+		DSSDBG("dss_runtime_get\n");
 
-static void dss_clk_enable_no_ctx(enum dss_clock clks)
-{
-	unsigned num_clks = count_clk_bits(clks);
-
-	if (clks & DSS_CLK_ICK)
-		clk_enable(dss.dss_ick);
-	if (clks & DSS_CLK_FCK)
-		clk_enable(dss.dss_fck);
-	if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-		clk_enable(dss.dss_sys_clk);
-	if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-		clk_enable(dss.dss_tv_fck);
-	if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-		clk_enable(dss.dss_video_fck);
-
-	dss.num_clks_enabled += num_clks;
-}
+		clk_enable(dss.dss_clk);
 
-void dss_clk_enable(enum dss_clock clks)
-{
-	bool check_ctx = dss.num_clks_enabled = 0;
+		r = pm_runtime_get_sync(&dss.pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err;
 
-	dss_clk_enable_no_ctx(clks);
+		if (dss_need_ctx_restore())
+			dss_restore_context();
+	}
 
-	/*
-	 * HACK: On omap4 the registers may not be accessible right after
-	 * enabling the clocks. At some point this will be handled by
-	 * pm_runtime, but for the time begin this should make things work.
-	 */
-	if (cpu_is_omap44xx() && check_ctx)
-		udelay(10);
+	mutex_unlock(&dss.runtime_lock);
 
-	if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
-		restore_all_ctx();
-}
+	return 0;
 
-static void dss_clk_disable_no_ctx(enum dss_clock clks)
-{
-	unsigned num_clks = count_clk_bits(clks);
-
-	if (clks & DSS_CLK_ICK)
-		clk_disable(dss.dss_ick);
-	if (clks & DSS_CLK_FCK)
-		clk_disable(dss.dss_fck);
-	if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-		clk_disable(dss.dss_sys_clk);
-	if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-		clk_disable(dss.dss_tv_fck);
-	if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-		clk_disable(dss.dss_video_fck);
-
-	dss.num_clks_enabled -= num_clks;
+err:
+	clk_disable(dss.dss_clk);
+	mutex_unlock(&dss.runtime_lock);
+	return r;
 }
 
-void dss_clk_disable(enum dss_clock clks)
+void dss_runtime_put(void)
 {
-	if (cpu_is_omap34xx()) {
-		unsigned num_clks = count_clk_bits(clks);
-
-		BUG_ON(dss.num_clks_enabled < num_clks);
+	mutex_lock(&dss.runtime_lock);
 
-		if (dss.num_clks_enabled = num_clks)
-			save_all_ctx();
-	}
+	if (--dss.runtime_count = 0) {
+		int r;
 
-	dss_clk_disable_no_ctx(clks);
-}
+		DSSDBG("dss_runtime_put\n");
 
-static void dss_clk_enable_all_no_ctx(void)
-{
-	enum dss_clock clks;
+		dss_save_context();
 
-	clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-	if (cpu_is_omap34xx())
-		clks |= DSS_CLK_VIDFCK;
-	dss_clk_enable_no_ctx(clks);
-}
+		r = pm_runtime_put_sync(&dss.pdev->dev);
+		WARN_ON(r);
 
-static void dss_clk_disable_all_no_ctx(void)
-{
-	enum dss_clock clks;
+		clk_disable(dss.dss_clk);
+	}
 
-	clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-	if (cpu_is_omap34xx())
-		clks |= DSS_CLK_VIDFCK;
-	dss_clk_disable_no_ctx(clks);
+	mutex_unlock(&dss.runtime_lock);
 }
 
 /* DEBUGFS */
@@ -1001,7 +802,6 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
-
 /* DSS HW IP initialisation */
 static int omap_dsshw_probe(struct platform_device *pdev)
 {
@@ -1028,19 +828,15 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	if (r)
 		goto err_clocks;
 
-	dss_clk_enable_all_no_ctx();
-
 	dss_init_ctx_loss_count();
 
-	/* disable LCD and DIGIT output. This seems to fix the synclost
-	 * problem that we get, if the bootloader starts the DSS and
-	 * the kernel resets it */
-	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+	mutex_init(&dss.runtime_lock);
 
-	_omap_dss_reset();
+	pm_runtime_enable(&pdev->dev);
 
-	/* autoidle */
-	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+	r = dss_runtime_get();
+	if (r)
+		goto err_runtime_get;
 
 	/* Select DPLL */
 	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
@@ -1068,19 +864,19 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 		goto err_sdi;
 	}
 
-	dss_save_context();
-
 	rev = dss_read_reg(DSS_REVISION);
 	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
 			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	dss_clk_disable_all_no_ctx();
+	dss_runtime_put();
 
 	return 0;
 err_sdi:
 	dpi_exit();
 err_dpi:
-	dss_clk_disable_all_no_ctx();
+	dss_runtime_put();
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
 	dss_put_clocks();
 err_clocks:
 	iounmap(dss.base);
@@ -1095,13 +891,7 @@ static int omap_dsshw_remove(struct platform_device *pdev)
 
 	iounmap(dss.base);
 
-	/*
-	 * As part of hwmod changes, DSS is not the only controller of dss
-	 * clocks; hwmod framework itself will also enable clocks during hwmod
-	 * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
-	 * need to disable clocks if their usecounts > 1.
-	 */
-	WARN_ON(dss.num_clks_enabled > 0);
+	pm_runtime_disable(&pdev->dev);
 
 	dss_put_clocks();
 
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index aeb611d..ce17a61 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -109,14 +109,6 @@ enum omap_parallel_interface_mode {
 	OMAP_DSS_PARALLELMODE_DSI,
 };
 
-enum dss_clock {
-	DSS_CLK_ICK	= 1 << 0,	/* DSS_L3_ICLK and DSS_L4_ICLK */
-	DSS_CLK_FCK	= 1 << 1,	/* DSS1_ALWON_FCLK */
-	DSS_CLK_SYSCK	= 1 << 2,	/* DSS2_ALWON_FCLK */
-	DSS_CLK_TVFCK	= 1 << 3,	/* DSS_TV_FCLK */
-	DSS_CLK_VIDFCK	= 1 << 4,	/* DSS_96M_FCLK*/
-};
-
 enum dss_hdmi_venc_clk_source_select {
 	DSS_VENC_TV_CLK = 0,
 	DSS_HDMI_M_PCLK = 1,
@@ -220,12 +212,10 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
 int dss_init_platform_driver(void);
 void dss_uninit_platform_driver(void);
 
+int dss_runtime_get(void);
+void dss_runtime_put(void);
+
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
-void dss_save_context(void);
-void dss_restore_context(void);
-void dss_clk_enable(enum dss_clock clks);
-void dss_clk_disable(enum dss_clock clks);
-unsigned long dss_clk_get_rate(enum dss_clock clk);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
@@ -282,15 +272,15 @@ struct file_operations;
 int dsi_init_platform_driver(void);
 void dsi_uninit_platform_driver(void);
 
+int dsi_runtime_get(struct platform_device *dsidev);
+void dsi_runtime_put(struct platform_device *dsidev);
+
 void dsi_dump_clocks(struct seq_file *s);
 void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
 		const struct file_operations *debug_fops);
 void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
 		const struct file_operations *debug_fops);
 
-void dsi_save_context(void);
-void dsi_restore_context(void);
-
 int dsi_init_display(struct omap_dss_device *display);
 void dsi_irq_handler(void);
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -316,6 +306,13 @@ static inline int dsi_init_platform_driver(void)
 static inline void dsi_uninit_platform_driver(void)
 {
 }
+static inline int dsi_runtime_get(struct platform_device *dsidev)
+{
+	return 0;
+}
+static inline void dsi_runtime_put(struct platform_device *dsidev)
+{
+}
 static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
 {
 	WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -383,8 +380,8 @@ void dispc_dump_regs(struct seq_file *s);
 void dispc_irq_handler(void);
 void dispc_fake_vsync_irq(void);
 
-void dispc_save_context(void);
-void dispc_restore_context(void);
+int dispc_runtime_get(void);
+void dispc_runtime_put(void);
 
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b630c98..5e5b98b 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -30,6 +30,8 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
 #include <video/omapdss.h>
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
 	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -52,6 +54,9 @@ static struct {
 	u8 edid_set;
 	bool custom_set;
 	struct hdmi_config cfg;
+
+	struct clk *sys_clk;
+	struct clk *hdmi_clk;
 } hdmi;
 
 /*
@@ -163,6 +168,56 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
 	return val;
 }
 
+static int hdmi_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("hdmi_runtime_get\n");
+
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
+
+	clk_enable(hdmi.sys_clk);
+	clk_enable(hdmi.hdmi_clk);
+
+	r = pm_runtime_get_sync(&hdmi.pdev->dev);
+	WARN_ON(r);
+	if (r < 0)
+		goto err_runtime_get;
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(hdmi.sys_clk);
+	clk_disable(hdmi.hdmi_clk);
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	return r;
+}
+
+static void hdmi_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("hdmi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&hdmi.pdev->dev);
+	WARN_ON(r);
+
+	clk_disable(hdmi.sys_clk);
+	clk_disable(hdmi.hdmi_clk);
+
+	dispc_runtime_put();
+	dss_runtime_put();
+}
+
 int hdmi_init_display(struct omap_dss_device *dssdev)
 {
 	DSSDBG("init_display\n");
@@ -312,30 +367,11 @@ static int hdmi_phy_init(void)
 	return 0;
 }
 
-static int hdmi_wait_softreset(void)
-{
-	/* reset W1 */
-	REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
-
-	/* wait till SOFTRESET = 0 */
-	if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
-		DSSERR("sysconfig reset failed\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
 static int hdmi_pll_program(struct hdmi_pll_info *fmt)
 {
 	u16 r = 0;
 	enum hdmi_clk_refsel refsel;
 
-	/* wait for wrapper reset */
-	r = hdmi_wait_softreset();
-	if (r)
-		return r;
-
 	r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
 	if (r)
 		return r;
@@ -1065,7 +1101,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	unsigned long clkin, refclk;
 	u32 mf;
 
-	clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
+	clkin = clk_get_rate(hdmi.sys_clk) / 10000;
 	/*
 	 * Input clock is predivided by N + 1
 	 * out put of which is reference clk
@@ -1099,16 +1135,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 
-static void hdmi_enable_clocks(int enable)
-{
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
-				DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
-				DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-}
-
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
 	int r, code = 0;
@@ -1116,7 +1142,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	struct omap_video_timings *p;
 	unsigned long phy;
 
-	hdmi_enable_clocks(1);
+	r = hdmi_runtime_get();
+	if (r)
+		return r;
 
 	dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
 
@@ -1181,7 +1209,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
 	return 0;
 err:
-	hdmi_enable_clocks(0);
+	hdmi_runtime_put();
 	return -EIO;
 }
 
@@ -1192,7 +1220,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi_wp_video_start(0);
 	hdmi_phy_off();
 	hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
-	hdmi_enable_clocks(0);
+	hdmi_runtime_put();
 
 	hdmi.edid_set = 0;
 }
@@ -1687,14 +1715,43 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
 };
 #endif
 
+static int hdmi_get_clocks(struct platform_device *pdev)
+{
+	struct clk *clk;
+
+	clk = clk_get(&pdev->dev, "sys_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get sys_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	hdmi.sys_clk = clk;
+
+	clk = clk_get(&pdev->dev, "hdmi_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get hdmi_clk\n");
+		clk_put(hdmi.sys_clk);
+		return PTR_ERR(clk);
+	}
+
+	hdmi.hdmi_clk = clk;
+
+	return 0;
+}
+
+static void hdmi_put_clocks(void)
+{
+	if (hdmi.sys_clk)
+		clk_put(hdmi.sys_clk);
+	if (hdmi.hdmi_clk)
+		clk_put(hdmi.hdmi_clk);
+}
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
 	struct resource *hdmi_mem;
-#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
-	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-	int ret;
-#endif
+	int r;
 
 	hdmi.pdata = pdev->dev.platform_data;
 	hdmi.pdev = pdev;
@@ -1714,17 +1771,25 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	r = hdmi_get_clocks(pdev);
+	if (r) {
+		iounmap(hdmi.base_wp);
+		return r;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
 	hdmi_panel_init();
 
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
 	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
 
 	/* Register ASoC codec DAI */
-	ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+	r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
 					&hdmi_codec_dai_drv, 1);
-	if (ret) {
+	if (r) {
 		DSSERR("can't register ASoC HDMI audio codec\n");
-		return ret;
+		return r;
 	}
 #endif
 	return 0;
@@ -1739,6 +1804,10 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
 	snd_soc_unregister_codec(&pdev->dev);
 #endif
 
+	pm_runtime_disable(&pdev->dev);
+
+	hdmi_put_clocks();
+
 	iounmap(hdmi.base_wp);
 
 	return 0;
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 9aeea50..a148a80 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -1236,6 +1236,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
 	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
 	spin_lock_irqsave(&dss_cache.lock, flags);
 
 	/* Configure overlays */
@@ -1409,7 +1413,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 	}
 
 	r = 0;
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 	if (!dss_cache.irq_enabled) {
 		u32 mask;
 
@@ -1422,10 +1425,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 		dss_cache.irq_enabled = true;
 	}
 	configure_dispc();
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
 	spin_unlock_irqrestore(&dss_cache.lock, flags);
 
+	dispc_runtime_put();
+
 	return r;
 }
 
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index cfbfc57..c84380c 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
 
 	old_mgr = ovl->manager;
 
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
 	/* detach old manager */
 	if (old_mgr) {
 		r = ovl->unset_manager(ovl);
 		if (r) {
 			DSSERR("detach failed\n");
-			return r;
+			goto err;
 		}
 
 		r = old_mgr->apply(old_mgr);
 		if (r)
-			return r;
+			goto err;
 	}
 
 	if (mgr) {
 		r = ovl->set_manager(ovl, mgr);
 		if (r) {
 			DSSERR("Failed to attach overlay\n");
-			return r;
+			goto err;
 		}
 
 		r = mgr->apply(mgr);
 		if (r)
-			return r;
+			goto err;
 	}
 
+	dispc_runtime_put();
+
 	return size;
+
+err:
+	dispc_runtime_put();
+	return r;
 }
 
 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -507,7 +517,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 
 	ovl->manager = mgr;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 	/* XXX: When there is an overlay on a DSI manual update display, and
 	 * the overlay is first disabled, then moved to tv, and enabled, we
 	 * seem to get SYNC_LOST_DIGIT error.
@@ -521,7 +530,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 	 * the overlay, but before moving the overlay to TV.
 	 */
 	dispc_set_channel_out(ovl->id, mgr->id);
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
 	return 0;
 }
@@ -722,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
 	}
 
 	if (mgr) {
+		dispc_runtime_get();
+
 		for (i = 0; i < dss_feat_get_num_ovls(); i++) {
 			struct omap_overlay *ovl;
 			ovl = omap_dss_get_overlay(i);
@@ -731,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
 				omap_dss_set_manager(ovl, mgr);
 			}
 		}
+
+		dispc_runtime_put();
 	}
 }
 
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index a873104..3e2f5cd 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -34,6 +34,7 @@
 #include <linux/seq_file.h>
 #include <linux/semaphore.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
@@ -121,12 +122,46 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
 	return __raw_readl(rfbi.base + idx.idx);
 }
 
-static void rfbi_enable_clocks(bool enable)
+static int rfbi_runtime_get(void)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	int r;
+
+	DSSDBG("rfbi_runtime_get\n");
+
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
+
+	r = pm_runtime_get_sync(&rfbi.pdev->dev);
+	WARN_ON(r);
+	if (r < 0)
+		goto err_runtime_get;
+
+	return 0;
+
+err_runtime_get:
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	return r;
+}
+
+static void rfbi_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("rfbi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&rfbi.pdev->dev);
+	WARN_ON(r);
+
+	dispc_runtime_put();
+	dss_runtime_put();
 }
 
 void rfbi_bus_lock(void)
@@ -806,7 +841,8 @@ void rfbi_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (rfbi_runtime_get())
+		return;
 
 	DUMPREG(RFBI_REVISION);
 	DUMPREG(RFBI_SYSCONFIG);
@@ -837,7 +873,7 @@ void rfbi_dump_regs(struct seq_file *s)
 	DUMPREG(RFBI_VSYNC_WIDTH);
 	DUMPREG(RFBI_HSYNC_WIDTH);
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	rfbi_runtime_put();
 #undef DUMPREG
 }
 
@@ -845,7 +881,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r;
 
-	rfbi_enable_clocks(1);
+	r = rfbi_runtime_get();
+	if (r)
+		return r;
 
 	r = omap_dss_start_device(dssdev);
 	if (r) {
@@ -880,6 +918,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 err1:
 	omap_dss_stop_device(dssdev);
 err0:
+	rfbi_runtime_put();
 	return r;
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -890,7 +929,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
 			DISPC_IRQ_FRAMEDONE);
 	omap_dss_stop_device(dssdev);
 
-	rfbi_enable_clocks(0);
+	rfbi_runtime_put();
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 
@@ -905,8 +944,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
 static int omap_rfbihw_probe(struct platform_device *pdev)
 {
 	u32 rev;
-	u32 l;
 	struct resource *rfbi_mem;
+	struct clk *clk;
+	int r;
 
 	rfbi.pdev = pdev;
 
@@ -915,36 +955,55 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
 	rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
 	if (!rfbi_mem) {
 		DSSERR("can't get IORESOURCE_MEM RFBI\n");
-		return -EINVAL;
+		r = -EINVAL;
+		goto err_ioremap;
 	}
 	rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
 	if (!rfbi.base) {
 		DSSERR("can't ioremap RFBI\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto err_ioremap;
 	}
 
-	rfbi_enable_clocks(1);
+	pm_runtime_enable(&pdev->dev);
+
+	r = rfbi_runtime_get();
+	if (r)
+		goto err_get_rfbi;
 
 	msleep(10);
 
-	rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+	clk = clk_get(&pdev->dev, "rfbi_iclk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get rfbi_iclk\n");
+		r = PTR_ERR(clk);
+		goto err_get_ick;
+	}
+
+	rfbi.l4_khz = clk_get_rate(clk) / 1000;
 
-	/* Enable autoidle and smart-idle */
-	l = rfbi_read_reg(RFBI_SYSCONFIG);
-	l |= (1 << 0) | (2 << 3);
-	rfbi_write_reg(RFBI_SYSCONFIG, l);
+	clk_put(clk);
 
 	rev = rfbi_read_reg(RFBI_REVISION);
 	dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	rfbi_enable_clocks(0);
+	rfbi_runtime_put();
 
 	return 0;
+
+err_get_ick:
+	rfbi_runtime_put();
+err_get_rfbi:
+	pm_runtime_disable(&pdev->dev);
+	iounmap(rfbi.base);
+err_ioremap:
+	return r;
 }
 
 static int omap_rfbihw_remove(struct platform_device *pdev)
 {
+	pm_runtime_disable(&pdev->dev);
 	iounmap(rfbi.base);
 	return 0;
 }
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 0bd4b03..3a688c8 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -20,13 +20,11 @@
 #define DSS_SUBSYS_NAME "SDI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 #include "dss.h"
 
 static struct {
@@ -60,14 +58,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
-		goto err0;
+		goto err_start_dev;
 	}
 
 	r = regulator_enable(sdi.vdds_sdi_reg);
 	if (r)
-		goto err1;
+		goto err_reg_enable;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
 
 	sdi_basic_init(dssdev);
 
@@ -80,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	r = dss_calc_clock_div(1, t->pixel_clock * 1000,
 			&dss_cinfo, &dispc_cinfo);
 	if (r)
-		goto err2;
+		goto err_calc_clock_div;
 
 	fck = dss_cinfo.fck;
 	lck_div = dispc_cinfo.lck_div;
@@ -101,27 +105,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
 	r = dss_set_clock_div(&dss_cinfo);
 	if (r)
-		goto err2;
+		goto err_set_dss_clock_div;
 
 	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
 	if (r)
-		goto err2;
+		goto err_set_dispc_clock_div;
 
 	dss_sdi_init(dssdev->phy.sdi.datapairs);
 	r = dss_sdi_enable();
 	if (r)
-		goto err1;
+		goto err_sdi_enable;
 	mdelay(2);
 
 	dssdev->manager->enable(dssdev->manager);
 
 	return 0;
-err2:
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+
+err_sdi_enable:
+err_set_dispc_clock_div:
+err_set_dss_clock_div:
+err_calc_clock_div:
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
 	regulator_disable(sdi.vdds_sdi_reg);
-err1:
+err_reg_enable:
 	omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
 	return r;
 }
 EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -132,7 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 
 	dss_sdi_disable();
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dispc_runtime_put();
+	dss_runtime_put();
 
 	regulator_disable(sdi.vdds_sdi_reg);
 
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 15b4431..4491983 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -33,6 +33,7 @@
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/cpu.h>
@@ -293,6 +294,12 @@ static struct {
 	struct mutex venc_lock;
 	u32 wss_data;
 	struct regulator *vdda_dac_reg;
+
+	struct mutex	runtime_lock;
+	int		runtime_count;
+
+	struct clk	*tv_clk;
+	struct clk	*tv_dac_clk;
 } venc;
 
 static inline void venc_write_reg(int idx, u32 val)
@@ -381,17 +388,71 @@ static void venc_reset(void)
 #endif
 }
 
-static void venc_enable_clocks(int enable)
+static int venc_runtime_get(void)
 {
-	if (enable) {
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
-		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
-			dss_clk_enable(DSS_CLK_VIDFCK);
-	} else {
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
-		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
-			dss_clk_disable(DSS_CLK_VIDFCK);
+	int r;
+
+	mutex_lock(&venc.runtime_lock);
+
+	if (venc.runtime_count++ = 0) {
+		DSSDBG("venc_runtime_get\n");
+
+		r = dss_runtime_get();
+		if (r)
+			goto err_get_dss;
+
+		r = dispc_runtime_get();
+		if (r)
+			goto err_get_dispc;
+
+		clk_enable(venc.tv_clk);
+		if (venc.tv_dac_clk)
+			clk_enable(venc.tv_dac_clk);
+
+		r = pm_runtime_get_sync(&venc.pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err_runtime_get;
 	}
+
+	mutex_unlock(&venc.runtime_lock);
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(venc.tv_clk);
+	if (venc.tv_dac_clk)
+		clk_disable(venc.tv_dac_clk);
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	mutex_unlock(&venc.runtime_lock);
+
+	return r;
+}
+
+static void venc_runtime_put(void)
+{
+	mutex_lock(&venc.runtime_lock);
+
+	if (--venc.runtime_count = 0) {
+		int r;
+
+		DSSDBG("venc_runtime_put\n");
+
+		r = pm_runtime_put_sync(&venc.pdev->dev);
+		WARN_ON(r);
+
+		clk_disable(venc.tv_clk);
+		if (venc.tv_dac_clk)
+			clk_disable(venc.tv_dac_clk);
+
+		dispc_runtime_put();
+		dss_runtime_put();
+	}
+
+	mutex_unlock(&venc.runtime_lock);
 }
 
 static const struct venc_config *venc_timings_to_config(
@@ -410,8 +471,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
 {
 	u32 l;
 
-	venc_enable_clocks(1);
-
 	venc_reset();
 	venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
 
@@ -452,8 +511,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
 		dssdev->platform_disable(dssdev);
 
 	regulator_disable(venc.vdda_dac_reg);
-
-	venc_enable_clocks(0);
 }
 
 
@@ -491,6 +548,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
 		goto err1;
 	}
 
+	r = venc_runtime_get();
+	if (r)
+		goto err1;
+
 	venc_power_on(dssdev);
 
 	venc.wss_data = 0;
@@ -524,6 +585,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 
 	venc_power_off(dssdev);
 
+	venc_runtime_put();
+
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 
 	omap_dss_stop_device(dssdev);
@@ -602,6 +665,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
 static int venc_set_wss(struct omap_dss_device *dssdev,	u32 wss)
 {
 	const struct venc_config *config;
+	int r;
 
 	DSSDBG("venc_set_wss\n");
 
@@ -612,16 +676,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev,	u32 wss)
 	/* Invert due to VENC_L21_WC_CTL:INV=1 */
 	venc.wss_data = (wss ^ 0xfffff) << 8;
 
-	venc_enable_clocks(1);
+	r = venc_runtime_get();
+	if (r)
+		goto err;
 
 	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
 			venc.wss_data);
 
-	venc_enable_clocks(0);
+	venc_runtime_put();
 
+err:
 	mutex_unlock(&venc.venc_lock);
 
-	return 0;
+	return r;
 }
 
 static struct omap_dss_driver venc_driver = {
@@ -677,7 +744,8 @@ void venc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 
-	venc_enable_clocks(1);
+	if (venc_runtime_get())
+		return;
 
 	DUMPREG(VENC_F_CONTROL);
 	DUMPREG(VENC_VIDOUT_CTRL);
@@ -721,16 +789,53 @@ void venc_dump_regs(struct seq_file *s)
 	DUMPREG(VENC_OUTPUT_CONTROL);
 	DUMPREG(VENC_OUTPUT_TEST);
 
-	venc_enable_clocks(0);
+	venc_runtime_put();
 
 #undef DUMPREG
 }
 
+static int venc_get_clocks(struct platform_device *pdev)
+{
+	struct clk *clk;
+
+	clk = clk_get(&pdev->dev, "tv_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get tv_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	venc.tv_clk = clk;
+
+	if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
+		clk = clk_get(&pdev->dev, "tv_dac_clk");
+		if (IS_ERR(clk)) {
+			DSSERR("can't get tv_dac_clk\n");
+			clk_put(venc.tv_clk);
+			return PTR_ERR(clk);
+		}
+	} else {
+		clk = NULL;
+	}
+
+	venc.tv_dac_clk = clk;
+
+	return 0;
+}
+
+static void venc_put_clocks(void)
+{
+	if (venc.tv_clk)
+		clk_put(venc.tv_clk);
+	if (venc.tv_dac_clk)
+		clk_put(venc.tv_dac_clk);
+}
+
 /* VENC HW IP initialisation */
 static int omap_venchw_probe(struct platform_device *pdev)
 {
 	u8 rev_id;
 	struct resource *venc_mem;
+	int r;
 
 	venc.pdev = pdev;
 
@@ -741,22 +846,41 @@ static int omap_venchw_probe(struct platform_device *pdev)
 	venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
 	if (!venc_mem) {
 		DSSERR("can't get IORESOURCE_MEM VENC\n");
-		return -EINVAL;
+		r = -EINVAL;
+		goto err_ioremap;
 	}
 	venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
 	if (!venc.base) {
 		DSSERR("can't ioremap VENC\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto err_ioremap;
 	}
 
-	venc_enable_clocks(1);
+	r = venc_get_clocks(pdev);
+	if (r)
+		goto err_get_clk;
+
+	mutex_init(&venc.runtime_lock);
+	pm_runtime_enable(&pdev->dev);
+
+	r = venc_runtime_get();
+	if (r)
+		goto err_get_venc;
 
 	rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
 	dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
 
-	venc_enable_clocks(0);
+	venc_runtime_put();
 
 	return omap_dss_register_driver(&venc_driver);
+
+err_get_venc:
+	pm_runtime_disable(&pdev->dev);
+	venc_put_clocks();
+err_get_clk:
+	iounmap(venc.base);
+err_ioremap:
+	return r;
 }
 
 static int omap_venchw_remove(struct platform_device *pdev)
@@ -767,6 +891,9 @@ static int omap_venchw_remove(struct platform_device *pdev)
 	}
 	omap_dss_unregister_driver(&venc_driver);
 
+	pm_runtime_disable(&pdev->dev);
+	venc_put_clocks();
+
 	iounmap(venc.base);
 	return 0;
 }
-- 
1.7.4.1


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

* [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Use PM runtime and HWMOD support to handle enabling and disabling of DSS
modules.

Each DSS module will have get and put functions which can be used to
enable and disable that module. The functions use pm_runtime and hwmod
opt-clocks to enable the hardware.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c   |  339 ++++++++++++++++++++++++----------
 drivers/video/omap2/dss/dpi.c     |   70 +++++---
 drivers/video/omap2/dss/dsi.c     |  250 ++++++++++++++++---------
 drivers/video/omap2/dss/dss.c     |  368 ++++++++-----------------------------
 drivers/video/omap2/dss/dss.h     |   33 ++--
 drivers/video/omap2/dss/hdmi.c    |  149 +++++++++++----
 drivers/video/omap2/dss/manager.c |    8 +-
 drivers/video/omap2/dss/overlay.c |   24 ++-
 drivers/video/omap2/dss/rfbi.c    |   97 ++++++++--
 drivers/video/omap2/dss/sdi.c     |   40 +++--
 drivers/video/omap2/dss/venc.c    |  171 +++++++++++++++---
 11 files changed, 926 insertions(+), 623 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ee2052f..57400f6 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -34,6 +34,7 @@
 #include <linux/hardirq.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/sram.h>
 #include <plat/clock.h>
@@ -93,7 +94,13 @@ struct dispc_irq_stats {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
+
+	int		ctx_loss_cnt;
+	struct mutex	runtime_lock;
+	int		runtime_count;
+
 	int irq;
+	struct clk *dss_clk;
 
 	u32	fifo_size[3];
 
@@ -140,13 +147,12 @@ static inline u32 dispc_read_reg(const u16 idx)
 #define RR(reg) \
 	dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
 
-void dispc_save_context(void)
+static void dispc_save_context(void)
 {
 	int i;
-	if (cpu_is_omap24xx())
-		return;
 
-	SR(SYSCONFIG);
+	DSSDBG("dispc_save_context\n");
+
 	SR(IRQENABLE);
 	SR(CONTROL);
 	SR(CONFIG);
@@ -314,10 +320,12 @@ void dispc_save_context(void)
 		SR(DIVISOR);
 }
 
-void dispc_restore_context(void)
+static void dispc_restore_context(void)
 {
 	int i;
-	RR(SYSCONFIG);
+
+	DSSDBG("dispc_restore_context\n");
+
 	/*RR(IRQENABLE);*/
 	/*RR(CONTROL);*/
 	RR(CONFIG);
@@ -501,14 +509,121 @@ void dispc_restore_context(void)
 #undef SR
 #undef RR
 
-static inline void enable_clocks(bool enable)
+static void dispc_init_ctx_loss_count(void)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	struct device *dev = &dispc.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt = 0;
+
+	/*
+	 * get_context_loss_count returns negative on error. We'll ignore the
+	 * error and store the error to ctx_loss_cnt, which will cause
+	 * dispc_need_ctx_restore() call to return true.
+	 */
+
+	if (board_data->get_context_loss_count)
+		cnt = board_data->get_context_loss_count(dev);
+
+	WARN_ON(cnt < 0);
+
+	dispc.ctx_loss_cnt = cnt;
+
+	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
+}
+
+static bool dispc_need_ctx_restore(void)
+{
+	struct device *dev = &dispc.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt;
+
+	/*
+	 * If get_context_loss_count is not available, assume that we need
+	 * context restore always.
+	 */
+	if (!board_data->get_context_loss_count)
+		return true;
+
+	cnt = board_data->get_context_loss_count(dev);
+	if (cnt < 0) {
+		dev_err(dev, "getting context loss count failed, will force "
+				"context restore\n");
+		dispc.ctx_loss_cnt = cnt;
+		return true;
+	}
+
+	if (cnt == dispc.ctx_loss_cnt)
+		return false;
+
+	DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt);
+	dispc.ctx_loss_cnt = cnt;
+
+	return true;
+}
+
+int dispc_runtime_get(void)
+{
+	int r;
+
+	mutex_lock(&dispc.runtime_lock);
+
+	if (dispc.runtime_count++ == 0) {
+		DSSDBG("dispc_runtime_get\n");
+
+		r = dss_runtime_get();
+		if (r)
+			goto err_dss_get;
+
+		/* XXX dispc fclk can also come from DSI PLL */
+		clk_enable(dispc.dss_clk);
+
+		r = pm_runtime_get_sync(&dispc.pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err_runtime_get;
+
+		if (dispc_need_ctx_restore())
+			dispc_restore_context();
+	}
+
+	mutex_unlock(&dispc.runtime_lock);
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(dispc.dss_clk);
+	dss_runtime_put();
+err_dss_get:
+	mutex_unlock(&dispc.runtime_lock);
+
+	return r;
 }
 
+void dispc_runtime_put(void)
+{
+	mutex_lock(&dispc.runtime_lock);
+
+	if (--dispc.runtime_count == 0) {
+		int r;
+
+		DSSDBG("dispc_runtime_put\n");
+
+		dispc_save_context();
+
+		r = pm_runtime_put_sync(&dispc.pdev->dev);
+		WARN_ON(r);
+
+		clk_disable(dispc.dss_clk);
+
+		dss_runtime_put();
+	}
+
+	mutex_unlock(&dispc.runtime_lock);
+}
+
+
 bool dispc_go_busy(enum omap_channel channel)
 {
 	int bit;
@@ -530,7 +645,7 @@ void dispc_go(enum omap_channel channel)
 	int bit;
 	bool enable_bit, go_bit;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	if (channel == OMAP_DSS_CHANNEL_LCD ||
 			channel == OMAP_DSS_CHANNEL_LCD2)
@@ -571,7 +686,7 @@ void dispc_go(enum omap_channel channel)
 	else
 		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
 end:
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -998,7 +1113,7 @@ void dispc_set_burst_size(enum omap_plane plane,
 	int shift;
 	u32 val;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	switch (plane) {
 	case OMAP_DSS_GFX:
@@ -1017,7 +1132,7 @@ void dispc_set_burst_size(enum omap_plane plane,
 	val = FLD_MOD(val, burst_size, shift+1, shift);
 	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_gamma_table(bool enable)
@@ -1054,9 +1169,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
 	else
 		bit = 10;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1064,9 +1179,9 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_digit_size(u16 width, u16 height)
@@ -1074,9 +1189,9 @@ void dispc_set_digit_size(u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void dispc_read_plane_fifo_sizes(void)
@@ -1085,7 +1200,7 @@ static void dispc_read_plane_fifo_sizes(void)
 	int plane;
 	u8 start, end;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
@@ -1095,7 +1210,7 @@ static void dispc_read_plane_fifo_sizes(void)
 		dispc.fifo_size[plane] = size;
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1110,7 +1225,7 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
 	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
 			plane,
@@ -1124,17 +1239,17 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 			FLD_VAL(high, hi_start, hi_end) |
 			FLD_VAL(low, lo_start, lo_end));
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_fifomerge(bool enable)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
 	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void _dispc_set_fir(enum omap_plane plane,
@@ -1756,9 +1871,9 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
 
 void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	_dispc_set_channel_out(plane, channel_out);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static int _dispc_setup_plane(enum omap_plane plane,
@@ -1954,7 +2069,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 	int r;
 	u32 irq;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	/* When we disable LCD output, we need to wait until frame is done.
 	 * Otherwise the DSS is still working, and turning off the clocks
@@ -1990,7 +2105,7 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 			DSSERR("failed to unregister FRAMEDONE isr\n");
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void _enable_digit_out(bool enable)
@@ -2003,10 +2118,10 @@ static void dispc_enable_digit_out(bool enable)
 	struct completion frame_done_completion;
 	int r;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
-		enable_clocks(0);
+		dispc_runtime_put();
 		return;
 	}
 
@@ -2061,7 +2176,7 @@ static void dispc_enable_digit_out(bool enable)
 		spin_unlock_irqrestore(&dispc.irq_lock, flags);
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2092,9 +2207,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_lcd_enable_signal(bool enable)
@@ -2102,9 +2217,9 @@ void dispc_lcd_enable_signal(bool enable)
 	if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_pck_free_enable(bool enable)
@@ -2112,19 +2227,19 @@ void dispc_pck_free_enable(bool enable)
 	if (!dss_has_feature(FEAT_PCKFREEENABLE))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (channel == OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
 	else
 		REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 
@@ -2147,27 +2262,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
 		return;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (channel == OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_loadmode(enum omap_dss_load_mode mode)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 
 void dispc_set_default_color(enum omap_channel channel, u32 color)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 u32 dispc_get_default_color(enum omap_channel channel)
@@ -2178,9 +2293,9 @@ u32 dispc_get_default_color(enum omap_channel channel)
 		channel != OMAP_DSS_CHANNEL_LCD &&
 		channel != OMAP_DSS_CHANNEL_LCD2);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return l;
 }
@@ -2189,7 +2304,7 @@ void dispc_set_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type type,
 		u32 trans_key)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2198,14 +2313,14 @@ void dispc_set_trans_key(enum omap_channel ch,
 		REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
 
 	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_get_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type *type,
 		u32 *trans_key)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (type) {
 		if (ch == OMAP_DSS_CHANNEL_LCD)
 			*type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2219,33 +2334,33 @@ void dispc_get_trans_key(enum omap_channel ch,
 
 	if (trans_key)
 		*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 {
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
@@ -2254,7 +2369,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return false;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 18, 18);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2263,7 +2378,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 18, 18);
 	else
 		BUG();
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2273,7 +2388,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 {
 	bool enabled;
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 10, 10);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2282,7 +2397,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 10, 10);
 	else
 		BUG();
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2310,12 +2425,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 		return;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	if (channel == OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2347,7 +2462,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		return;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	if (channel == OMAP_DSS_CHANNEL_LCD2) {
 		l = dispc_read_reg(DISPC_CONTROL2);
@@ -2361,7 +2476,7 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		dispc_write_reg(DISPC_CONTROL, l);
 	}
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2414,10 +2529,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
 			FLD_VAL(vbp, 31, 20);
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
 	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 /* change name to mode? */
@@ -2460,10 +2575,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 	BUG_ON(lck_div < 1);
 	BUG_ON(pck_div < 2);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2482,7 +2597,7 @@ unsigned long dispc_fclk_rate(void)
 
 	switch (dss_get_dispc_clk_source()) {
 	case OMAP_DSS_CLK_SRC_FCK:
-		r = dss_clk_get_rate(DSS_CLK_FCK);
+		r = clk_get_rate(dispc.dss_clk);
 		break;
 	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 		dsidev = dsi_get_dsidev_from_id(0);
@@ -2512,7 +2627,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
 
 	switch (dss_get_lcd_clk_source(channel)) {
 	case OMAP_DSS_CLK_SRC_FCK:
-		r = dss_clk_get_rate(DSS_CLK_FCK);
+		r = clk_get_rate(dispc.dss_clk);
 		break;
 	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 		dsidev = dsi_get_dsidev_from_id(0);
@@ -2551,7 +2666,8 @@ void dispc_dump_clocks(struct seq_file *s)
 	enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
 	enum omap_dss_clk_source lcd_clk_src;
 
-	enable_clocks(1);
+	if (dispc_runtime_get())
+		return;
 
 	seq_printf(s, "- DISPC -\n");
 
@@ -2599,7 +2715,8 @@ void dispc_dump_clocks(struct seq_file *s)
 		seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
 				dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
 	}
-	enable_clocks(0);
+
+	dispc_runtime_put();
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2654,7 +2771,8 @@ void dispc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dispc_runtime_get())
+		return;
 
 	DUMPREG(DISPC_REVISION);
 	DUMPREG(DISPC_SYSCONFIG);
@@ -2899,7 +3017,7 @@ void dispc_dump_regs(struct seq_file *s)
 		DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dispc_runtime_put();
 #undef DUMPREG
 }
 
@@ -2920,9 +3038,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
 	l |= FLD_VAL(acbi, 11, 8);
 	l |= FLD_VAL(acb, 7, 0);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	dispc_write_reg(DISPC_POL_FREQ(channel), l);
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 void dispc_set_pol_freq(enum omap_channel channel,
@@ -3043,7 +3161,7 @@ static void _omap_dispc_set_irqs(void)
 		mask |= isr_data->mask;
 	}
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	old_mask = dispc_read_reg(DISPC_IRQENABLE);
 	/* clear the irqstatus for newly enabled irqs */
@@ -3051,7 +3169,7 @@ static void _omap_dispc_set_irqs(void)
 
 	dispc_write_reg(DISPC_IRQENABLE, mask);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3560,13 +3678,6 @@ static void _omap_dispc_initial_config(void)
 {
 	u32 l;
 
-	l = dispc_read_reg(DISPC_SYSCONFIG);
-	l = FLD_MOD(l, 2, 13, 12);	/* MIDLEMODE: smart standby */
-	l = FLD_MOD(l, 2, 4, 3);	/* SIDLEMODE: smart idle */
-	l = FLD_MOD(l, 1, 2, 2);	/* ENWAKEUP */
-	l = FLD_MOD(l, 1, 0, 0);	/* AUTOIDLE */
-	dispc_write_reg(DISPC_SYSCONFIG, l);
-
 	/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
 	if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
 		l = dispc_read_reg(DISPC_DIVISOR);
@@ -3596,9 +3707,9 @@ int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
 	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 	_dispc_enable_plane(plane, enable);
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return 0;
 }
@@ -3625,7 +3736,7 @@ int dispc_setup_plane(enum omap_plane plane,
 	       ilace, color_mode,
 	       rotation, mirror, channel);
 
-	enable_clocks(1);
+	dispc_runtime_get();
 
 	r = _dispc_setup_plane(plane,
 			   paddr, screen_width,
@@ -3639,7 +3750,7 @@ int dispc_setup_plane(enum omap_plane plane,
 			   pre_mult_alpha,
 			   channel, puv_addr);
 
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return r;
 }
@@ -3650,9 +3761,19 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 	u32 rev;
 	int r = 0;
 	struct resource *dispc_mem;
+	struct clk *clk;
 
 	dispc.pdev = pdev;
 
+	clk = clk_get(&pdev->dev, "dss_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get dss_clk\n");
+		r = PTR_ERR(clk);
+		goto err_get_clk;
+	}
+
+	dispc.dss_clk = clk;
+
 	spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3666,51 +3787,67 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 	if (!dispc_mem) {
 		DSSERR("can't get IORESOURCE_MEM DISPC\n");
 		r = -EINVAL;
-		goto fail0;
+		goto err_ioremap;
 	}
 	dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
 	if (!dispc.base) {
 		DSSERR("can't ioremap DISPC\n");
 		r = -ENOMEM;
-		goto fail0;
+		goto err_ioremap;
 	}
 	dispc.irq = platform_get_irq(dispc.pdev, 0);
 	if (dispc.irq < 0) {
 		DSSERR("platform_get_irq failed\n");
 		r = -ENODEV;
-		goto fail1;
+		goto err_irq;
 	}
 
 	r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
 		"OMAP DISPC", dispc.pdev);
 	if (r < 0) {
 		DSSERR("request_irq failed\n");
-		goto fail1;
+		goto err_irq;
 	}
 
-	enable_clocks(1);
+	dispc_init_ctx_loss_count();
+
+	mutex_init(&dispc.runtime_lock);
+
+	pm_runtime_enable(&pdev->dev);
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_runtime_get;
 
 	_omap_dispc_initial_config();
 
 	_omap_dispc_initialize_irq();
 
-	dispc_save_context();
-
 	rev = dispc_read_reg(DISPC_REVISION);
 	dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	enable_clocks(0);
+	dispc_runtime_put();
 
 	return 0;
-fail1:
+
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
+	free_irq(dispc.irq, dispc.pdev);
+err_irq:
 	iounmap(dispc.base);
-fail0:
+err_ioremap:
+	clk_put(dispc.dss_clk);
+err_get_clk:
 	return r;
 }
 
 static int omap_dispchw_remove(struct platform_device *pdev)
 {
+	pm_runtime_disable(&pdev->dev);
+
+	clk_put(dispc.dss_clk);
+
 	free_irq(dispc.irq, dispc.pdev);
 	iounmap(dispc.base);
 	return 0;
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index bab55cd..f053b18 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -23,7 +23,6 @@
 #define DSS_SUBSYS_NAME "DPI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/errno.h>
@@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 	bool is_tft;
 	int r = 0;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-
 	dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
 			dssdev->panel.acbi, dssdev->panel.acb);
 
@@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 		r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
 				&fck, &lck_div, &pck_div);
 	if (r)
-		goto err0;
+		return r;
 
 	pck = fck / lck_div / pck_div / 1000;
 
@@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 
 	dispc_set_lcd_timings(dssdev->manager->id, t);
 
-err0:
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-	return r;
+	return 0;
 }
 
-static int dpi_basic_init(struct omap_dss_device *dssdev)
+static void dpi_basic_init(struct omap_dss_device *dssdev)
 {
 	bool is_tft;
 
@@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
 			OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
 	dispc_set_tft_data_lines(dssdev->manager->id,
 			dssdev->phy.dpi.data_lines);
-
-	return 0;
 }
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -186,30 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
-		goto err0;
+		goto err_start_dev;
 	}
 
 	if (cpu_is_omap34xx()) {
 		r = regulator_enable(dpi.vdds_dsi_reg);
 		if (r)
-			goto err1;
+			goto err_reg_enable;
 	}
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
 
-	r = dpi_basic_init(dssdev);
+	r = dispc_runtime_get();
 	if (r)
-		goto err2;
+		goto err_get_dispc;
+
+	dpi_basic_init(dssdev);
 
 	if (dpi_use_dsi_pll(dssdev)) {
+		r = dsi_runtime_get(dpi.dsidev);
+		if (r)
+			goto err_get_dsi;
+
 		r = dsi_pll_init(dpi.dsidev, 0, 1);
 		if (r)
-			goto err2;
+			goto err_dsi_pll_init;
 	}
 
 	r = dpi_set_mode(dssdev);
 	if (r)
-		goto err3;
+		goto err_set_mode;
 
 	mdelay(2);
 
@@ -217,16 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 	return 0;
 
-err3:
+err_set_mode:
 	if (dpi_use_dsi_pll(dssdev))
 		dsi_pll_uninit(dpi.dsidev, true);
-err2:
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+err_dsi_pll_init:
+	if (dpi_use_dsi_pll(dssdev))
+		dsi_runtime_put(dpi.dsidev);
+err_get_dsi:
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
 	if (cpu_is_omap34xx())
 		regulator_disable(dpi.vdds_dsi_reg);
-err1:
+err_reg_enable:
 	omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
 	return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -238,9 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 	if (dpi_use_dsi_pll(dssdev)) {
 		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 		dsi_pll_uninit(dpi.dsidev, true);
+		dsi_runtime_put(dpi.dsidev);
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dispc_runtime_put();
+	dss_runtime_put();
 
 	if (cpu_is_omap34xx())
 		regulator_disable(dpi.vdds_dsi_reg);
@@ -252,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
 void dpi_set_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
+	int r;
+
 	DSSDBG("dpi_set_timings\n");
 	dssdev->panel.timings = *timings;
 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+		r = dss_runtime_get();
+		if (r)
+			return;
+
+		r = dispc_runtime_get();
+		if (r) {
+			dss_runtime_put();
+			return;
+		}
+
 		dpi_set_mode(dssdev);
 		dispc_go(dssdev->manager->id);
+
+		dispc_runtime_put();
+		dss_runtime_put();
 	}
 }
 EXPORT_SYMBOL(dpi_set_timings);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 0609885..89c4203 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -36,6 +36,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -267,8 +268,15 @@ struct dsi_isr_tables {
 struct dsi_data {
 	struct platform_device *pdev;
 	void __iomem	*base;
+
+	struct mutex	runtime_lock;
+	int		runtime_count;
+
 	int irq;
 
+	struct clk *dss_clk;
+	struct clk *sys_clk;
+
 	void (*dsi_mux_pads)(bool enable);
 
 	struct dsi_clock_info current_cinfo;
@@ -389,15 +397,6 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
 	return __raw_readl(dsi->base + idx.idx);
 }
 
-
-void dsi_save_context(void)
-{
-}
-
-void dsi_restore_context(void)
-{
-}
-
 void dsi_bus_lock(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -1048,13 +1047,69 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
 	return e;
 }
 
-/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
-static inline void enable_clocks(bool enable)
+int dsi_runtime_get(struct platform_device *dsidev)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	int r;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	mutex_lock(&dsi->runtime_lock);
+
+	if (dsi->runtime_count++ == 0) {
+		DSSDBG("dsi_runtime_get\n");
+
+		r = dss_runtime_get();
+		if (r)
+			goto err_get_dss;
+
+		r = dispc_runtime_get();
+		if (r)
+			goto err_get_dispc;
+
+		/* XXX dsi fclk can also come from DSI PLL */
+		clk_enable(dsi->dss_clk);
+
+		r = pm_runtime_get_sync(&dsi->pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err_runtime_get;
+	}
+
+	mutex_unlock(&dsi->runtime_lock);
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(dsi->dss_clk);
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	mutex_unlock(&dsi->runtime_lock);
+
+	return r;
+}
+
+void dsi_runtime_put(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	mutex_lock(&dsi->runtime_lock);
+
+	if (--dsi->runtime_count == 0) {
+		int r;
+
+		DSSDBG("dsi_runtime_put\n");
+
+		r = pm_runtime_put_sync(&dsi->pdev->dev);
+		WARN_ON(r);
+
+		clk_disable(dsi->dss_clk);
+
+		dispc_runtime_put();
+		dss_runtime_put();
+	}
+
+	mutex_unlock(&dsi->runtime_lock);
 }
 
 /* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1064,9 +1119,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
 	if (enable)
-		dss_clk_enable(DSS_CLK_SYSCK);
+		clk_enable(dsi->sys_clk);
 	else
-		dss_clk_disable(DSS_CLK_SYSCK);
+		clk_disable(dsi->sys_clk);
 
 	if (enable && dsi->pll_locked) {
 		if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1159,10 +1214,11 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 {
 	unsigned long r;
 	int dsi_module = dsi_get_dsidev_id(dsidev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
 	if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
 		/* DSI FCLK source is DSS_CLK_FCK */
-		r = dss_clk_get_rate(DSS_CLK_FCK);
+		r = clk_get_rate(dsi->dss_clk);
 	} else {
 		/* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
 		r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1271,7 +1327,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
 		return -EINVAL;
 
 	if (cinfo->use_sys_clk) {
-		cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
+		cinfo->clkin = clk_get_rate(dsi->sys_clk);
 		/* XXX it is unclear if highfreq should be used
 		 * with DSS_SYS_CLK source also */
 		cinfo->highfreq = 0;
@@ -1320,7 +1376,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
 	int match = 0;
 	unsigned long dss_sys_clk, max_dss_fck;
 
-	dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
+	dss_sys_clk = clk_get_rate(dsi->sys_clk);
 
 	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
@@ -1610,7 +1666,6 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 		dsi->vdds_dsi_reg = vdds_dsi;
 	}
 
-	enable_clocks(1);
 	dsi_enable_pll_clock(dsidev, 1);
 	/*
 	 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1662,7 +1717,6 @@ err1:
 	}
 err0:
 	dsi_disable_scp_clk(dsidev);
-	enable_clocks(0);
 	dsi_enable_pll_clock(dsidev, 0);
 	return r;
 }
@@ -1680,7 +1734,6 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
 	}
 
 	dsi_disable_scp_clk(dsidev);
-	enable_clocks(0);
 	dsi_enable_pll_clock(dsidev, 0);
 
 	DSSDBG("PLL uninit done\n");
@@ -1697,7 +1750,8 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 	dispc_clk_src = dss_get_dispc_clk_source();
 	dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
 
-	enable_clocks(1);
+	if (dsi_runtime_get(dsidev))
+		return;
 
 	seq_printf(s,	"- DSI%d PLL -\n", dsi_module + 1);
 
@@ -1740,7 +1794,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 
 	seq_printf(s,	"LP_CLK\t\t%lu\n", cinfo->lp_clk);
 
-	enable_clocks(0);
+	dsi_runtime_put(dsidev);
 }
 
 void dsi_dump_clocks(struct seq_file *s)
@@ -1882,7 +1936,8 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dsi_runtime_get(dsidev))
+		return;
 	dsi_enable_scp_clk(dsidev);
 
 	DUMPREG(DSI_REVISION);
@@ -1956,7 +2011,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
 	DUMPREG(DSI_PLL_CONFIGURATION2);
 
 	dsi_disable_scp_clk(dsidev);
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dsi_runtime_put(dsidev);
 #undef DUMPREG
 }
 
@@ -2472,28 +2527,6 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
 		dsi->dsi_mux_pads(false);
 }
 
-static int _dsi_wait_reset(struct platform_device *dsidev)
-{
-	int t = 0;
-
-	while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
-		if (++t > 5) {
-			DSSERR("soft reset failed\n");
-			return -ENODEV;
-		}
-		udelay(1);
-	}
-
-	return 0;
-}
-
-static int _dsi_reset(struct platform_device *dsidev)
-{
-	/* Soft reset */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
-	return _dsi_wait_reset(dsidev);
-}
-
 static void dsi_config_tx_fifo(struct platform_device *dsidev,
 		enum fifo_size size1, enum fifo_size size2,
 		enum fifo_size size3, enum fifo_size size4)
@@ -4211,22 +4244,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 	dsi_pll_uninit(dsidev, disconnect_lanes);
 }
 
-static int dsi_core_init(struct platform_device *dsidev)
-{
-	/* Autoidle */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
-
-	/* ENWAKEUP */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
-
-	/* SIDLEMODE smart-idle */
-	REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
-
-	_dsi_initialize_irq(dsidev);
-
-	return 0;
-}
-
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4242,37 +4259,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
-		goto err0;
+		goto err_start_dev;
 	}
 
-	enable_clocks(1);
-	dsi_enable_pll_clock(dsidev, 1);
-
-	r = _dsi_reset(dsidev);
+	r = dsi_runtime_get(dsidev);
 	if (r)
-		goto err1;
+		goto err_get_dsi;
 
-	dsi_core_init(dsidev);
+	dsi_enable_pll_clock(dsidev, 1);
+
+	_dsi_initialize_irq(dsidev);
 
 	r = dsi_display_init_dispc(dssdev);
 	if (r)
-		goto err1;
+		goto err_init_dispc;
 
 	r = dsi_display_init_dsi(dssdev);
 	if (r)
-		goto err2;
+		goto err_init_dsi;
 
 	mutex_unlock(&dsi->lock);
 
 	return 0;
 
-err2:
+err_init_dsi:
 	dsi_display_uninit_dispc(dssdev);
-err1:
-	enable_clocks(0);
+err_init_dispc:
 	dsi_enable_pll_clock(dsidev, 0);
+	dsi_runtime_put(dsidev);
+err_get_dsi:
 	omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
 	mutex_unlock(&dsi->lock);
 	DSSDBG("dsi_display_enable FAILED\n");
 	return r;
@@ -4295,7 +4312,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
 	dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
 
-	enable_clocks(0);
+	dsi_runtime_put(dsidev);
 	dsi_enable_pll_clock(dsidev, 0);
 
 	omap_dss_stop_device(dssdev);
@@ -4450,6 +4467,42 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
 	dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
+static int dsi_get_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct clk *clk;
+
+	clk = clk_get(&dsidev->dev, "dss_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get dss_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	dsi->dss_clk = clk;
+
+	clk = clk_get(&dsidev->dev, "sys_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get sys_clk\n");
+		clk_put(dsi->dss_clk);
+		dsi->dss_clk = NULL;
+		return PTR_ERR(clk);
+	}
+
+	dsi->sys_clk = clk;
+
+	return 0;
+}
+
+static void dsi_put_clocks(struct platform_device *dsidev)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	if (dsi->dss_clk)
+		clk_put(dsi->dss_clk);
+	if (dsi->sys_clk)
+		clk_put(dsi->sys_clk);
+}
+
 /* DSI1 HW IP initialisation */
 static int omap_dsi1hw_probe(struct platform_device *dsidev)
 {
@@ -4463,7 +4516,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
 	if (!dsi) {
 		r = -ENOMEM;
-		goto err0;
+		goto err_alloc;
 	}
 
 	dsi->pdev = dsidev;
@@ -4486,6 +4539,14 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 	mutex_init(&dsi->lock);
 	sema_init(&dsi->bus_lock, 1);
 
+	r = dsi_get_clocks(dsidev);
+	if (r)
+		goto err_get_clk;
+
+	mutex_init(&dsi->runtime_lock);
+
+	pm_runtime_enable(&dsidev->dev);
+
 	INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
 			dsi_framedone_timeout_work_callback);
 
@@ -4498,26 +4559,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 	if (!dsi_mem) {
 		DSSERR("can't get IORESOURCE_MEM DSI\n");
 		r = -EINVAL;
-		goto err1;
+		goto err_ioremap;
 	}
 	dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
 	if (!dsi->base) {
 		DSSERR("can't ioremap DSI\n");
 		r = -ENOMEM;
-		goto err1;
+		goto err_ioremap;
 	}
 	dsi->irq = platform_get_irq(dsi->pdev, 0);
 	if (dsi->irq < 0) {
 		DSSERR("platform_get_irq failed\n");
 		r = -ENODEV;
-		goto err2;
+		goto err_get_irq;
 	}
 
 	r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
 		dev_name(&dsidev->dev), dsi->pdev);
 	if (r < 0) {
 		DSSERR("request_irq failed\n");
-		goto err2;
+		goto err_get_irq;
 	}
 
 	/* DSI VCs initialization */
@@ -4529,7 +4590,9 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 
 	dsi_calc_clock_param_ranges(dsidev);
 
-	enable_clocks(1);
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		goto err_get_dsi;
 
 	rev = dsi_read_reg(dsidev, DSI_REVISION);
 	dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4537,14 +4600,19 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
 
 	dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
 
-	enable_clocks(0);
+	dsi_runtime_put(dsidev);
 
 	return 0;
-err2:
+
+err_get_dsi:
+	free_irq(dsi->irq, dsi->pdev);
+err_get_irq:
 	iounmap(dsi->base);
-err1:
+err_ioremap:
+	pm_runtime_disable(&dsidev->dev);
+err_get_clk:
 	kfree(dsi);
-err0:
+err_alloc:
 	return r;
 }
 
@@ -4554,6 +4622,10 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
 
 	WARN_ON(dsi->scp_clk_refcount > 0);
 
+	pm_runtime_disable(&dsidev->dev);
+
+	dsi_put_clocks(dsidev);
+
 	if (dsi->vdds_dsi_reg != NULL) {
 		if (dsi->vdds_dsi_enabled) {
 			regulator_disable(dsi->vdds_dsi_reg);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index a0e933a..c8d7357 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -60,15 +61,13 @@ struct dss_reg {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
+
 	int		ctx_loss_cnt;
+	struct mutex	runtime_lock;
+	int		runtime_count;
 
 	struct clk	*dpll4_m4_ck;
-	struct clk	*dss_ick;
-	struct clk	*dss_fck;
-	struct clk	*dss_sys_clk;
-	struct clk	*dss_tv_fck;
-	struct clk	*dss_video_fck;
-	unsigned	num_clks_enabled;
+	struct clk	*dss_clk;
 
 	unsigned long	cache_req_pck;
 	unsigned long	cache_prate;
@@ -88,13 +87,6 @@ static const char * const dss_generic_clk_source_names[] = {
 	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
 };
 
-static void dss_clk_enable_all_no_ctx(void);
-static void dss_clk_disable_all_no_ctx(void);
-static void dss_clk_enable_no_ctx(enum dss_clock clks);
-static void dss_clk_disable_no_ctx(enum dss_clock clks);
-
-static int _omap_dss_wait_reset(void);
-
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 {
 	__raw_writel(val, dss.base + idx.idx);
@@ -110,12 +102,10 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
 #define RR(reg) \
 	dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
 
-void dss_save_context(void)
+static void dss_save_context(void)
 {
-	if (cpu_is_omap24xx())
-		return;
+	DSSDBG("dss_save_context\n");
 
-	SR(SYSCONFIG);
 	SR(CONTROL);
 
 	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -125,12 +115,10 @@ void dss_save_context(void)
 	}
 }
 
-void dss_restore_context(void)
+static void dss_restore_context(void)
 {
-	if (_omap_dss_wait_reset())
-		DSSERR("DSS not coming out of reset after sleep\n");
+	DSSDBG("dss_restore_context\n");
 
-	RR(SYSCONFIG);
 	RR(CONTROL);
 
 	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -235,6 +223,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
 	return dss_generic_clk_source_names[clk_src];
 }
 
+
 void dss_dump_clocks(struct seq_file *s)
 {
 	unsigned long dpll4_ck_rate;
@@ -242,13 +231,14 @@ void dss_dump_clocks(struct seq_file *s)
 	const char *fclk_name, *fclk_real_name;
 	unsigned long fclk_rate;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dss_runtime_get())
+		return;
 
 	seq_printf(s, "- DSS -\n");
 
 	fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
 	fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
-	fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
+	fclk_rate = clk_get_rate(dss.dss_clk);
 
 	if (dss.dpll4_m4_ck) {
 		dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -274,14 +264,15 @@ void dss_dump_clocks(struct seq_file *s)
 				fclk_rate);
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dss_runtime_put();
 }
 
 void dss_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (dss_runtime_get())
+		return;
 
 	DUMPREG(DSS_REVISION);
 	DUMPREG(DSS_SYSCONFIG);
@@ -295,7 +286,7 @@ void dss_dump_regs(struct seq_file *s)
 		DUMPREG(DSS_SDI_STATUS);
 	}
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dss_runtime_put();
 #undef DUMPREG
 }
 
@@ -438,7 +429,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
 	} else {
 		if (cinfo->fck_div != 0)
 			return -EINVAL;
-		cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+		cinfo->fck = clk_get_rate(dss.dss_clk);
 	}
 
 	return 0;
@@ -468,7 +459,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
 
 int dss_get_clock_div(struct dss_clock_info *cinfo)
 {
-	cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+	cinfo->fck = clk_get_rate(dss.dss_clk);
 
 	if (dss.dpll4_m4_ck) {
 		unsigned long prate;
@@ -513,7 +504,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
 
 	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
-	fck = dss_clk_get_rate(DSS_CLK_FCK);
+	fck = clk_get_rate(dss.dss_clk);
 	if (req_pck == dss.cache_req_pck &&
 			((cpu_is_omap34xx() && prate == dss.cache_prate) ||
 			 dss.cache_dss_cinfo.fck == fck)) {
@@ -540,7 +531,7 @@ retry:
 	if (dss.dpll4_m4_ck == NULL) {
 		struct dispc_clock_info cur_dispc;
 		/* XXX can we change the clock on omap2? */
-		fck = dss_clk_get_rate(DSS_CLK_FCK);
+		fck = clk_get_rate(dss.dss_clk);
 		fck_div = 1;
 
 		dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -617,28 +608,6 @@ found:
 	return 0;
 }
 
-static int _omap_dss_wait_reset(void)
-{
-	int t = 0;
-
-	while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
-		if (++t > 1000) {
-			DSSERR("soft reset failed\n");
-			return -ENODEV;
-		}
-		udelay(1);
-	}
-
-	return 0;
-}
-
-static int _omap_dss_reset(void)
-{
-	/* Soft reset */
-	REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
-	return _omap_dss_wait_reset();
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
 	int l = 0;
@@ -719,131 +688,45 @@ static bool dss_need_ctx_restore(void)
 	return true;
 }
 
-static void save_all_ctx(void)
-{
-	DSSDBG("save context\n");
-
-	dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-
-	dss_save_context();
-	dispc_save_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_save_context();
-#endif
-
-	dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-}
-
-static void restore_all_ctx(void)
-{
-	DSSDBG("restore context\n");
-
-	dss_clk_enable_all_no_ctx();
-
-	dss_restore_context();
-	dispc_restore_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_restore_context();
-#endif
-
-	dss_clk_disable_all_no_ctx();
-}
-
-static int dss_get_clock(struct clk **clock, const char *clk_name)
-{
-	struct clk *clk;
-
-	clk = clk_get(&dss.pdev->dev, clk_name);
-
-	if (IS_ERR(clk)) {
-		DSSERR("can't get clock %s", clk_name);
-		return PTR_ERR(clk);
-	}
-
-	*clock = clk;
-
-	DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
-
-	return 0;
-}
-
 static int dss_get_clocks(void)
 {
+	struct clk *clk;
 	int r;
-	struct clk *dpll4_m4_ck;
-	struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-
-	dss.dss_ick = NULL;
-	dss.dss_fck = NULL;
-	dss.dss_sys_clk = NULL;
-	dss.dss_tv_fck = NULL;
-	dss.dss_video_fck = NULL;
-
-	r = dss_get_clock(&dss.dss_ick, "ick");
-	if (r)
-		goto err;
 
-	r = dss_get_clock(&dss.dss_fck, "fck");
-	if (r)
-		goto err;
-
-	if (!pdata->opt_clock_available) {
-		r = -ENODEV;
+	clk = clk_get(&dss.pdev->dev, "dss_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get clock dss_clk\n");
+		r = PTR_ERR(clk);
 		goto err;
 	}
 
-	if (pdata->opt_clock_available("sys_clk")) {
-		r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
-		if (r)
-			goto err;
-	}
-
-	if (pdata->opt_clock_available("tv_clk")) {
-		r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
-		if (r)
-			goto err;
-	}
-
-	if (pdata->opt_clock_available("video_clk")) {
-		r = dss_get_clock(&dss.dss_video_fck, "video_clk");
-		if (r)
-			goto err;
-	}
+	dss.dss_clk = clk;
 
 	if (cpu_is_omap34xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
+		clk = clk_get(NULL, "dpll4_m4_ck");
+		if (IS_ERR(clk)) {
 			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
+			r = PTR_ERR(clk);
 			goto err;
 		}
 	} else if (cpu_is_omap44xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
-			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
+		clk = clk_get(NULL, "dpll_per_m5x2_ck");
+		if (IS_ERR(clk)) {
+			DSSERR("Failed to get dpll_per_m5x2_ck\n");
+			r = PTR_ERR(clk);
 			goto err;
 		}
 	} else { /* omap24xx */
-		dpll4_m4_ck = NULL;
+		clk = NULL;
 	}
 
-	dss.dpll4_m4_ck = dpll4_m4_ck;
-
+	dss.dpll4_m4_ck = clk;
 
 	return 0;
 
 err:
-	if (dss.dss_ick)
-		clk_put(dss.dss_ick);
-	if (dss.dss_fck)
-		clk_put(dss.dss_fck);
-	if (dss.dss_sys_clk)
-		clk_put(dss.dss_sys_clk);
-	if (dss.dss_tv_fck)
-		clk_put(dss.dss_tv_fck);
-	if (dss.dss_video_fck)
-		clk_put(dss.dss_video_fck);
+	if (dss.dss_clk)
+		clk_put(dss.dss_clk);
 	if (dss.dpll4_m4_ck)
 		clk_put(dss.dpll4_m4_ck);
 
@@ -854,139 +737,57 @@ static void dss_put_clocks(void)
 {
 	if (dss.dpll4_m4_ck)
 		clk_put(dss.dpll4_m4_ck);
-	if (dss.dss_video_fck)
-		clk_put(dss.dss_video_fck);
-	if (dss.dss_tv_fck)
-		clk_put(dss.dss_tv_fck);
-	if (dss.dss_sys_clk)
-		clk_put(dss.dss_sys_clk);
-	clk_put(dss.dss_fck);
-	clk_put(dss.dss_ick);
+	clk_put(dss.dss_clk);
 }
 
-unsigned long dss_clk_get_rate(enum dss_clock clk)
+int dss_runtime_get(void)
 {
-	switch (clk) {
-	case DSS_CLK_ICK:
-		return clk_get_rate(dss.dss_ick);
-	case DSS_CLK_FCK:
-		return clk_get_rate(dss.dss_fck);
-	case DSS_CLK_SYSCK:
-		return clk_get_rate(dss.dss_sys_clk);
-	case DSS_CLK_TVFCK:
-		return clk_get_rate(dss.dss_tv_fck);
-	case DSS_CLK_VIDFCK:
-		return clk_get_rate(dss.dss_video_fck);
-	}
+	int r;
 
-	BUG();
-	return 0;
-}
+	mutex_lock(&dss.runtime_lock);
 
-static unsigned count_clk_bits(enum dss_clock clks)
-{
-	unsigned num_clks = 0;
-
-	if (clks & DSS_CLK_ICK)
-		++num_clks;
-	if (clks & DSS_CLK_FCK)
-		++num_clks;
-	if (clks & DSS_CLK_SYSCK)
-		++num_clks;
-	if (clks & DSS_CLK_TVFCK)
-		++num_clks;
-	if (clks & DSS_CLK_VIDFCK)
-		++num_clks;
-
-	return num_clks;
-}
+	if (dss.runtime_count++ == 0) {
+		DSSDBG("dss_runtime_get\n");
 
-static void dss_clk_enable_no_ctx(enum dss_clock clks)
-{
-	unsigned num_clks = count_clk_bits(clks);
-
-	if (clks & DSS_CLK_ICK)
-		clk_enable(dss.dss_ick);
-	if (clks & DSS_CLK_FCK)
-		clk_enable(dss.dss_fck);
-	if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-		clk_enable(dss.dss_sys_clk);
-	if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-		clk_enable(dss.dss_tv_fck);
-	if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-		clk_enable(dss.dss_video_fck);
-
-	dss.num_clks_enabled += num_clks;
-}
+		clk_enable(dss.dss_clk);
 
-void dss_clk_enable(enum dss_clock clks)
-{
-	bool check_ctx = dss.num_clks_enabled == 0;
+		r = pm_runtime_get_sync(&dss.pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err;
 
-	dss_clk_enable_no_ctx(clks);
+		if (dss_need_ctx_restore())
+			dss_restore_context();
+	}
 
-	/*
-	 * HACK: On omap4 the registers may not be accessible right after
-	 * enabling the clocks. At some point this will be handled by
-	 * pm_runtime, but for the time begin this should make things work.
-	 */
-	if (cpu_is_omap44xx() && check_ctx)
-		udelay(10);
+	mutex_unlock(&dss.runtime_lock);
 
-	if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
-		restore_all_ctx();
-}
+	return 0;
 
-static void dss_clk_disable_no_ctx(enum dss_clock clks)
-{
-	unsigned num_clks = count_clk_bits(clks);
-
-	if (clks & DSS_CLK_ICK)
-		clk_disable(dss.dss_ick);
-	if (clks & DSS_CLK_FCK)
-		clk_disable(dss.dss_fck);
-	if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-		clk_disable(dss.dss_sys_clk);
-	if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-		clk_disable(dss.dss_tv_fck);
-	if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-		clk_disable(dss.dss_video_fck);
-
-	dss.num_clks_enabled -= num_clks;
+err:
+	clk_disable(dss.dss_clk);
+	mutex_unlock(&dss.runtime_lock);
+	return r;
 }
 
-void dss_clk_disable(enum dss_clock clks)
+void dss_runtime_put(void)
 {
-	if (cpu_is_omap34xx()) {
-		unsigned num_clks = count_clk_bits(clks);
-
-		BUG_ON(dss.num_clks_enabled < num_clks);
+	mutex_lock(&dss.runtime_lock);
 
-		if (dss.num_clks_enabled == num_clks)
-			save_all_ctx();
-	}
+	if (--dss.runtime_count == 0) {
+		int r;
 
-	dss_clk_disable_no_ctx(clks);
-}
+		DSSDBG("dss_runtime_put\n");
 
-static void dss_clk_enable_all_no_ctx(void)
-{
-	enum dss_clock clks;
+		dss_save_context();
 
-	clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-	if (cpu_is_omap34xx())
-		clks |= DSS_CLK_VIDFCK;
-	dss_clk_enable_no_ctx(clks);
-}
+		r = pm_runtime_put_sync(&dss.pdev->dev);
+		WARN_ON(r);
 
-static void dss_clk_disable_all_no_ctx(void)
-{
-	enum dss_clock clks;
+		clk_disable(dss.dss_clk);
+	}
 
-	clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-	if (cpu_is_omap34xx())
-		clks |= DSS_CLK_VIDFCK;
-	dss_clk_disable_no_ctx(clks);
+	mutex_unlock(&dss.runtime_lock);
 }
 
 /* DEBUGFS */
@@ -1001,7 +802,6 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
-
 /* DSS HW IP initialisation */
 static int omap_dsshw_probe(struct platform_device *pdev)
 {
@@ -1028,19 +828,15 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	if (r)
 		goto err_clocks;
 
-	dss_clk_enable_all_no_ctx();
-
 	dss_init_ctx_loss_count();
 
-	/* disable LCD and DIGIT output. This seems to fix the synclost
-	 * problem that we get, if the bootloader starts the DSS and
-	 * the kernel resets it */
-	omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+	mutex_init(&dss.runtime_lock);
 
-	_omap_dss_reset();
+	pm_runtime_enable(&pdev->dev);
 
-	/* autoidle */
-	REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+	r = dss_runtime_get();
+	if (r)
+		goto err_runtime_get;
 
 	/* Select DPLL */
 	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
@@ -1068,19 +864,19 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 		goto err_sdi;
 	}
 
-	dss_save_context();
-
 	rev = dss_read_reg(DSS_REVISION);
 	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
 			FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	dss_clk_disable_all_no_ctx();
+	dss_runtime_put();
 
 	return 0;
 err_sdi:
 	dpi_exit();
 err_dpi:
-	dss_clk_disable_all_no_ctx();
+	dss_runtime_put();
+err_runtime_get:
+	pm_runtime_disable(&pdev->dev);
 	dss_put_clocks();
 err_clocks:
 	iounmap(dss.base);
@@ -1095,13 +891,7 @@ static int omap_dsshw_remove(struct platform_device *pdev)
 
 	iounmap(dss.base);
 
-	/*
-	 * As part of hwmod changes, DSS is not the only controller of dss
-	 * clocks; hwmod framework itself will also enable clocks during hwmod
-	 * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
-	 * need to disable clocks if their usecounts > 1.
-	 */
-	WARN_ON(dss.num_clks_enabled > 0);
+	pm_runtime_disable(&pdev->dev);
 
 	dss_put_clocks();
 
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index aeb611d..ce17a61 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -109,14 +109,6 @@ enum omap_parallel_interface_mode {
 	OMAP_DSS_PARALLELMODE_DSI,
 };
 
-enum dss_clock {
-	DSS_CLK_ICK	= 1 << 0,	/* DSS_L3_ICLK and DSS_L4_ICLK */
-	DSS_CLK_FCK	= 1 << 1,	/* DSS1_ALWON_FCLK */
-	DSS_CLK_SYSCK	= 1 << 2,	/* DSS2_ALWON_FCLK */
-	DSS_CLK_TVFCK	= 1 << 3,	/* DSS_TV_FCLK */
-	DSS_CLK_VIDFCK	= 1 << 4,	/* DSS_96M_FCLK*/
-};
-
 enum dss_hdmi_venc_clk_source_select {
 	DSS_VENC_TV_CLK = 0,
 	DSS_HDMI_M_PCLK = 1,
@@ -220,12 +212,10 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
 int dss_init_platform_driver(void);
 void dss_uninit_platform_driver(void);
 
+int dss_runtime_get(void);
+void dss_runtime_put(void);
+
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
-void dss_save_context(void);
-void dss_restore_context(void);
-void dss_clk_enable(enum dss_clock clks);
-void dss_clk_disable(enum dss_clock clks);
-unsigned long dss_clk_get_rate(enum dss_clock clk);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
@@ -282,15 +272,15 @@ struct file_operations;
 int dsi_init_platform_driver(void);
 void dsi_uninit_platform_driver(void);
 
+int dsi_runtime_get(struct platform_device *dsidev);
+void dsi_runtime_put(struct platform_device *dsidev);
+
 void dsi_dump_clocks(struct seq_file *s);
 void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
 		const struct file_operations *debug_fops);
 void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
 		const struct file_operations *debug_fops);
 
-void dsi_save_context(void);
-void dsi_restore_context(void);
-
 int dsi_init_display(struct omap_dss_device *display);
 void dsi_irq_handler(void);
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -316,6 +306,13 @@ static inline int dsi_init_platform_driver(void)
 static inline void dsi_uninit_platform_driver(void)
 {
 }
+static inline int dsi_runtime_get(struct platform_device *dsidev)
+{
+	return 0;
+}
+static inline void dsi_runtime_put(struct platform_device *dsidev)
+{
+}
 static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
 {
 	WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -383,8 +380,8 @@ void dispc_dump_regs(struct seq_file *s);
 void dispc_irq_handler(void);
 void dispc_fake_vsync_irq(void);
 
-void dispc_save_context(void);
-void dispc_restore_context(void);
+int dispc_runtime_get(void);
+void dispc_runtime_put(void);
 
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b630c98..5e5b98b 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -30,6 +30,8 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
 #include <video/omapdss.h>
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
 	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -52,6 +54,9 @@ static struct {
 	u8 edid_set;
 	bool custom_set;
 	struct hdmi_config cfg;
+
+	struct clk *sys_clk;
+	struct clk *hdmi_clk;
 } hdmi;
 
 /*
@@ -163,6 +168,56 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
 	return val;
 }
 
+static int hdmi_runtime_get(void)
+{
+	int r;
+
+	DSSDBG("hdmi_runtime_get\n");
+
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
+
+	clk_enable(hdmi.sys_clk);
+	clk_enable(hdmi.hdmi_clk);
+
+	r = pm_runtime_get_sync(&hdmi.pdev->dev);
+	WARN_ON(r);
+	if (r < 0)
+		goto err_runtime_get;
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(hdmi.sys_clk);
+	clk_disable(hdmi.hdmi_clk);
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	return r;
+}
+
+static void hdmi_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("hdmi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&hdmi.pdev->dev);
+	WARN_ON(r);
+
+	clk_disable(hdmi.sys_clk);
+	clk_disable(hdmi.hdmi_clk);
+
+	dispc_runtime_put();
+	dss_runtime_put();
+}
+
 int hdmi_init_display(struct omap_dss_device *dssdev)
 {
 	DSSDBG("init_display\n");
@@ -312,30 +367,11 @@ static int hdmi_phy_init(void)
 	return 0;
 }
 
-static int hdmi_wait_softreset(void)
-{
-	/* reset W1 */
-	REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
-
-	/* wait till SOFTRESET == 0 */
-	if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
-		DSSERR("sysconfig reset failed\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
 static int hdmi_pll_program(struct hdmi_pll_info *fmt)
 {
 	u16 r = 0;
 	enum hdmi_clk_refsel refsel;
 
-	/* wait for wrapper reset */
-	r = hdmi_wait_softreset();
-	if (r)
-		return r;
-
 	r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
 	if (r)
 		return r;
@@ -1065,7 +1101,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	unsigned long clkin, refclk;
 	u32 mf;
 
-	clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
+	clkin = clk_get_rate(hdmi.sys_clk) / 10000;
 	/*
 	 * Input clock is predivided by N + 1
 	 * out put of which is reference clk
@@ -1099,16 +1135,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 
-static void hdmi_enable_clocks(int enable)
-{
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
-				DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
-				DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-}
-
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
 	int r, code = 0;
@@ -1116,7 +1142,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	struct omap_video_timings *p;
 	unsigned long phy;
 
-	hdmi_enable_clocks(1);
+	r = hdmi_runtime_get();
+	if (r)
+		return r;
 
 	dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
 
@@ -1181,7 +1209,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
 	return 0;
 err:
-	hdmi_enable_clocks(0);
+	hdmi_runtime_put();
 	return -EIO;
 }
 
@@ -1192,7 +1220,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi_wp_video_start(0);
 	hdmi_phy_off();
 	hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
-	hdmi_enable_clocks(0);
+	hdmi_runtime_put();
 
 	hdmi.edid_set = 0;
 }
@@ -1687,14 +1715,43 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
 };
 #endif
 
+static int hdmi_get_clocks(struct platform_device *pdev)
+{
+	struct clk *clk;
+
+	clk = clk_get(&pdev->dev, "sys_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get sys_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	hdmi.sys_clk = clk;
+
+	clk = clk_get(&pdev->dev, "hdmi_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get hdmi_clk\n");
+		clk_put(hdmi.sys_clk);
+		return PTR_ERR(clk);
+	}
+
+	hdmi.hdmi_clk = clk;
+
+	return 0;
+}
+
+static void hdmi_put_clocks(void)
+{
+	if (hdmi.sys_clk)
+		clk_put(hdmi.sys_clk);
+	if (hdmi.hdmi_clk)
+		clk_put(hdmi.hdmi_clk);
+}
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
 	struct resource *hdmi_mem;
-#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
-	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-	int ret;
-#endif
+	int r;
 
 	hdmi.pdata = pdev->dev.platform_data;
 	hdmi.pdev = pdev;
@@ -1714,17 +1771,25 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	r = hdmi_get_clocks(pdev);
+	if (r) {
+		iounmap(hdmi.base_wp);
+		return r;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
 	hdmi_panel_init();
 
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
 	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
 
 	/* Register ASoC codec DAI */
-	ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+	r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
 					&hdmi_codec_dai_drv, 1);
-	if (ret) {
+	if (r) {
 		DSSERR("can't register ASoC HDMI audio codec\n");
-		return ret;
+		return r;
 	}
 #endif
 	return 0;
@@ -1739,6 +1804,10 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
 	snd_soc_unregister_codec(&pdev->dev);
 #endif
 
+	pm_runtime_disable(&pdev->dev);
+
+	hdmi_put_clocks();
+
 	iounmap(hdmi.base_wp);
 
 	return 0;
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 9aeea50..a148a80 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -1236,6 +1236,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
 	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
 	spin_lock_irqsave(&dss_cache.lock, flags);
 
 	/* Configure overlays */
@@ -1409,7 +1413,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 	}
 
 	r = 0;
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 	if (!dss_cache.irq_enabled) {
 		u32 mask;
 
@@ -1422,10 +1425,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 		dss_cache.irq_enabled = true;
 	}
 	configure_dispc();
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
 	spin_unlock_irqrestore(&dss_cache.lock, flags);
 
+	dispc_runtime_put();
+
 	return r;
 }
 
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index cfbfc57..c84380c 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
 
 	old_mgr = ovl->manager;
 
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
 	/* detach old manager */
 	if (old_mgr) {
 		r = ovl->unset_manager(ovl);
 		if (r) {
 			DSSERR("detach failed\n");
-			return r;
+			goto err;
 		}
 
 		r = old_mgr->apply(old_mgr);
 		if (r)
-			return r;
+			goto err;
 	}
 
 	if (mgr) {
 		r = ovl->set_manager(ovl, mgr);
 		if (r) {
 			DSSERR("Failed to attach overlay\n");
-			return r;
+			goto err;
 		}
 
 		r = mgr->apply(mgr);
 		if (r)
-			return r;
+			goto err;
 	}
 
+	dispc_runtime_put();
+
 	return size;
+
+err:
+	dispc_runtime_put();
+	return r;
 }
 
 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -507,7 +517,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 
 	ovl->manager = mgr;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 	/* XXX: When there is an overlay on a DSI manual update display, and
 	 * the overlay is first disabled, then moved to tv, and enabled, we
 	 * seem to get SYNC_LOST_DIGIT error.
@@ -521,7 +530,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 	 * the overlay, but before moving the overlay to TV.
 	 */
 	dispc_set_channel_out(ovl->id, mgr->id);
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
 	return 0;
 }
@@ -722,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
 	}
 
 	if (mgr) {
+		dispc_runtime_get();
+
 		for (i = 0; i < dss_feat_get_num_ovls(); i++) {
 			struct omap_overlay *ovl;
 			ovl = omap_dss_get_overlay(i);
@@ -731,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
 				omap_dss_set_manager(ovl, mgr);
 			}
 		}
+
+		dispc_runtime_put();
 	}
 }
 
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index a873104..3e2f5cd 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -34,6 +34,7 @@
 #include <linux/seq_file.h>
 #include <linux/semaphore.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
@@ -121,12 +122,46 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
 	return __raw_readl(rfbi.base + idx.idx);
 }
 
-static void rfbi_enable_clocks(bool enable)
+static int rfbi_runtime_get(void)
 {
-	if (enable)
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-	else
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	int r;
+
+	DSSDBG("rfbi_runtime_get\n");
+
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
+
+	r = pm_runtime_get_sync(&rfbi.pdev->dev);
+	WARN_ON(r);
+	if (r < 0)
+		goto err_runtime_get;
+
+	return 0;
+
+err_runtime_get:
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	return r;
+}
+
+static void rfbi_runtime_put(void)
+{
+	int r;
+
+	DSSDBG("rfbi_runtime_put\n");
+
+	r = pm_runtime_put_sync(&rfbi.pdev->dev);
+	WARN_ON(r);
+
+	dispc_runtime_put();
+	dss_runtime_put();
 }
 
 void rfbi_bus_lock(void)
@@ -806,7 +841,8 @@ void rfbi_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	if (rfbi_runtime_get())
+		return;
 
 	DUMPREG(RFBI_REVISION);
 	DUMPREG(RFBI_SYSCONFIG);
@@ -837,7 +873,7 @@ void rfbi_dump_regs(struct seq_file *s)
 	DUMPREG(RFBI_VSYNC_WIDTH);
 	DUMPREG(RFBI_HSYNC_WIDTH);
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	rfbi_runtime_put();
 #undef DUMPREG
 }
 
@@ -845,7 +881,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r;
 
-	rfbi_enable_clocks(1);
+	r = rfbi_runtime_get();
+	if (r)
+		return r;
 
 	r = omap_dss_start_device(dssdev);
 	if (r) {
@@ -880,6 +918,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 err1:
 	omap_dss_stop_device(dssdev);
 err0:
+	rfbi_runtime_put();
 	return r;
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -890,7 +929,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
 			DISPC_IRQ_FRAMEDONE);
 	omap_dss_stop_device(dssdev);
 
-	rfbi_enable_clocks(0);
+	rfbi_runtime_put();
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 
@@ -905,8 +944,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
 static int omap_rfbihw_probe(struct platform_device *pdev)
 {
 	u32 rev;
-	u32 l;
 	struct resource *rfbi_mem;
+	struct clk *clk;
+	int r;
 
 	rfbi.pdev = pdev;
 
@@ -915,36 +955,55 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
 	rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
 	if (!rfbi_mem) {
 		DSSERR("can't get IORESOURCE_MEM RFBI\n");
-		return -EINVAL;
+		r = -EINVAL;
+		goto err_ioremap;
 	}
 	rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
 	if (!rfbi.base) {
 		DSSERR("can't ioremap RFBI\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto err_ioremap;
 	}
 
-	rfbi_enable_clocks(1);
+	pm_runtime_enable(&pdev->dev);
+
+	r = rfbi_runtime_get();
+	if (r)
+		goto err_get_rfbi;
 
 	msleep(10);
 
-	rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+	clk = clk_get(&pdev->dev, "rfbi_iclk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get rfbi_iclk\n");
+		r = PTR_ERR(clk);
+		goto err_get_ick;
+	}
+
+	rfbi.l4_khz = clk_get_rate(clk) / 1000;
 
-	/* Enable autoidle and smart-idle */
-	l = rfbi_read_reg(RFBI_SYSCONFIG);
-	l |= (1 << 0) | (2 << 3);
-	rfbi_write_reg(RFBI_SYSCONFIG, l);
+	clk_put(clk);
 
 	rev = rfbi_read_reg(RFBI_REVISION);
 	dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	rfbi_enable_clocks(0);
+	rfbi_runtime_put();
 
 	return 0;
+
+err_get_ick:
+	rfbi_runtime_put();
+err_get_rfbi:
+	pm_runtime_disable(&pdev->dev);
+	iounmap(rfbi.base);
+err_ioremap:
+	return r;
 }
 
 static int omap_rfbihw_remove(struct platform_device *pdev)
 {
+	pm_runtime_disable(&pdev->dev);
 	iounmap(rfbi.base);
 	return 0;
 }
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 0bd4b03..3a688c8 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -20,13 +20,11 @@
 #define DSS_SUBSYS_NAME "SDI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 #include "dss.h"
 
 static struct {
@@ -60,14 +58,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	r = omap_dss_start_device(dssdev);
 	if (r) {
 		DSSERR("failed to start device\n");
-		goto err0;
+		goto err_start_dev;
 	}
 
 	r = regulator_enable(sdi.vdds_sdi_reg);
 	if (r)
-		goto err1;
+		goto err_reg_enable;
 
-	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+	r = dss_runtime_get();
+	if (r)
+		goto err_get_dss;
+
+	r = dispc_runtime_get();
+	if (r)
+		goto err_get_dispc;
 
 	sdi_basic_init(dssdev);
 
@@ -80,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 	r = dss_calc_clock_div(1, t->pixel_clock * 1000,
 			&dss_cinfo, &dispc_cinfo);
 	if (r)
-		goto err2;
+		goto err_calc_clock_div;
 
 	fck = dss_cinfo.fck;
 	lck_div = dispc_cinfo.lck_div;
@@ -101,27 +105,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
 	r = dss_set_clock_div(&dss_cinfo);
 	if (r)
-		goto err2;
+		goto err_set_dss_clock_div;
 
 	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
 	if (r)
-		goto err2;
+		goto err_set_dispc_clock_div;
 
 	dss_sdi_init(dssdev->phy.sdi.datapairs);
 	r = dss_sdi_enable();
 	if (r)
-		goto err1;
+		goto err_sdi_enable;
 	mdelay(2);
 
 	dssdev->manager->enable(dssdev->manager);
 
 	return 0;
-err2:
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+
+err_sdi_enable:
+err_set_dispc_clock_div:
+err_set_dss_clock_div:
+err_calc_clock_div:
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
 	regulator_disable(sdi.vdds_sdi_reg);
-err1:
+err_reg_enable:
 	omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
 	return r;
 }
 EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -132,7 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 
 	dss_sdi_disable();
 
-	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+	dispc_runtime_put();
+	dss_runtime_put();
 
 	regulator_disable(sdi.vdds_sdi_reg);
 
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 15b4431..4491983 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -33,6 +33,7 @@
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/cpu.h>
@@ -293,6 +294,12 @@ static struct {
 	struct mutex venc_lock;
 	u32 wss_data;
 	struct regulator *vdda_dac_reg;
+
+	struct mutex	runtime_lock;
+	int		runtime_count;
+
+	struct clk	*tv_clk;
+	struct clk	*tv_dac_clk;
 } venc;
 
 static inline void venc_write_reg(int idx, u32 val)
@@ -381,17 +388,71 @@ static void venc_reset(void)
 #endif
 }
 
-static void venc_enable_clocks(int enable)
+static int venc_runtime_get(void)
 {
-	if (enable) {
-		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
-		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
-			dss_clk_enable(DSS_CLK_VIDFCK);
-	} else {
-		dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK);
-		if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK))
-			dss_clk_disable(DSS_CLK_VIDFCK);
+	int r;
+
+	mutex_lock(&venc.runtime_lock);
+
+	if (venc.runtime_count++ == 0) {
+		DSSDBG("venc_runtime_get\n");
+
+		r = dss_runtime_get();
+		if (r)
+			goto err_get_dss;
+
+		r = dispc_runtime_get();
+		if (r)
+			goto err_get_dispc;
+
+		clk_enable(venc.tv_clk);
+		if (venc.tv_dac_clk)
+			clk_enable(venc.tv_dac_clk);
+
+		r = pm_runtime_get_sync(&venc.pdev->dev);
+		WARN_ON(r);
+		if (r < 0)
+			goto err_runtime_get;
 	}
+
+	mutex_unlock(&venc.runtime_lock);
+
+	return 0;
+
+err_runtime_get:
+	clk_disable(venc.tv_clk);
+	if (venc.tv_dac_clk)
+		clk_disable(venc.tv_dac_clk);
+	dispc_runtime_put();
+err_get_dispc:
+	dss_runtime_put();
+err_get_dss:
+	mutex_unlock(&venc.runtime_lock);
+
+	return r;
+}
+
+static void venc_runtime_put(void)
+{
+	mutex_lock(&venc.runtime_lock);
+
+	if (--venc.runtime_count == 0) {
+		int r;
+
+		DSSDBG("venc_runtime_put\n");
+
+		r = pm_runtime_put_sync(&venc.pdev->dev);
+		WARN_ON(r);
+
+		clk_disable(venc.tv_clk);
+		if (venc.tv_dac_clk)
+			clk_disable(venc.tv_dac_clk);
+
+		dispc_runtime_put();
+		dss_runtime_put();
+	}
+
+	mutex_unlock(&venc.runtime_lock);
 }
 
 static const struct venc_config *venc_timings_to_config(
@@ -410,8 +471,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
 {
 	u32 l;
 
-	venc_enable_clocks(1);
-
 	venc_reset();
 	venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
 
@@ -452,8 +511,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
 		dssdev->platform_disable(dssdev);
 
 	regulator_disable(venc.vdda_dac_reg);
-
-	venc_enable_clocks(0);
 }
 
 
@@ -491,6 +548,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
 		goto err1;
 	}
 
+	r = venc_runtime_get();
+	if (r)
+		goto err1;
+
 	venc_power_on(dssdev);
 
 	venc.wss_data = 0;
@@ -524,6 +585,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 
 	venc_power_off(dssdev);
 
+	venc_runtime_put();
+
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 
 	omap_dss_stop_device(dssdev);
@@ -602,6 +665,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
 static int venc_set_wss(struct omap_dss_device *dssdev,	u32 wss)
 {
 	const struct venc_config *config;
+	int r;
 
 	DSSDBG("venc_set_wss\n");
 
@@ -612,16 +676,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev,	u32 wss)
 	/* Invert due to VENC_L21_WC_CTL:INV=1 */
 	venc.wss_data = (wss ^ 0xfffff) << 8;
 
-	venc_enable_clocks(1);
+	r = venc_runtime_get();
+	if (r)
+		goto err;
 
 	venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
 			venc.wss_data);
 
-	venc_enable_clocks(0);
+	venc_runtime_put();
 
+err:
 	mutex_unlock(&venc.venc_lock);
 
-	return 0;
+	return r;
 }
 
 static struct omap_dss_driver venc_driver = {
@@ -677,7 +744,8 @@ void venc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 
-	venc_enable_clocks(1);
+	if (venc_runtime_get())
+		return;
 
 	DUMPREG(VENC_F_CONTROL);
 	DUMPREG(VENC_VIDOUT_CTRL);
@@ -721,16 +789,53 @@ void venc_dump_regs(struct seq_file *s)
 	DUMPREG(VENC_OUTPUT_CONTROL);
 	DUMPREG(VENC_OUTPUT_TEST);
 
-	venc_enable_clocks(0);
+	venc_runtime_put();
 
 #undef DUMPREG
 }
 
+static int venc_get_clocks(struct platform_device *pdev)
+{
+	struct clk *clk;
+
+	clk = clk_get(&pdev->dev, "tv_clk");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get tv_clk\n");
+		return PTR_ERR(clk);
+	}
+
+	venc.tv_clk = clk;
+
+	if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
+		clk = clk_get(&pdev->dev, "tv_dac_clk");
+		if (IS_ERR(clk)) {
+			DSSERR("can't get tv_dac_clk\n");
+			clk_put(venc.tv_clk);
+			return PTR_ERR(clk);
+		}
+	} else {
+		clk = NULL;
+	}
+
+	venc.tv_dac_clk = clk;
+
+	return 0;
+}
+
+static void venc_put_clocks(void)
+{
+	if (venc.tv_clk)
+		clk_put(venc.tv_clk);
+	if (venc.tv_dac_clk)
+		clk_put(venc.tv_dac_clk);
+}
+
 /* VENC HW IP initialisation */
 static int omap_venchw_probe(struct platform_device *pdev)
 {
 	u8 rev_id;
 	struct resource *venc_mem;
+	int r;
 
 	venc.pdev = pdev;
 
@@ -741,22 +846,41 @@ static int omap_venchw_probe(struct platform_device *pdev)
 	venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
 	if (!venc_mem) {
 		DSSERR("can't get IORESOURCE_MEM VENC\n");
-		return -EINVAL;
+		r = -EINVAL;
+		goto err_ioremap;
 	}
 	venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
 	if (!venc.base) {
 		DSSERR("can't ioremap VENC\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto err_ioremap;
 	}
 
-	venc_enable_clocks(1);
+	r = venc_get_clocks(pdev);
+	if (r)
+		goto err_get_clk;
+
+	mutex_init(&venc.runtime_lock);
+	pm_runtime_enable(&pdev->dev);
+
+	r = venc_runtime_get();
+	if (r)
+		goto err_get_venc;
 
 	rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
 	dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
 
-	venc_enable_clocks(0);
+	venc_runtime_put();
 
 	return omap_dss_register_driver(&venc_driver);
+
+err_get_venc:
+	pm_runtime_disable(&pdev->dev);
+	venc_put_clocks();
+err_get_clk:
+	iounmap(venc.base);
+err_ioremap:
+	return r;
 }
 
 static int omap_venchw_remove(struct platform_device *pdev)
@@ -767,6 +891,9 @@ static int omap_venchw_remove(struct platform_device *pdev)
 	}
 	omap_dss_unregister_driver(&venc_driver);
 
+	pm_runtime_disable(&pdev->dev);
+	venc_put_clocks();
+
 	iounmap(venc.base);
 	return 0;
 }
-- 
1.7.4.1


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

* [PATCH 20/27] OMAP4: HWMOD: Remove unneeded DSS opt clocks
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Some of the optional clocks for dss_core are not needed. Remove them.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 4f6ae94..b374cd0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1164,10 +1164,7 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-	{ .role = "sys_clk", .clk = "dss_sys_clk" },
-	{ .role = "tv_clk", .clk = "dss_tv_clk" },
 	{ .role = "dss_clk", .clk = "dss_dss_clk" },
-	{ .role = "video_clk", .clk = "dss_48mhz_clk" },
 };
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
-- 
1.7.4.1


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

* [PATCH 20/27] OMAP4: HWMOD: Remove unneeded DSS opt clocks
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

Some of the optional clocks for dss_core are not needed. Remove them.

Cc: Benoit Cousson <b-cousson@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 4f6ae94..b374cd0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1164,10 +1164,7 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-	{ .role = "sys_clk", .clk = "dss_sys_clk" },
-	{ .role = "tv_clk", .clk = "dss_tv_clk" },
 	{ .role = "dss_clk", .clk = "dss_dss_clk" },
-	{ .role = "video_clk", .clk = "dss_48mhz_clk" },
 };
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
-- 
1.7.4.1


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

* [PATCH 21/27] OMAP: DSS2: Remove unused opt_clock_available
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

opt_clock_available() is no longer needed, so remove it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |   12 ------------
 include/video/omapdss.h       |    2 --
 2 files changed, 0 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index c7e19c4..af43620 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -46,17 +46,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
 /* oh_core is used for getting opt-clocks */
 static struct omap_hwmod	*oh_core;
 
-static bool opt_clock_available(const char *clk_role)
-{
-	int i;
-
-	for (i = 0; i < oh_core->opt_clks_cnt; i++) {
-		if (!strcmp(oh_core->opt_clks[i].role, clk_role))
-			return true;
-	}
-	return false;
-}
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -120,7 +109,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	pdata.board_data = board_data;
 	pdata.board_data->get_context_loss_count  		omap_pm_get_dev_context_loss_count;
-	pdata.opt_clock_available = opt_clock_available;
 
 	for (i = 0; i < oh_count; i++) {
 		oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 4f914a5..06914b1 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -264,8 +264,6 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data)
 struct omap_display_platform_data {
 	struct omap_dss_board_info *board_data;
 	/* TODO: Additional members to be added when PM is considered */
-
-	bool (*opt_clock_available)(const char *clk_role);
 };
 
 struct omap_video_timings {
-- 
1.7.4.1


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

* [PATCH 21/27] OMAP: DSS2: Remove unused opt_clock_available
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

opt_clock_available() is no longer needed, so remove it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |   12 ------------
 include/video/omapdss.h       |    2 --
 2 files changed, 0 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index c7e19c4..af43620 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -46,17 +46,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
 /* oh_core is used for getting opt-clocks */
 static struct omap_hwmod	*oh_core;
 
-static bool opt_clock_available(const char *clk_role)
-{
-	int i;
-
-	for (i = 0; i < oh_core->opt_clks_cnt; i++) {
-		if (!strcmp(oh_core->opt_clks[i].role, clk_role))
-			return true;
-	}
-	return false;
-}
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -120,7 +109,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	pdata.board_data = board_data;
 	pdata.board_data->get_context_loss_count =
 		omap_pm_get_dev_context_loss_count;
-	pdata.opt_clock_available = opt_clock_available;
 
 	for (i = 0; i < oh_count; i++) {
 		oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 4f914a5..06914b1 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -264,8 +264,6 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data)
 struct omap_display_platform_data {
 	struct omap_dss_board_info *board_data;
 	/* TODO: Additional members to be added when PM is considered */
-
-	bool (*opt_clock_available)(const char *clk_role);
 };
 
 struct omap_video_timings {
-- 
1.7.4.1


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

* [PATCH 22/27] OMAP: DSS2: DISPC: remove finegrained clk enables/disables
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

dispc.c enables and disables clocks in almost every function to make
sure the clocks are enabled when the function is called. This is rather
unoptimal way to handle the problem.

With pm_runtime other components have to call dispc_runtime_get() to
enable dispc clocks before calling any other dispc functions. Thus the
finegrained clk enables/disables can be removed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |  165 +++++----------------------------------
 1 files changed, 19 insertions(+), 146 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 57400f6..b13a656 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -645,8 +645,6 @@ void dispc_go(enum omap_channel channel)
 	int bit;
 	bool enable_bit, go_bit;
 
-	dispc_runtime_get();
-
 	if (channel = OMAP_DSS_CHANNEL_LCD ||
 			channel = OMAP_DSS_CHANNEL_LCD2)
 		bit = 0; /* LCDENABLE */
@@ -660,7 +658,7 @@ void dispc_go(enum omap_channel channel)
 		enable_bit = REG_GET(DISPC_CONTROL, bit, bit) = 1;
 
 	if (!enable_bit)
-		goto end;
+		return;
 
 	if (channel = OMAP_DSS_CHANNEL_LCD ||
 			channel = OMAP_DSS_CHANNEL_LCD2)
@@ -675,7 +673,7 @@ void dispc_go(enum omap_channel channel)
 
 	if (go_bit) {
 		DSSERR("GO bit not down for channel %d\n", channel);
-		goto end;
+		return;
 	}
 
 	DSSDBG("GO %s\n", channel = OMAP_DSS_CHANNEL_LCD ? "LCD" :
@@ -685,8 +683,6 @@ void dispc_go(enum omap_channel channel)
 		REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
-end:
-	dispc_runtime_put();
 }
 
 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -1060,7 +1056,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
 }
 
-static void _dispc_set_channel_out(enum omap_plane plane,
+void dispc_set_channel_out(enum omap_plane plane,
 		enum omap_channel channel)
 {
 	int shift;
@@ -1113,8 +1109,6 @@ void dispc_set_burst_size(enum omap_plane plane,
 	int shift;
 	u32 val;
 
-	dispc_runtime_get();
-
 	switch (plane) {
 	case OMAP_DSS_GFX:
 		shift = 6;
@@ -1131,8 +1125,6 @@ void dispc_set_burst_size(enum omap_plane plane,
 	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
 	val = FLD_MOD(val, burst_size, shift+1, shift);
 	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
-
-	dispc_runtime_put();
 }
 
 void dispc_enable_gamma_table(bool enable)
@@ -1169,9 +1161,7 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
 	else
 		bit = 10;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
-	dispc_runtime_put();
 }
 
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1179,9 +1169,7 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-	dispc_runtime_put();
 }
 
 void dispc_set_digit_size(u16 width, u16 height)
@@ -1189,9 +1177,7 @@ void dispc_set_digit_size(u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
-	dispc_runtime_put();
 }
 
 static void dispc_read_plane_fifo_sizes(void)
@@ -1200,8 +1186,6 @@ static void dispc_read_plane_fifo_sizes(void)
 	int plane;
 	u8 start, end;
 
-	dispc_runtime_get();
-
 	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
 	for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
@@ -1209,8 +1193,6 @@ static void dispc_read_plane_fifo_sizes(void)
 			start, end);
 		dispc.fifo_size[plane] = size;
 	}
-
-	dispc_runtime_put();
 }
 
 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1225,8 +1207,6 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
 	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-	dispc_runtime_get();
-
 	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
 			plane,
 			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
@@ -1238,18 +1218,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
 			FLD_VAL(high, hi_start, hi_end) |
 			FLD_VAL(low, lo_start, lo_end));
-
-	dispc_runtime_put();
 }
 
 void dispc_enable_fifomerge(bool enable)
 {
-	dispc_runtime_get();
-
 	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
 	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
-
-	dispc_runtime_put();
 }
 
 static void _dispc_set_fir(enum omap_plane plane,
@@ -1869,14 +1843,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
 	return dispc_pclk_rate(channel) * vf * hf;
 }
 
-void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
-{
-	dispc_runtime_get();
-	_dispc_set_channel_out(plane, channel_out);
-	dispc_runtime_put();
-}
-
-static int _dispc_setup_plane(enum omap_plane plane,
+int dispc_setup_plane(enum omap_plane plane,
 		u32 paddr, u16 screen_width,
 		u16 pos_x, u16 pos_y,
 		u16 width, u16 height,
@@ -1884,7 +1851,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
 		enum omap_color_mode color_mode,
 		bool ilace,
 		enum omap_dss_rotation_type rotation_type,
-		u8 rotation, int mirror,
+		u8 rotation, bool mirror,
 		u8 global_alpha, u8 pre_mult_alpha,
 		enum omap_channel channel, u32 puv_addr)
 {
@@ -1898,6 +1865,14 @@ static int _dispc_setup_plane(enum omap_plane plane,
 	u16 frame_height = height;
 	unsigned int field_offset = 0;
 
+	DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
+	       "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
+	       plane, paddr, screen_width, pos_x, pos_y,
+	       width, height,
+	       out_width, out_height,
+	       ilace, color_mode,
+	       rotation, mirror, channel);
+
 	if (paddr = 0)
 		return -EINVAL;
 
@@ -2043,9 +2018,13 @@ static int _dispc_setup_plane(enum omap_plane plane,
 	return 0;
 }
 
-static void _dispc_enable_plane(enum omap_plane plane, bool enable)
+int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
+	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+	return 0;
 }
 
 static void dispc_disable_isr(void *data, u32 mask)
@@ -2069,8 +2048,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 	int r;
 	u32 irq;
 
-	dispc_runtime_get();
-
 	/* When we disable LCD output, we need to wait until frame is done.
 	 * Otherwise the DSS is still working, and turning off the clocks
 	 * prevents DSS from going to OFF mode */
@@ -2104,8 +2081,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 		if (r)
 			DSSERR("failed to unregister FRAMEDONE isr\n");
 	}
-
-	dispc_runtime_put();
 }
 
 static void _enable_digit_out(bool enable)
@@ -2118,12 +2093,8 @@ static void dispc_enable_digit_out(bool enable)
 	struct completion frame_done_completion;
 	int r;
 
-	dispc_runtime_get();
-
-	if (REG_GET(DISPC_CONTROL, 1, 1) = enable) {
-		dispc_runtime_put();
+	if (REG_GET(DISPC_CONTROL, 1, 1) = enable)
 		return;
-	}
 
 	if (enable) {
 		unsigned long flags;
@@ -2175,8 +2146,6 @@ static void dispc_enable_digit_out(bool enable)
 		_omap_dispc_set_irqs();
 		spin_unlock_irqrestore(&dispc.irq_lock, flags);
 	}
-
-	dispc_runtime_put();
 }
 
 bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2207,9 +2176,7 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 		return;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-	dispc_runtime_put();
 }
 
 void dispc_lcd_enable_signal(bool enable)
@@ -2217,9 +2184,7 @@ void dispc_lcd_enable_signal(bool enable)
 	if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
 		return;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-	dispc_runtime_put();
 }
 
 void dispc_pck_free_enable(bool enable)
@@ -2227,19 +2192,15 @@ void dispc_pck_free_enable(bool enable)
 	if (!dss_has_feature(FEAT_PCKFREEENABLE))
 		return;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-	dispc_runtime_put();
 }
 
 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
-	dispc_runtime_get();
 	if (channel = OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
 	else
 		REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
-	dispc_runtime_put();
 }
 
 
@@ -2262,27 +2223,21 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
 		return;
 	}
 
-	dispc_runtime_get();
 	if (channel = OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
-	dispc_runtime_put();
 }
 
 void dispc_set_loadmode(enum omap_dss_load_mode mode)
 {
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-	dispc_runtime_put();
 }
 
 
 void dispc_set_default_color(enum omap_channel channel, u32 color)
 {
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-	dispc_runtime_put();
 }
 
 u32 dispc_get_default_color(enum omap_channel channel)
@@ -2293,9 +2248,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
 		channel != OMAP_DSS_CHANNEL_LCD &&
 		channel != OMAP_DSS_CHANNEL_LCD2);
 
-	dispc_runtime_get();
 	l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-	dispc_runtime_put();
 
 	return l;
 }
@@ -2304,7 +2257,6 @@ void dispc_set_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type type,
 		u32 trans_key)
 {
-	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
@@ -2313,14 +2265,12 @@ void dispc_set_trans_key(enum omap_channel ch,
 		REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
 
 	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-	dispc_runtime_put();
 }
 
 void dispc_get_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type *type,
 		u32 *trans_key)
 {
-	dispc_runtime_get();
 	if (type) {
 		if (ch = OMAP_DSS_CHANNEL_LCD)
 			*type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2334,33 +2284,28 @@ void dispc_get_trans_key(enum omap_channel ch,
 
 	if (trans_key)
 		*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-	dispc_runtime_put();
 }
 
 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 {
-	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
-	dispc_runtime_put();
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return;
 
-	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
-	dispc_runtime_put();
 }
 bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
@@ -2369,7 +2314,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return false;
 
-	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 18, 18);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
@@ -2378,7 +2322,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 18, 18);
 	else
 		BUG();
-	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2388,7 +2331,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 {
 	bool enabled;
 
-	dispc_runtime_get();
 	if (ch = OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 10, 10);
 	else if (ch = OMAP_DSS_CHANNEL_DIGIT)
@@ -2397,7 +2339,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 10, 10);
 	else
 		BUG();
-	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2425,12 +2366,10 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 		return;
 	}
 
-	dispc_runtime_get();
 	if (channel = OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
-	dispc_runtime_put();
 }
 
 void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2462,8 +2401,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		return;
 	}
 
-	dispc_runtime_get();
-
 	if (channel = OMAP_DSS_CHANNEL_LCD2) {
 		l = dispc_read_reg(DISPC_CONTROL2);
 		l = FLD_MOD(l, stallmode, 11, 11);
@@ -2475,8 +2412,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		l = FLD_MOD(l, gpout1, 16, 16);
 		dispc_write_reg(DISPC_CONTROL, l);
 	}
-
-	dispc_runtime_put();
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2529,10 +2464,8 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
 			FLD_VAL(vbp, 31, 20);
 	}
 
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
 	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-	dispc_runtime_put();
 }
 
 /* change name to mode? */
@@ -2575,10 +2508,8 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 	BUG_ON(lck_div < 1);
 	BUG_ON(pck_div < 2);
 
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-	dispc_runtime_put();
 }
 
 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -3038,9 +2969,7 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
 	l |= FLD_VAL(acbi, 11, 8);
 	l |= FLD_VAL(acb, 7, 0);
 
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_POL_FREQ(channel), l);
-	dispc_runtime_put();
 }
 
 void dispc_set_pol_freq(enum omap_channel channel,
@@ -3161,15 +3090,11 @@ static void _omap_dispc_set_irqs(void)
 		mask |= isr_data->mask;
 	}
 
-	dispc_runtime_get();
-
 	old_mask = dispc_read_reg(DISPC_IRQENABLE);
 	/* clear the irqstatus for newly enabled irqs */
 	dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
 
 	dispc_write_reg(DISPC_IRQENABLE, mask);
-
-	dispc_runtime_put();
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3703,58 +3628,6 @@ static void _omap_dispc_initial_config(void)
 	dispc_read_plane_fifo_sizes();
 }
 
-int dispc_enable_plane(enum omap_plane plane, bool enable)
-{
-	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
-	dispc_runtime_get();
-	_dispc_enable_plane(plane, enable);
-	dispc_runtime_put();
-
-	return 0;
-}
-
-int dispc_setup_plane(enum omap_plane plane,
-		       u32 paddr, u16 screen_width,
-		       u16 pos_x, u16 pos_y,
-		       u16 width, u16 height,
-		       u16 out_width, u16 out_height,
-		       enum omap_color_mode color_mode,
-		       bool ilace,
-		       enum omap_dss_rotation_type rotation_type,
-		       u8 rotation, bool mirror, u8 global_alpha,
-		       u8 pre_mult_alpha, enum omap_channel channel,
-		       u32 puv_addr)
-{
-	int r = 0;
-
-	DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
-	       "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
-	       plane, paddr, screen_width, pos_x, pos_y,
-	       width, height,
-	       out_width, out_height,
-	       ilace, color_mode,
-	       rotation, mirror, channel);
-
-	dispc_runtime_get();
-
-	r = _dispc_setup_plane(plane,
-			   paddr, screen_width,
-			   pos_x, pos_y,
-			   width, height,
-			   out_width, out_height,
-			   color_mode, ilace,
-			   rotation_type,
-			   rotation, mirror,
-			   global_alpha,
-			   pre_mult_alpha,
-			   channel, puv_addr);
-
-	dispc_runtime_put();
-
-	return r;
-}
-
 /* DISPC HW IP initialisation */
 static int omap_dispchw_probe(struct platform_device *pdev)
 {
-- 
1.7.4.1


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

* [PATCH 22/27] OMAP: DSS2: DISPC: remove finegrained clk enables/disables
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

dispc.c enables and disables clocks in almost every function to make
sure the clocks are enabled when the function is called. This is rather
unoptimal way to handle the problem.

With pm_runtime other components have to call dispc_runtime_get() to
enable dispc clocks before calling any other dispc functions. Thus the
finegrained clk enables/disables can be removed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |  165 +++++----------------------------------
 1 files changed, 19 insertions(+), 146 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 57400f6..b13a656 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -645,8 +645,6 @@ void dispc_go(enum omap_channel channel)
 	int bit;
 	bool enable_bit, go_bit;
 
-	dispc_runtime_get();
-
 	if (channel == OMAP_DSS_CHANNEL_LCD ||
 			channel == OMAP_DSS_CHANNEL_LCD2)
 		bit = 0; /* LCDENABLE */
@@ -660,7 +658,7 @@ void dispc_go(enum omap_channel channel)
 		enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
 
 	if (!enable_bit)
-		goto end;
+		return;
 
 	if (channel == OMAP_DSS_CHANNEL_LCD ||
 			channel == OMAP_DSS_CHANNEL_LCD2)
@@ -675,7 +673,7 @@ void dispc_go(enum omap_channel channel)
 
 	if (go_bit) {
 		DSSERR("GO bit not down for channel %d\n", channel);
-		goto end;
+		return;
 	}
 
 	DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
@@ -685,8 +683,6 @@ void dispc_go(enum omap_channel channel)
 		REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
-end:
-	dispc_runtime_put();
 }
 
 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -1060,7 +1056,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
 }
 
-static void _dispc_set_channel_out(enum omap_plane plane,
+void dispc_set_channel_out(enum omap_plane plane,
 		enum omap_channel channel)
 {
 	int shift;
@@ -1113,8 +1109,6 @@ void dispc_set_burst_size(enum omap_plane plane,
 	int shift;
 	u32 val;
 
-	dispc_runtime_get();
-
 	switch (plane) {
 	case OMAP_DSS_GFX:
 		shift = 6;
@@ -1131,8 +1125,6 @@ void dispc_set_burst_size(enum omap_plane plane,
 	val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
 	val = FLD_MOD(val, burst_size, shift+1, shift);
 	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
-
-	dispc_runtime_put();
 }
 
 void dispc_enable_gamma_table(bool enable)
@@ -1169,9 +1161,7 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
 	else
 		bit = 10;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
-	dispc_runtime_put();
 }
 
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1179,9 +1169,7 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-	dispc_runtime_put();
 }
 
 void dispc_set_digit_size(u16 width, u16 height)
@@ -1189,9 +1177,7 @@ void dispc_set_digit_size(u16 width, u16 height)
 	u32 val;
 	BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
 	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
-	dispc_runtime_put();
 }
 
 static void dispc_read_plane_fifo_sizes(void)
@@ -1200,8 +1186,6 @@ static void dispc_read_plane_fifo_sizes(void)
 	int plane;
 	u8 start, end;
 
-	dispc_runtime_get();
-
 	dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
 	for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
@@ -1209,8 +1193,6 @@ static void dispc_read_plane_fifo_sizes(void)
 			start, end);
 		dispc.fifo_size[plane] = size;
 	}
-
-	dispc_runtime_put();
 }
 
 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1225,8 +1207,6 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 	dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
 	dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-	dispc_runtime_get();
-
 	DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
 			plane,
 			REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
@@ -1238,18 +1218,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
 	dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
 			FLD_VAL(high, hi_start, hi_end) |
 			FLD_VAL(low, lo_start, lo_end));
-
-	dispc_runtime_put();
 }
 
 void dispc_enable_fifomerge(bool enable)
 {
-	dispc_runtime_get();
-
 	DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
 	REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
-
-	dispc_runtime_put();
 }
 
 static void _dispc_set_fir(enum omap_plane plane,
@@ -1869,14 +1843,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
 	return dispc_pclk_rate(channel) * vf * hf;
 }
 
-void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
-{
-	dispc_runtime_get();
-	_dispc_set_channel_out(plane, channel_out);
-	dispc_runtime_put();
-}
-
-static int _dispc_setup_plane(enum omap_plane plane,
+int dispc_setup_plane(enum omap_plane plane,
 		u32 paddr, u16 screen_width,
 		u16 pos_x, u16 pos_y,
 		u16 width, u16 height,
@@ -1884,7 +1851,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
 		enum omap_color_mode color_mode,
 		bool ilace,
 		enum omap_dss_rotation_type rotation_type,
-		u8 rotation, int mirror,
+		u8 rotation, bool mirror,
 		u8 global_alpha, u8 pre_mult_alpha,
 		enum omap_channel channel, u32 puv_addr)
 {
@@ -1898,6 +1865,14 @@ static int _dispc_setup_plane(enum omap_plane plane,
 	u16 frame_height = height;
 	unsigned int field_offset = 0;
 
+	DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
+	       "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
+	       plane, paddr, screen_width, pos_x, pos_y,
+	       width, height,
+	       out_width, out_height,
+	       ilace, color_mode,
+	       rotation, mirror, channel);
+
 	if (paddr == 0)
 		return -EINVAL;
 
@@ -2043,9 +2018,13 @@ static int _dispc_setup_plane(enum omap_plane plane,
 	return 0;
 }
 
-static void _dispc_enable_plane(enum omap_plane plane, bool enable)
+int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
+	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
 	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+	return 0;
 }
 
 static void dispc_disable_isr(void *data, u32 mask)
@@ -2069,8 +2048,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 	int r;
 	u32 irq;
 
-	dispc_runtime_get();
-
 	/* When we disable LCD output, we need to wait until frame is done.
 	 * Otherwise the DSS is still working, and turning off the clocks
 	 * prevents DSS from going to OFF mode */
@@ -2104,8 +2081,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
 		if (r)
 			DSSERR("failed to unregister FRAMEDONE isr\n");
 	}
-
-	dispc_runtime_put();
 }
 
 static void _enable_digit_out(bool enable)
@@ -2118,12 +2093,8 @@ static void dispc_enable_digit_out(bool enable)
 	struct completion frame_done_completion;
 	int r;
 
-	dispc_runtime_get();
-
-	if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
-		dispc_runtime_put();
+	if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
 		return;
-	}
 
 	if (enable) {
 		unsigned long flags;
@@ -2175,8 +2146,6 @@ static void dispc_enable_digit_out(bool enable)
 		_omap_dispc_set_irqs();
 		spin_unlock_irqrestore(&dispc.irq_lock, flags);
 	}
-
-	dispc_runtime_put();
 }
 
 bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2207,9 +2176,7 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 		return;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-	dispc_runtime_put();
 }
 
 void dispc_lcd_enable_signal(bool enable)
@@ -2217,9 +2184,7 @@ void dispc_lcd_enable_signal(bool enable)
 	if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
 		return;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-	dispc_runtime_put();
 }
 
 void dispc_pck_free_enable(bool enable)
@@ -2227,19 +2192,15 @@ void dispc_pck_free_enable(bool enable)
 	if (!dss_has_feature(FEAT_PCKFREEENABLE))
 		return;
 
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-	dispc_runtime_put();
 }
 
 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
-	dispc_runtime_get();
 	if (channel == OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
 	else
 		REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
-	dispc_runtime_put();
 }
 
 
@@ -2262,27 +2223,21 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
 		return;
 	}
 
-	dispc_runtime_get();
 	if (channel == OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
-	dispc_runtime_put();
 }
 
 void dispc_set_loadmode(enum omap_dss_load_mode mode)
 {
-	dispc_runtime_get();
 	REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-	dispc_runtime_put();
 }
 
 
 void dispc_set_default_color(enum omap_channel channel, u32 color)
 {
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-	dispc_runtime_put();
 }
 
 u32 dispc_get_default_color(enum omap_channel channel)
@@ -2293,9 +2248,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
 		channel != OMAP_DSS_CHANNEL_LCD &&
 		channel != OMAP_DSS_CHANNEL_LCD2);
 
-	dispc_runtime_get();
 	l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-	dispc_runtime_put();
 
 	return l;
 }
@@ -2304,7 +2257,6 @@ void dispc_set_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type type,
 		u32 trans_key)
 {
-	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2313,14 +2265,12 @@ void dispc_set_trans_key(enum omap_channel ch,
 		REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
 
 	dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-	dispc_runtime_put();
 }
 
 void dispc_get_trans_key(enum omap_channel ch,
 		enum omap_dss_trans_key_type *type,
 		u32 *trans_key)
 {
-	dispc_runtime_get();
 	if (type) {
 		if (ch == OMAP_DSS_CHANNEL_LCD)
 			*type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2334,33 +2284,28 @@ void dispc_get_trans_key(enum omap_channel ch,
 
 	if (trans_key)
 		*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-	dispc_runtime_put();
 }
 
 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 {
-	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
-	dispc_runtime_put();
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return;
 
-	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
 		REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
 	else /* OMAP_DSS_CHANNEL_LCD2 */
 		REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
-	dispc_runtime_put();
 }
 bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
@@ -2369,7 +2314,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 	if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
 		return false;
 
-	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 18, 18);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2378,7 +2322,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 18, 18);
 	else
 		BUG();
-	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2388,7 +2331,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 {
 	bool enabled;
 
-	dispc_runtime_get();
 	if (ch == OMAP_DSS_CHANNEL_LCD)
 		enabled = REG_GET(DISPC_CONFIG, 10, 10);
 	else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2397,7 +2339,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 		enabled = REG_GET(DISPC_CONFIG2, 10, 10);
 	else
 		BUG();
-	dispc_runtime_put();
 
 	return enabled;
 }
@@ -2425,12 +2366,10 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 		return;
 	}
 
-	dispc_runtime_get();
 	if (channel == OMAP_DSS_CHANNEL_LCD2)
 		REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
 	else
 		REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
-	dispc_runtime_put();
 }
 
 void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2462,8 +2401,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		return;
 	}
 
-	dispc_runtime_get();
-
 	if (channel == OMAP_DSS_CHANNEL_LCD2) {
 		l = dispc_read_reg(DISPC_CONTROL2);
 		l = FLD_MOD(l, stallmode, 11, 11);
@@ -2475,8 +2412,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
 		l = FLD_MOD(l, gpout1, 16, 16);
 		dispc_write_reg(DISPC_CONTROL, l);
 	}
-
-	dispc_runtime_put();
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2529,10 +2464,8 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
 			FLD_VAL(vbp, 31, 20);
 	}
 
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
 	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-	dispc_runtime_put();
 }
 
 /* change name to mode? */
@@ -2575,10 +2508,8 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 	BUG_ON(lck_div < 1);
 	BUG_ON(pck_div < 2);
 
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_DIVISORo(channel),
 			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-	dispc_runtime_put();
 }
 
 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -3038,9 +2969,7 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
 	l |= FLD_VAL(acbi, 11, 8);
 	l |= FLD_VAL(acb, 7, 0);
 
-	dispc_runtime_get();
 	dispc_write_reg(DISPC_POL_FREQ(channel), l);
-	dispc_runtime_put();
 }
 
 void dispc_set_pol_freq(enum omap_channel channel,
@@ -3161,15 +3090,11 @@ static void _omap_dispc_set_irqs(void)
 		mask |= isr_data->mask;
 	}
 
-	dispc_runtime_get();
-
 	old_mask = dispc_read_reg(DISPC_IRQENABLE);
 	/* clear the irqstatus for newly enabled irqs */
 	dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
 
 	dispc_write_reg(DISPC_IRQENABLE, mask);
-
-	dispc_runtime_put();
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3703,58 +3628,6 @@ static void _omap_dispc_initial_config(void)
 	dispc_read_plane_fifo_sizes();
 }
 
-int dispc_enable_plane(enum omap_plane plane, bool enable)
-{
-	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
-	dispc_runtime_get();
-	_dispc_enable_plane(plane, enable);
-	dispc_runtime_put();
-
-	return 0;
-}
-
-int dispc_setup_plane(enum omap_plane plane,
-		       u32 paddr, u16 screen_width,
-		       u16 pos_x, u16 pos_y,
-		       u16 width, u16 height,
-		       u16 out_width, u16 out_height,
-		       enum omap_color_mode color_mode,
-		       bool ilace,
-		       enum omap_dss_rotation_type rotation_type,
-		       u8 rotation, bool mirror, u8 global_alpha,
-		       u8 pre_mult_alpha, enum omap_channel channel,
-		       u32 puv_addr)
-{
-	int r = 0;
-
-	DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
-	       "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
-	       plane, paddr, screen_width, pos_x, pos_y,
-	       width, height,
-	       out_width, out_height,
-	       ilace, color_mode,
-	       rotation, mirror, channel);
-
-	dispc_runtime_get();
-
-	r = _dispc_setup_plane(plane,
-			   paddr, screen_width,
-			   pos_x, pos_y,
-			   width, height,
-			   out_width, out_height,
-			   color_mode, ilace,
-			   rotation_type,
-			   rotation, mirror,
-			   global_alpha,
-			   pre_mult_alpha,
-			   channel, puv_addr);
-
-	dispc_runtime_put();
-
-	return r;
-}
-
 /* DISPC HW IP initialisation */
 static int omap_dispchw_probe(struct platform_device *pdev)
 {
-- 
1.7.4.1


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

* [PATCH 23/27] OMAP: DSS2: Remove unused code from display.c
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

oh_core variable is no longer used, so it and its initialization can be
removed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |   10 ----------
 1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index af43620..a5b7a23 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -43,9 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
 	},
 };
 
-/* oh_core is used for getting opt-clocks */
-static struct omap_hwmod	*oh_core;
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -99,13 +96,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 		oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
 	}
 
-	/* opt_clks are always associated with dss hwmod */
-	oh_core = omap_hwmod_lookup("dss_core");
-	if (!oh_core) {
-		pr_err("Could not look up dss_core.\n");
-		return -ENODEV;
-	}
-
 	pdata.board_data = board_data;
 	pdata.board_data->get_context_loss_count  		omap_pm_get_dev_context_loss_count;
-- 
1.7.4.1


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

* [PATCH 23/27] OMAP: DSS2: Remove unused code from display.c
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

oh_core variable is no longer used, so it and its initialization can be
removed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/display.c |   10 ----------
 1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index af43620..a5b7a23 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -43,9 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
 	},
 };
 
-/* oh_core is used for getting opt-clocks */
-static struct omap_hwmod	*oh_core;
-
 struct omap_dss_hwmod_data {
 	const char *oh_name;
 	const char *dev_name;
@@ -99,13 +96,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 		oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
 	}
 
-	/* opt_clks are always associated with dss hwmod */
-	oh_core = omap_hwmod_lookup("dss_core");
-	if (!oh_core) {
-		pr_err("Could not look up dss_core.\n");
-		return -ENODEV;
-	}
-
 	pdata.board_data = board_data;
 	pdata.board_data->get_context_loss_count =
 		omap_pm_get_dev_context_loss_count;
-- 
1.7.4.1


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

* [PATCH 24/27] OMAP: DSS2: Remove ctx loss count from dss.c
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

dss.c only saves 1 register (3 in OMAP3) so the extra overhead from
need_ctx_restore & co. is probably bigger than the time spent saving and
restoring those few registers every time.

So remove the code from dss.c and restore context every time dss has
been off.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   61 +----------------------------------------
 1 files changed, 1 insertions(+), 60 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index c8d7357..91572b6 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -62,7 +62,6 @@ static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
 
-	int		ctx_loss_cnt;
 	struct mutex	runtime_lock;
 	int		runtime_count;
 
@@ -633,61 +632,6 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
 	REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15);	/* VENC_HDMI_SWITCH */
 }
 
-/* CONTEXT */
-static void dss_init_ctx_loss_count(void)
-{
-	struct device *dev = &dss.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt = 0;
-
-	/*
-	 * get_context_loss_count returns negative on error. We'll ignore the
-	 * error and store the error to ctx_loss_cnt, which will cause
-	 * dss_need_ctx_restore() call to return true.
-	 */
-
-	if (board_data->get_context_loss_count)
-		cnt = board_data->get_context_loss_count(dev);
-
-	WARN_ON(cnt < 0);
-
-	dss.ctx_loss_cnt = cnt;
-
-	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
-}
-
-static bool dss_need_ctx_restore(void)
-{
-	struct device *dev = &dss.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt;
-
-	/*
-	 * If get_context_loss_count is not available, assume that we need
-	 * context restore always.
-	 */
-	if (!board_data->get_context_loss_count)
-		return true;
-
-	cnt = board_data->get_context_loss_count(dev);
-	if (cnt < 0) {
-		dev_err(dev, "getting context loss count failed, will force "
-				"context restore\n");
-		dss.ctx_loss_cnt = cnt;
-		return true;
-	}
-
-	if (cnt = dss.ctx_loss_cnt)
-		return false;
-
-	DSSDBG("ctx_loss_cnt %d -> %d\n", dss.ctx_loss_cnt, cnt);
-	dss.ctx_loss_cnt = cnt;
-
-	return true;
-}
-
 static int dss_get_clocks(void)
 {
 	struct clk *clk;
@@ -756,8 +700,7 @@ int dss_runtime_get(void)
 		if (r < 0)
 			goto err;
 
-		if (dss_need_ctx_restore())
-			dss_restore_context();
+		dss_restore_context();
 	}
 
 	mutex_unlock(&dss.runtime_lock);
@@ -828,8 +771,6 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	if (r)
 		goto err_clocks;
 
-	dss_init_ctx_loss_count();
-
 	mutex_init(&dss.runtime_lock);
 
 	pm_runtime_enable(&pdev->dev);
-- 
1.7.4.1


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

* [PATCH 24/27] OMAP: DSS2: Remove ctx loss count from dss.c
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

dss.c only saves 1 register (3 in OMAP3) so the extra overhead from
need_ctx_restore & co. is probably bigger than the time spent saving and
restoring those few registers every time.

So remove the code from dss.c and restore context every time dss has
been off.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   61 +----------------------------------------
 1 files changed, 1 insertions(+), 60 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index c8d7357..91572b6 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -62,7 +62,6 @@ static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
 
-	int		ctx_loss_cnt;
 	struct mutex	runtime_lock;
 	int		runtime_count;
 
@@ -633,61 +632,6 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
 	REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15);	/* VENC_HDMI_SWITCH */
 }
 
-/* CONTEXT */
-static void dss_init_ctx_loss_count(void)
-{
-	struct device *dev = &dss.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt = 0;
-
-	/*
-	 * get_context_loss_count returns negative on error. We'll ignore the
-	 * error and store the error to ctx_loss_cnt, which will cause
-	 * dss_need_ctx_restore() call to return true.
-	 */
-
-	if (board_data->get_context_loss_count)
-		cnt = board_data->get_context_loss_count(dev);
-
-	WARN_ON(cnt < 0);
-
-	dss.ctx_loss_cnt = cnt;
-
-	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
-}
-
-static bool dss_need_ctx_restore(void)
-{
-	struct device *dev = &dss.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt;
-
-	/*
-	 * If get_context_loss_count is not available, assume that we need
-	 * context restore always.
-	 */
-	if (!board_data->get_context_loss_count)
-		return true;
-
-	cnt = board_data->get_context_loss_count(dev);
-	if (cnt < 0) {
-		dev_err(dev, "getting context loss count failed, will force "
-				"context restore\n");
-		dss.ctx_loss_cnt = cnt;
-		return true;
-	}
-
-	if (cnt == dss.ctx_loss_cnt)
-		return false;
-
-	DSSDBG("ctx_loss_cnt %d -> %d\n", dss.ctx_loss_cnt, cnt);
-	dss.ctx_loss_cnt = cnt;
-
-	return true;
-}
-
 static int dss_get_clocks(void)
 {
 	struct clk *clk;
@@ -756,8 +700,7 @@ int dss_runtime_get(void)
 		if (r < 0)
 			goto err;
 
-		if (dss_need_ctx_restore())
-			dss_restore_context();
+		dss_restore_context();
 	}
 
 	mutex_unlock(&dss.runtime_lock);
@@ -828,8 +771,6 @@ static int omap_dsshw_probe(struct platform_device *pdev)
 	if (r)
 		goto err_clocks;
 
-	dss_init_ctx_loss_count();
-
 	mutex_init(&dss.runtime_lock);
 
 	pm_runtime_enable(&pdev->dev);
-- 
1.7.4.1


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

* [PATCH 25/27] OMAP4: CLKDEV: Remove omapdss clock aliases
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

omapdss driver now gets the clocks via hwmod opt clocks, so clock
aliases for omapdss_dss are no longer needed.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 8c96567..4d278e7 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3114,11 +3114,11 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
 	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-	CLK("omapdss_dss",	"sys_clk",			&dss_sys_clk,	CK_443X),
-	CLK("omapdss_dss",	"tv_clk",			&dss_tv_clk,	CK_443X),
-	CLK("omapdss_dss",	"video_clk",			&dss_48mhz_clk,	CK_443X),
-	CLK("omapdss_dss",	"fck",				&dss_dss_clk,	CK_443X),
-	CLK("omapdss_dss",	"ick",				&dss_fck,	CK_443X),
+	CLK(NULL,	"sys_clk",			&dss_sys_clk,	CK_443X),
+	CLK(NULL,	"tv_clk",			&dss_tv_clk,	CK_443X),
+	CLK(NULL,	"video_clk",			&dss_48mhz_clk,	CK_443X),
+	CLK(NULL,	"fck",				&dss_dss_clk,	CK_443X),
+	CLK(NULL,	"ick",				&dss_fck,	CK_443X),
 	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
 	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
 	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
-- 
1.7.4.1


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

* [PATCH 25/27] OMAP4: CLKDEV: Remove omapdss clock aliases
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

omapdss driver now gets the clocks via hwmod opt clocks, so clock
aliases for omapdss_dss are no longer needed.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/clock44xx_data.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 8c96567..4d278e7 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3114,11 +3114,11 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
 	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-	CLK("omapdss_dss",	"sys_clk",			&dss_sys_clk,	CK_443X),
-	CLK("omapdss_dss",	"tv_clk",			&dss_tv_clk,	CK_443X),
-	CLK("omapdss_dss",	"video_clk",			&dss_48mhz_clk,	CK_443X),
-	CLK("omapdss_dss",	"fck",				&dss_dss_clk,	CK_443X),
-	CLK("omapdss_dss",	"ick",				&dss_fck,	CK_443X),
+	CLK(NULL,	"sys_clk",			&dss_sys_clk,	CK_443X),
+	CLK(NULL,	"tv_clk",			&dss_tv_clk,	CK_443X),
+	CLK(NULL,	"video_clk",			&dss_48mhz_clk,	CK_443X),
+	CLK(NULL,	"fck",				&dss_dss_clk,	CK_443X),
+	CLK(NULL,	"ick",				&dss_fck,	CK_443X),
 	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
 	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
 	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
-- 
1.7.4.1


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

* [PATCH 26/27] OMAP: DSS2: DISPC: Fix context save/restore
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The current method of saving and restoring the context could cause a
restore before saving, effectively "restoring" zero values to registers.

Add ctx_valid field to indicate if the saved context is valid and can be
restored.

Also restructure the code to save the ctx_loss_count in save_context(),
which makes more sense than the previous method of storing new
ctx_loss_count in dispc_need_ctx_restore.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   97 +++++++++++++++-----------------------
 1 files changed, 38 insertions(+), 59 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b13a656..73f1105 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -110,6 +110,7 @@ static struct {
 	u32 error_irqs;
 	struct work_struct error_work;
 
+	bool		ctx_valid;
 	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -142,6 +143,23 @@ static inline u32 dispc_read_reg(const u16 idx)
 	return __raw_readl(dispc.base + idx);
 }
 
+static int dispc_get_ctx_loss_count(void)
+{
+	struct device *dev = &dispc.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt;
+
+	if (!board_data->get_context_loss_count)
+		return -ENOENT;
+
+	cnt = board_data->get_context_loss_count(dev);
+
+	WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+	return cnt;
+}
+
 #define SR(reg) \
 	dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
 #define RR(reg) \
@@ -318,14 +336,30 @@ static void dispc_save_context(void)
 
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		SR(DIVISOR);
+
+	dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
+	dispc.ctx_valid = true;
+
+	DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
 }
 
 static void dispc_restore_context(void)
 {
-	int i;
+	int i, ctx;
 
 	DSSDBG("dispc_restore_context\n");
 
+	if (!dispc.ctx_valid)
+		return;
+
+	ctx = dispc_get_ctx_loss_count();
+
+	if (ctx >= 0 && ctx = dispc.ctx_loss_cnt)
+		return;
+
+	DSSDBG("ctx_loss_count: saved %d, current %d\n",
+			dispc.ctx_loss_cnt, ctx);
+
 	/*RR(IRQENABLE);*/
 	/*RR(CONTROL);*/
 	RR(CONFIG);
@@ -504,65 +538,13 @@ static void dispc_restore_context(void)
 	 * the context is fully restored
 	 */
 	RR(IRQENABLE);
+
+	DSSDBG("context restored\n");
 }
 
 #undef SR
 #undef RR
 
-static void dispc_init_ctx_loss_count(void)
-{
-	struct device *dev = &dispc.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt = 0;
-
-	/*
-	 * get_context_loss_count returns negative on error. We'll ignore the
-	 * error and store the error to ctx_loss_cnt, which will cause
-	 * dispc_need_ctx_restore() call to return true.
-	 */
-
-	if (board_data->get_context_loss_count)
-		cnt = board_data->get_context_loss_count(dev);
-
-	WARN_ON(cnt < 0);
-
-	dispc.ctx_loss_cnt = cnt;
-
-	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
-}
-
-static bool dispc_need_ctx_restore(void)
-{
-	struct device *dev = &dispc.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt;
-
-	/*
-	 * If get_context_loss_count is not available, assume that we need
-	 * context restore always.
-	 */
-	if (!board_data->get_context_loss_count)
-		return true;
-
-	cnt = board_data->get_context_loss_count(dev);
-	if (cnt < 0) {
-		dev_err(dev, "getting context loss count failed, will force "
-				"context restore\n");
-		dispc.ctx_loss_cnt = cnt;
-		return true;
-	}
-
-	if (cnt = dispc.ctx_loss_cnt)
-		return false;
-
-	DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt);
-	dispc.ctx_loss_cnt = cnt;
-
-	return true;
-}
-
 int dispc_runtime_get(void)
 {
 	int r;
@@ -584,8 +566,7 @@ int dispc_runtime_get(void)
 		if (r < 0)
 			goto err_runtime_get;
 
-		if (dispc_need_ctx_restore())
-			dispc_restore_context();
+		dispc_restore_context();
 	}
 
 	mutex_unlock(&dispc.runtime_lock);
@@ -3682,8 +3663,6 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 		goto err_irq;
 	}
 
-	dispc_init_ctx_loss_count();
-
 	mutex_init(&dispc.runtime_lock);
 
 	pm_runtime_enable(&pdev->dev);
-- 
1.7.4.1


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

* [PATCH 26/27] OMAP: DSS2: DISPC: Fix context save/restore
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The current method of saving and restoring the context could cause a
restore before saving, effectively "restoring" zero values to registers.

Add ctx_valid field to indicate if the saved context is valid and can be
restored.

Also restructure the code to save the ctx_loss_count in save_context(),
which makes more sense than the previous method of storing new
ctx_loss_count in dispc_need_ctx_restore.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   97 +++++++++++++++-----------------------
 1 files changed, 38 insertions(+), 59 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b13a656..73f1105 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -110,6 +110,7 @@ static struct {
 	u32 error_irqs;
 	struct work_struct error_work;
 
+	bool		ctx_valid;
 	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -142,6 +143,23 @@ static inline u32 dispc_read_reg(const u16 idx)
 	return __raw_readl(dispc.base + idx);
 }
 
+static int dispc_get_ctx_loss_count(void)
+{
+	struct device *dev = &dispc.pdev->dev;
+	struct omap_display_platform_data *pdata = dev->platform_data;
+	struct omap_dss_board_info *board_data = pdata->board_data;
+	int cnt;
+
+	if (!board_data->get_context_loss_count)
+		return -ENOENT;
+
+	cnt = board_data->get_context_loss_count(dev);
+
+	WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+	return cnt;
+}
+
 #define SR(reg) \
 	dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
 #define RR(reg) \
@@ -318,14 +336,30 @@ static void dispc_save_context(void)
 
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		SR(DIVISOR);
+
+	dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
+	dispc.ctx_valid = true;
+
+	DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
 }
 
 static void dispc_restore_context(void)
 {
-	int i;
+	int i, ctx;
 
 	DSSDBG("dispc_restore_context\n");
 
+	if (!dispc.ctx_valid)
+		return;
+
+	ctx = dispc_get_ctx_loss_count();
+
+	if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
+		return;
+
+	DSSDBG("ctx_loss_count: saved %d, current %d\n",
+			dispc.ctx_loss_cnt, ctx);
+
 	/*RR(IRQENABLE);*/
 	/*RR(CONTROL);*/
 	RR(CONFIG);
@@ -504,65 +538,13 @@ static void dispc_restore_context(void)
 	 * the context is fully restored
 	 */
 	RR(IRQENABLE);
+
+	DSSDBG("context restored\n");
 }
 
 #undef SR
 #undef RR
 
-static void dispc_init_ctx_loss_count(void)
-{
-	struct device *dev = &dispc.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt = 0;
-
-	/*
-	 * get_context_loss_count returns negative on error. We'll ignore the
-	 * error and store the error to ctx_loss_cnt, which will cause
-	 * dispc_need_ctx_restore() call to return true.
-	 */
-
-	if (board_data->get_context_loss_count)
-		cnt = board_data->get_context_loss_count(dev);
-
-	WARN_ON(cnt < 0);
-
-	dispc.ctx_loss_cnt = cnt;
-
-	DSSDBG("initial ctx_loss_cnt %u\n", cnt);
-}
-
-static bool dispc_need_ctx_restore(void)
-{
-	struct device *dev = &dispc.pdev->dev;
-	struct omap_display_platform_data *pdata = dev->platform_data;
-	struct omap_dss_board_info *board_data = pdata->board_data;
-	int cnt;
-
-	/*
-	 * If get_context_loss_count is not available, assume that we need
-	 * context restore always.
-	 */
-	if (!board_data->get_context_loss_count)
-		return true;
-
-	cnt = board_data->get_context_loss_count(dev);
-	if (cnt < 0) {
-		dev_err(dev, "getting context loss count failed, will force "
-				"context restore\n");
-		dispc.ctx_loss_cnt = cnt;
-		return true;
-	}
-
-	if (cnt == dispc.ctx_loss_cnt)
-		return false;
-
-	DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt);
-	dispc.ctx_loss_cnt = cnt;
-
-	return true;
-}
-
 int dispc_runtime_get(void)
 {
 	int r;
@@ -584,8 +566,7 @@ int dispc_runtime_get(void)
 		if (r < 0)
 			goto err_runtime_get;
 
-		if (dispc_need_ctx_restore())
-			dispc_restore_context();
+		dispc_restore_context();
 	}
 
 	mutex_unlock(&dispc.runtime_lock);
@@ -3682,8 +3663,6 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 		goto err_irq;
 	}
 
-	dispc_init_ctx_loss_count();
-
 	mutex_init(&dispc.runtime_lock);
 
 	pm_runtime_enable(&pdev->dev);
-- 
1.7.4.1


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

* [PATCH 27/27] OMAP: DSS2: DSS: Fix context save/restore
  2011-06-03 10:00 ` Tomi Valkeinen
@ 2011-06-03 10:00   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The current method of saving and restoring the context could cause a
restore before saving, effectively "restoring" zero values to registers.

Add ctx_valid field to indicate if the saved context is valid and can be
restored.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 91572b6..964eb08 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -77,6 +77,7 @@ static struct {
 	enum omap_dss_clk_source dispc_clk_source;
 	enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
 
+	bool		ctx_valid;
 	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
@@ -112,12 +113,19 @@ static void dss_save_context(void)
 		SR(SDI_CONTROL);
 		SR(PLL_CONTROL);
 	}
+
+	dss.ctx_valid = true;
+
+	DSSDBG("context saved\n");
 }
 
 static void dss_restore_context(void)
 {
 	DSSDBG("dss_restore_context\n");
 
+	if (!dss.ctx_valid)
+		return;
+
 	RR(CONTROL);
 
 	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -125,6 +133,8 @@ static void dss_restore_context(void)
 		RR(SDI_CONTROL);
 		RR(PLL_CONTROL);
 	}
+
+	DSSDBG("context restored\n");
 }
 
 #undef SR
-- 
1.7.4.1


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

* [PATCH 27/27] OMAP: DSS2: DSS: Fix context save/restore
@ 2011-06-03 10:00   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 10:00 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: b-cousson, paul, khilman, Tomi Valkeinen

The current method of saving and restoring the context could cause a
restore before saving, effectively "restoring" zero values to registers.

Add ctx_valid field to indicate if the saved context is valid and can be
restored.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 91572b6..964eb08 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -77,6 +77,7 @@ static struct {
 	enum omap_dss_clk_source dispc_clk_source;
 	enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
 
+	bool		ctx_valid;
 	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
@@ -112,12 +113,19 @@ static void dss_save_context(void)
 		SR(SDI_CONTROL);
 		SR(PLL_CONTROL);
 	}
+
+	dss.ctx_valid = true;
+
+	DSSDBG("context saved\n");
 }
 
 static void dss_restore_context(void)
 {
 	DSSDBG("dss_restore_context\n");
 
+	if (!dss.ctx_valid)
+		return;
+
 	RR(CONTROL);
 
 	if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -125,6 +133,8 @@ static void dss_restore_context(void)
 		RR(SDI_CONTROL);
 		RR(PLL_CONTROL);
 	}
+
+	DSSDBG("context restored\n");
 }
 
 #undef SR
-- 
1.7.4.1


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

* Re: [PATCH 01/27] OMAP: change get_context_loss_count ret value to int
  2011-06-03 10:00   ` Tomi Valkeinen
@ 2011-06-03 16:32     ` Kevin Hilman
  -1 siblings, 0 replies; 108+ messages in thread
From: Kevin Hilman @ 2011-06-03 16:32 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> get_context_loss_count functions return context loss count as u32, and
> zero means an error. However, zero is also returned when context has
> never been lost and could also be returned when the context loss count
> has wrapped and goes to zero.
>
> Change the functions to return an int, with negative value meaning an
> error.
>
> OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the
> hsmmc code handles the returned value as an int, with negative value
> meaning an error, this patch actually fixes hsmmc code also.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Acked-by: Kevin Hilman <khilman@ti.com>

This one should be separated out into a fix for v3.0-rc, and queued by
Paul (also Cc'd to linux-arm-kernel.)

Kevin

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

* Re: [PATCH 01/27] OMAP: change get_context_loss_count ret value to int
@ 2011-06-03 16:32     ` Kevin Hilman
  0 siblings, 0 replies; 108+ messages in thread
From: Kevin Hilman @ 2011-06-03 16:32 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> get_context_loss_count functions return context loss count as u32, and
> zero means an error. However, zero is also returned when context has
> never been lost and could also be returned when the context loss count
> has wrapped and goes to zero.
>
> Change the functions to return an int, with negative value meaning an
> error.
>
> OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the
> hsmmc code handles the returned value as an int, with negative value
> meaning an error, this patch actually fixes hsmmc code also.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Acked-by: Kevin Hilman <khilman@ti.com>

This one should be separated out into a fix for v3.0-rc, and queued by
Paul (also Cc'd to linux-arm-kernel.)

Kevin

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-03 10:00   ` Tomi Valkeinen
@ 2011-06-03 16:45     ` Kevin Hilman
  -1 siblings, 0 replies; 108+ messages in thread
From: Kevin Hilman @ 2011-06-03 16:45 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> modules.
>
> Each DSS module will have get and put functions which can be used to
> enable and disable that module. The functions use pm_runtime and hwmod
> opt-clocks to enable the hardware.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

[...]

> +int dispc_runtime_get(void)
> +{
> +	int r;
> +
> +	mutex_lock(&dispc.runtime_lock);

It's not clear to me what the lock is trying to protect.  I guess it's
the counter?  I don't think it should be needed...

> +	if (dispc.runtime_count++ = 0) {

You shouldn't need your own use-counting here.  The runtime PM core is
already doing usage counting.

Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
core when the usage count goes to/from zero.

IOW, this function should simply be a pm_runtime_get_sync(), and the
rest of the stuff in this function should be done in the
->runtime_resume() callback, which is only executed when the usage_count
transitions from zero.

> +		DSSDBG("dispc_runtime_get\n");
> +
> +		r = dss_runtime_get();
> +		if (r)
> +			goto err_dss_get;
> +
> +		/* XXX dispc fclk can also come from DSI PLL */
> +		clk_enable(dispc.dss_clk);
> +
> +		r = pm_runtime_get_sync(&dispc.pdev->dev);
> +		WARN_ON(r);
> +		if (r < 0)
> +			goto err_runtime_get;
> +
> +		if (dispc_need_ctx_restore())
> +			dispc_restore_context();
> +	}
> +
> +	mutex_unlock(&dispc.runtime_lock);
> +
> +	return 0;
> +
> +err_runtime_get:
> +	clk_disable(dispc.dss_clk);
> +	dss_runtime_put();
> +err_dss_get:
> +	mutex_unlock(&dispc.runtime_lock);
> +
> +	return r;
>  }
>  
> +void dispc_runtime_put(void)
> +{
> +	mutex_lock(&dispc.runtime_lock);
> +
> +	if (--dispc.runtime_count = 0) {
> +		int r;

Same problem here.  

No usage counting is required (and probably no locking either.)  This
function should simply be a pm_runtime_put(), and the rest of the stuff
should be in the driver's ->runtime_suspend() callback.

> +		DSSDBG("dispc_runtime_put\n");
> +
> +		dispc_save_context();
> +
> +		r = pm_runtime_put_sync(&dispc.pdev->dev);

Does this need to be the _sync() version?  It looks like it could be use
the "normal" (async) version.: pm_runtime_put().

> +		WARN_ON(r);
> +
> +		clk_disable(dispc.dss_clk);
> +
> +		dss_runtime_put();
> +	}
> +
> +	mutex_unlock(&dispc.runtime_lock);
> +}
> +
> +
>  bool dispc_go_busy(enum omap_channel channel)
>  {
>  	int bit;
> @@ -530,7 +645,7 @@ void dispc_go(enum omap_channel channel)
>  	int bit;
>  	bool enable_bit, go_bit;
>  
> -	enable_clocks(1);
> +	dispc_runtime_get();

Based on the above suggestions, you probably don't need dedicated
functions for this.  Just call pm_runtime_get_sync() here...

>  	if (channel = OMAP_DSS_CHANNEL_LCD ||
>  			channel = OMAP_DSS_CHANNEL_LCD2)
> @@ -571,7 +686,7 @@ void dispc_go(enum omap_channel channel)
>  	else
>  		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
>  end:
> -	enable_clocks(0);
> +	dispc_runtime_put();

...and the pm_runtime_put() here.


Kevin

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-03 16:45     ` Kevin Hilman
  0 siblings, 0 replies; 108+ messages in thread
From: Kevin Hilman @ 2011-06-03 16:45 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> modules.
>
> Each DSS module will have get and put functions which can be used to
> enable and disable that module. The functions use pm_runtime and hwmod
> opt-clocks to enable the hardware.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

[...]

> +int dispc_runtime_get(void)
> +{
> +	int r;
> +
> +	mutex_lock(&dispc.runtime_lock);

It's not clear to me what the lock is trying to protect.  I guess it's
the counter?  I don't think it should be needed...

> +	if (dispc.runtime_count++ == 0) {

You shouldn't need your own use-counting here.  The runtime PM core is
already doing usage counting.

Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
core when the usage count goes to/from zero.

IOW, this function should simply be a pm_runtime_get_sync(), and the
rest of the stuff in this function should be done in the
->runtime_resume() callback, which is only executed when the usage_count
transitions from zero.

> +		DSSDBG("dispc_runtime_get\n");
> +
> +		r = dss_runtime_get();
> +		if (r)
> +			goto err_dss_get;
> +
> +		/* XXX dispc fclk can also come from DSI PLL */
> +		clk_enable(dispc.dss_clk);
> +
> +		r = pm_runtime_get_sync(&dispc.pdev->dev);
> +		WARN_ON(r);
> +		if (r < 0)
> +			goto err_runtime_get;
> +
> +		if (dispc_need_ctx_restore())
> +			dispc_restore_context();
> +	}
> +
> +	mutex_unlock(&dispc.runtime_lock);
> +
> +	return 0;
> +
> +err_runtime_get:
> +	clk_disable(dispc.dss_clk);
> +	dss_runtime_put();
> +err_dss_get:
> +	mutex_unlock(&dispc.runtime_lock);
> +
> +	return r;
>  }
>  
> +void dispc_runtime_put(void)
> +{
> +	mutex_lock(&dispc.runtime_lock);
> +
> +	if (--dispc.runtime_count == 0) {
> +		int r;

Same problem here.  

No usage counting is required (and probably no locking either.)  This
function should simply be a pm_runtime_put(), and the rest of the stuff
should be in the driver's ->runtime_suspend() callback.

> +		DSSDBG("dispc_runtime_put\n");
> +
> +		dispc_save_context();
> +
> +		r = pm_runtime_put_sync(&dispc.pdev->dev);

Does this need to be the _sync() version?  It looks like it could be use
the "normal" (async) version.: pm_runtime_put().

> +		WARN_ON(r);
> +
> +		clk_disable(dispc.dss_clk);
> +
> +		dss_runtime_put();
> +	}
> +
> +	mutex_unlock(&dispc.runtime_lock);
> +}
> +
> +
>  bool dispc_go_busy(enum omap_channel channel)
>  {
>  	int bit;
> @@ -530,7 +645,7 @@ void dispc_go(enum omap_channel channel)
>  	int bit;
>  	bool enable_bit, go_bit;
>  
> -	enable_clocks(1);
> +	dispc_runtime_get();

Based on the above suggestions, you probably don't need dedicated
functions for this.  Just call pm_runtime_get_sync() here...

>  	if (channel == OMAP_DSS_CHANNEL_LCD ||
>  			channel == OMAP_DSS_CHANNEL_LCD2)
> @@ -571,7 +686,7 @@ void dispc_go(enum omap_channel channel)
>  	else
>  		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
>  end:
> -	enable_clocks(0);
> +	dispc_runtime_put();

...and the pm_runtime_put() here.


Kevin

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-03 16:45     ` Kevin Hilman
@ 2011-06-03 17:43       ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 17:43 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Hi Kevin,

On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> > modules.
> >
> > Each DSS module will have get and put functions which can be used to
> > enable and disable that module. The functions use pm_runtime and hwmod
> > opt-clocks to enable the hardware.
> >
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> 
> [...]
> 
> > +int dispc_runtime_get(void)
> > +{
> > +	int r;
> > +
> > +	mutex_lock(&dispc.runtime_lock);
> 
> It's not clear to me what the lock is trying to protect.  I guess it's
> the counter?  I don't think it should be needed...

Yes, the counter. I don't think

if (dispc.runtime_count++ = 0)

is thread safe.

> > +	if (dispc.runtime_count++ = 0) {
> 
> You shouldn't need your own use-counting here.  The runtime PM core is
> already doing usage counting.
> 
> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
> core when the usage count goes to/from zero.

Yes, I wish I could do that =).

I tried to explain this in the 00-patch, I guess I should've explained
it in this patch also. Perhaps also in a comment.

From the introduction:

---

Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
problem is that on OMAP4 we have to enable an optional clock before calling
pm_runtime_get(), and similarly we need to keep the optional clock enabled
until after pm_runtime_put() has been called.

This causes some extra complications. For example, we can't use runtime_resume
callback to enable the opt clocks, as they are required before calling
pm_runtime_get().

---

So, the opt clock handling required by the driver pretty much messes the
whole idea of pm_runtime callbacks here. We can't do pretty much
anything in the suspend and resume callbacks.

We can't do save_context() in the suspend callback, because suspend
could be called later, after pm_runtime_put_sync() and
dispc_runtime_put() has returned. And and that point we've turned off
the opt clock and can't touch the registers. If we'd move the opt-clock
clk_disable to suspend, but clk_enable in dispc_runtime_get(), we'd get
mismatched clk_disable/enable, so we can't do that. etc.

I didn't come up with any other solutions to this. In the end, the
dispc_runtime_get/put are quite clean functions (well, says me =), and
their usage is more or less equivalent to pm_runtime_get/put. So I don't
see it as a horrible solution.

If and when the hwmod/pm_runtime/something handles this opt-clock issue,
it shouldn't be too big of a job to use pm_runtime properly in the
omapdss. Of course, if you or somebody else has a solution for this now,
I'm more than happy to use it =).

And this opt-clock problem pretty much covers all your comments below,
except one which I've answered also.

> IOW, this function should simply be a pm_runtime_get_sync(), and the
> rest of the stuff in this function should be done in the
> ->runtime_resume() callback, which is only executed when the usage_count
> transitions from zero.
> 
> > +		DSSDBG("dispc_runtime_get\n");
> > +
> > +		r = dss_runtime_get();
> > +		if (r)
> > +			goto err_dss_get;
> > +
> > +		/* XXX dispc fclk can also come from DSI PLL */
> > +		clk_enable(dispc.dss_clk);
> > +
> > +		r = pm_runtime_get_sync(&dispc.pdev->dev);
> > +		WARN_ON(r);
> > +		if (r < 0)
> > +			goto err_runtime_get;
> > +
> > +		if (dispc_need_ctx_restore())
> > +			dispc_restore_context();
> > +	}
> > +
> > +	mutex_unlock(&dispc.runtime_lock);
> > +
> > +	return 0;
> > +
> > +err_runtime_get:
> > +	clk_disable(dispc.dss_clk);
> > +	dss_runtime_put();
> > +err_dss_get:
> > +	mutex_unlock(&dispc.runtime_lock);
> > +
> > +	return r;
> >  }
> >  
> > +void dispc_runtime_put(void)
> > +{
> > +	mutex_lock(&dispc.runtime_lock);
> > +
> > +	if (--dispc.runtime_count = 0) {
> > +		int r;
> 
> Same problem here.  
> 
> No usage counting is required (and probably no locking either.)  This
> function should simply be a pm_runtime_put(), and the rest of the stuff
> should be in the driver's ->runtime_suspend() callback.
> 
> > +		DSSDBG("dispc_runtime_put\n");
> > +
> > +		dispc_save_context();
> > +
> > +		r = pm_runtime_put_sync(&dispc.pdev->dev);
> 
> Does this need to be the _sync() version?  It looks like it could be use
> the "normal" (async) version.: pm_runtime_put().

It's sync because we turn off the opt clock below, and the HW shouldn't
be touched after that, which I guess pm_runtime_put (or the subsequent
async suspend) could do.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-03 17:43       ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-03 17:43 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Hi Kevin,

On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> > modules.
> >
> > Each DSS module will have get and put functions which can be used to
> > enable and disable that module. The functions use pm_runtime and hwmod
> > opt-clocks to enable the hardware.
> >
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> 
> [...]
> 
> > +int dispc_runtime_get(void)
> > +{
> > +	int r;
> > +
> > +	mutex_lock(&dispc.runtime_lock);
> 
> It's not clear to me what the lock is trying to protect.  I guess it's
> the counter?  I don't think it should be needed...

Yes, the counter. I don't think

if (dispc.runtime_count++ == 0)

is thread safe.

> > +	if (dispc.runtime_count++ == 0) {
> 
> You shouldn't need your own use-counting here.  The runtime PM core is
> already doing usage counting.
> 
> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
> core when the usage count goes to/from zero.

Yes, I wish I could do that =).

I tried to explain this in the 00-patch, I guess I should've explained
it in this patch also. Perhaps also in a comment.

>From the introduction:

---

Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
problem is that on OMAP4 we have to enable an optional clock before calling
pm_runtime_get(), and similarly we need to keep the optional clock enabled
until after pm_runtime_put() has been called.

This causes some extra complications. For example, we can't use runtime_resume
callback to enable the opt clocks, as they are required before calling
pm_runtime_get().

---

So, the opt clock handling required by the driver pretty much messes the
whole idea of pm_runtime callbacks here. We can't do pretty much
anything in the suspend and resume callbacks.

We can't do save_context() in the suspend callback, because suspend
could be called later, after pm_runtime_put_sync() and
dispc_runtime_put() has returned. And and that point we've turned off
the opt clock and can't touch the registers. If we'd move the opt-clock
clk_disable to suspend, but clk_enable in dispc_runtime_get(), we'd get
mismatched clk_disable/enable, so we can't do that. etc.

I didn't come up with any other solutions to this. In the end, the
dispc_runtime_get/put are quite clean functions (well, says me =), and
their usage is more or less equivalent to pm_runtime_get/put. So I don't
see it as a horrible solution.

If and when the hwmod/pm_runtime/something handles this opt-clock issue,
it shouldn't be too big of a job to use pm_runtime properly in the
omapdss. Of course, if you or somebody else has a solution for this now,
I'm more than happy to use it =).

And this opt-clock problem pretty much covers all your comments below,
except one which I've answered also.

> IOW, this function should simply be a pm_runtime_get_sync(), and the
> rest of the stuff in this function should be done in the
> ->runtime_resume() callback, which is only executed when the usage_count
> transitions from zero.
> 
> > +		DSSDBG("dispc_runtime_get\n");
> > +
> > +		r = dss_runtime_get();
> > +		if (r)
> > +			goto err_dss_get;
> > +
> > +		/* XXX dispc fclk can also come from DSI PLL */
> > +		clk_enable(dispc.dss_clk);
> > +
> > +		r = pm_runtime_get_sync(&dispc.pdev->dev);
> > +		WARN_ON(r);
> > +		if (r < 0)
> > +			goto err_runtime_get;
> > +
> > +		if (dispc_need_ctx_restore())
> > +			dispc_restore_context();
> > +	}
> > +
> > +	mutex_unlock(&dispc.runtime_lock);
> > +
> > +	return 0;
> > +
> > +err_runtime_get:
> > +	clk_disable(dispc.dss_clk);
> > +	dss_runtime_put();
> > +err_dss_get:
> > +	mutex_unlock(&dispc.runtime_lock);
> > +
> > +	return r;
> >  }
> >  
> > +void dispc_runtime_put(void)
> > +{
> > +	mutex_lock(&dispc.runtime_lock);
> > +
> > +	if (--dispc.runtime_count == 0) {
> > +		int r;
> 
> Same problem here.  
> 
> No usage counting is required (and probably no locking either.)  This
> function should simply be a pm_runtime_put(), and the rest of the stuff
> should be in the driver's ->runtime_suspend() callback.
> 
> > +		DSSDBG("dispc_runtime_put\n");
> > +
> > +		dispc_save_context();
> > +
> > +		r = pm_runtime_put_sync(&dispc.pdev->dev);
> 
> Does this need to be the _sync() version?  It looks like it could be use
> the "normal" (async) version.: pm_runtime_put().

It's sync because we turn off the opt clock below, and the HW shouldn't
be touched after that, which I guess pm_runtime_put (or the subsequent
async suspend) could do.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-03 17:43       ` Tomi Valkeinen
@ 2011-06-03 22:53         ` Kevin Hilman
  -1 siblings, 0 replies; 108+ messages in thread
From: Kevin Hilman @ 2011-06-03 22:53 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> Hi Kevin,
>
> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
>> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
>> 
>> > Use PM runtime and HWMOD support to handle enabling and disabling of DSS
>> > modules.
>> >
>> > Each DSS module will have get and put functions which can be used to
>> > enable and disable that module. The functions use pm_runtime and hwmod
>> > opt-clocks to enable the hardware.
>> >
>> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> 
>> [...]
>> 
>> > +int dispc_runtime_get(void)
>> > +{
>> > +	int r;
>> > +
>> > +	mutex_lock(&dispc.runtime_lock);
>> 
>> It's not clear to me what the lock is trying to protect.  I guess it's
>> the counter?  I don't think it should be needed...
>
> Yes, the counter. I don't think
>
> if (dispc.runtime_count++ = 0)
>
> is thread safe.

OK, if it's just the counter, you can drop the mutex and use an atomic
variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
from reading what exactly is protected.

>> > +	if (dispc.runtime_count++ = 0) {
>> 
>> You shouldn't need your own use-counting here.  The runtime PM core is
>> already doing usage counting.
>> 
>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
>> core when the usage count goes to/from zero.
>
> Yes, I wish I could do that =).
>
> I tried to explain this in the 00-patch, I guess I should've explained
> it in this patch also. Perhaps also in a comment.

Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
about DSS, so I was focused in on the runtime PM implementation only.
Sorry about that.

> From the introduction:
>
> ---
>
> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
> problem is that on OMAP4 we have to enable an optional clock before calling
> pm_runtime_get(), and similarly we need to keep the optional clock enabled
> until after pm_runtime_put() has been called.

Just to clarify, what exactly does the opt clock have to be enabled for?

From what I can gather, this particular opt clock has to be enabled for
the hwmod itself to be enabled (or disabled), correct?

This has been a known issue for reset[1], but I wasn't aware that it was
needed for a normal (re)enable of the hwmod.

> This causes some extra complications. For example, we can't use runtime_resume
> callback to enable the opt clocks, as they are required before calling
> pm_runtime_get().
>

Yuck.

> ---
>
> So, the opt clock handling required by the driver pretty much messes the
> whole idea of pm_runtime callbacks here. We can't do pretty much
> anything in the suspend and resume callbacks.
>
> We can't do save_context() in the suspend callback, because suspend
> could be called later, after pm_runtime_put_sync() and
> dispc_runtime_put() has returned. And and that point we've turned off
> the opt clock and can't touch the registers. If we'd move the opt-clock
> clk_disable to suspend, but clk_enable in dispc_runtime_get(), we'd get
> mismatched clk_disable/enable, so we can't do that. etc.

Double yuck.

It's clear now that you at least wanted to do the "right" thing and
thought about the variousways to do it, but weren't able to for various
reasons.  Thanks!

> I didn't come up with any other solutions to this. In the end, the
> dispc_runtime_get/put are quite clean functions (well, says me =), and
> their usage is more or less equivalent to pm_runtime_get/put. So I don't
> see it as a horrible solution.

I agree, it's not horrible.  Just induces very mild nausea.  ;)

> If and when the hwmod/pm_runtime/something handles this opt-clock issue,
> it shouldn't be too big of a job to use pm_runtime properly in the
> omapdss. 

Agreed.  I certainly won't hold up this patch unless we come up with an
alternate solution very quickly (which I will try below, and wait for
Paul/Benoit to correct me.)

> Of course, if you or somebody else has a solution for this now, I'm
> more than happy to use it =).

I don't have a solid solution, but so far, this sounds like an IP
requirement that should be managed at the hwmod level.

One approach would be to have an option to selectively manage optional
clocks in the hwmod enable/idle path.  We're doing it for reset[1], but
not for anything else.  And based on the changelog there[1], it doesn't
even sound like we fully understand the exact requirements around reset.

From the contortions you've had to go through though, it sounds like the
same optional clocks that are needed for reset are needed for a "normal"
module enable/disable.

I tried a simple hack to do that below[2].  Can you see if that works
for you and if you can remove the opt clk mgmt from your driver(s)?  I
only boot tested it on 3430/n900 which only has this opt-clk flag set
for the GPIO IP blocks.
 
Another idea off the top of my head is to extend runtime PM to have a
couple additional callbacks.  Something like ->runtime_resume_prepare()
which would be called before the HW is enabled (and thus before
->runtime_resume()), and similarily ->runtime_suspend_complete() which
would be called after ->runtime_suspend() and after the HW has been
disabled.

I don't really like this approach because so far this is the only driver
that has needed something like this.  And in the case of this IP the
enable/disable of the optional clocks seems like a HW requirement for
the correct enable/disable of the IP, so it seems like something that
should be managed by the hwmod.

Now I'll wait for Benoit/Paul to enlighten us.

> And this opt-clock problem pretty much covers all your comments below,
> except one which I've answered also.
>
>> IOW, this function should simply be a pm_runtime_get_sync(), and the
>> rest of the stuff in this function should be done in the
>> ->runtime_resume() callback, which is only executed when the usage_count
>> transitions from zero.
>> 
>> > +		DSSDBG("dispc_runtime_get\n");
>> > +
>> > +		r = dss_runtime_get();
>> > +		if (r)
>> > +			goto err_dss_get;
>> > +
>> > +		/* XXX dispc fclk can also come from DSI PLL */
>> > +		clk_enable(dispc.dss_clk);
>> > +
>> > +		r = pm_runtime_get_sync(&dispc.pdev->dev);
>> > +		WARN_ON(r);
>> > +		if (r < 0)
>> > +			goto err_runtime_get;
>> > +
>> > +		if (dispc_need_ctx_restore())
>> > +			dispc_restore_context();
>> > +	}
>> > +
>> > +	mutex_unlock(&dispc.runtime_lock);
>> > +
>> > +	return 0;
>> > +
>> > +err_runtime_get:
>> > +	clk_disable(dispc.dss_clk);
>> > +	dss_runtime_put();
>> > +err_dss_get:
>> > +	mutex_unlock(&dispc.runtime_lock);
>> > +
>> > +	return r;
>> >  }
>> >  
>> > +void dispc_runtime_put(void)
>> > +{
>> > +	mutex_lock(&dispc.runtime_lock);
>> > +
>> > +	if (--dispc.runtime_count = 0) {
>> > +		int r;
>> 
>> Same problem here.  
>> 
>> No usage counting is required (and probably no locking either.)  This
>> function should simply be a pm_runtime_put(), and the rest of the stuff
>> should be in the driver's ->runtime_suspend() callback.
>> 
>> > +		DSSDBG("dispc_runtime_put\n");
>> > +
>> > +		dispc_save_context();
>> > +
>> > +		r = pm_runtime_put_sync(&dispc.pdev->dev);
>> 
>> Does this need to be the _sync() version?  It looks like it could be use
>> the "normal" (async) version.: pm_runtime_put().
>
> It's sync because we turn off the opt clock below, and the HW shouldn't
> be touched after that, which I guess pm_runtime_put (or the subsequent
> async suspend) could do.

OK, I see now.

Kevin


[1]
commit 96835af970e5d6aeedf868e53590a947be5e4a7a
Author: Benoit Cousson <b-cousson@ti.com>
Date:   Tue Sep 21 18:57:58 2010 +0200

    OMAP: hwmod: Fix softreset for modules with optional clocks
    
    Some modules (like GPIO, DSS...) require optionals clock to be enabled
    in order to complete the sofreset properly.
    Add a HWMOD_CONTROL_OPT_CLKS_IN_RESET flag to force all optional clocks
    to be enabled before reset. Disabled them once the reset is done.
    
    TODO:
    For the moment it is very hard to understand from the HW spec, which
    optional clock is needed and which one is not. So the current approach
    will enable all the optional clocks.
    Paul proposed a much finer approach that will allow to tag only the needed
    clock in the optional clock table. This might be doable as soon as we have
    a clear understanding of these dependencies.
    
    Reported-by: Partha Basak <p-basak2@ti.com>
    Signed-off-by: Benoit Cousson <b-cousson@ti.com>
    Signed-off-by: Paul Walmsley <paul@pwsan.com>
    Cc: Kevin Hilman <khilman@deeprootsystems.com>


[2]
From d2806a4148fbed869eff8703b1137cd35d16ef53 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@ti.com>
Date: Fri, 3 Jun 2011 15:33:25 -0700
Subject: [PATCH] OMAP2+: omap_hwmod: selectively manage optional clocks in enable/disable

Only-a-Test-Hack-and-Certainly-Not-Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6c..7bcf802 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -586,6 +586,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
 	return ret;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh);
+static void _disable_optional_clocks(struct omap_hwmod *oh);
+
 /**
  * _enable_clocks - enable hwmod main clock and interface clocks
  * @oh: struct omap_hwmod *
@@ -599,6 +602,9 @@ static int _enable_clocks(struct omap_hwmod *oh)
 
 	pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
 
+	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+		_enable_optional_clocks(oh);
+
 	if (oh->_clk)
 		clk_enable(oh->_clk);
 
@@ -642,6 +648,9 @@ static int _disable_clocks(struct omap_hwmod *oh)
 		}
 	}
 
+	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+		_disable_optional_clocks(oh);
+
 	/* The opt clocks are controlled by the device driver. */
 
 	return 0;
-- 
1.7.4


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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-03 22:53         ` Kevin Hilman
  0 siblings, 0 replies; 108+ messages in thread
From: Kevin Hilman @ 2011-06-03 22:53 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, b-cousson, paul

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> Hi Kevin,
>
> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
>> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
>> 
>> > Use PM runtime and HWMOD support to handle enabling and disabling of DSS
>> > modules.
>> >
>> > Each DSS module will have get and put functions which can be used to
>> > enable and disable that module. The functions use pm_runtime and hwmod
>> > opt-clocks to enable the hardware.
>> >
>> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> 
>> [...]
>> 
>> > +int dispc_runtime_get(void)
>> > +{
>> > +	int r;
>> > +
>> > +	mutex_lock(&dispc.runtime_lock);
>> 
>> It's not clear to me what the lock is trying to protect.  I guess it's
>> the counter?  I don't think it should be needed...
>
> Yes, the counter. I don't think
>
> if (dispc.runtime_count++ == 0)
>
> is thread safe.

OK, if it's just the counter, you can drop the mutex and use an atomic
variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
from reading what exactly is protected.

>> > +	if (dispc.runtime_count++ == 0) {
>> 
>> You shouldn't need your own use-counting here.  The runtime PM core is
>> already doing usage counting.
>> 
>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
>> core when the usage count goes to/from zero.
>
> Yes, I wish I could do that =).
>
> I tried to explain this in the 00-patch, I guess I should've explained
> it in this patch also. Perhaps also in a comment.

Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
about DSS, so I was focused in on the runtime PM implementation only.
Sorry about that.

> From the introduction:
>
> ---
>
> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
> problem is that on OMAP4 we have to enable an optional clock before calling
> pm_runtime_get(), and similarly we need to keep the optional clock enabled
> until after pm_runtime_put() has been called.

Just to clarify, what exactly does the opt clock have to be enabled for?

>From what I can gather, this particular opt clock has to be enabled for
the hwmod itself to be enabled (or disabled), correct?

This has been a known issue for reset[1], but I wasn't aware that it was
needed for a normal (re)enable of the hwmod.

> This causes some extra complications. For example, we can't use runtime_resume
> callback to enable the opt clocks, as they are required before calling
> pm_runtime_get().
>

Yuck.

> ---
>
> So, the opt clock handling required by the driver pretty much messes the
> whole idea of pm_runtime callbacks here. We can't do pretty much
> anything in the suspend and resume callbacks.
>
> We can't do save_context() in the suspend callback, because suspend
> could be called later, after pm_runtime_put_sync() and
> dispc_runtime_put() has returned. And and that point we've turned off
> the opt clock and can't touch the registers. If we'd move the opt-clock
> clk_disable to suspend, but clk_enable in dispc_runtime_get(), we'd get
> mismatched clk_disable/enable, so we can't do that. etc.

Double yuck.

It's clear now that you at least wanted to do the "right" thing and
thought about the variousways to do it, but weren't able to for various
reasons.  Thanks!

> I didn't come up with any other solutions to this. In the end, the
> dispc_runtime_get/put are quite clean functions (well, says me =), and
> their usage is more or less equivalent to pm_runtime_get/put. So I don't
> see it as a horrible solution.

I agree, it's not horrible.  Just induces very mild nausea.  ;)

> If and when the hwmod/pm_runtime/something handles this opt-clock issue,
> it shouldn't be too big of a job to use pm_runtime properly in the
> omapdss. 

Agreed.  I certainly won't hold up this patch unless we come up with an
alternate solution very quickly (which I will try below, and wait for
Paul/Benoit to correct me.)

> Of course, if you or somebody else has a solution for this now, I'm
> more than happy to use it =).

I don't have a solid solution, but so far, this sounds like an IP
requirement that should be managed at the hwmod level.

One approach would be to have an option to selectively manage optional
clocks in the hwmod enable/idle path.  We're doing it for reset[1], but
not for anything else.  And based on the changelog there[1], it doesn't
even sound like we fully understand the exact requirements around reset.

>From the contortions you've had to go through though, it sounds like the
same optional clocks that are needed for reset are needed for a "normal"
module enable/disable.

I tried a simple hack to do that below[2].  Can you see if that works
for you and if you can remove the opt clk mgmt from your driver(s)?  I
only boot tested it on 3430/n900 which only has this opt-clk flag set
for the GPIO IP blocks.
 
Another idea off the top of my head is to extend runtime PM to have a
couple additional callbacks.  Something like ->runtime_resume_prepare()
which would be called before the HW is enabled (and thus before
->runtime_resume()), and similarily ->runtime_suspend_complete() which
would be called after ->runtime_suspend() and after the HW has been
disabled.

I don't really like this approach because so far this is the only driver
that has needed something like this.  And in the case of this IP the
enable/disable of the optional clocks seems like a HW requirement for
the correct enable/disable of the IP, so it seems like something that
should be managed by the hwmod.

Now I'll wait for Benoit/Paul to enlighten us.

> And this opt-clock problem pretty much covers all your comments below,
> except one which I've answered also.
>
>> IOW, this function should simply be a pm_runtime_get_sync(), and the
>> rest of the stuff in this function should be done in the
>> ->runtime_resume() callback, which is only executed when the usage_count
>> transitions from zero.
>> 
>> > +		DSSDBG("dispc_runtime_get\n");
>> > +
>> > +		r = dss_runtime_get();
>> > +		if (r)
>> > +			goto err_dss_get;
>> > +
>> > +		/* XXX dispc fclk can also come from DSI PLL */
>> > +		clk_enable(dispc.dss_clk);
>> > +
>> > +		r = pm_runtime_get_sync(&dispc.pdev->dev);
>> > +		WARN_ON(r);
>> > +		if (r < 0)
>> > +			goto err_runtime_get;
>> > +
>> > +		if (dispc_need_ctx_restore())
>> > +			dispc_restore_context();
>> > +	}
>> > +
>> > +	mutex_unlock(&dispc.runtime_lock);
>> > +
>> > +	return 0;
>> > +
>> > +err_runtime_get:
>> > +	clk_disable(dispc.dss_clk);
>> > +	dss_runtime_put();
>> > +err_dss_get:
>> > +	mutex_unlock(&dispc.runtime_lock);
>> > +
>> > +	return r;
>> >  }
>> >  
>> > +void dispc_runtime_put(void)
>> > +{
>> > +	mutex_lock(&dispc.runtime_lock);
>> > +
>> > +	if (--dispc.runtime_count == 0) {
>> > +		int r;
>> 
>> Same problem here.  
>> 
>> No usage counting is required (and probably no locking either.)  This
>> function should simply be a pm_runtime_put(), and the rest of the stuff
>> should be in the driver's ->runtime_suspend() callback.
>> 
>> > +		DSSDBG("dispc_runtime_put\n");
>> > +
>> > +		dispc_save_context();
>> > +
>> > +		r = pm_runtime_put_sync(&dispc.pdev->dev);
>> 
>> Does this need to be the _sync() version?  It looks like it could be use
>> the "normal" (async) version.: pm_runtime_put().
>
> It's sync because we turn off the opt clock below, and the HW shouldn't
> be touched after that, which I guess pm_runtime_put (or the subsequent
> async suspend) could do.

OK, I see now.

Kevin


[1]
commit 96835af970e5d6aeedf868e53590a947be5e4a7a
Author: Benoit Cousson <b-cousson@ti.com>
Date:   Tue Sep 21 18:57:58 2010 +0200

    OMAP: hwmod: Fix softreset for modules with optional clocks
    
    Some modules (like GPIO, DSS...) require optionals clock to be enabled
    in order to complete the sofreset properly.
    Add a HWMOD_CONTROL_OPT_CLKS_IN_RESET flag to force all optional clocks
    to be enabled before reset. Disabled them once the reset is done.
    
    TODO:
    For the moment it is very hard to understand from the HW spec, which
    optional clock is needed and which one is not. So the current approach
    will enable all the optional clocks.
    Paul proposed a much finer approach that will allow to tag only the needed
    clock in the optional clock table. This might be doable as soon as we have
    a clear understanding of these dependencies.
    
    Reported-by: Partha Basak <p-basak2@ti.com>
    Signed-off-by: Benoit Cousson <b-cousson@ti.com>
    Signed-off-by: Paul Walmsley <paul@pwsan.com>
    Cc: Kevin Hilman <khilman@deeprootsystems.com>


[2]
>From d2806a4148fbed869eff8703b1137cd35d16ef53 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@ti.com>
Date: Fri, 3 Jun 2011 15:33:25 -0700
Subject: [PATCH] OMAP2+: omap_hwmod: selectively manage optional clocks in enable/disable

Only-a-Test-Hack-and-Certainly-Not-Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 293fa6c..7bcf802 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -586,6 +586,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
 	return ret;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh);
+static void _disable_optional_clocks(struct omap_hwmod *oh);
+
 /**
  * _enable_clocks - enable hwmod main clock and interface clocks
  * @oh: struct omap_hwmod *
@@ -599,6 +602,9 @@ static int _enable_clocks(struct omap_hwmod *oh)
 
 	pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
 
+	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+		_enable_optional_clocks(oh);
+
 	if (oh->_clk)
 		clk_enable(oh->_clk);
 
@@ -642,6 +648,9 @@ static int _disable_clocks(struct omap_hwmod *oh)
 		}
 	}
 
+	if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+		_disable_optional_clocks(oh);
+
 	/* The opt clocks are controlled by the device driver. */
 
 	return 0;
-- 
1.7.4


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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-03 22:53         ` Kevin Hilman
@ 2011-06-04  8:01           ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-04  8:01 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, linux-fbdev, b-cousson, paul

On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > Hi Kevin,
> >
> > On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
> >> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> >> 
> >> > Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> >> > modules.
> >> >
> >> > Each DSS module will have get and put functions which can be used to
> >> > enable and disable that module. The functions use pm_runtime and hwmod
> >> > opt-clocks to enable the hardware.
> >> >
> >> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >> 
> >> [...]
> >> 
> >> > +int dispc_runtime_get(void)
> >> > +{
> >> > +	int r;
> >> > +
> >> > +	mutex_lock(&dispc.runtime_lock);
> >> 
> >> It's not clear to me what the lock is trying to protect.  I guess it's
> >> the counter?  I don't think it should be needed...
> >
> > Yes, the counter. I don't think
> >
> > if (dispc.runtime_count++ = 0)
> >
> > is thread safe.
> 
> OK, if it's just the counter, you can drop the mutex and use an atomic
> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
> from reading what exactly is protected.

Hmm, sorry, my mistake. It's actually for the whole function: we can't
do "put" before the whole "get" has finished. Otherwise we could end up,
for example, disabling a clock before enabling it.

> >> > +	if (dispc.runtime_count++ = 0) {
> >> 
> >> You shouldn't need your own use-counting here.  The runtime PM core is
> >> already doing usage counting.
> >> 
> >> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
> >> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
> >> core when the usage count goes to/from zero.
> >
> > Yes, I wish I could do that =).
> >
> > I tried to explain this in the 00-patch, I guess I should've explained
> > it in this patch also. Perhaps also in a comment.
> 
> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
> about DSS, so I was focused in on the runtime PM implementation only.
> Sorry about that.
> 
> > From the introduction:
> >
> > ---
> >
> > Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
> > problem is that on OMAP4 we have to enable an optional clock before calling
> > pm_runtime_get(), and similarly we need to keep the optional clock enabled
> > until after pm_runtime_put() has been called.
> 
> Just to clarify, what exactly does the opt clock have to be enabled for?

I'm not sure if this is a valid definition, but in my mind the opt clock
has two uses: 1) a functional clock, to make the HW tick and registers
accessible, and 2) act as a source clock for the outgoing pixel clock.

Of these, the first one is the one that matters in this scope. So, it's
a mandatory clock, but it's optional in the sense that there are other
clocks that can be used in place of that clock.

All OMAPs support the DSS fclk from PRCM (this is the default). If I
remember right, OMAP2 also supports using sys clock as the DSS fclk.
OMAP3 and 4 support using DSI PLL (whose source clock is sys clock) as
the fclk.

> From what I can gather, this particular opt clock has to be enabled for
> the hwmod itself to be enabled (or disabled), correct?

Yes, the registers are unaccessible and the HW doesn't come out of reset
without the fclk.

> This has been a known issue for reset[1], but I wasn't aware that it was
> needed for a normal (re)enable of the hwmod.
> 
> > This causes some extra complications. For example, we can't use runtime_resume
> > callback to enable the opt clocks, as they are required before calling
> > pm_runtime_get().
> >
> 
> Yuck.
> 
> > ---
> >
> > So, the opt clock handling required by the driver pretty much messes the
> > whole idea of pm_runtime callbacks here. We can't do pretty much
> > anything in the suspend and resume callbacks.
> >
> > We can't do save_context() in the suspend callback, because suspend
> > could be called later, after pm_runtime_put_sync() and
> > dispc_runtime_put() has returned. And and that point we've turned off
> > the opt clock and can't touch the registers. If we'd move the opt-clock
> > clk_disable to suspend, but clk_enable in dispc_runtime_get(), we'd get
> > mismatched clk_disable/enable, so we can't do that. etc.
> 
> Double yuck.
> 
> It's clear now that you at least wanted to do the "right" thing and
> thought about the variousways to do it, but weren't able to for various
> reasons.  Thanks!
> 
> > I didn't come up with any other solutions to this. In the end, the
> > dispc_runtime_get/put are quite clean functions (well, says me =), and
> > their usage is more or less equivalent to pm_runtime_get/put. So I don't
> > see it as a horrible solution.
> 
> I agree, it's not horrible.  Just induces very mild nausea.  ;)
> 
> > If and when the hwmod/pm_runtime/something handles this opt-clock issue,
> > it shouldn't be too big of a job to use pm_runtime properly in the
> > omapdss. 
> 
> Agreed.  I certainly won't hold up this patch unless we come up with an
> alternate solution very quickly (which I will try below, and wait for
> Paul/Benoit to correct me.)
> 
> > Of course, if you or somebody else has a solution for this now, I'm
> > more than happy to use it =).
> 
> I don't have a solid solution, but so far, this sounds like an IP
> requirement that should be managed at the hwmod level.

I agree.

How I imagine things should work is that the hwmod code defaults to the
standard PRCM clock, but allows us to change the functional clock at a
later time, allowing the original clock to be disabled.

But I don't know how this would work in practice. The DSI PLL clock has
to be programmed via DSI HW, and the bits that control the clock muxes
are inside DSS. So the HWMOD code can't probably handle this by itself,
but needs the DSS to do certain things at certain times.

> One approach would be to have an option to selectively manage optional
> clocks in the hwmod enable/idle path.  We're doing it for reset[1], but
> not for anything else.  And based on the changelog there[1], it doesn't
> even sound like we fully understand the exact requirements around reset.

Yes, the OMAP4 DSS reset is a bit unclear for me.

> From the contortions you've had to go through though, it sounds like the
> same optional clocks that are needed for reset are needed for a "normal"
> module enable/disable.
> 
> I tried a simple hack to do that below[2].  Can you see if that works
> for you and if you can remove the opt clk mgmt from your driver(s)?  I
> only boot tested it on 3430/n900 which only has this opt-clk flag set
> for the GPIO IP blocks.

I didn't test it yet, but I would imagine it works. But it doesn't help
us towards properly using the other clocks as fclk.

However, it's not really any worse than the current DSS code. We don't
currently turn off the DSS fclk from the PRCM, even if we would use the
clock from the DSI PLL.

So perhaps an approach where hwmod would enable the fclk from the PRCM
automatically would be good. It's no worse than the other option, and 
it'd give us the ability to use pm_runtime in the proper way.

In this (hopefully temporary) solution the clock wouldn't really be
optional clock, but mandatory.

> Another idea off the top of my head is to extend runtime PM to have a
> couple additional callbacks.  Something like ->runtime_resume_prepare()
> which would be called before the HW is enabled (and thus before
> ->runtime_resume()), and similarily ->runtime_suspend_complete() which
> would be called after ->runtime_suspend() and after the HW has been
> disabled.
> 
> I don't really like this approach because so far this is the only driver
> that has needed something like this.  And in the case of this IP the
> enable/disable of the optional clocks seems like a HW requirement for
> the correct enable/disable of the IP, so it seems like something that
> should be managed by the hwmod.

Yes, I agree, that doesn't sound like a very good approach.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-04  8:01           ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-04  8:01 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, linux-fbdev, b-cousson, paul

On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > Hi Kevin,
> >
> > On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
> >> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> >> 
> >> > Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> >> > modules.
> >> >
> >> > Each DSS module will have get and put functions which can be used to
> >> > enable and disable that module. The functions use pm_runtime and hwmod
> >> > opt-clocks to enable the hardware.
> >> >
> >> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >> 
> >> [...]
> >> 
> >> > +int dispc_runtime_get(void)
> >> > +{
> >> > +	int r;
> >> > +
> >> > +	mutex_lock(&dispc.runtime_lock);
> >> 
> >> It's not clear to me what the lock is trying to protect.  I guess it's
> >> the counter?  I don't think it should be needed...
> >
> > Yes, the counter. I don't think
> >
> > if (dispc.runtime_count++ == 0)
> >
> > is thread safe.
> 
> OK, if it's just the counter, you can drop the mutex and use an atomic
> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
> from reading what exactly is protected.

Hmm, sorry, my mistake. It's actually for the whole function: we can't
do "put" before the whole "get" has finished. Otherwise we could end up,
for example, disabling a clock before enabling it.

> >> > +	if (dispc.runtime_count++ == 0) {
> >> 
> >> You shouldn't need your own use-counting here.  The runtime PM core is
> >> already doing usage counting.
> >> 
> >> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
> >> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
> >> core when the usage count goes to/from zero.
> >
> > Yes, I wish I could do that =).
> >
> > I tried to explain this in the 00-patch, I guess I should've explained
> > it in this patch also. Perhaps also in a comment.
> 
> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
> about DSS, so I was focused in on the runtime PM implementation only.
> Sorry about that.
> 
> > From the introduction:
> >
> > ---
> >
> > Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
> > problem is that on OMAP4 we have to enable an optional clock before calling
> > pm_runtime_get(), and similarly we need to keep the optional clock enabled
> > until after pm_runtime_put() has been called.
> 
> Just to clarify, what exactly does the opt clock have to be enabled for?

I'm not sure if this is a valid definition, but in my mind the opt clock
has two uses: 1) a functional clock, to make the HW tick and registers
accessible, and 2) act as a source clock for the outgoing pixel clock.

Of these, the first one is the one that matters in this scope. So, it's
a mandatory clock, but it's optional in the sense that there are other
clocks that can be used in place of that clock.

All OMAPs support the DSS fclk from PRCM (this is the default). If I
remember right, OMAP2 also supports using sys clock as the DSS fclk.
OMAP3 and 4 support using DSI PLL (whose source clock is sys clock) as
the fclk.

> From what I can gather, this particular opt clock has to be enabled for
> the hwmod itself to be enabled (or disabled), correct?

Yes, the registers are unaccessible and the HW doesn't come out of reset
without the fclk.

> This has been a known issue for reset[1], but I wasn't aware that it was
> needed for a normal (re)enable of the hwmod.
> 
> > This causes some extra complications. For example, we can't use runtime_resume
> > callback to enable the opt clocks, as they are required before calling
> > pm_runtime_get().
> >
> 
> Yuck.
> 
> > ---
> >
> > So, the opt clock handling required by the driver pretty much messes the
> > whole idea of pm_runtime callbacks here. We can't do pretty much
> > anything in the suspend and resume callbacks.
> >
> > We can't do save_context() in the suspend callback, because suspend
> > could be called later, after pm_runtime_put_sync() and
> > dispc_runtime_put() has returned. And and that point we've turned off
> > the opt clock and can't touch the registers. If we'd move the opt-clock
> > clk_disable to suspend, but clk_enable in dispc_runtime_get(), we'd get
> > mismatched clk_disable/enable, so we can't do that. etc.
> 
> Double yuck.
> 
> It's clear now that you at least wanted to do the "right" thing and
> thought about the variousways to do it, but weren't able to for various
> reasons.  Thanks!
> 
> > I didn't come up with any other solutions to this. In the end, the
> > dispc_runtime_get/put are quite clean functions (well, says me =), and
> > their usage is more or less equivalent to pm_runtime_get/put. So I don't
> > see it as a horrible solution.
> 
> I agree, it's not horrible.  Just induces very mild nausea.  ;)
> 
> > If and when the hwmod/pm_runtime/something handles this opt-clock issue,
> > it shouldn't be too big of a job to use pm_runtime properly in the
> > omapdss. 
> 
> Agreed.  I certainly won't hold up this patch unless we come up with an
> alternate solution very quickly (which I will try below, and wait for
> Paul/Benoit to correct me.)
> 
> > Of course, if you or somebody else has a solution for this now, I'm
> > more than happy to use it =).
> 
> I don't have a solid solution, but so far, this sounds like an IP
> requirement that should be managed at the hwmod level.

I agree.

How I imagine things should work is that the hwmod code defaults to the
standard PRCM clock, but allows us to change the functional clock at a
later time, allowing the original clock to be disabled.

But I don't know how this would work in practice. The DSI PLL clock has
to be programmed via DSI HW, and the bits that control the clock muxes
are inside DSS. So the HWMOD code can't probably handle this by itself,
but needs the DSS to do certain things at certain times.

> One approach would be to have an option to selectively manage optional
> clocks in the hwmod enable/idle path.  We're doing it for reset[1], but
> not for anything else.  And based on the changelog there[1], it doesn't
> even sound like we fully understand the exact requirements around reset.

Yes, the OMAP4 DSS reset is a bit unclear for me.

> From the contortions you've had to go through though, it sounds like the
> same optional clocks that are needed for reset are needed for a "normal"
> module enable/disable.
> 
> I tried a simple hack to do that below[2].  Can you see if that works
> for you and if you can remove the opt clk mgmt from your driver(s)?  I
> only boot tested it on 3430/n900 which only has this opt-clk flag set
> for the GPIO IP blocks.

I didn't test it yet, but I would imagine it works. But it doesn't help
us towards properly using the other clocks as fclk.

However, it's not really any worse than the current DSS code. We don't
currently turn off the DSS fclk from the PRCM, even if we would use the
clock from the DSI PLL.

So perhaps an approach where hwmod would enable the fclk from the PRCM
automatically would be good. It's no worse than the other option, and 
it'd give us the ability to use pm_runtime in the proper way.

In this (hopefully temporary) solution the clock wouldn't really be
optional clock, but mandatory.

> Another idea off the top of my head is to extend runtime PM to have a
> couple additional callbacks.  Something like ->runtime_resume_prepare()
> which would be called before the HW is enabled (and thus before
> ->runtime_resume()), and similarily ->runtime_suspend_complete() which
> would be called after ->runtime_suspend() and after the HW has been
> disabled.
> 
> I don't really like this approach because so far this is the only driver
> that has needed something like this.  And in the case of this IP the
> enable/disable of the optional clocks seems like a HW requirement for
> the correct enable/disable of the IP, so it seems like something that
> should be managed by the hwmod.

Yes, I agree, that doesn't sound like a very good approach.

 Tomi



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

* Re: [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
  2011-06-03 10:00   ` Tomi Valkeinen
@ 2011-06-06  5:53     ` Archit Taneja
  -1 siblings, 0 replies; 108+ messages in thread
From: Archit Taneja @ 2011-06-06  5:41 UTC (permalink / raw)
  To: Valkeinen, Tomi
  Cc: linux-omap, linux-fbdev, Cousson, Benoit, paul, Hilman, Kevin

Hi,

On Friday 03 June 2011 03:30 PM, Valkeinen, Tomi wrote:
> LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause
> any problems currently, as DSI HW is reset when it is enabled. However,
> if the reset is not done, operation fails if the bits are still set.
>
> So reset the bits after entering ULPS to ensure operation even without
> HW reset.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dsi.c |    4 ++++
>   1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> index 69c2d4f..4496d09 100644
> --- a/drivers/video/omap2/dss/dsi.c
> +++ b/drivers/video/omap2/dss/dsi.c
> @@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
>   	dsi_unregister_isr_cio(dsidev, dsi_completion_handler,&completion,
>   			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
>
> +	/* Reset LANEx_ULPS_SIG2 */
> +	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0<<  0) | (0<<  1) | (0<<  2),
> +		7, 5);
> +

We may need to reset more lanes based on the number of lanes the panel 
is using. We could calculate a mask here instead.

Archit
>   	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
>
>   	dsi_if_enable(dsidev, false);


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

* Re: [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
@ 2011-06-06  5:53     ` Archit Taneja
  0 siblings, 0 replies; 108+ messages in thread
From: Archit Taneja @ 2011-06-06  5:53 UTC (permalink / raw)
  To: Valkeinen, Tomi
  Cc: linux-omap, linux-fbdev, Cousson, Benoit, paul, Hilman, Kevin

Hi,

On Friday 03 June 2011 03:30 PM, Valkeinen, Tomi wrote:
> LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause
> any problems currently, as DSI HW is reset when it is enabled. However,
> if the reset is not done, operation fails if the bits are still set.
>
> So reset the bits after entering ULPS to ensure operation even without
> HW reset.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dsi.c |    4 ++++
>   1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> index 69c2d4f..4496d09 100644
> --- a/drivers/video/omap2/dss/dsi.c
> +++ b/drivers/video/omap2/dss/dsi.c
> @@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
>   	dsi_unregister_isr_cio(dsidev, dsi_completion_handler,&completion,
>   			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
>
> +	/* Reset LANEx_ULPS_SIG2 */
> +	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0<<  0) | (0<<  1) | (0<<  2),
> +		7, 5);
> +

We may need to reset more lanes based on the number of lanes the panel 
is using. We could calculate a mask here instead.

Archit
>   	dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
>
>   	dsi_if_enable(dsidev, false);


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

* Re: [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
  2011-06-06  5:53     ` Archit Taneja
@ 2011-06-06  7:21       ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06  7:21 UTC (permalink / raw)
  To: Archit Taneja
  Cc: linux-omap, linux-fbdev, Cousson, Benoit, paul, Hilman, Kevin

On Mon, 2011-06-06 at 11:11 +0530, Archit Taneja wrote:
> Hi,
> 
> On Friday 03 June 2011 03:30 PM, Valkeinen, Tomi wrote:
> > LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause
> > any problems currently, as DSI HW is reset when it is enabled. However,
> > if the reset is not done, operation fails if the bits are still set.
> >
> > So reset the bits after entering ULPS to ensure operation even without
> > HW reset.
> >
> > Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> > ---
> >   drivers/video/omap2/dss/dsi.c |    4 ++++
> >   1 files changed, 4 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> > index 69c2d4f..4496d09 100644
> > --- a/drivers/video/omap2/dss/dsi.c
> > +++ b/drivers/video/omap2/dss/dsi.c
> > @@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
> >   	dsi_unregister_isr_cio(dsidev, dsi_completion_handler,&completion,
> >   			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
> >
> > +	/* Reset LANEx_ULPS_SIG2 */
> > +	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0<<  0) | (0<<  1) | (0<<  2),
> > +		7, 5);
> > +
> 
> We may need to reset more lanes based on the number of lanes the panel 
> is using. We could calculate a mask here instead.

Yes, I noticed that but I decided just to fix the bug here. The same
bits are set a few lines earlier.

We should go through all the lane configs in dsi.c, and come up with a
way to easily get the necessary masks.

 Tomi



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

* Re: [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
@ 2011-06-06  7:21       ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06  7:21 UTC (permalink / raw)
  To: Archit Taneja
  Cc: linux-omap, linux-fbdev, Cousson, Benoit, paul, Hilman, Kevin

On Mon, 2011-06-06 at 11:11 +0530, Archit Taneja wrote:
> Hi,
> 
> On Friday 03 June 2011 03:30 PM, Valkeinen, Tomi wrote:
> > LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause
> > any problems currently, as DSI HW is reset when it is enabled. However,
> > if the reset is not done, operation fails if the bits are still set.
> >
> > So reset the bits after entering ULPS to ensure operation even without
> > HW reset.
> >
> > Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> > ---
> >   drivers/video/omap2/dss/dsi.c |    4 ++++
> >   1 files changed, 4 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> > index 69c2d4f..4496d09 100644
> > --- a/drivers/video/omap2/dss/dsi.c
> > +++ b/drivers/video/omap2/dss/dsi.c
> > @@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
> >   	dsi_unregister_isr_cio(dsidev, dsi_completion_handler,&completion,
> >   			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
> >
> > +	/* Reset LANEx_ULPS_SIG2 */
> > +	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0<<  0) | (0<<  1) | (0<<  2),
> > +		7, 5);
> > +
> 
> We may need to reset more lanes based on the number of lanes the panel 
> is using. We could calculate a mask here instead.

Yes, I noticed that but I decided just to fix the bug here. The same
bits are set a few lines earlier.

We should go through all the lane configs in dsi.c, and come up with a
way to easily get the necessary masks.

 Tomi



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

* Re: [PATCH 01/27] OMAP: change get_context_loss_count ret value to
  2011-06-03 16:32     ` Kevin Hilman
@ 2011-06-06  7:28       ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06  7:28 UTC (permalink / raw)
  To: Kevin Hilman, paul; +Cc: linux-omap, linux-fbdev, b-cousson

On Fri, 2011-06-03 at 09:32 -0700, Kevin Hilman wrote:
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > get_context_loss_count functions return context loss count as u32, and
> > zero means an error. However, zero is also returned when context has
> > never been lost and could also be returned when the context loss count
> > has wrapped and goes to zero.
> >
> > Change the functions to return an int, with negative value meaning an
> > error.
> >
> > OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the
> > hsmmc code handles the returned value as an int, with negative value
> > meaning an error, this patch actually fixes hsmmc code also.
> >
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> > Acked-by: Kevin Hilman <khilman@ti.com>
> 
> This one should be separated out into a fix for v3.0-rc, and queued by
> Paul (also Cc'd to linux-arm-kernel.)

Yup, I added it here for completeness to get a working patch series. The
same patch has also been sent separately.

 Tomi



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

* Re: [PATCH 01/27] OMAP: change get_context_loss_count ret value to int
@ 2011-06-06  7:28       ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06  7:28 UTC (permalink / raw)
  To: Kevin Hilman, paul; +Cc: linux-omap, linux-fbdev, b-cousson

On Fri, 2011-06-03 at 09:32 -0700, Kevin Hilman wrote:
> Tomi Valkeinen <tomi.valkeinen@ti.com> writes:
> 
> > get_context_loss_count functions return context loss count as u32, and
> > zero means an error. However, zero is also returned when context has
> > never been lost and could also be returned when the context loss count
> > has wrapped and goes to zero.
> >
> > Change the functions to return an int, with negative value meaning an
> > error.
> >
> > OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the
> > hsmmc code handles the returned value as an int, with negative value
> > meaning an error, this patch actually fixes hsmmc code also.
> >
> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> > Acked-by: Kevin Hilman <khilman@ti.com>
> 
> This one should be separated out into a fix for v3.0-rc, and queued by
> Paul (also Cc'd to linux-arm-kernel.)

Yup, I added it here for completeness to get a working patch series. The
same patch has also been sent separately.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-04  8:01           ` Tomi Valkeinen
@ 2011-06-06 12:56             ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 12:56 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

Hi Tomi,

On 6/4/2011 10:01 AM, Valkeinen, Tomi wrote:
> On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
>> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
>>
>>> Hi Kevin,
>>>
>>> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
>>>> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
>>>>
>>>>> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
>>>>> modules.
>>>>>
>>>>> Each DSS module will have get and put functions which can be used to
>>>>> enable and disable that module. The functions use pm_runtime and hwmod
>>>>> opt-clocks to enable the hardware.
>>>>>
>>>>> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
>>>>
>>>> [...]
>>>>
>>>>> +int dispc_runtime_get(void)
>>>>> +{
>>>>> +	int r;
>>>>> +
>>>>> +	mutex_lock(&dispc.runtime_lock);
>>>>
>>>> It's not clear to me what the lock is trying to protect.  I guess it's
>>>> the counter?  I don't think it should be needed...
>>>
>>> Yes, the counter. I don't think
>>>
>>> if (dispc.runtime_count++ = 0)
>>>
>>> is thread safe.
>>
>> OK, if it's just the counter, you can drop the mutex and use an atomic
>> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
>> from reading what exactly is protected.
>
> Hmm, sorry, my mistake. It's actually for the whole function: we can't
> do "put" before the whole "get" has finished. Otherwise we could end up,
> for example, disabling a clock before enabling it.
>
>>>>> +	if (dispc.runtime_count++ = 0) {
>>>>
>>>> You shouldn't need your own use-counting here.  The runtime PM core is
>>>> already doing usage counting.
>>>>
>>>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
>>>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
>>>> core when the usage count goes to/from zero.
>>>
>>> Yes, I wish I could do that =).
>>>
>>> I tried to explain this in the 00-patch, I guess I should've explained
>>> it in this patch also. Perhaps also in a comment.
>>
>> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
>> about DSS, so I was focused in on the runtime PM implementation only.
>> Sorry about that.
>>
>>>  From the introduction:
>>>
>>> ---
>>>
>>> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
>>> problem is that on OMAP4 we have to enable an optional clock before calling
>>> pm_runtime_get(), and similarly we need to keep the optional clock enabled
>>> until after pm_runtime_put() has been called.
>>
>> Just to clarify, what exactly does the opt clock have to be enabled for?
>
> I'm not sure if this is a valid definition, but in my mind the opt clock
> has two uses: 1) a functional clock, to make the HW tick and registers
> accessible, and 2) act as a source clock for the outgoing pixel clock.

That terminology in the PRCM just means that an opt clock will not be 
handled automatically by the PRCM and will require SW control.
This is not the case for mandatory clock. Upon module enable the PRCM 
will ensure that all mandatory clocks (functional and interface) are 
enabled automagically. If the clock is marked as optional it means that 
the SW will have to enable it explicitly before enabling the module.

The modulemode was not there previously on OMAP2 & 3, but it is more or 
less equivalent to icken=1 + fcken=1.
This idea was to hide the explicit clock management especially for the 
iclk that were already supposed to always be in autoidle.

Since the current hwmod + clock fmwks are still based on the previous 
clock centric approach we used to have on OMAP2 & 3, we cannot match 
properly the modulemode to any clock and thus cannot handle properly the 
DSS fclk as the main clock instead of the optional clock.

A temporary option will be to consider the modulemode as the interface 
clock and thus remove it from the main_clk and replace it by the real 
DSS fclk.

It should work be will unfortunately not be compliant with PRCM 
recommendation to enable the modulemode once every clocks are enabled.

The long term solution is to update the hwmod fmwk to handle the 
modulemode directly and not through the clock fmwk. It will allow the 
main_clk to be connnected to the dss_fclk.

You will not have that nasty opt_clock issue anymore.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 12:56             ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 12:56 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

Hi Tomi,

On 6/4/2011 10:01 AM, Valkeinen, Tomi wrote:
> On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
>> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
>>
>>> Hi Kevin,
>>>
>>> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
>>>> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
>>>>
>>>>> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
>>>>> modules.
>>>>>
>>>>> Each DSS module will have get and put functions which can be used to
>>>>> enable and disable that module. The functions use pm_runtime and hwmod
>>>>> opt-clocks to enable the hardware.
>>>>>
>>>>> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
>>>>
>>>> [...]
>>>>
>>>>> +int dispc_runtime_get(void)
>>>>> +{
>>>>> +	int r;
>>>>> +
>>>>> +	mutex_lock(&dispc.runtime_lock);
>>>>
>>>> It's not clear to me what the lock is trying to protect.  I guess it's
>>>> the counter?  I don't think it should be needed...
>>>
>>> Yes, the counter. I don't think
>>>
>>> if (dispc.runtime_count++ == 0)
>>>
>>> is thread safe.
>>
>> OK, if it's just the counter, you can drop the mutex and use an atomic
>> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
>> from reading what exactly is protected.
>
> Hmm, sorry, my mistake. It's actually for the whole function: we can't
> do "put" before the whole "get" has finished. Otherwise we could end up,
> for example, disabling a clock before enabling it.
>
>>>>> +	if (dispc.runtime_count++ == 0) {
>>>>
>>>> You shouldn't need your own use-counting here.  The runtime PM core is
>>>> already doing usage counting.
>>>>
>>>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
>>>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
>>>> core when the usage count goes to/from zero.
>>>
>>> Yes, I wish I could do that =).
>>>
>>> I tried to explain this in the 00-patch, I guess I should've explained
>>> it in this patch also. Perhaps also in a comment.
>>
>> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
>> about DSS, so I was focused in on the runtime PM implementation only.
>> Sorry about that.
>>
>>>  From the introduction:
>>>
>>> ---
>>>
>>> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
>>> problem is that on OMAP4 we have to enable an optional clock before calling
>>> pm_runtime_get(), and similarly we need to keep the optional clock enabled
>>> until after pm_runtime_put() has been called.
>>
>> Just to clarify, what exactly does the opt clock have to be enabled for?
>
> I'm not sure if this is a valid definition, but in my mind the opt clock
> has two uses: 1) a functional clock, to make the HW tick and registers
> accessible, and 2) act as a source clock for the outgoing pixel clock.

That terminology in the PRCM just means that an opt clock will not be 
handled automatically by the PRCM and will require SW control.
This is not the case for mandatory clock. Upon module enable the PRCM 
will ensure that all mandatory clocks (functional and interface) are 
enabled automagically. If the clock is marked as optional it means that 
the SW will have to enable it explicitly before enabling the module.

The modulemode was not there previously on OMAP2 & 3, but it is more or 
less equivalent to icken=1 + fcken=1.
This idea was to hide the explicit clock management especially for the 
iclk that were already supposed to always be in autoidle.

Since the current hwmod + clock fmwks are still based on the previous 
clock centric approach we used to have on OMAP2 & 3, we cannot match 
properly the modulemode to any clock and thus cannot handle properly the 
DSS fclk as the main clock instead of the optional clock.

A temporary option will be to consider the modulemode as the interface 
clock and thus remove it from the main_clk and replace it by the real 
DSS fclk.

It should work be will unfortunately not be compliant with PRCM 
recommendation to enable the modulemode once every clocks are enabled.

The long term solution is to update the hwmod fmwk to handle the 
modulemode directly and not through the clock fmwk. It will allow the 
main_clk to be connnected to the dss_fclk.

You will not have that nasty opt_clock issue anymore.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 12:56             ` Cousson, Benoit
@ 2011-06-06 13:01               ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06 13:01 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
> Hi Tomi,
> 
> On 6/4/2011 10:01 AM, Valkeinen, Tomi wrote:
> > On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
> >> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
> >>
> >>> Hi Kevin,
> >>>
> >>> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
> >>>> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
> >>>>
> >>>>> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> >>>>> modules.
> >>>>>
> >>>>> Each DSS module will have get and put functions which can be used to
> >>>>> enable and disable that module. The functions use pm_runtime and hwmod
> >>>>> opt-clocks to enable the hardware.
> >>>>>
> >>>>> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> >>>>
> >>>> [...]
> >>>>
> >>>>> +int dispc_runtime_get(void)
> >>>>> +{
> >>>>> +	int r;
> >>>>> +
> >>>>> +	mutex_lock(&dispc.runtime_lock);
> >>>>
> >>>> It's not clear to me what the lock is trying to protect.  I guess it's
> >>>> the counter?  I don't think it should be needed...
> >>>
> >>> Yes, the counter. I don't think
> >>>
> >>> if (dispc.runtime_count++ = 0)
> >>>
> >>> is thread safe.
> >>
> >> OK, if it's just the counter, you can drop the mutex and use an atomic
> >> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
> >> from reading what exactly is protected.
> >
> > Hmm, sorry, my mistake. It's actually for the whole function: we can't
> > do "put" before the whole "get" has finished. Otherwise we could end up,
> > for example, disabling a clock before enabling it.
> >
> >>>>> +	if (dispc.runtime_count++ = 0) {
> >>>>
> >>>> You shouldn't need your own use-counting here.  The runtime PM core is
> >>>> already doing usage counting.
> >>>>
> >>>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
> >>>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
> >>>> core when the usage count goes to/from zero.
> >>>
> >>> Yes, I wish I could do that =).
> >>>
> >>> I tried to explain this in the 00-patch, I guess I should've explained
> >>> it in this patch also. Perhaps also in a comment.
> >>
> >> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
> >> about DSS, so I was focused in on the runtime PM implementation only.
> >> Sorry about that.
> >>
> >>>  From the introduction:
> >>>
> >>> ---
> >>>
> >>> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
> >>> problem is that on OMAP4 we have to enable an optional clock before calling
> >>> pm_runtime_get(), and similarly we need to keep the optional clock enabled
> >>> until after pm_runtime_put() has been called.
> >>
> >> Just to clarify, what exactly does the opt clock have to be enabled for?
> >
> > I'm not sure if this is a valid definition, but in my mind the opt clock
> > has two uses: 1) a functional clock, to make the HW tick and registers
> > accessible, and 2) act as a source clock for the outgoing pixel clock.
> 
> That terminology in the PRCM just means that an opt clock will not be 
> handled automatically by the PRCM and will require SW control.
> This is not the case for mandatory clock. Upon module enable the PRCM 
> will ensure that all mandatory clocks (functional and interface) are 
> enabled automagically. If the clock is marked as optional it means that 
> the SW will have to enable it explicitly before enabling the module.
> 
> The modulemode was not there previously on OMAP2 & 3, but it is more or 
> less equivalent to icken=1 + fcken=1.
> This idea was to hide the explicit clock management especially for the 
> iclk that were already supposed to always be in autoidle.
> 
> Since the current hwmod + clock fmwks are still based on the previous 
> clock centric approach we used to have on OMAP2 & 3, we cannot match 
> properly the modulemode to any clock and thus cannot handle properly the 
> DSS fclk as the main clock instead of the optional clock.
> 
> A temporary option will be to consider the modulemode as the interface 
> clock and thus remove it from the main_clk and replace it by the real 
> DSS fclk.
> 
> It should work be will unfortunately not be compliant with PRCM 
> recommendation to enable the modulemode once every clocks are enabled.
> 
> The long term solution is to update the hwmod fmwk to handle the 
> modulemode directly and not through the clock fmwk. It will allow the 
> main_clk to be connnected to the dss_fclk.
> 
> You will not have that nasty opt_clock issue anymore.

In this long term solution, if the dss_fclk is the main_clk, how does
the framework handle the situation when we want to switch from the
standard DSS fclk to the one from DSI PLL?

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 13:01               ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06 13:01 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
> Hi Tomi,
> 
> On 6/4/2011 10:01 AM, Valkeinen, Tomi wrote:
> > On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
> >> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
> >>
> >>> Hi Kevin,
> >>>
> >>> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
> >>>> Tomi Valkeinen<tomi.valkeinen@ti.com>  writes:
> >>>>
> >>>>> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
> >>>>> modules.
> >>>>>
> >>>>> Each DSS module will have get and put functions which can be used to
> >>>>> enable and disable that module. The functions use pm_runtime and hwmod
> >>>>> opt-clocks to enable the hardware.
> >>>>>
> >>>>> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> >>>>
> >>>> [...]
> >>>>
> >>>>> +int dispc_runtime_get(void)
> >>>>> +{
> >>>>> +	int r;
> >>>>> +
> >>>>> +	mutex_lock(&dispc.runtime_lock);
> >>>>
> >>>> It's not clear to me what the lock is trying to protect.  I guess it's
> >>>> the counter?  I don't think it should be needed...
> >>>
> >>> Yes, the counter. I don't think
> >>>
> >>> if (dispc.runtime_count++ == 0)
> >>>
> >>> is thread safe.
> >>
> >> OK, if it's just the counter, you can drop the mutex and use an atomic
> >> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
> >> from reading what exactly is protected.
> >
> > Hmm, sorry, my mistake. It's actually for the whole function: we can't
> > do "put" before the whole "get" has finished. Otherwise we could end up,
> > for example, disabling a clock before enabling it.
> >
> >>>>> +	if (dispc.runtime_count++ == 0) {
> >>>>
> >>>> You shouldn't need your own use-counting here.  The runtime PM core is
> >>>> already doing usage counting.
> >>>>
> >>>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
> >>>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
> >>>> core when the usage count goes to/from zero.
> >>>
> >>> Yes, I wish I could do that =).
> >>>
> >>> I tried to explain this in the 00-patch, I guess I should've explained
> >>> it in this patch also. Perhaps also in a comment.
> >>
> >> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
> >> about DSS, so I was focused in on the runtime PM implementation only.
> >> Sorry about that.
> >>
> >>>  From the introduction:
> >>>
> >>> ---
> >>>
> >>> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
> >>> problem is that on OMAP4 we have to enable an optional clock before calling
> >>> pm_runtime_get(), and similarly we need to keep the optional clock enabled
> >>> until after pm_runtime_put() has been called.
> >>
> >> Just to clarify, what exactly does the opt clock have to be enabled for?
> >
> > I'm not sure if this is a valid definition, but in my mind the opt clock
> > has two uses: 1) a functional clock, to make the HW tick and registers
> > accessible, and 2) act as a source clock for the outgoing pixel clock.
> 
> That terminology in the PRCM just means that an opt clock will not be 
> handled automatically by the PRCM and will require SW control.
> This is not the case for mandatory clock. Upon module enable the PRCM 
> will ensure that all mandatory clocks (functional and interface) are 
> enabled automagically. If the clock is marked as optional it means that 
> the SW will have to enable it explicitly before enabling the module.
> 
> The modulemode was not there previously on OMAP2 & 3, but it is more or 
> less equivalent to icken=1 + fcken=1.
> This idea was to hide the explicit clock management especially for the 
> iclk that were already supposed to always be in autoidle.
> 
> Since the current hwmod + clock fmwks are still based on the previous 
> clock centric approach we used to have on OMAP2 & 3, we cannot match 
> properly the modulemode to any clock and thus cannot handle properly the 
> DSS fclk as the main clock instead of the optional clock.
> 
> A temporary option will be to consider the modulemode as the interface 
> clock and thus remove it from the main_clk and replace it by the real 
> DSS fclk.
> 
> It should work be will unfortunately not be compliant with PRCM 
> recommendation to enable the modulemode once every clocks are enabled.
> 
> The long term solution is to update the hwmod fmwk to handle the 
> modulemode directly and not through the clock fmwk. It will allow the 
> main_clk to be connnected to the dss_fclk.
> 
> You will not have that nasty opt_clock issue anymore.

In this long term solution, if the dss_fclk is the main_clk, how does
the framework handle the situation when we want to switch from the
standard DSS fclk to the one from DSI PLL?

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 13:01               ` Tomi Valkeinen
@ 2011-06-06 13:15                 ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 13:15 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>> Hi Tomi,
>>
>> On 6/4/2011 10:01 AM, Valkeinen, Tomi wrote:
>>> On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
>>>> Tomi Valkeinen<tomi.valkeinen@ti.com>   writes:
>>>>
>>>>> Hi Kevin,
>>>>>
>>>>> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
>>>>>> Tomi Valkeinen<tomi.valkeinen@ti.com>   writes:
>>>>>>
>>>>>>> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
>>>>>>> modules.
>>>>>>>
>>>>>>> Each DSS module will have get and put functions which can be used to
>>>>>>> enable and disable that module. The functions use pm_runtime and hwmod
>>>>>>> opt-clocks to enable the hardware.
>>>>>>>
>>>>>>> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>> +int dispc_runtime_get(void)
>>>>>>> +{
>>>>>>> +	int r;
>>>>>>> +
>>>>>>> +	mutex_lock(&dispc.runtime_lock);
>>>>>>
>>>>>> It's not clear to me what the lock is trying to protect.  I guess it's
>>>>>> the counter?  I don't think it should be needed...
>>>>>
>>>>> Yes, the counter. I don't think
>>>>>
>>>>> if (dispc.runtime_count++ = 0)
>>>>>
>>>>> is thread safe.
>>>>
>>>> OK, if it's just the counter, you can drop the mutex and use an atomic
>>>> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
>>>> from reading what exactly is protected.
>>>
>>> Hmm, sorry, my mistake. It's actually for the whole function: we can't
>>> do "put" before the whole "get" has finished. Otherwise we could end up,
>>> for example, disabling a clock before enabling it.
>>>
>>>>>>> +	if (dispc.runtime_count++ = 0) {
>>>>>>
>>>>>> You shouldn't need your own use-counting here.  The runtime PM core is
>>>>>> already doing usage counting.
>>>>>>
>>>>>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
>>>>>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
>>>>>> core when the usage count goes to/from zero.
>>>>>
>>>>> Yes, I wish I could do that =).
>>>>>
>>>>> I tried to explain this in the 00-patch, I guess I should've explained
>>>>> it in this patch also. Perhaps also in a comment.
>>>>
>>>> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
>>>> about DSS, so I was focused in on the runtime PM implementation only.
>>>> Sorry about that.
>>>>
>>>>>    From the introduction:
>>>>>
>>>>> ---
>>>>>
>>>>> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
>>>>> problem is that on OMAP4 we have to enable an optional clock before calling
>>>>> pm_runtime_get(), and similarly we need to keep the optional clock enabled
>>>>> until after pm_runtime_put() has been called.
>>>>
>>>> Just to clarify, what exactly does the opt clock have to be enabled for?
>>>
>>> I'm not sure if this is a valid definition, but in my mind the opt clock
>>> has two uses: 1) a functional clock, to make the HW tick and registers
>>> accessible, and 2) act as a source clock for the outgoing pixel clock.
>>
>> That terminology in the PRCM just means that an opt clock will not be
>> handled automatically by the PRCM and will require SW control.
>> This is not the case for mandatory clock. Upon module enable the PRCM
>> will ensure that all mandatory clocks (functional and interface) are
>> enabled automagically. If the clock is marked as optional it means that
>> the SW will have to enable it explicitly before enabling the module.
>>
>> The modulemode was not there previously on OMAP2&  3, but it is more or
>> less equivalent to icken=1 + fcken=1.
>> This idea was to hide the explicit clock management especially for the
>> iclk that were already supposed to always be in autoidle.
>>
>> Since the current hwmod + clock fmwks are still based on the previous
>> clock centric approach we used to have on OMAP2&  3, we cannot match
>> properly the modulemode to any clock and thus cannot handle properly the
>> DSS fclk as the main clock instead of the optional clock.
>>
>> A temporary option will be to consider the modulemode as the interface
>> clock and thus remove it from the main_clk and replace it by the real
>> DSS fclk.
>>
>> It should work be will unfortunately not be compliant with PRCM
>> recommendation to enable the modulemode once every clocks are enabled.
>>
>> The long term solution is to update the hwmod fmwk to handle the
>> modulemode directly and not through the clock fmwk. It will allow the
>> main_clk to be connnected to the dss_fclk.
>>
>> You will not have that nasty opt_clock issue anymore.
>
> In this long term solution, if the dss_fclk is the main_clk, how does
> the framework handle the situation when we want to switch from the
> standard DSS fclk to the one from DSI PLL?

That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk 
is to ensure that the module is accessible by the driver whatever the 
PRCM clock used.
Enabling the DSI PLL will require the PRCM clock to be enabled first.

Using the DSI PLL as the fclk is doable, but is it really useful or needed?
Assuming you need that mode, you will always have to explicitly switch 
from DSI to PRCM clock before trying to disable the DSS.
This is something you will have to do inside the DSS driver. It should 
be transparent to the hwmod fmwk.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 13:15                 ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 13:15 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>> Hi Tomi,
>>
>> On 6/4/2011 10:01 AM, Valkeinen, Tomi wrote:
>>> On Fri, 2011-06-03 at 15:53 -0700, Kevin Hilman wrote:
>>>> Tomi Valkeinen<tomi.valkeinen@ti.com>   writes:
>>>>
>>>>> Hi Kevin,
>>>>>
>>>>> On Fri, 2011-06-03 at 09:45 -0700, Kevin Hilman wrote:
>>>>>> Tomi Valkeinen<tomi.valkeinen@ti.com>   writes:
>>>>>>
>>>>>>> Use PM runtime and HWMOD support to handle enabling and disabling of DSS
>>>>>>> modules.
>>>>>>>
>>>>>>> Each DSS module will have get and put functions which can be used to
>>>>>>> enable and disable that module. The functions use pm_runtime and hwmod
>>>>>>> opt-clocks to enable the hardware.
>>>>>>>
>>>>>>> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>> +int dispc_runtime_get(void)
>>>>>>> +{
>>>>>>> +	int r;
>>>>>>> +
>>>>>>> +	mutex_lock(&dispc.runtime_lock);
>>>>>>
>>>>>> It's not clear to me what the lock is trying to protect.  I guess it's
>>>>>> the counter?  I don't think it should be needed...
>>>>>
>>>>> Yes, the counter. I don't think
>>>>>
>>>>> if (dispc.runtime_count++ == 0)
>>>>>
>>>>> is thread safe.
>>>>
>>>> OK, if it's just the counter, you can drop the mutex and use an atomic
>>>> variable and use atomic_inc(), atomic_dec() etc.  Then it will be clear
>>>> from reading what exactly is protected.
>>>
>>> Hmm, sorry, my mistake. It's actually for the whole function: we can't
>>> do "put" before the whole "get" has finished. Otherwise we could end up,
>>> for example, disabling a clock before enabling it.
>>>
>>>>>>> +	if (dispc.runtime_count++ == 0) {
>>>>>>
>>>>>> You shouldn't need your own use-counting here.  The runtime PM core is
>>>>>> already doing usage counting.
>>>>>>
>>>>>> Instead, you need to use the ->runtime_suspend() and ->runtime_resume()
>>>>>> callbacks (in dev_pm_ops).  These callbacks are called by the runtime PM
>>>>>> core when the usage count goes to/from zero.
>>>>>
>>>>> Yes, I wish I could do that =).
>>>>>
>>>>> I tried to explain this in the 00-patch, I guess I should've explained
>>>>> it in this patch also. Perhaps also in a comment.
>>>>
>>>> Oops, my fault.  I didn't read the whole 00 patch.  I'm pretty ignorant
>>>> about DSS, so I was focused in on the runtime PM implementation only.
>>>> Sorry about that.
>>>>
>>>>>    From the introduction:
>>>>>
>>>>> ---
>>>>>
>>>>> Due to DSS' peculiar clock setup the code is not as elegant as I'd like. The
>>>>> problem is that on OMAP4 we have to enable an optional clock before calling
>>>>> pm_runtime_get(), and similarly we need to keep the optional clock enabled
>>>>> until after pm_runtime_put() has been called.
>>>>
>>>> Just to clarify, what exactly does the opt clock have to be enabled for?
>>>
>>> I'm not sure if this is a valid definition, but in my mind the opt clock
>>> has two uses: 1) a functional clock, to make the HW tick and registers
>>> accessible, and 2) act as a source clock for the outgoing pixel clock.
>>
>> That terminology in the PRCM just means that an opt clock will not be
>> handled automatically by the PRCM and will require SW control.
>> This is not the case for mandatory clock. Upon module enable the PRCM
>> will ensure that all mandatory clocks (functional and interface) are
>> enabled automagically. If the clock is marked as optional it means that
>> the SW will have to enable it explicitly before enabling the module.
>>
>> The modulemode was not there previously on OMAP2&  3, but it is more or
>> less equivalent to icken=1 + fcken=1.
>> This idea was to hide the explicit clock management especially for the
>> iclk that were already supposed to always be in autoidle.
>>
>> Since the current hwmod + clock fmwks are still based on the previous
>> clock centric approach we used to have on OMAP2&  3, we cannot match
>> properly the modulemode to any clock and thus cannot handle properly the
>> DSS fclk as the main clock instead of the optional clock.
>>
>> A temporary option will be to consider the modulemode as the interface
>> clock and thus remove it from the main_clk and replace it by the real
>> DSS fclk.
>>
>> It should work be will unfortunately not be compliant with PRCM
>> recommendation to enable the modulemode once every clocks are enabled.
>>
>> The long term solution is to update the hwmod fmwk to handle the
>> modulemode directly and not through the clock fmwk. It will allow the
>> main_clk to be connnected to the dss_fclk.
>>
>> You will not have that nasty opt_clock issue anymore.
>
> In this long term solution, if the dss_fclk is the main_clk, how does
> the framework handle the situation when we want to switch from the
> standard DSS fclk to the one from DSI PLL?

That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk 
is to ensure that the module is accessible by the driver whatever the 
PRCM clock used.
Enabling the DSI PLL will require the PRCM clock to be enabled first.

Using the DSI PLL as the fclk is doable, but is it really useful or needed?
Assuming you need that mode, you will always have to explicitly switch 
from DSI to PRCM clock before trying to disable the DSS.
This is something you will have to do inside the DSS driver. It should 
be transparent to the hwmod fmwk.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 13:15                 ` Cousson, Benoit
@ 2011-06-06 13:21                   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06 13:21 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
> > On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:

> > In this long term solution, if the dss_fclk is the main_clk, how does
> > the framework handle the situation when we want to switch from the
> > standard DSS fclk to the one from DSI PLL?
> 
> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk 
> is to ensure that the module is accessible by the driver whatever the 
> PRCM clock used.
> Enabling the DSI PLL will require the PRCM clock to be enabled first.
> 
> Using the DSI PLL as the fclk is doable, but is it really useful or needed?

Yes, it's useful and needed. It gives us much finer control to the clock
frequencies, and so allows us to go to higher frequencies and also more
exactly to the required pixel clock.

> Assuming you need that mode, you will always have to explicitly switch 
> from DSI to PRCM clock before trying to disable the DSS.
> This is something you will have to do inside the DSS driver. It should 
> be transparent to the hwmod fmwk.

This sounds ok.

I think the main question is how do we disable the standard DSS fclk
from PRCM when using DSI PLL? As far as I know, disabling that clock
will allow some areas of OMAP to be shut down even while DSS is working.
So from power management point of view it sounds a needed feature.

If the clock is main_clk for the HWMOD, it sounds to me it's always
enabled if the HWMOD is enabled?

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 13:21                   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06 13:21 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
> > On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:

> > In this long term solution, if the dss_fclk is the main_clk, how does
> > the framework handle the situation when we want to switch from the
> > standard DSS fclk to the one from DSI PLL?
> 
> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk 
> is to ensure that the module is accessible by the driver whatever the 
> PRCM clock used.
> Enabling the DSI PLL will require the PRCM clock to be enabled first.
> 
> Using the DSI PLL as the fclk is doable, but is it really useful or needed?

Yes, it's useful and needed. It gives us much finer control to the clock
frequencies, and so allows us to go to higher frequencies and also more
exactly to the required pixel clock.

> Assuming you need that mode, you will always have to explicitly switch 
> from DSI to PRCM clock before trying to disable the DSS.
> This is something you will have to do inside the DSS driver. It should 
> be transparent to the hwmod fmwk.

This sounds ok.

I think the main question is how do we disable the standard DSS fclk
from PRCM when using DSI PLL? As far as I know, disabling that clock
will allow some areas of OMAP to be shut down even while DSS is working.
So from power management point of view it sounds a needed feature.

If the clock is main_clk for the HWMOD, it sounds to me it's always
enabled if the HWMOD is enabled?

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 13:21                   ` Tomi Valkeinen
@ 2011-06-06 13:46                     ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 13:46 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/6/2011 3:21 PM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
>> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
>>> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>
>>> In this long term solution, if the dss_fclk is the main_clk, how does
>>> the framework handle the situation when we want to switch from the
>>> standard DSS fclk to the one from DSI PLL?
>>
>> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk
>> is to ensure that the module is accessible by the driver whatever the
>> PRCM clock used.
>> Enabling the DSI PLL will require the PRCM clock to be enabled first.
>>
>> Using the DSI PLL as the fclk is doable, but is it really useful or needed?
>
> Yes, it's useful and needed. It gives us much finer control to the clock
> frequencies, and so allows us to go to higher frequencies and also more
> exactly to the required pixel clock.
>
>> Assuming you need that mode, you will always have to explicitly switch
>> from DSI to PRCM clock before trying to disable the DSS.
>> This is something you will have to do inside the DSS driver. It should
>> be transparent to the hwmod fmwk.
>
> This sounds ok.
>
> I think the main question is how do we disable the standard DSS fclk
> from PRCM when using DSI PLL? As far as I know, disabling that clock
> will allow some areas of OMAP to be shut down even while DSS is working.
> So from power management point of view it sounds a needed feature.

Yes, at least in theory, but considering that any use case that will 
require the DSI PLL will use a LCD panel + backlight, or an OLED panel 
that will consume 50 times more than the 186 MHz clock, I do not think 
it is really needed.
Moreover, that clock is generated by the PER DPLL that will be always 
enabled in most usecase because it does generate the UART, I2C and most 
basic peripherals clocks. If we cannot gate the PER DPLL, there is no 
saving to expect from gating the DSS fclk only.
Bottom-line is that there is no practical power saving to expect from 
that mode.

> If the clock is main_clk for the HWMOD, it sounds to me it's always
> enabled if the HWMOD is enabled?

Yes, but that sounds to me a good trade off to avoid unnecessary 
complexity in your driver or in the hwmod fmwk.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 13:46                     ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 13:46 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/6/2011 3:21 PM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
>> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
>>> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>
>>> In this long term solution, if the dss_fclk is the main_clk, how does
>>> the framework handle the situation when we want to switch from the
>>> standard DSS fclk to the one from DSI PLL?
>>
>> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk
>> is to ensure that the module is accessible by the driver whatever the
>> PRCM clock used.
>> Enabling the DSI PLL will require the PRCM clock to be enabled first.
>>
>> Using the DSI PLL as the fclk is doable, but is it really useful or needed?
>
> Yes, it's useful and needed. It gives us much finer control to the clock
> frequencies, and so allows us to go to higher frequencies and also more
> exactly to the required pixel clock.
>
>> Assuming you need that mode, you will always have to explicitly switch
>> from DSI to PRCM clock before trying to disable the DSS.
>> This is something you will have to do inside the DSS driver. It should
>> be transparent to the hwmod fmwk.
>
> This sounds ok.
>
> I think the main question is how do we disable the standard DSS fclk
> from PRCM when using DSI PLL? As far as I know, disabling that clock
> will allow some areas of OMAP to be shut down even while DSS is working.
> So from power management point of view it sounds a needed feature.

Yes, at least in theory, but considering that any use case that will 
require the DSI PLL will use a LCD panel + backlight, or an OLED panel 
that will consume 50 times more than the 186 MHz clock, I do not think 
it is really needed.
Moreover, that clock is generated by the PER DPLL that will be always 
enabled in most usecase because it does generate the UART, I2C and most 
basic peripherals clocks. If we cannot gate the PER DPLL, there is no 
saving to expect from gating the DSS fclk only.
Bottom-line is that there is no practical power saving to expect from 
that mode.

> If the clock is main_clk for the HWMOD, it sounds to me it's always
> enabled if the HWMOD is enabled?

Yes, but that sounds to me a good trade off to avoid unnecessary 
complexity in your driver or in the hwmod fmwk.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 13:46                     ` Cousson, Benoit
@ 2011-06-06 13:55                       ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06 13:55 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 15:46 +0200, Cousson, Benoit wrote:
> On 6/6/2011 3:21 PM, Valkeinen, Tomi wrote:
> > On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
> >> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
> >>> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
> >
> >>> In this long term solution, if the dss_fclk is the main_clk, how does
> >>> the framework handle the situation when we want to switch from the
> >>> standard DSS fclk to the one from DSI PLL?
> >>
> >> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk
> >> is to ensure that the module is accessible by the driver whatever the
> >> PRCM clock used.
> >> Enabling the DSI PLL will require the PRCM clock to be enabled first.
> >>
> >> Using the DSI PLL as the fclk is doable, but is it really useful or needed?
> >
> > Yes, it's useful and needed. It gives us much finer control to the clock
> > frequencies, and so allows us to go to higher frequencies and also more
> > exactly to the required pixel clock.
> >
> >> Assuming you need that mode, you will always have to explicitly switch
> >> from DSI to PRCM clock before trying to disable the DSS.
> >> This is something you will have to do inside the DSS driver. It should
> >> be transparent to the hwmod fmwk.
> >
> > This sounds ok.
> >
> > I think the main question is how do we disable the standard DSS fclk
> > from PRCM when using DSI PLL? As far as I know, disabling that clock
> > will allow some areas of OMAP to be shut down even while DSS is working.
> > So from power management point of view it sounds a needed feature.
> 
> Yes, at least in theory, but considering that any use case that will 
> require the DSI PLL will use a LCD panel + backlight, or an OLED panel 
> that will consume 50 times more than the 186 MHz clock, I do not think 
> it is really needed.
> Moreover, that clock is generated by the PER DPLL that will be always 
> enabled in most usecase because it does generate the UART, I2C and most 
> basic peripherals clocks. If we cannot gate the PER DPLL, there is no 
> saving to expect from gating the DSS fclk only.
> Bottom-line is that there is no practical power saving to expect from 
> that mode.
> 
> > If the clock is main_clk for the HWMOD, it sounds to me it's always
> > enabled if the HWMOD is enabled?
> 
> Yes, but that sounds to me a good trade off to avoid unnecessary 
> complexity in your driver or in the hwmod fmwk.

Ok, if there are no real power savings there, then I agree, it's
pointless to add that complexity.

So how do we go forward in short term? I'd very much like to remove all
the "silly" code from the DSS pm_runtime patch series caused by this
opt_clock handling. Is it possible to get some kind of a temporary
solution in the hwmod framework which would somehow solve this from DSS
driver's point of view? A flag that causes hwmod fmwk to enable
opt-clocks automatically? Or is it possible to have more than one
mandatory clock?

This way when your long-term solution is done, the driver would not need
any changes.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 13:55                       ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-06 13:55 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 15:46 +0200, Cousson, Benoit wrote:
> On 6/6/2011 3:21 PM, Valkeinen, Tomi wrote:
> > On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
> >> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
> >>> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
> >
> >>> In this long term solution, if the dss_fclk is the main_clk, how does
> >>> the framework handle the situation when we want to switch from the
> >>> standard DSS fclk to the one from DSI PLL?
> >>
> >> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk
> >> is to ensure that the module is accessible by the driver whatever the
> >> PRCM clock used.
> >> Enabling the DSI PLL will require the PRCM clock to be enabled first.
> >>
> >> Using the DSI PLL as the fclk is doable, but is it really useful or needed?
> >
> > Yes, it's useful and needed. It gives us much finer control to the clock
> > frequencies, and so allows us to go to higher frequencies and also more
> > exactly to the required pixel clock.
> >
> >> Assuming you need that mode, you will always have to explicitly switch
> >> from DSI to PRCM clock before trying to disable the DSS.
> >> This is something you will have to do inside the DSS driver. It should
> >> be transparent to the hwmod fmwk.
> >
> > This sounds ok.
> >
> > I think the main question is how do we disable the standard DSS fclk
> > from PRCM when using DSI PLL? As far as I know, disabling that clock
> > will allow some areas of OMAP to be shut down even while DSS is working.
> > So from power management point of view it sounds a needed feature.
> 
> Yes, at least in theory, but considering that any use case that will 
> require the DSI PLL will use a LCD panel + backlight, or an OLED panel 
> that will consume 50 times more than the 186 MHz clock, I do not think 
> it is really needed.
> Moreover, that clock is generated by the PER DPLL that will be always 
> enabled in most usecase because it does generate the UART, I2C and most 
> basic peripherals clocks. If we cannot gate the PER DPLL, there is no 
> saving to expect from gating the DSS fclk only.
> Bottom-line is that there is no practical power saving to expect from 
> that mode.
> 
> > If the clock is main_clk for the HWMOD, it sounds to me it's always
> > enabled if the HWMOD is enabled?
> 
> Yes, but that sounds to me a good trade off to avoid unnecessary 
> complexity in your driver or in the hwmod fmwk.

Ok, if there are no real power savings there, then I agree, it's
pointless to add that complexity.

So how do we go forward in short term? I'd very much like to remove all
the "silly" code from the DSS pm_runtime patch series caused by this
opt_clock handling. Is it possible to get some kind of a temporary
solution in the hwmod framework which would somehow solve this from DSS
driver's point of view? A flag that causes hwmod fmwk to enable
opt-clocks automatically? Or is it possible to have more than one
mandatory clock?

This way when your long-term solution is done, the driver would not need
any changes.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 13:55                       ` Tomi Valkeinen
@ 2011-06-06 15:28                         ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 15:28 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/6/2011 3:55 PM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 15:46 +0200, Cousson, Benoit wrote:
>> On 6/6/2011 3:21 PM, Valkeinen, Tomi wrote:
>>> On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
>>>> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
>>>>> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>>>
>>>>> In this long term solution, if the dss_fclk is the main_clk, how does
>>>>> the framework handle the situation when we want to switch from the
>>>>> standard DSS fclk to the one from DSI PLL?
>>>>
>>>> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk
>>>> is to ensure that the module is accessible by the driver whatever the
>>>> PRCM clock used.
>>>> Enabling the DSI PLL will require the PRCM clock to be enabled first.
>>>>
>>>> Using the DSI PLL as the fclk is doable, but is it really useful or needed?
>>>
>>> Yes, it's useful and needed. It gives us much finer control to the clock
>>> frequencies, and so allows us to go to higher frequencies and also more
>>> exactly to the required pixel clock.
>>>
>>>> Assuming you need that mode, you will always have to explicitly switch
>>>> from DSI to PRCM clock before trying to disable the DSS.
>>>> This is something you will have to do inside the DSS driver. It should
>>>> be transparent to the hwmod fmwk.
>>>
>>> This sounds ok.
>>>
>>> I think the main question is how do we disable the standard DSS fclk
>>> from PRCM when using DSI PLL? As far as I know, disabling that clock
>>> will allow some areas of OMAP to be shut down even while DSS is working.
>>> So from power management point of view it sounds a needed feature.
>>
>> Yes, at least in theory, but considering that any use case that will
>> require the DSI PLL will use a LCD panel + backlight, or an OLED panel
>> that will consume 50 times more than the 186 MHz clock, I do not think
>> it is really needed.
>> Moreover, that clock is generated by the PER DPLL that will be always
>> enabled in most usecase because it does generate the UART, I2C and most
>> basic peripherals clocks. If we cannot gate the PER DPLL, there is no
>> saving to expect from gating the DSS fclk only.
>> Bottom-line is that there is no practical power saving to expect from
>> that mode.
>>
>>> If the clock is main_clk for the HWMOD, it sounds to me it's always
>>> enabled if the HWMOD is enabled?
>>
>> Yes, but that sounds to me a good trade off to avoid unnecessary
>> complexity in your driver or in the hwmod fmwk.
>
> Ok, if there are no real power savings there, then I agree, it's
> pointless to add that complexity.
>
> So how do we go forward in short term? I'd very much like to remove all
> the "silly" code from the DSS pm_runtime patch series caused by this
> opt_clock handling. Is it possible to get some kind of a temporary
> solution in the hwmod framework which would somehow solve this from DSS
> driver's point of view? A flag that causes hwmod fmwk to enable
> opt-clocks automatically? Or is it possible to have more than one
> mandatory clock?

Before doing that, could you maybe just try something to make OMAP4 
looks a little bit more like OMAP3?

dss_fck -> ick
dss_dss_fck -> main_clk

That should ensure that both modulemode and the PRCM fclk will be 
managed by pm_runtime.

I just did a basic patch for the first module, you should maybe change 
some other entries.

Regards,
Benoit

---
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c 
b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 614d680..4dfd18a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1134,7 +1134,7 @@ static struct omap_hwmod_addr_space 
omap44xx_dss_dma_addrs[] = {
  static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
         .master         = &omap44xx_l3_main_2_hwmod,
         .slave          = &omap44xx_dss_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
         .addr           = omap44xx_dss_dma_addrs,
         .addr_cnt       = ARRAY_SIZE(omap44xx_dss_dma_addrs),
         .user           = OCP_USER_SDMA,
@@ -1167,14 +1167,13 @@ static struct omap_hwmod_ocp_if 
*omap44xx_dss_slaves[] = {
  static struct omap_hwmod_opt_clk dss_opt_clks[] = {
         { .role = "sys_clk", .clk = "dss_sys_clk" },
         { .role = "tv_clk", .clk = "dss_tv_clk" },
-       { .role = "dss_clk", .clk = "dss_dss_clk" },
         { .role = "video_clk", .clk = "dss_48mhz_clk" },
  };

  static struct omap_hwmod omap44xx_dss_hwmod = {
         .name           = "dss_core",
         .class          = &omap44xx_dss_hwmod_class,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_fck",
         .prcm           = {
                 .omap4 = {
                         .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-06 15:28                         ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-06 15:28 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/6/2011 3:55 PM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 15:46 +0200, Cousson, Benoit wrote:
>> On 6/6/2011 3:21 PM, Valkeinen, Tomi wrote:
>>> On Mon, 2011-06-06 at 15:15 +0200, Cousson, Benoit wrote:
>>>> On 6/6/2011 3:01 PM, Valkeinen, Tomi wrote:
>>>>> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>>>
>>>>> In this long term solution, if the dss_fclk is the main_clk, how does
>>>>> the framework handle the situation when we want to switch from the
>>>>> standard DSS fclk to the one from DSI PLL?
>>>>
>>>> That part cannot be done by the hwmod fmwk anyway. The goal of the fmwk
>>>> is to ensure that the module is accessible by the driver whatever the
>>>> PRCM clock used.
>>>> Enabling the DSI PLL will require the PRCM clock to be enabled first.
>>>>
>>>> Using the DSI PLL as the fclk is doable, but is it really useful or needed?
>>>
>>> Yes, it's useful and needed. It gives us much finer control to the clock
>>> frequencies, and so allows us to go to higher frequencies and also more
>>> exactly to the required pixel clock.
>>>
>>>> Assuming you need that mode, you will always have to explicitly switch
>>>> from DSI to PRCM clock before trying to disable the DSS.
>>>> This is something you will have to do inside the DSS driver. It should
>>>> be transparent to the hwmod fmwk.
>>>
>>> This sounds ok.
>>>
>>> I think the main question is how do we disable the standard DSS fclk
>>> from PRCM when using DSI PLL? As far as I know, disabling that clock
>>> will allow some areas of OMAP to be shut down even while DSS is working.
>>> So from power management point of view it sounds a needed feature.
>>
>> Yes, at least in theory, but considering that any use case that will
>> require the DSI PLL will use a LCD panel + backlight, or an OLED panel
>> that will consume 50 times more than the 186 MHz clock, I do not think
>> it is really needed.
>> Moreover, that clock is generated by the PER DPLL that will be always
>> enabled in most usecase because it does generate the UART, I2C and most
>> basic peripherals clocks. If we cannot gate the PER DPLL, there is no
>> saving to expect from gating the DSS fclk only.
>> Bottom-line is that there is no practical power saving to expect from
>> that mode.
>>
>>> If the clock is main_clk for the HWMOD, it sounds to me it's always
>>> enabled if the HWMOD is enabled?
>>
>> Yes, but that sounds to me a good trade off to avoid unnecessary
>> complexity in your driver or in the hwmod fmwk.
>
> Ok, if there are no real power savings there, then I agree, it's
> pointless to add that complexity.
>
> So how do we go forward in short term? I'd very much like to remove all
> the "silly" code from the DSS pm_runtime patch series caused by this
> opt_clock handling. Is it possible to get some kind of a temporary
> solution in the hwmod framework which would somehow solve this from DSS
> driver's point of view? A flag that causes hwmod fmwk to enable
> opt-clocks automatically? Or is it possible to have more than one
> mandatory clock?

Before doing that, could you maybe just try something to make OMAP4 
looks a little bit more like OMAP3?

dss_fck -> ick
dss_dss_fck -> main_clk

That should ensure that both modulemode and the PRCM fclk will be 
managed by pm_runtime.

I just did a basic patch for the first module, you should maybe change 
some other entries.

Regards,
Benoit

---
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c 
b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 614d680..4dfd18a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1134,7 +1134,7 @@ static struct omap_hwmod_addr_space 
omap44xx_dss_dma_addrs[] = {
  static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
         .master         = &omap44xx_l3_main_2_hwmod,
         .slave          = &omap44xx_dss_hwmod,
-       .clk            = "l3_div_ck",
+       .clk            = "dss_fck",
         .addr           = omap44xx_dss_dma_addrs,
         .addr_cnt       = ARRAY_SIZE(omap44xx_dss_dma_addrs),
         .user           = OCP_USER_SDMA,
@@ -1167,14 +1167,13 @@ static struct omap_hwmod_ocp_if 
*omap44xx_dss_slaves[] = {
  static struct omap_hwmod_opt_clk dss_opt_clks[] = {
         { .role = "sys_clk", .clk = "dss_sys_clk" },
         { .role = "tv_clk", .clk = "dss_tv_clk" },
-       { .role = "dss_clk", .clk = "dss_dss_clk" },
         { .role = "video_clk", .clk = "dss_48mhz_clk" },
  };

  static struct omap_hwmod omap44xx_dss_hwmod = {
         .name           = "dss_core",
         .class          = &omap44xx_dss_hwmod_class,
-       .main_clk       = "dss_fck",
+       .main_clk       = "dss_dss_fck",
         .prcm           = {
                 .omap4 = {
                         .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 12:56             ` Cousson, Benoit
@ 2011-06-07  6:47               ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  6:47 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:

> That terminology in the PRCM just means that an opt clock will not be 
> handled automatically by the PRCM and will require SW control.
> This is not the case for mandatory clock. Upon module enable the PRCM 
> will ensure that all mandatory clocks (functional and interface) are 
> enabled automagically. If the clock is marked as optional it means that 
> the SW will have to enable it explicitly before enabling the module.

Is that correct? This would mean that whenever a hwmod has opt clock, it
needs to implement similar hack functions that are present in this
patch, to be able to enable the opt clock before enabling the hwmod, and
to disable the opt clock after disabling the hwmod.

I'd rather hope the optional clock could be enabled whenever the driver
needs it, between enabling and disabling the hwmod.

If it's required that the opt clocks are enabled before enabling the
hwmod, what is the point of having them as optional and driver
controlled? The hwmod fmwk could as well handle the opt clocks in that
case.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07  6:47               ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  6:47 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:

> That terminology in the PRCM just means that an opt clock will not be 
> handled automatically by the PRCM and will require SW control.
> This is not the case for mandatory clock. Upon module enable the PRCM 
> will ensure that all mandatory clocks (functional and interface) are 
> enabled automagically. If the clock is marked as optional it means that 
> the SW will have to enable it explicitly before enabling the module.

Is that correct? This would mean that whenever a hwmod has opt clock, it
needs to implement similar hack functions that are present in this
patch, to be able to enable the opt clock before enabling the hwmod, and
to disable the opt clock after disabling the hwmod.

I'd rather hope the optional clock could be enabled whenever the driver
needs it, between enabling and disabling the hwmod.

If it's required that the opt clocks are enabled before enabling the
hwmod, what is the point of having them as optional and driver
controlled? The hwmod fmwk could as well handle the opt clocks in that
case.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-06 15:28                         ` Cousson, Benoit
@ 2011-06-07  6:52                           ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  6:52 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:

> Before doing that, could you maybe just try something to make OMAP4 
> looks a little bit more like OMAP3?
> 
> dss_fck -> ick
> dss_dss_fck -> main_clk
> 
> That should ensure that both modulemode and the PRCM fclk will be 
> managed by pm_runtime.

I made the changes as you suggested, and while I haven't made the
changes to omapdss yet to see if I can remove the dispc_runtime_get/put
style function, I can boot up and start the dss.

However, after booting up but before enabling the dss driver, I can see
that the clock counts are:

dss_tv_clk 0
dss_sys_clk 0
dss_fck 7
dss_dss_clk 0
dss_48mhz_clk 0

So the modulemode is set for all dss hwmods? Isn't this exactly how it's
_not_ meant to be, as modulemode should be set only after enabling the
fck?

 Tomi


diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index b374cd0..d7d86b6 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1133,7 +1133,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1170,7 +1170,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap44xx_dss_hwmod_class,
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1230,7 +1230,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dispc_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dispc_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1279,7 +1279,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1335,7 +1335,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dsi1_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dsi1_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1377,7 +1377,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
 	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1412,7 +1412,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dsi2_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dsi2_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1449,7 +1449,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
 	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1502,7 +1502,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_hdmi_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_hdmi_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1544,7 +1544,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1595,7 +1595,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_rfbi_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_rfbi_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1634,7 +1634,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.class		= &omap44xx_rfbi_hwmod_class,
 	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1670,7 +1670,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_venc_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_venc_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1707,7 +1707,7 @@ static struct omap_hwmod_opt_clk venc_opt_clks[] = {
 static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07  6:52                           ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  6:52 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:

> Before doing that, could you maybe just try something to make OMAP4 
> looks a little bit more like OMAP3?
> 
> dss_fck -> ick
> dss_dss_fck -> main_clk
> 
> That should ensure that both modulemode and the PRCM fclk will be 
> managed by pm_runtime.

I made the changes as you suggested, and while I haven't made the
changes to omapdss yet to see if I can remove the dispc_runtime_get/put
style function, I can boot up and start the dss.

However, after booting up but before enabling the dss driver, I can see
that the clock counts are:

dss_tv_clk 0
dss_sys_clk 0
dss_fck 7
dss_dss_clk 0
dss_48mhz_clk 0

So the modulemode is set for all dss hwmods? Isn't this exactly how it's
_not_ meant to be, as modulemode should be set only after enabling the
fck?

 Tomi


diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index b374cd0..d7d86b6 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1133,7 +1133,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1170,7 +1170,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap44xx_dss_hwmod_class,
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1230,7 +1230,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dispc_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dispc_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1279,7 +1279,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1335,7 +1335,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dsi1_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dsi1_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1377,7 +1377,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
 	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1412,7 +1412,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_dsi2_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_dsi2_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1449,7 +1449,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
 	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1502,7 +1502,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_hdmi_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_hdmi_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1544,7 +1544,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1595,7 +1595,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_rfbi_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_rfbi_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1634,7 +1634,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.class		= &omap44xx_rfbi_hwmod_class,
 	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -1670,7 +1670,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
 	.master		= &omap44xx_l3_main_2_hwmod,
 	.slave		= &omap44xx_dss_venc_hwmod,
-	.clk		= "l3_div_ck",
+	.clk		= "dss_fck",
 	.addr		= omap44xx_dss_venc_dma_addrs,
 	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
 	.user		= OCP_USER_SDMA,
@@ -1707,7 +1707,7 @@ static struct omap_hwmod_opt_clk venc_opt_clks[] = {
 static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
-	.main_clk	= "dss_fck",
+	.main_clk	= "dss_dss_clk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07  6:47               ` Tomi Valkeinen
@ 2011-06-07  7:12                 ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07  7:12 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 8:47 AM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>
>> That terminology in the PRCM just means that an opt clock will not be
>> handled automatically by the PRCM and will require SW control.
>> This is not the case for mandatory clock. Upon module enable the PRCM
>> will ensure that all mandatory clocks (functional and interface) are
>> enabled automagically. If the clock is marked as optional it means that
>> the SW will have to enable it explicitly before enabling the module.
>
> Is that correct? This would mean that whenever a hwmod has opt clock, it
> needs to implement similar hack functions that are present in this
> patch, to be able to enable the opt clock before enabling the hwmod, and
> to disable the opt clock after disabling the hwmod.

No, because most hwmods with opt_clock does have a real main_clk as 
well. In the case of the GPIO, the driver need to enable the opt clock 
only if the debounce feature is needed.
In general we always have one main functional clock to enable the module 
first.

> I'd rather hope the optional clock could be enabled whenever the driver
> needs it, between enabling and disabling the hwmod.

Yeah, this is the case most of the time, except for you.

> If it's required that the opt clocks are enabled before enabling the
> hwmod, what is the point of having them as optional and driver
> controlled? The hwmod fmwk could as well handle the opt clocks in that
> case.

There is no point... It is just due to the particular clock setting 
required by the DSS. That specific case was simply not taken into 
account originally. You are just the first one to hit that issue :-(

Just because the DSS can choose its main functional clock, the HW team 
decided to mark them all as opt clock, in order to let the SW decide 
which one to use.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07  7:12                 ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07  7:12 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 8:47 AM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 14:56 +0200, Cousson, Benoit wrote:
>
>> That terminology in the PRCM just means that an opt clock will not be
>> handled automatically by the PRCM and will require SW control.
>> This is not the case for mandatory clock. Upon module enable the PRCM
>> will ensure that all mandatory clocks (functional and interface) are
>> enabled automagically. If the clock is marked as optional it means that
>> the SW will have to enable it explicitly before enabling the module.
>
> Is that correct? This would mean that whenever a hwmod has opt clock, it
> needs to implement similar hack functions that are present in this
> patch, to be able to enable the opt clock before enabling the hwmod, and
> to disable the opt clock after disabling the hwmod.

No, because most hwmods with opt_clock does have a real main_clk as 
well. In the case of the GPIO, the driver need to enable the opt clock 
only if the debounce feature is needed.
In general we always have one main functional clock to enable the module 
first.

> I'd rather hope the optional clock could be enabled whenever the driver
> needs it, between enabling and disabling the hwmod.

Yeah, this is the case most of the time, except for you.

> If it's required that the opt clocks are enabled before enabling the
> hwmod, what is the point of having them as optional and driver
> controlled? The hwmod fmwk could as well handle the opt clocks in that
> case.

There is no point... It is just due to the particular clock setting 
required by the DSS. That specific case was simply not taken into 
account originally. You are just the first one to hit that issue :-(

Just because the DSS can choose its main functional clock, the HW team 
decided to mark them all as opt clock, in order to let the SW decide 
which one to use.

Regards,
Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07  7:12                 ` Cousson, Benoit
@ 2011-06-07  7:21                   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  7:21 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 09:12 +0200, Cousson, Benoit wrote:
> On 6/7/2011 8:47 AM, Valkeinen, Tomi wrote:

> > I'd rather hope the optional clock could be enabled whenever the driver
> > needs it, between enabling and disabling the hwmod.
> 
> Yeah, this is the case most of the time, except for you.

Are you talking only about the DSS_FCLK opt-clock from PRCM, or all DSS
opt clocks (sys clk, hdmi clk, tv clk, dac clock)?

I hope the rest of the opt clocks can be enabled later. Although I guess
all/many of them will be needed during reset, but that should be already
handled by the hwmod fmwk.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07  7:21                   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  7:21 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 09:12 +0200, Cousson, Benoit wrote:
> On 6/7/2011 8:47 AM, Valkeinen, Tomi wrote:

> > I'd rather hope the optional clock could be enabled whenever the driver
> > needs it, between enabling and disabling the hwmod.
> 
> Yeah, this is the case most of the time, except for you.

Are you talking only about the DSS_FCLK opt-clock from PRCM, or all DSS
opt clocks (sys clk, hdmi clk, tv clk, dac clock)?

I hope the rest of the opt clocks can be enabled later. Although I guess
all/many of them will be needed during reset, but that should be already
handled by the hwmod fmwk.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07  7:21                   ` Tomi Valkeinen
@ 2011-06-07  7:27                     ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07  7:27 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 9:21 AM, Valkeinen, Tomi wrote:
> On Tue, 2011-06-07 at 09:12 +0200, Cousson, Benoit wrote:
>> On 6/7/2011 8:47 AM, Valkeinen, Tomi wrote:
>
>>> I'd rather hope the optional clock could be enabled whenever the driver
>>> needs it, between enabling and disabling the hwmod.
>>
>> Yeah, this is the case most of the time, except for you.
>
> Are you talking only about the DSS_FCLK opt-clock from PRCM, or all DSS
> opt clocks (sys clk, hdmi clk, tv clk, dac clock)?
>
> I hope the rest of the opt clocks can be enabled later. Although I guess
> all/many of them will be needed during reset, but that should be already
> handled by the hwmod fmwk.

Yes, sorry, for the confusion, but the point is that they all look the 
same to me :-)

The PRCM does not make any difference for any of these opt_clock, they 
are all under SW control.

Except that one of them must be enabled because internally it is used as 
a functional clock.

Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07  7:27                     ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07  7:27 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 9:21 AM, Valkeinen, Tomi wrote:
> On Tue, 2011-06-07 at 09:12 +0200, Cousson, Benoit wrote:
>> On 6/7/2011 8:47 AM, Valkeinen, Tomi wrote:
>
>>> I'd rather hope the optional clock could be enabled whenever the driver
>>> needs it, between enabling and disabling the hwmod.
>>
>> Yeah, this is the case most of the time, except for you.
>
> Are you talking only about the DSS_FCLK opt-clock from PRCM, or all DSS
> opt clocks (sys clk, hdmi clk, tv clk, dac clock)?
>
> I hope the rest of the opt clocks can be enabled later. Although I guess
> all/many of them will be needed during reset, but that should be already
> handled by the hwmod fmwk.

Yes, sorry, for the confusion, but the point is that they all look the 
same to me :-)

The PRCM does not make any difference for any of these opt_clock, they 
are all under SW control.

Except that one of them must be enabled because internally it is used as 
a functional clock.

Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07  6:52                           ` Tomi Valkeinen
@ 2011-06-07  9:08                             ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  9:08 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 09:52 +0300, Tomi Valkeinen wrote:
> On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
> 
> > Before doing that, could you maybe just try something to make OMAP4 
> > looks a little bit more like OMAP3?
> > 
> > dss_fck -> ick
> > dss_dss_fck -> main_clk
> > 
> > That should ensure that both modulemode and the PRCM fclk will be 
> > managed by pm_runtime.
> 
> I made the changes as you suggested, and while I haven't made the
> changes to omapdss yet to see if I can remove the dispc_runtime_get/put
> style function, I can boot up and start the dss.
> 
> However, after booting up but before enabling the dss driver, I can see
> that the clock counts are:
> 
> dss_tv_clk 0
> dss_sys_clk 0
> dss_fck 7
> dss_dss_clk 0
> dss_48mhz_clk 0
> 
> So the modulemode is set for all dss hwmods? Isn't this exactly how it's
> _not_ meant to be, as modulemode should be set only after enabling the
> fck?

This also seems to keep the DSS from going to RET or OFF, at least in
the TI internal PM testing tree.

So is the PM side buggy there, and it shouldn't care about the
modulemode being enabled if other clocks are off, or is it the hwmod
side that's buggy, and it should disable the modulemode also?

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07  9:08                             ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07  9:08 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 09:52 +0300, Tomi Valkeinen wrote:
> On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
> 
> > Before doing that, could you maybe just try something to make OMAP4 
> > looks a little bit more like OMAP3?
> > 
> > dss_fck -> ick
> > dss_dss_fck -> main_clk
> > 
> > That should ensure that both modulemode and the PRCM fclk will be 
> > managed by pm_runtime.
> 
> I made the changes as you suggested, and while I haven't made the
> changes to omapdss yet to see if I can remove the dispc_runtime_get/put
> style function, I can boot up and start the dss.
> 
> However, after booting up but before enabling the dss driver, I can see
> that the clock counts are:
> 
> dss_tv_clk 0
> dss_sys_clk 0
> dss_fck 7
> dss_dss_clk 0
> dss_48mhz_clk 0
> 
> So the modulemode is set for all dss hwmods? Isn't this exactly how it's
> _not_ meant to be, as modulemode should be set only after enabling the
> fck?

This also seems to keep the DSS from going to RET or OFF, at least in
the TI internal PM testing tree.

So is the PM side buggy there, and it shouldn't care about the
modulemode being enabled if other clocks are off, or is it the hwmod
side that's buggy, and it should disable the modulemode also?

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07  6:52                           ` Tomi Valkeinen
@ 2011-06-07 11:37                             ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07 11:37 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 8:52 AM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
>
>> Before doing that, could you maybe just try something to make OMAP4
>> looks a little bit more like OMAP3?
>>
>> dss_fck ->  ick
>> dss_dss_fck ->  main_clk
>>
>> That should ensure that both modulemode and the PRCM fclk will be
>> managed by pm_runtime.
>
> I made the changes as you suggested, and while I haven't made the
> changes to omapdss yet to see if I can remove the dispc_runtime_get/put
> style function, I can boot up and start the dss.
>
> However, after booting up but before enabling the dss driver, I can see
> that the clock counts are:
>
> dss_tv_clk 0
> dss_sys_clk 0
> dss_fck 7
> dss_dss_clk 0
> dss_48mhz_clk 0
>
> So the modulemode is set for all dss hwmods? Isn't this exactly how it's
> _not_ meant to be, as modulemode should be set only after enabling the
> fck?

The issue is that there is only one modulemode for the whole DSS.
Potentially only the dss_hwmod should have it. But then you have to 
ensure that this device is enabled before any other DSS devices.

If you cannot do that at your level, we will have to set a hwmod 
dependency between DSS modules and the main DSS subsystem.
For the moment we do not have such HW dependencies.

Benoit

>
>   Tomi
>
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> index b374cd0..d7d86b6 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> @@ -1133,7 +1133,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1170,7 +1170,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
>   static struct omap_hwmod omap44xx_dss_hwmod = {
>   	.name		= "dss_core",
>   	.class		=&omap44xx_dss_hwmod_class,
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1230,7 +1230,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_dispc_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dispc_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1279,7 +1279,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
>   	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1335,7 +1335,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_dsi1_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dsi1_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1377,7 +1377,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
>   	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1412,7 +1412,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_dsi2_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dsi2_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1449,7 +1449,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
>   	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1502,7 +1502,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_hdmi_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_hdmi_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1544,7 +1544,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
>   	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1595,7 +1595,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_rfbi_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_rfbi_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1634,7 +1634,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
>   	.class		=&omap44xx_rfbi_hwmod_class,
>   	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1670,7 +1670,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_venc_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_venc_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1707,7 +1707,7 @@ static struct omap_hwmod_opt_clk venc_opt_clks[] = {
>   static struct omap_hwmod omap44xx_dss_venc_hwmod = {
>   	.name		= "dss_venc",
>   	.class		=&omap44xx_venc_hwmod_class,
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
>
>


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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07 11:37                             ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07 11:37 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 8:52 AM, Valkeinen, Tomi wrote:
> On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
>
>> Before doing that, could you maybe just try something to make OMAP4
>> looks a little bit more like OMAP3?
>>
>> dss_fck ->  ick
>> dss_dss_fck ->  main_clk
>>
>> That should ensure that both modulemode and the PRCM fclk will be
>> managed by pm_runtime.
>
> I made the changes as you suggested, and while I haven't made the
> changes to omapdss yet to see if I can remove the dispc_runtime_get/put
> style function, I can boot up and start the dss.
>
> However, after booting up but before enabling the dss driver, I can see
> that the clock counts are:
>
> dss_tv_clk 0
> dss_sys_clk 0
> dss_fck 7
> dss_dss_clk 0
> dss_48mhz_clk 0
>
> So the modulemode is set for all dss hwmods? Isn't this exactly how it's
> _not_ meant to be, as modulemode should be set only after enabling the
> fck?

The issue is that there is only one modulemode for the whole DSS.
Potentially only the dss_hwmod should have it. But then you have to 
ensure that this device is enabled before any other DSS devices.

If you cannot do that at your level, we will have to set a hwmod 
dependency between DSS modules and the main DSS subsystem.
For the moment we do not have such HW dependencies.

Benoit

>
>   Tomi
>
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> index b374cd0..d7d86b6 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
> @@ -1133,7 +1133,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1170,7 +1170,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
>   static struct omap_hwmod omap44xx_dss_hwmod = {
>   	.name		= "dss_core",
>   	.class		=&omap44xx_dss_hwmod_class,
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1230,7 +1230,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_dispc_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dispc_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1279,7 +1279,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
>   	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1335,7 +1335,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_dsi1_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dsi1_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1377,7 +1377,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
>   	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1412,7 +1412,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_dsi2_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_dsi2_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1449,7 +1449,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
>   	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1502,7 +1502,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_hdmi_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_hdmi_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1544,7 +1544,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
>   	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
>   	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1595,7 +1595,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_rfbi_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_rfbi_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1634,7 +1634,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
>   	.class		=&omap44xx_rfbi_hwmod_class,
>   	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
>   	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
> @@ -1670,7 +1670,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
>   static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
>   	.master		=&omap44xx_l3_main_2_hwmod,
>   	.slave		=&omap44xx_dss_venc_hwmod,
> -	.clk		= "l3_div_ck",
> +	.clk		= "dss_fck",
>   	.addr		= omap44xx_dss_venc_dma_addrs,
>   	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
>   	.user		= OCP_USER_SDMA,
> @@ -1707,7 +1707,7 @@ static struct omap_hwmod_opt_clk venc_opt_clks[] = {
>   static struct omap_hwmod omap44xx_dss_venc_hwmod = {
>   	.name		= "dss_venc",
>   	.class		=&omap44xx_venc_hwmod_class,
> -	.main_clk	= "dss_fck",
> +	.main_clk	= "dss_dss_clk",
>   	.prcm = {
>   		.omap4 = {
>   			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
>
>


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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07 11:37                             ` Cousson, Benoit
@ 2011-06-07 11:51                               ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07 11:51 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:
> On 6/7/2011 8:52 AM, Valkeinen, Tomi wrote:
> > On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
> >
> >> Before doing that, could you maybe just try something to make OMAP4
> >> looks a little bit more like OMAP3?
> >>
> >> dss_fck ->  ick
> >> dss_dss_fck ->  main_clk
> >>
> >> That should ensure that both modulemode and the PRCM fclk will be
> >> managed by pm_runtime.
> >
> > I made the changes as you suggested, and while I haven't made the
> > changes to omapdss yet to see if I can remove the dispc_runtime_get/put
> > style function, I can boot up and start the dss.
> >
> > However, after booting up but before enabling the dss driver, I can see
> > that the clock counts are:
> >
> > dss_tv_clk 0
> > dss_sys_clk 0
> > dss_fck 7
> > dss_dss_clk 0
> > dss_48mhz_clk 0
> >
> > So the modulemode is set for all dss hwmods? Isn't this exactly how it's
> > _not_ meant to be, as modulemode should be set only after enabling the
> > fck?
> 
> The issue is that there is only one modulemode for the whole DSS.
> Potentially only the dss_hwmod should have it. But then you have to 
> ensure that this device is enabled before any other DSS devices.

Does that change anything? Isn't the above (modulemode enabled before
opt clock) still true, even if it was enabled only once for the dss_core
hwmod?

And for PM, it doesn't matter if the dss_fck is enabled once or seven
times, I presume a use count of one will still prevent RET or OFF?

> If you cannot do that at your level, we will have to set a hwmod 
> dependency between DSS modules and the main DSS subsystem.
> For the moment we do not have such HW dependencies.

I can do this in the driver, and in fact I already do. The dss_core
hwmod is enabled by all the other hwmods before they do anything.

My reasoning for this dependency is that the dss_core contains for
example the clock mux registers, and other misc registers used by most
other dss modules. But I'm not sure if this dependency should be in the
hwmod level or not.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07 11:51                               ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-07 11:51 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:
> On 6/7/2011 8:52 AM, Valkeinen, Tomi wrote:
> > On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
> >
> >> Before doing that, could you maybe just try something to make OMAP4
> >> looks a little bit more like OMAP3?
> >>
> >> dss_fck ->  ick
> >> dss_dss_fck ->  main_clk
> >>
> >> That should ensure that both modulemode and the PRCM fclk will be
> >> managed by pm_runtime.
> >
> > I made the changes as you suggested, and while I haven't made the
> > changes to omapdss yet to see if I can remove the dispc_runtime_get/put
> > style function, I can boot up and start the dss.
> >
> > However, after booting up but before enabling the dss driver, I can see
> > that the clock counts are:
> >
> > dss_tv_clk 0
> > dss_sys_clk 0
> > dss_fck 7
> > dss_dss_clk 0
> > dss_48mhz_clk 0
> >
> > So the modulemode is set for all dss hwmods? Isn't this exactly how it's
> > _not_ meant to be, as modulemode should be set only after enabling the
> > fck?
> 
> The issue is that there is only one modulemode for the whole DSS.
> Potentially only the dss_hwmod should have it. But then you have to 
> ensure that this device is enabled before any other DSS devices.

Does that change anything? Isn't the above (modulemode enabled before
opt clock) still true, even if it was enabled only once for the dss_core
hwmod?

And for PM, it doesn't matter if the dss_fck is enabled once or seven
times, I presume a use count of one will still prevent RET or OFF?

> If you cannot do that at your level, we will have to set a hwmod 
> dependency between DSS modules and the main DSS subsystem.
> For the moment we do not have such HW dependencies.

I can do this in the driver, and in fact I already do. The dss_core
hwmod is enabled by all the other hwmods before they do anything.

My reasoning for this dependency is that the dss_core contains for
example the clock mux registers, and other misc registers used by most
other dss modules. But I'm not sure if this dependency should be in the
hwmod level or not.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07 11:51                               ` Tomi Valkeinen
@ 2011-06-07 16:43                                 ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07 16:43 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 1:51 PM, Valkeinen, Tomi wrote:
> On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:
>> On 6/7/2011 8:52 AM, Valkeinen, Tomi wrote:
>>> On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
>>>
>>>> Before doing that, could you maybe just try something to make OMAP4
>>>> looks a little bit more like OMAP3?
>>>>
>>>> dss_fck ->   ick
>>>> dss_dss_fck ->   main_clk
>>>>
>>>> That should ensure that both modulemode and the PRCM fclk will be
>>>> managed by pm_runtime.
>>>
>>> I made the changes as you suggested, and while I haven't made the
>>> changes to omapdss yet to see if I can remove the dispc_runtime_get/put
>>> style function, I can boot up and start the dss.
>>>
>>> However, after booting up but before enabling the dss driver, I can see
>>> that the clock counts are:
>>>
>>> dss_tv_clk 0
>>> dss_sys_clk 0
>>> dss_fck 7
>>> dss_dss_clk 0
>>> dss_48mhz_clk 0
>>>
>>> So the modulemode is set for all dss hwmods? Isn't this exactly how it's
>>> _not_ meant to be, as modulemode should be set only after enabling the
>>> fck?
>>
>> The issue is that there is only one modulemode for the whole DSS.
>> Potentially only the dss_hwmod should have it. But then you have to
>> ensure that this device is enabled before any other DSS devices.
>
> Does that change anything? Isn't the above (modulemode enabled before
> opt clock) still true, even if it was enabled only once for the dss_core
> hwmod?

It does not really change anything, but it is more accurate.
Modulemode need to be enable after the opt clocks that act as a 
functional clock and before enabling HW_AUTO for the clockdomain.

The important parameter is the clock domain mode change. It is another 
issue that we have to fix. It might not affect you for the moment.

> And for PM, it doesn't matter if the dss_fck is enabled once or seven
> times, I presume a use count of one will still prevent RET or OFF?
>
>> If you cannot do that at your level, we will have to set a hwmod
>> dependency between DSS modules and the main DSS subsystem.
>> For the moment we do not have such HW dependencies.
>
> I can do this in the driver, and in fact I already do. The dss_core
> hwmod is enabled by all the other hwmods before they do anything.
>
> My reasoning for this dependency is that the dss_core contains for
> example the clock mux registers, and other misc registers used by most
> other dss modules. But I'm not sure if this dependency should be in the
> hwmod level or not.

It makes sense for me as well to have that dependency between drivers.

Having it for hwmod for my point of view will make the hwmod state out 
of sync with the driver that manage it potentially. That kind of hard 
coded dependencies at hwmod level should maybe be considered only if the 
dependent hwmod does not belong to any driver.

Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-07 16:43                                 ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-07 16:43 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/7/2011 1:51 PM, Valkeinen, Tomi wrote:
> On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:
>> On 6/7/2011 8:52 AM, Valkeinen, Tomi wrote:
>>> On Mon, 2011-06-06 at 17:28 +0200, Cousson, Benoit wrote:
>>>
>>>> Before doing that, could you maybe just try something to make OMAP4
>>>> looks a little bit more like OMAP3?
>>>>
>>>> dss_fck ->   ick
>>>> dss_dss_fck ->   main_clk
>>>>
>>>> That should ensure that both modulemode and the PRCM fclk will be
>>>> managed by pm_runtime.
>>>
>>> I made the changes as you suggested, and while I haven't made the
>>> changes to omapdss yet to see if I can remove the dispc_runtime_get/put
>>> style function, I can boot up and start the dss.
>>>
>>> However, after booting up but before enabling the dss driver, I can see
>>> that the clock counts are:
>>>
>>> dss_tv_clk 0
>>> dss_sys_clk 0
>>> dss_fck 7
>>> dss_dss_clk 0
>>> dss_48mhz_clk 0
>>>
>>> So the modulemode is set for all dss hwmods? Isn't this exactly how it's
>>> _not_ meant to be, as modulemode should be set only after enabling the
>>> fck?
>>
>> The issue is that there is only one modulemode for the whole DSS.
>> Potentially only the dss_hwmod should have it. But then you have to
>> ensure that this device is enabled before any other DSS devices.
>
> Does that change anything? Isn't the above (modulemode enabled before
> opt clock) still true, even if it was enabled only once for the dss_core
> hwmod?

It does not really change anything, but it is more accurate.
Modulemode need to be enable after the opt clocks that act as a 
functional clock and before enabling HW_AUTO for the clockdomain.

The important parameter is the clock domain mode change. It is another 
issue that we have to fix. It might not affect you for the moment.

> And for PM, it doesn't matter if the dss_fck is enabled once or seven
> times, I presume a use count of one will still prevent RET or OFF?
>
>> If you cannot do that at your level, we will have to set a hwmod
>> dependency between DSS modules and the main DSS subsystem.
>> For the moment we do not have such HW dependencies.
>
> I can do this in the driver, and in fact I already do. The dss_core
> hwmod is enabled by all the other hwmods before they do anything.
>
> My reasoning for this dependency is that the dss_core contains for
> example the clock mux registers, and other misc registers used by most
> other dss modules. But I'm not sure if this dependency should be in the
> hwmod level or not.

It makes sense for me as well to have that dependency between drivers.

Having it for hwmod for my point of view will make the hwmod state out 
of sync with the driver that manage it potentially. That kind of hard 
coded dependencies at hwmod level should maybe be considered only if the 
dependent hwmod does not belong to any driver.

Benoit

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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-07 16:43                                 ` Cousson, Benoit
@ 2011-06-08  7:55                                   ` Tomi Valkeinen
  -1 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-08  7:55 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 18:43 +0200, Cousson, Benoit wrote:
> On 6/7/2011 1:51 PM, Valkeinen, Tomi wrote:
> > On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:

> >> The issue is that there is only one modulemode for the whole DSS.
> >> Potentially only the dss_hwmod should have it. But then you have to
> >> ensure that this device is enabled before any other DSS devices.
> >
> > Does that change anything? Isn't the above (modulemode enabled before
> > opt clock) still true, even if it was enabled only once for the dss_core
> > hwmod?
> 
> It does not really change anything, but it is more accurate.
> Modulemode need to be enable after the opt clocks that act as a 
> functional clock and before enabling HW_AUTO for the clockdomain.
> 
> The important parameter is the clock domain mode change. It is another 
> issue that we have to fix. It might not affect you for the moment.

Ok. But the main issue now is the PM. If I change the clocks in hwmod
data as you suggested, dss_fck will always stay enabled and prevent RET
and OFF. So the fix is not acceptable even for temporary use.

So is there some way to fix this, or shall we just go forward with the
current patch series having the somewhat hacky way to use pm_runtime?

I would personally like to get the driver right from the start, even if
that means more hacks in the hwmod fmwk (because that's where the
problems are). But if that is very difficult, I'm fine with the current
patch series.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-08  7:55                                   ` Tomi Valkeinen
  0 siblings, 0 replies; 108+ messages in thread
From: Tomi Valkeinen @ 2011-06-08  7:55 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On Tue, 2011-06-07 at 18:43 +0200, Cousson, Benoit wrote:
> On 6/7/2011 1:51 PM, Valkeinen, Tomi wrote:
> > On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:

> >> The issue is that there is only one modulemode for the whole DSS.
> >> Potentially only the dss_hwmod should have it. But then you have to
> >> ensure that this device is enabled before any other DSS devices.
> >
> > Does that change anything? Isn't the above (modulemode enabled before
> > opt clock) still true, even if it was enabled only once for the dss_core
> > hwmod?
> 
> It does not really change anything, but it is more accurate.
> Modulemode need to be enable after the opt clocks that act as a 
> functional clock and before enabling HW_AUTO for the clockdomain.
> 
> The important parameter is the clock domain mode change. It is another 
> issue that we have to fix. It might not affect you for the moment.

Ok. But the main issue now is the PM. If I change the clocks in hwmod
data as you suggested, dss_fck will always stay enabled and prevent RET
and OFF. So the fix is not acceptable even for temporary use.

So is there some way to fix this, or shall we just go forward with the
current patch series having the somewhat hacky way to use pm_runtime?

I would personally like to get the driver right from the start, even if
that means more hacks in the hwmod fmwk (because that's where the
problems are). But if that is very difficult, I'm fine with the current
patch series.

 Tomi



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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
  2011-06-08  7:55                                   ` Tomi Valkeinen
@ 2011-06-08 20:39                                     ` Cousson, Benoit
  -1 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-08 20:39 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/8/2011 9:55 AM, Valkeinen, Tomi wrote:
> On Tue, 2011-06-07 at 18:43 +0200, Cousson, Benoit wrote:
>> On 6/7/2011 1:51 PM, Valkeinen, Tomi wrote:
>>> On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:
>
>>>> The issue is that there is only one modulemode for the whole DSS.
>>>> Potentially only the dss_hwmod should have it. But then you have to
>>>> ensure that this device is enabled before any other DSS devices.
>>>
>>> Does that change anything? Isn't the above (modulemode enabled before
>>> opt clock) still true, even if it was enabled only once for the dss_core
>>> hwmod?
>>
>> It does not really change anything, but it is more accurate.
>> Modulemode need to be enable after the opt clocks that act as a
>> functional clock and before enabling HW_AUTO for the clockdomain.
>>
>> The important parameter is the clock domain mode change. It is another
>> issue that we have to fix. It might not affect you for the moment.
>
> Ok. But the main issue now is the PM. If I change the clocks in hwmod
> data as you suggested, dss_fck will always stay enabled and prevent RET
> and OFF. So the fix is not acceptable even for temporary use.

Mmm, the issue is probably due to the way we are managing interface 
clock that are usually able to autoidle. Because of that the 
_disable_clocks function will not try to disable an interface clock 
except if you use the following flag: OCPIF_SWSUP_IDLE.

  static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
  	.master		= &omap44xx_l3_main_2_hwmod,
  	.slave		= &omap44xx_dss_hwmod,
	.clk		= "dss_fck",
  	.addr		= omap44xx_dss_dma_addrs,
  	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
  	.user		= OCP_USER_SDMA,
+	.flags 		= OCPIF_SWSUP_IDLE,

>
> So is there some way to fix this, or shall we just go forward with the
> current patch series having the somewhat hacky way to use pm_runtime?
>
> I would personally like to get the driver right from the start, even if
> that means more hacks in the hwmod fmwk (because that's where the
> problems are). But if that is very difficult, I'm fine with the current
> patch series.

I hope we'll be able to fix the fmwk for 3.0.1.

Benoit


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

* Re: [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support
@ 2011-06-08 20:39                                     ` Cousson, Benoit
  0 siblings, 0 replies; 108+ messages in thread
From: Cousson, Benoit @ 2011-06-08 20:39 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: Hilman, Kevin, linux-omap, linux-fbdev, paul

On 6/8/2011 9:55 AM, Valkeinen, Tomi wrote:
> On Tue, 2011-06-07 at 18:43 +0200, Cousson, Benoit wrote:
>> On 6/7/2011 1:51 PM, Valkeinen, Tomi wrote:
>>> On Tue, 2011-06-07 at 13:37 +0200, Cousson, Benoit wrote:
>
>>>> The issue is that there is only one modulemode for the whole DSS.
>>>> Potentially only the dss_hwmod should have it. But then you have to
>>>> ensure that this device is enabled before any other DSS devices.
>>>
>>> Does that change anything? Isn't the above (modulemode enabled before
>>> opt clock) still true, even if it was enabled only once for the dss_core
>>> hwmod?
>>
>> It does not really change anything, but it is more accurate.
>> Modulemode need to be enable after the opt clocks that act as a
>> functional clock and before enabling HW_AUTO for the clockdomain.
>>
>> The important parameter is the clock domain mode change. It is another
>> issue that we have to fix. It might not affect you for the moment.
>
> Ok. But the main issue now is the PM. If I change the clocks in hwmod
> data as you suggested, dss_fck will always stay enabled and prevent RET
> and OFF. So the fix is not acceptable even for temporary use.

Mmm, the issue is probably due to the way we are managing interface 
clock that are usually able to autoidle. Because of that the 
_disable_clocks function will not try to disable an interface clock 
except if you use the following flag: OCPIF_SWSUP_IDLE.

  static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
  	.master		= &omap44xx_l3_main_2_hwmod,
  	.slave		= &omap44xx_dss_hwmod,
	.clk		= "dss_fck",
  	.addr		= omap44xx_dss_dma_addrs,
  	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
  	.user		= OCP_USER_SDMA,
+	.flags 		= OCPIF_SWSUP_IDLE,

>
> So is there some way to fix this, or shall we just go forward with the
> current patch series having the somewhat hacky way to use pm_runtime?
>
> I would personally like to get the driver right from the start, even if
> that means more hacks in the hwmod fmwk (because that's where the
> problems are). But if that is very difficult, I'm fine with the current
> patch series.

I hope we'll be able to fix the fmwk for 3.0.1.

Benoit


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

end of thread, other threads:[~2011-06-08 20:39 UTC | newest]

Thread overview: 108+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-03 10:00 [PATCH 00/27] OMAP DSS runtime PM adaptation Tomi Valkeinen
2011-06-03 10:00 ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 01/27] OMAP: change get_context_loss_count ret value to int Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 16:32   ` Kevin Hilman
2011-06-03 16:32     ` Kevin Hilman
2011-06-06  7:28     ` [PATCH 01/27] OMAP: change get_context_loss_count ret value to Tomi Valkeinen
2011-06-06  7:28       ` [PATCH 01/27] OMAP: change get_context_loss_count ret value to int Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 02/27] OMAP: DSS2: Taal: Make driver more fault tolerant Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 03/27] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-06  5:41   ` Archit Taneja
2011-06-06  5:53     ` Archit Taneja
2011-06-06  7:21     ` Tomi Valkeinen
2011-06-06  7:21       ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 04/27] OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 05/27] OMAP: DSS2: Clean up probe for DSS & DSI Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 06/27] OMAP: DSS2: Init dispc first before other components Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 07/27] OMAP: DSS2: Remove clk optimization at dss init Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 08/27] OMAP: DSS2: rewrite use of context_loss_count Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 09/27] OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 10/27] OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 11/27] OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 12/27] OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2 Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 13/27] OMAP: DSS2: Remove core_dump_clocks Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 14/27] OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 15/27] OMAP4: HWMOD: Modify DSS opt clocks Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 16/27] OMAP3: HWMOD: Add " Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 17/27] OMAP2420: " Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 18/27] OMAP2430: " Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 19/27] OMAP: DSS2: Use PM runtime & HWMOD support Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 16:45   ` Kevin Hilman
2011-06-03 16:45     ` Kevin Hilman
2011-06-03 17:43     ` Tomi Valkeinen
2011-06-03 17:43       ` Tomi Valkeinen
2011-06-03 22:53       ` Kevin Hilman
2011-06-03 22:53         ` Kevin Hilman
2011-06-04  8:01         ` Tomi Valkeinen
2011-06-04  8:01           ` Tomi Valkeinen
2011-06-06 12:56           ` Cousson, Benoit
2011-06-06 12:56             ` Cousson, Benoit
2011-06-06 13:01             ` Tomi Valkeinen
2011-06-06 13:01               ` Tomi Valkeinen
2011-06-06 13:15               ` Cousson, Benoit
2011-06-06 13:15                 ` Cousson, Benoit
2011-06-06 13:21                 ` Tomi Valkeinen
2011-06-06 13:21                   ` Tomi Valkeinen
2011-06-06 13:46                   ` Cousson, Benoit
2011-06-06 13:46                     ` Cousson, Benoit
2011-06-06 13:55                     ` Tomi Valkeinen
2011-06-06 13:55                       ` Tomi Valkeinen
2011-06-06 15:28                       ` Cousson, Benoit
2011-06-06 15:28                         ` Cousson, Benoit
2011-06-07  6:52                         ` Tomi Valkeinen
2011-06-07  6:52                           ` Tomi Valkeinen
2011-06-07  9:08                           ` Tomi Valkeinen
2011-06-07  9:08                             ` Tomi Valkeinen
2011-06-07 11:37                           ` Cousson, Benoit
2011-06-07 11:37                             ` Cousson, Benoit
2011-06-07 11:51                             ` Tomi Valkeinen
2011-06-07 11:51                               ` Tomi Valkeinen
2011-06-07 16:43                               ` Cousson, Benoit
2011-06-07 16:43                                 ` Cousson, Benoit
2011-06-08  7:55                                 ` Tomi Valkeinen
2011-06-08  7:55                                   ` Tomi Valkeinen
2011-06-08 20:39                                   ` Cousson, Benoit
2011-06-08 20:39                                     ` Cousson, Benoit
2011-06-07  6:47             ` Tomi Valkeinen
2011-06-07  6:47               ` Tomi Valkeinen
2011-06-07  7:12               ` Cousson, Benoit
2011-06-07  7:12                 ` Cousson, Benoit
2011-06-07  7:21                 ` Tomi Valkeinen
2011-06-07  7:21                   ` Tomi Valkeinen
2011-06-07  7:27                   ` Cousson, Benoit
2011-06-07  7:27                     ` Cousson, Benoit
2011-06-03 10:00 ` [PATCH 20/27] OMAP4: HWMOD: Remove unneeded DSS opt clocks Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 21/27] OMAP: DSS2: Remove unused opt_clock_available Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 22/27] OMAP: DSS2: DISPC: remove finegrained clk enables/disables Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 23/27] OMAP: DSS2: Remove unused code from display.c Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 24/27] OMAP: DSS2: Remove ctx loss count from dss.c Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 25/27] OMAP4: CLKDEV: Remove omapdss clock aliases Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 26/27] OMAP: DSS2: DISPC: Fix context save/restore Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen
2011-06-03 10:00 ` [PATCH 27/27] OMAP: DSS2: DSS: " Tomi Valkeinen
2011-06-03 10:00   ` Tomi Valkeinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.