public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] OMAP2PLUS: DSS: Ensure DSS works correctly if display is enabled in bootloader
@ 2011-09-08  9:56 Archit Taneja
  2011-09-08 11:28 ` Tomi Valkeinen
  0 siblings, 1 reply; 2+ messages in thread
From: Archit Taneja @ 2011-09-08  9:56 UTC (permalink / raw)
  To: tomi.valkeinen
  Cc: santosh.shilimkar, r.sricharan, tony, linux-omap, Archit Taneja

Resetting DISPC when a DISPC output is enabled causes the DSS to go into an
inconsistent state. Thus if the bootloader has enabled a display, the hwmod code
cannot reset the DISPC module just like that, but the outputs need to be
disabled first.

Add function dispc_disable_outputs() which disables all active overlay manager
and ensure all frame transfers are completed.

Modify omap_dss_reset() to call this function and clear DSS_CONTROL,
DSS_SDI_CONTROL and DSS_PLL_CONTROL so that DSS is in a clean state when the
DSS2 driver starts.

Tested-by: R, Sricharan <r.sricharan@ti.com>
Signed-off-by: Archit Taneja <archit@ti.com>
---
Note:
This resolves the hang issue(caused by a L3 errod during boot) seen on the
beagle board C3, which has a factory bootloader that enables display. The issue
is resovled with this patch.

The patch depends on a HWMOD patch series which has been posted by Tomi, it can
be tested by applying over the following branch:

https://gitorious.org/linux-omap-dss2/linux/commits/master

 arch/arm/mach-omap2/display.c |  110 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 93db7c1..eab81f4 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -30,6 +30,30 @@
 
 #include "control.h"
 
+#define DISPC_BASE_OMAP2	0x48050400
+#define DISPC_BASE_OMAP4	0x48041000
+
+#define DISPC_REG(base, offset)	(base + offset)
+
+#define DISPC_CONTROL		0x0040
+#define DISPC_CONTROL2		0x0238
+#define DISPC_IRQSTATUS		0x0018
+
+#define DSS_SYSCONFIG		0x10
+#define DSS_SYSSTATUS		0x14
+#define DSS_CONTROL		0x40
+#define DSS_SDI_CONTROL		0x44
+#define DSS_PLL_CONTROL		0x48
+
+#define LCD_EN_MASK		(0x1 << 0)
+#define DIGIT_EN_MASK		(0x1 << 1)
+
+#define FRAMEDONE_IRQ_SHIFT	0
+#define EVSYNC_EVEN_IRQ_SHIFT	2
+#define EVSYNC_ODD_IRQ_SHIFT	3
+#define FRAMEDONE2_IRQ_SHIFT	22
+#define FRAMEDONETV_IRQ_SHIFT	24
+
 static struct platform_device omap_display_device = {
 	.name          = "omapdss",
 	.id            = -1,
@@ -182,6 +206,78 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	return r;
 }
 
+static void dispc_disable_outputs(void)
+{
+	u32 val, irq_mask, base;
+	bool lcd_en, digit_en, lcd2_en = false;
+	int i, num_mgrs;
+
+	if (cpu_is_omap44xx()) {
+		base = DISPC_BASE_OMAP4;
+		num_mgrs = 3;
+	} else {
+		base = DISPC_BASE_OMAP2;
+		num_mgrs = 2;
+	}
+
+	/* store value of LCDENABLE and DIGITENABLE bits */
+	val = omap_readl(DISPC_REG(base, DISPC_CONTROL));
+	lcd_en = val & LCD_EN_MASK;
+	digit_en = val & DIGIT_EN_MASK;
+
+	/* store value of LCDENABLE for LCD2 */
+	if (num_mgrs > 2) {
+		val = omap_readl(DISPC_REG(base, DISPC_CONTROL2));
+		lcd2_en = val & LCD_EN_MASK;
+	}
+
+	/*
+	 * If any manager was enabled, we need to disable it before DSS clocks
+	 * are disabled or DISPC module is reset
+	 */
+	if (lcd_en || digit_en || lcd2_en) {
+		irq_mask = (lcd_en ? 1 : 0) << FRAMEDONE_IRQ_SHIFT;
+
+		if (cpu_is_omap44xx())
+			irq_mask |= (digit_en ? 1 : 0) << FRAMEDONETV_IRQ_SHIFT;
+		else
+			irq_mask |= (digit_en ? 1 : 0) << EVSYNC_EVEN_IRQ_SHIFT |
+				(digit_en ? 1 : 0) << EVSYNC_ODD_IRQ_SHIFT;
+
+		irq_mask |= (lcd2_en ? 1 : 0) << FRAMEDONE2_IRQ_SHIFT;
+
+		/*
+		 * clear any previous FRAMEDONE, FRAMEDONETV, EVSYNC_EVEN/ODD
+		 * or FRAMEDONE2 interrupts
+		 */
+		omap_writel(irq_mask, DISPC_REG(base, DISPC_IRQSTATUS));
+
+		/* disable LCD and TV managers */
+		val = omap_readl(DISPC_REG(base, DISPC_CONTROL));
+		val &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
+		omap_writel(val, DISPC_REG(base, DISPC_CONTROL));
+
+		/* disable LCD2 manager */
+		if (num_mgrs > 2) {
+			val = omap_readl(DISPC_REG(base, DISPC_CONTROL2));
+			val &= ~LCD_EN_MASK;
+			omap_writel(val, DISPC_REG(base, DISPC_CONTROL2));
+		}
+
+		i = 0;
+		while ((omap_readl(DISPC_REG(base, DISPC_IRQSTATUS)) & irq_mask) !=
+				irq_mask) {
+			i++;
+			if (i > 100) {
+				printk(KERN_ERR "didn't get FRAMEDONE1/2 or TV"
+					" interrupt\n");
+				break;
+			}
+			mdelay(1);
+		}
+	}
+}
+
 #define MAX_MODULE_SOFTRESET_WAIT	10000
 int omap_dss_reset(struct omap_hwmod *oh)
 {
@@ -198,6 +294,20 @@ int omap_dss_reset(struct omap_hwmod *oh)
 		if (oc->_clk)
 			clk_enable(oc->_clk);
 
+	dispc_disable_outputs();
+
+	/* clear SDI registers */
+	if (cpu_is_omap3430()) {
+		omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
+		omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
+	}
+
+	/*
+	 * clear DSS_CONTROL register to switch DSS clock sources to
+	 * PRCM clock, if any
+	 */
+	omap_hwmod_write(0x0, oh, DSS_CONTROL);
+
 	omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
 				& SYSS_RESETDONE_MASK),
 			MAX_MODULE_SOFTRESET_WAIT, c);
-- 
1.7.1


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

* Re: [PATCH] OMAP2PLUS: DSS: Ensure DSS works correctly if display is enabled in bootloader
  2011-09-08  9:56 [PATCH] OMAP2PLUS: DSS: Ensure DSS works correctly if display is enabled in bootloader Archit Taneja
@ 2011-09-08 11:28 ` Tomi Valkeinen
  0 siblings, 0 replies; 2+ messages in thread
From: Tomi Valkeinen @ 2011-09-08 11:28 UTC (permalink / raw)
  To: Archit Taneja, Paul Walmsley
  Cc: santosh.shilimkar, r.sricharan, tony, linux-omap

Hi,

I guess this should go through Paul. Paul, this is based on the DSS
HWMOD patches from me, and needed for cases where the bootloader has
enabled the DSS.

On Thu, 2011-09-08 at 15:26 +0530, Archit Taneja wrote:
> Resetting DISPC when a DISPC output is enabled causes the DSS to go into an
> inconsistent state. Thus if the bootloader has enabled a display, the hwmod code
> cannot reset the DISPC module just like that, but the outputs need to be
> disabled first.
> 
> Add function dispc_disable_outputs() which disables all active overlay manager
> and ensure all frame transfers are completed.
> 
> Modify omap_dss_reset() to call this function and clear DSS_CONTROL,
> DSS_SDI_CONTROL and DSS_PLL_CONTROL so that DSS is in a clean state when the
> DSS2 driver starts.
> 
> Tested-by: R, Sricharan <r.sricharan@ti.com>
> Signed-off-by: Archit Taneja <archit@ti.com>
> ---
> Note:
> This resolves the hang issue(caused by a L3 errod during boot) seen on the
> beagle board C3, which has a factory bootloader that enables display. The issue
> is resovled with this patch.

This note would be useful to have in the actual commit desc also. (with
error and resolved typofixed =).

Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

 Tomi

> 
> The patch depends on a HWMOD patch series which has been posted by Tomi, it can
> be tested by applying over the following branch:
> 
> https://gitorious.org/linux-omap-dss2/linux/commits/master
> 
>  arch/arm/mach-omap2/display.c |  110 +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 110 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
> index 93db7c1..eab81f4 100644
> --- a/arch/arm/mach-omap2/display.c
> +++ b/arch/arm/mach-omap2/display.c
> @@ -30,6 +30,30 @@
>  
>  #include "control.h"
>  
> +#define DISPC_BASE_OMAP2	0x48050400
> +#define DISPC_BASE_OMAP4	0x48041000
> +
> +#define DISPC_REG(base, offset)	(base + offset)
> +
> +#define DISPC_CONTROL		0x0040
> +#define DISPC_CONTROL2		0x0238
> +#define DISPC_IRQSTATUS		0x0018
> +
> +#define DSS_SYSCONFIG		0x10
> +#define DSS_SYSSTATUS		0x14
> +#define DSS_CONTROL		0x40
> +#define DSS_SDI_CONTROL		0x44
> +#define DSS_PLL_CONTROL		0x48
> +
> +#define LCD_EN_MASK		(0x1 << 0)
> +#define DIGIT_EN_MASK		(0x1 << 1)
> +
> +#define FRAMEDONE_IRQ_SHIFT	0
> +#define EVSYNC_EVEN_IRQ_SHIFT	2
> +#define EVSYNC_ODD_IRQ_SHIFT	3
> +#define FRAMEDONE2_IRQ_SHIFT	22
> +#define FRAMEDONETV_IRQ_SHIFT	24
> +
>  static struct platform_device omap_display_device = {
>  	.name          = "omapdss",
>  	.id            = -1,
> @@ -182,6 +206,78 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
>  	return r;
>  }
>  
> +static void dispc_disable_outputs(void)
> +{
> +	u32 val, irq_mask, base;
> +	bool lcd_en, digit_en, lcd2_en = false;
> +	int i, num_mgrs;
> +
> +	if (cpu_is_omap44xx()) {
> +		base = DISPC_BASE_OMAP4;
> +		num_mgrs = 3;
> +	} else {
> +		base = DISPC_BASE_OMAP2;
> +		num_mgrs = 2;
> +	}
> +
> +	/* store value of LCDENABLE and DIGITENABLE bits */
> +	val = omap_readl(DISPC_REG(base, DISPC_CONTROL));
> +	lcd_en = val & LCD_EN_MASK;
> +	digit_en = val & DIGIT_EN_MASK;
> +
> +	/* store value of LCDENABLE for LCD2 */
> +	if (num_mgrs > 2) {
> +		val = omap_readl(DISPC_REG(base, DISPC_CONTROL2));
> +		lcd2_en = val & LCD_EN_MASK;
> +	}
> +
> +	/*
> +	 * If any manager was enabled, we need to disable it before DSS clocks
> +	 * are disabled or DISPC module is reset
> +	 */
> +	if (lcd_en || digit_en || lcd2_en) {
> +		irq_mask = (lcd_en ? 1 : 0) << FRAMEDONE_IRQ_SHIFT;
> +
> +		if (cpu_is_omap44xx())
> +			irq_mask |= (digit_en ? 1 : 0) << FRAMEDONETV_IRQ_SHIFT;
> +		else
> +			irq_mask |= (digit_en ? 1 : 0) << EVSYNC_EVEN_IRQ_SHIFT |
> +				(digit_en ? 1 : 0) << EVSYNC_ODD_IRQ_SHIFT;
> +
> +		irq_mask |= (lcd2_en ? 1 : 0) << FRAMEDONE2_IRQ_SHIFT;
> +
> +		/*
> +		 * clear any previous FRAMEDONE, FRAMEDONETV, EVSYNC_EVEN/ODD
> +		 * or FRAMEDONE2 interrupts
> +		 */
> +		omap_writel(irq_mask, DISPC_REG(base, DISPC_IRQSTATUS));
> +
> +		/* disable LCD and TV managers */
> +		val = omap_readl(DISPC_REG(base, DISPC_CONTROL));
> +		val &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
> +		omap_writel(val, DISPC_REG(base, DISPC_CONTROL));
> +
> +		/* disable LCD2 manager */
> +		if (num_mgrs > 2) {
> +			val = omap_readl(DISPC_REG(base, DISPC_CONTROL2));
> +			val &= ~LCD_EN_MASK;
> +			omap_writel(val, DISPC_REG(base, DISPC_CONTROL2));
> +		}
> +
> +		i = 0;
> +		while ((omap_readl(DISPC_REG(base, DISPC_IRQSTATUS)) & irq_mask) !=
> +				irq_mask) {
> +			i++;
> +			if (i > 100) {
> +				printk(KERN_ERR "didn't get FRAMEDONE1/2 or TV"
> +					" interrupt\n");
> +				break;
> +			}
> +			mdelay(1);
> +		}
> +	}
> +}
> +
>  #define MAX_MODULE_SOFTRESET_WAIT	10000
>  int omap_dss_reset(struct omap_hwmod *oh)
>  {
> @@ -198,6 +294,20 @@ int omap_dss_reset(struct omap_hwmod *oh)
>  		if (oc->_clk)
>  			clk_enable(oc->_clk);
>  
> +	dispc_disable_outputs();
> +
> +	/* clear SDI registers */
> +	if (cpu_is_omap3430()) {
> +		omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
> +		omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
> +	}
> +
> +	/*
> +	 * clear DSS_CONTROL register to switch DSS clock sources to
> +	 * PRCM clock, if any
> +	 */
> +	omap_hwmod_write(0x0, oh, DSS_CONTROL);
> +
>  	omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
>  				& SYSS_RESETDONE_MASK),
>  			MAX_MODULE_SOFTRESET_WAIT, c);



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

end of thread, other threads:[~2011-09-08 11:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-08  9:56 [PATCH] OMAP2PLUS: DSS: Ensure DSS works correctly if display is enabled in bootloader Archit Taneja
2011-09-08 11:28 ` Tomi Valkeinen

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