Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [GIT PULL] ARM: amba: Enable module alias autogeneration for
From: Dave Martin @ 2011-11-22 12:07 UTC (permalink / raw)
  To: Alessandro Rubini
  Cc: linux, patches, linux-kernel, linux-arm-kernel, alan, a.zummo,
	alsa-devel, cjb, dan.j.williams, dmitry.torokhov, grant.likely,
	perex, jassisinghbrar, julia, linus.walleij, linux-fbdev,
	linux-input, linux-mmc, linux-serial, linux-watchdog, lethal,
	Pawel.Moll, rtc-linux, spi-devel-general, tiwai, vinod.koul, wim
In-Reply-To: <20111122115632.GA5165@mail.gnudd.com>

On Tue, Nov 22, 2011 at 12:56:32PM +0100, Alessandro Rubini wrote:
> > I have Acks on some of the driver patches and no comments on the
> > rest.  I've been circulating these for some time, so if you're
> > happy to pull those driver patches via your tree, please go ahead.
> 
> Sure I have no problem with the nomadik-rng.c, (so please have my
> Acked-by: -- sorry for not noting it earlier) but I think this

thanks

> file2alias thing needs a serious rework to split each bus in a
> different file, using ELF sections like we do elsewhere.
> 
> I posted a patch last week but I got no comment at all. Maybe this
> is the time to ask for comments? I can rebase and repost if needed.
> 
>   lkml.org/lkml/2011/11/4/125 (0/2: description of the work)
>   lkml.org/lkml/2011/11/4/126 (1/2: turn the if plethora to table lookup)
>   lkml.org/lkml/2011/11/4/127 (2/2: partial split to type-specific files).

Splitting this up doesn't look like a silly idea -- I thought it was
unfortunate to have to patch a core file just to add a bus type.

I guess the question is how many new buses we get over time.  If they
only get added gradually, people might not be too concerned.  Of course,
this is one of those maintenance issues which can only get worse as time
goes on.

Cheers
---Dave

^ permalink raw reply

* Re: [GIT PULL] ARM: amba: Enable module alias autogeneration for
From: Alessandro Rubini @ 2011-11-22 11:56 UTC (permalink / raw)
  To: dave.martin
  Cc: alsa-devel, tiwai, linus.walleij, linux-fbdev, perex,
	grant.likely, wim, julia, linux, rtc-linux, vinod.koul,
	jassisinghbrar, linux-serial, linux-input, cjb, linux-watchdog,
	Pawel.Moll, patches, dan.j.williams, linux-arm-kernel, alan,
	a.zummo, dmitry.torokhov, linux-mmc, linux-kernel, lethal,
	spi-devel-general
In-Reply-To: <1321961573-4562-1-git-send-email-dave.martin@linaro.org>

> I have Acks on some of the driver patches and no comments on the
> rest.  I've been circulating these for some time, so if you're
> happy to pull those driver patches via your tree, please go ahead.

Sure I have no problem with the nomadik-rng.c, (so please have my
Acked-by: -- sorry for not noting it earlier) but I think this
file2alias thing needs a serious rework to split each bus in a
different file, using ELF sections like we do elsewhere.

I posted a patch last week but I got no comment at all. Maybe this
is the time to ask for comments? I can rebase and repost if needed.

  lkml.org/lkml/2011/11/4/125 (0/2: description of the work)
  lkml.org/lkml/2011/11/4/126 (1/2: turn the if plethora to table lookup)
  lkml.org/lkml/2011/11/4/127 (2/2: partial split to type-specific files).

thanks
/alessandro

^ permalink raw reply

* Re: [PATCH 08/65] OMAPDSS: remove partial update from panel-taal
From: Archit Taneja @ 2011-11-22 11:55 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev, linux-omap, archit
In-Reply-To: <1321953724-6350-9-git-send-email-tomi.valkeinen@ti.com>

On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
> Partial update for manual update displays has never worked quite well:
> * The HW has limitations on the update area, and the x and width need to
>    be even.
> * Showing a part of a scaled overlay causes artifacts.
> * Makes the management of dispc very complex
>
> Considering the above points and the fact that partial update is not
> used anywhere, this and the following patches remove the partial update
> support. This will greatly simplify the following re-write of the apply
> mechanism to get proper locking and additional features like fifo-merge.
>
> This patch removes the partial update from the panel-taal.c.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/displays/panel-taal.c |   16 ++++------------
>   1 files changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
> index 0aa6c5d..dd64bd1 100644
> --- a/drivers/video/omap2/displays/panel-taal.c
> +++ b/drivers/video/omap2/displays/panel-taal.c
> @@ -198,12 +198,6 @@ struct taal_data {
>   	bool te_enabled;
>
>   	atomic_t do_update;
> -	struct {
> -		u16 x;
> -		u16 y;
> -		u16 w;
> -		u16 h;
> -	} update_region;
>   	int channel;
>
>   	struct delayed_work te_timeout_work;
> @@ -1440,16 +1434,14 @@ static int taal_update(struct omap_dss_device *dssdev,
>   		goto err;
>   	}
>
> -	r = taal_set_update_window(td, x, y, w, h);
> +	/* XXX no need to send this every frame, but dsi break if not done */
> +	r = taal_set_update_window(td, 0, 0,
> +			td->panel_config->timings.x_res,
> +			td->panel_config->timings.y_res);

How about sending a null short packet, and a BTA after that. This will 
keep automatic TE mode in place, and we'll need to send 1 short packet 
instead of 2 long packets every frame.

We should of course do this if we aren't planning to get partial update 
back in the near future.

Archit

>   	if (r)
>   		goto err;
>
>   	if (td->te_enabled&&  panel_data->use_ext_te) {
> -		td->update_region.x = x;
> -		td->update_region.y = y;
> -		td->update_region.w = w;
> -		td->update_region.h = h;
> -		barrier();
>   		schedule_delayed_work(&td->te_timeout_work,
>   				msecs_to_jiffies(250));
>   		atomic_set(&td->do_update, 1);


^ permalink raw reply

* Re: [PATCH 06/65] OMAPDSS: remove partial update from the overlay
From: Archit Taneja @ 2011-11-22 11:53 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev, linux-omap, archit
In-Reply-To: <1321953724-6350-7-git-send-email-tomi.valkeinen@ti.com>

On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
> Partial update for manual update displays has never worked quite well:
> * The HW has limitations on the update area, and the x and width need to
>    be even.

There are also some issues with partial update on OMAP4 even when 'x and 
width are even'. There seems to be DISPC timeouts when the update area 
is too small. Its easy to reproduce it by running the 'rect' test for a 
while. For those who are interested, the rect testcase can be found in:

git://gitorious.org/linux-omap-dss2/omapfb-tests.git

Archit

> * Showing a part of a scaled overlay causes artifacts.
> * Makes the management of dispc very complex
>
> Considering the above points and the fact that partial update is not
> used anywhere, this and the following patches remove the partial update
> support. This will greatly simplify the following re-write of the apply
> mechanism to get proper locking and additional features like fifo-merge.
>
> This patch removes the partial update from the manager.c.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dsi.c     |    2 -
>   drivers/video/omap2/dss/dss.h     |    3 -
>   drivers/video/omap2/dss/manager.c |  333 +------------------------------------
>   drivers/video/omap2/dss/rfbi.c    |    1 -
>   4 files changed, 6 insertions(+), 333 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
> index 5abf8e7..787cebd 100644
> --- a/drivers/video/omap2/dss/dsi.c
> +++ b/drivers/video/omap2/dss/dsi.c
> @@ -4172,8 +4172,6 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
>
>   	dsi_perf_mark_setup(dsidev);
>
> -	dss_setup_partial_planes(dssdev, x, y, w, h,
> -			enlarge_update_area);
>   	dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
>
>   	return 0;
> diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
> index 313a7ca..7f6a612 100644
> --- a/drivers/video/omap2/dss/dss.h
> +++ b/drivers/video/omap2/dss/dss.h
> @@ -182,9 +182,6 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
>   int dss_init_overlay_managers(struct platform_device *pdev);
>   void dss_uninit_overlay_managers(struct platform_device *pdev);
>   int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
> -void dss_setup_partial_planes(struct omap_dss_device *dssdev,
> -				u16 *x, u16 *y, u16 *w, u16 *h,
> -				bool enlarge_update_area);
>   void dss_start_update(struct omap_dss_device *dssdev);
>
>   /* overlay */
> diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
> index 1be5f47..c616f85 100644
> --- a/drivers/video/omap2/dss/manager.c
> +++ b/drivers/video/omap2/dss/manager.c
> @@ -530,13 +530,6 @@ struct manager_cache_data {
>
>   	bool manual_update;
>   	bool do_manual_update;
> -
> -	/* manual update region */
> -	u16 x, y, w, h;
> -
> -	/* enlarge the update area if the update area contains scaled
> -	 * overlays */
> -	bool enlarge_update_area;
>   };
>
>   static struct {
> @@ -762,65 +755,11 @@ static int overlay_enabled(struct omap_overlay *ovl)
>   	return ovl->info.enabled&&  ovl->manager&&  ovl->manager->device;
>   }
>
> -/* Is rect1 a subset of rect2? */
> -static bool rectangle_subset(int x1, int y1, int w1, int h1,
> -		int x2, int y2, int w2, int h2)
> -{
> -	if (x1<  x2 || y1<  y2)
> -		return false;
> -
> -	if (x1 + w1>  x2 + w2)
> -		return false;
> -
> -	if (y1 + h1>  y2 + h2)
> -		return false;
> -
> -	return true;
> -}
> -
> -/* Do rect1 and rect2 overlap? */
> -static bool rectangle_intersects(int x1, int y1, int w1, int h1,
> -		int x2, int y2, int w2, int h2)
> -{
> -	if (x1>= x2 + w2)
> -		return false;
> -
> -	if (x2>= x1 + w1)
> -		return false;
> -
> -	if (y1>= y2 + h2)
> -		return false;
> -
> -	if (y2>= y1 + h1)
> -		return false;
> -
> -	return true;
> -}
> -
> -static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
> -{
> -	struct omap_overlay_info *oi =&oc->info;
> -
> -	if (oi->out_width != 0&&  oi->width != oi->out_width)
> -		return true;
> -
> -	if (oi->out_height != 0&&  oi->height != oi->out_height)
> -		return true;
> -
> -	return false;
> -}
> -
>   static int configure_overlay(enum omap_plane plane)
>   {
>   	struct overlay_cache_data *c;
> -	struct manager_cache_data *mc;
> -	struct omap_overlay_info *oi, new_oi;
> -	struct omap_overlay_manager_info *mi;
> -	u16 outw, outh;
> -	u16 x, y, w, h;
> -	u32 paddr;
> +	struct omap_overlay_info *oi;
>   	int r;
> -	u16 orig_w, orig_h, orig_outw, orig_outh;
>
>   	DSSDBGF("%d", plane);
>
> @@ -832,120 +771,7 @@ static int configure_overlay(enum omap_plane plane)
>   		return 0;
>   	}
>
> -	mc =&dss_cache.manager_cache[c->channel];
> -	mi =&mc->info;
> -
> -	x = oi->pos_x;
> -	y = oi->pos_y;
> -	w = oi->width;
> -	h = oi->height;
> -	outw = oi->out_width = 0 ? oi->width : oi->out_width;
> -	outh = oi->out_height = 0 ? oi->height : oi->out_height;
> -	paddr = oi->paddr;
> -
> -	orig_w = w;
> -	orig_h = h;
> -	orig_outw = outw;
> -	orig_outh = outh;
> -
> -	if (mc->manual_update&&  mc->do_manual_update) {
> -		unsigned bpp;
> -		unsigned scale_x_m = w, scale_x_d = outw;
> -		unsigned scale_y_m = h, scale_y_d = outh;
> -
> -		/* If the overlay is outside the update region, disable it */
> -		if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
> -					x, y, outw, outh)) {
> -			dispc_ovl_enable(plane, 0);
> -			return 0;
> -		}
> -
> -		switch (oi->color_mode) {
> -		case OMAP_DSS_COLOR_NV12:
> -			bpp = 8;
> -			break;
> -		case OMAP_DSS_COLOR_RGB16:
> -		case OMAP_DSS_COLOR_ARGB16:
> -		case OMAP_DSS_COLOR_YUV2:
> -		case OMAP_DSS_COLOR_UYVY:
> -		case OMAP_DSS_COLOR_RGBA16:
> -		case OMAP_DSS_COLOR_RGBX16:
> -		case OMAP_DSS_COLOR_ARGB16_1555:
> -		case OMAP_DSS_COLOR_XRGB16_1555:
> -			bpp = 16;
> -			break;
> -
> -		case OMAP_DSS_COLOR_RGB24P:
> -			bpp = 24;
> -			break;
> -
> -		case OMAP_DSS_COLOR_RGB24U:
> -		case OMAP_DSS_COLOR_ARGB32:
> -		case OMAP_DSS_COLOR_RGBA32:
> -		case OMAP_DSS_COLOR_RGBX32:
> -			bpp = 32;
> -			break;
> -
> -		default:
> -			BUG();
> -		}
> -
> -		if (mc->x>  oi->pos_x) {
> -			x = 0;
> -			outw -= (mc->x - oi->pos_x);
> -			paddr += (mc->x - oi->pos_x) *
> -				scale_x_m / scale_x_d * bpp / 8;
> -		} else {
> -			x = oi->pos_x - mc->x;
> -		}
> -
> -		if (mc->y>  oi->pos_y) {
> -			y = 0;
> -			outh -= (mc->y - oi->pos_y);
> -			paddr += (mc->y - oi->pos_y) *
> -				scale_y_m / scale_y_d *
> -				oi->screen_width * bpp / 8;
> -		} else {
> -			y = oi->pos_y - mc->y;
> -		}
> -
> -		if (mc->w<  (x + outw))
> -			outw -= (x + outw) - (mc->w);
> -
> -		if (mc->h<  (y + outh))
> -			outh -= (y + outh) - (mc->h);
> -
> -		w = w * outw / orig_outw;
> -		h = h * outh / orig_outh;
> -
> -		/* YUV mode overlay's input width has to be even and the
> -		 * algorithm above may adjust the width to be odd.
> -		 *
> -		 * Here we adjust the width if needed, preferring to increase
> -		 * the width if the original width was bigger.
> -		 */
> -		if ((w&  1)&&
> -				(oi->color_mode = OMAP_DSS_COLOR_YUV2 ||
> -				 oi->color_mode = OMAP_DSS_COLOR_UYVY)) {
> -			if (orig_w>  w)
> -				w += 1;
> -			else
> -				w -= 1;
> -		}
> -	}
> -
> -	new_oi = *oi;
> -
> -	/* update new_oi members which could have been possibly updated */
> -	new_oi.pos_x = x;
> -	new_oi.pos_y = y;
> -	new_oi.width = w;
> -	new_oi.height = h;
> -	new_oi.out_width = outw;
> -	new_oi.out_height = outh;
> -	new_oi.paddr = paddr;
> -
> -	r = dispc_ovl_setup(plane,&new_oi, c->ilace, c->channel,
> +	r = dispc_ovl_setup(plane, oi, c->ilace, c->channel,
>   		c->replication, c->fifo_low, c->fifo_high);
>   	if (r) {
>   		/* this shouldn't happen */
> @@ -1070,170 +896,23 @@ static int configure_dispc(void)
>   	return r;
>   }
>
> -/* Make the coordinates even. There are some strange problems with OMAP and
> - * partial DSI update when the update widths are odd. */
> -static void make_even(u16 *x, u16 *w)
> -{
> -	u16 x1, x2;
> -
> -	x1 = *x;
> -	x2 = *x + *w;
> -
> -	x1&= ~1;
> -	x2 = ALIGN(x2, 2);
> -
> -	*x = x1;
> -	*w = x2 - x1;
> -}
> -
> -/* Configure dispc for partial update. Return possibly modified update
> - * area */
> -void dss_setup_partial_planes(struct omap_dss_device *dssdev,
> -		u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
> +void dss_start_update(struct omap_dss_device *dssdev)
>   {
> -	struct overlay_cache_data *oc;
>   	struct manager_cache_data *mc;
> -	struct omap_overlay_info *oi;
> +	struct overlay_cache_data *oc;
>   	const int num_ovls = dss_feat_get_num_ovls();
> +	const int num_mgrs = dss_feat_get_num_mgrs();
>   	struct omap_overlay_manager *mgr;
>   	int i;
> -	u16 x, y, w, h;
> -	unsigned long flags;
> -	bool area_changed;
> -
> -	x = *xi;
> -	y = *yi;
> -	w = *wi;
> -	h = *hi;
> -
> -	DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
> -		*xi, *yi, *wi, *hi);
>
>   	mgr = dssdev->manager;
>
> -	if (!mgr) {
> -		DSSDBG("no manager\n");
> -		return;
> -	}
> -
> -	make_even(&x,&w);
> -
> -	spin_lock_irqsave(&dss_cache.lock, flags);
> -
> -	/*
> -	 * Execute the outer loop until the inner loop has completed
> -	 * once without increasing the update area. This will ensure that
> -	 * all scaled overlays end up completely within the update area.
> -	 */
> -	do {
> -		area_changed = false;
> -
> -		/* We need to show the whole overlay if it is scaled. So look
> -		 * for those, and make the update area larger if found.
> -		 * Also mark the overlay cache dirty */
> -		for (i = 0; i<  num_ovls; ++i) {
> -			unsigned x1, y1, x2, y2;
> -			unsigned outw, outh;
> -
> -			oc =&dss_cache.overlay_cache[i];
> -			oi =&oc->info;
> -
> -			if (oc->channel != mgr->id)
> -				continue;
> -
> -			oc->dirty = true;
> -
> -			if (!enlarge_update_area)
> -				continue;
> -
> -			if (!oc->enabled)
> -				continue;
> -
> -			if (!dispc_is_overlay_scaled(oc))
> -				continue;
> -
> -			outw = oi->out_width = 0 ?
> -				oi->width : oi->out_width;
> -			outh = oi->out_height = 0 ?
> -				oi->height : oi->out_height;
> -
> -			/* is the overlay outside the update region? */
> -			if (!rectangle_intersects(x, y, w, h,
> -						oi->pos_x, oi->pos_y,
> -						outw, outh))
> -				continue;
> -
> -			/* if the overlay totally inside the update region? */
> -			if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
> -						x, y, w, h))
> -				continue;
> -
> -			if (x>  oi->pos_x)
> -				x1 = oi->pos_x;
> -			else
> -				x1 = x;
> -
> -			if (y>  oi->pos_y)
> -				y1 = oi->pos_y;
> -			else
> -				y1 = y;
> -
> -			if ((x + w)<  (oi->pos_x + outw))
> -				x2 = oi->pos_x + outw;
> -			else
> -				x2 = x + w;
> -
> -			if ((y + h)<  (oi->pos_y + outh))
> -				y2 = oi->pos_y + outh;
> -			else
> -				y2 = y + h;
> -
> -			x = x1;
> -			y = y1;
> -			w = x2 - x1;
> -			h = y2 - y1;
> -
> -			make_even(&x,&w);
> -
> -			DSSDBG("changing upd area due to ovl(%d) "
> -			       "scaling %d,%d %dx%d\n",
> -				i, x, y, w, h);
> -
> -			area_changed = true;
> -		}
> -	} while (area_changed);
> -
>   	mc =&dss_cache.manager_cache[mgr->id];
> -	mc->do_manual_update = true;
> -	mc->enlarge_update_area = enlarge_update_area;
> -	mc->x = x;
> -	mc->y = y;
> -	mc->w = w;
> -	mc->h = h;
>
> +	mc->do_manual_update = true;
>   	configure_dispc();
> -
>   	mc->do_manual_update = false;
>
> -	spin_unlock_irqrestore(&dss_cache.lock, flags);
> -
> -	*xi = x;
> -	*yi = y;
> -	*wi = w;
> -	*hi = h;
> -}
> -
> -void dss_start_update(struct omap_dss_device *dssdev)
> -{
> -	struct manager_cache_data *mc;
> -	struct overlay_cache_data *oc;
> -	const int num_ovls = dss_feat_get_num_ovls();
> -	const int num_mgrs = dss_feat_get_num_mgrs();
> -	struct omap_overlay_manager *mgr;
> -	int i;
> -
> -	mgr = dssdev->manager;
> -
>   	for (i = 0; i<  num_ovls; ++i) {
>   		oc =&dss_cache.overlay_cache[i];
>   		if (oc->channel != mgr->id)
> diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
> index 1130c60..814bb95 100644
> --- a/drivers/video/omap2/dss/rfbi.c
> +++ b/drivers/video/omap2/dss/rfbi.c
> @@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
>   	if (*w = 0 || *h = 0)
>   		return -EINVAL;
>
> -	dss_setup_partial_planes(dssdev, x, y, w, h, true);
>   	dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
>
>   	return 0;


^ permalink raw reply

* [GIT PULL] ARM: amba: Enable module alias autogeneration for AMBA drivers
From: Dave Martin @ 2011-11-22 11:32 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: patches, linux-kernel, linux-arm-kernel, Alan Cox,
	Alessandro Rubini, Alessandro Zummo, alsa-devel, Chris Ball,
	Dan Williams, Dmitry Torokhov, Grant Likely, Jaroslav Kysela,
	Jassi Brar, Julia Lawall, Linus Walleij, linux-fbdev, linux-input,
	linux-mmc, linux-serial, linux-watchdog, Paul Mundt,
	Paweł Moll, rtc-linux, spi-devel-general, Takashi Iwai

Hi Russell,

This series enables the general infrastructure for modalias
generation to work for AMBA devices, and enables it in the affected
drivers.

Since there are several patches here, I though it better to send a
pull request.

The first two patches (subject lines "ARM: amba: ...") are the core
patches; the remainder of the patches are the driver changes --
each is trivial and simply adds a MODULE_DEVICE_ALIAS() entry.

I have Acks on some of the driver patches and no comments on the
rest.  I've been circulating these for some time, so if you're
happy to pull those driver patches via your tree, please go ahead.

Otherwise, let me know and I can continue trying to push the driver
patches via other routes.

Cheers
---Dave

The following changes since commit cfcfc9eca2bcbd26a8e206baeb005b055dbf8e37:

  Linux 3.2-rc2 (2011-11-15 15:02:59 -0200)

are available in the git repository at:
  git://git.linaro.org/people/dmart/linux-2.6-arm.git arm/amba-modalias+for-rmk

Dave Martin (16):
      ARM: amba: Move definition of struct amba_id to mod_devicetable.h
      ARM: amba: Auto-generate AMBA driver module aliases during modpost
      hwrng: nomadik: Enable module alias autogeneration for AMBA drivers
      dmaengine: pl08x: Enable module alias autogeneration for AMBA drivers
      dmaengine: pl330: Enable module alias autogeneration for AMBA drivers
      gpio: pl061: Enable module alias autogeneration for AMBA drivers
      input: ambakmi: Enable module alias autogeneration for AMBA drivers
      mmc: mmci: Enable module alias autogeneration for AMBA drivers
      rtc: pl030: Enable module alias autogeneration for AMBA drivers
      rtc: pl031: Enable module alias autogeneration for AMBA drivers
      spi: pl022: Enable module alias autogeneration for AMBA drivers
      serial: pl010: Enable module alias autogeneration for AMBA drivers
      serial: pl011: Enable module alias autogeneration for AMBA drivers
      fbdev: amba: Enable module alias autogeneration for AMBA drivers
      watchdog: sp805: Enable module alias autogeneration for AMBA drivers
      sound: aaci: Enable module alias autogeneration for AMBA drivers

 drivers/amba/bus.c                   |    4 ++
 drivers/char/hw_random/nomadik-rng.c |    2 +
 drivers/dma/amba-pl08x.c             |    2 +
 drivers/dma/pl330.c                  |    2 +
 drivers/gpio/gpio-pl061.c            |    2 +
 drivers/input/serio/ambakmi.c        |    2 +
 drivers/mmc/host/mmci.c              |    2 +
 drivers/rtc/rtc-pl030.c              |    2 +
 drivers/rtc/rtc-pl031.c              |    2 +
 drivers/spi/spi-pl022.c              |    2 +
 drivers/tty/serial/amba-pl010.c      |    2 +
 drivers/tty/serial/amba-pl011.c      |    2 +
 drivers/video/amba-clcd.c            |    2 +
 drivers/watchdog/sp805_wdt.c         |    2 +
 include/linux/amba/bus.h             |    7 +---
 include/linux/mod_devicetable.h      |   18 ++++++++
 scripts/mod/file2alias.c             |   72 ++++++++++++++++++++++++++++++++++
 sound/arm/aaci.c                     |    2 +
 18 files changed, 123 insertions(+), 6 deletions(-)





^ permalink raw reply

* [PATCH 65/65] OMAPDSS: check the return value of dss_mgr_enable()
From: Tomi Valkeinen @ 2011-11-22  9:22 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Now that dss_mgr_enable returns an error value, check it in all the
places dss_mgr_enable is used, and bail out properly.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dpi.c  |    5 ++++-
 drivers/video/omap2/dss/dsi.c  |   11 ++++++++++-
 drivers/video/omap2/dss/hdmi.c |    9 ++++++++-
 drivers/video/omap2/dss/sdi.c  |    6 +++++-
 drivers/video/omap2/dss/venc.c |   26 +++++++++++++++++++++++---
 5 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 79c4df3..395d658 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -223,10 +223,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 	mdelay(2);
 
-	dss_mgr_enable(dssdev->manager);
+	r = dss_mgr_enable(dssdev->manager);
+	if (r)
+		goto err_mgr_enable;
 
 	return 0;
 
+err_mgr_enable:
 err_set_mode:
 	if (dpi_use_dsi_pll(dssdev))
 		dsi_pll_uninit(dpi.dsidev, true);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a35f3fb..57fda24 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3945,6 +3945,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
 	u8 data_type;
 	u16 word_count;
+	int r;
 
 	if (dssdev->panel.dsi_mode = OMAP_DSS_DSI_VIDEO_MODE) {
 		switch (dssdev->panel.dsi_pix_fmt) {
@@ -3979,7 +3980,15 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 		dsi_if_enable(dsidev, true);
 	}
 
-	dss_mgr_enable(dssdev->manager);
+	r = dss_mgr_enable(dssdev->manager);
+	if (r) {
+		if (dssdev->panel.dsi_mode = OMAP_DSS_DSI_VIDEO_MODE) {
+			dsi_if_enable(dsidev, false);
+			dsi_vc_enable(dsidev, channel, false);
+		}
+
+		return r;
+	}
 
 	return 0;
 }
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index e245a2b..b064762 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -387,9 +387,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
 	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
 
-	dss_mgr_enable(dssdev->manager);
+	r = dss_mgr_enable(dssdev->manager);
+	if (r)
+		goto err_mgr_enable;
 
 	return 0;
+
+err_mgr_enable:
+	hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
+	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 err:
 	hdmi_runtime_put();
 	return -EIO;
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 02da8be..8266ca0 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -123,10 +123,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 		goto err_sdi_enable;
 	mdelay(2);
 
-	dss_mgr_enable(dssdev->manager);
+	r = dss_mgr_enable(dssdev->manager);
+	if (r)
+		goto err_mgr_enable;
 
 	return 0;
 
+err_mgr_enable:
+	dss_sdi_disable();
 err_sdi_enable:
 err_set_dispc_clock_div:
 err_set_dss_clock_div:
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 101fcd7..b3e9f90 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -417,9 +417,10 @@ static const struct venc_config *venc_timings_to_config(
 	BUG();
 }
 
-static void venc_power_on(struct omap_dss_device *dssdev)
+static int venc_power_on(struct omap_dss_device *dssdev)
 {
 	u32 l;
+	int r;
 
 	venc_reset();
 	venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
@@ -447,7 +448,22 @@ static void venc_power_on(struct omap_dss_device *dssdev)
 	if (dssdev->platform_enable)
 		dssdev->platform_enable(dssdev);
 
-	dss_mgr_enable(dssdev->manager);
+	r = dss_mgr_enable(dssdev->manager);
+	if (r)
+		goto err;
+
+	return 0;
+
+err:
+	venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+	dss_set_dac_pwrdn_bgz(0);
+
+	if (dssdev->platform_disable)
+		dssdev->platform_disable(dssdev);
+
+	regulator_disable(venc.vdda_dac_reg);
+
+	return r;
 }
 
 static void venc_power_off(struct omap_dss_device *dssdev)
@@ -504,7 +520,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err1;
 
-	venc_power_on(dssdev);
+	r = venc_power_on(dssdev);
+	if (r)
+		goto err2;
 
 	venc.wss_data = 0;
 
@@ -512,6 +530,8 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
 
 	mutex_unlock(&venc.venc_lock);
 	return 0;
+err2:
+	venc_runtime_put();
 err1:
 	omap_dss_stop_device(dssdev);
 err0:
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 64/65] OMAPDSS: APPLY: add return value to dss_mgr_enable()
From: Tomi Valkeinen @ 2011-11-22  9:22 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Now that dss_mgr_enable() can fail due to checks, make it return the
error value.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 72afa85..1ce4c00 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -967,7 +967,7 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
 	}
 }
 
-void dss_mgr_enable(struct omap_overlay_manager *mgr)
+int dss_mgr_enable(struct omap_overlay_manager *mgr)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
@@ -986,8 +986,7 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 	if (r) {
 		DSSERR("failed to enable manager %d: check_settings failed\n",
 				mgr->id);
-		spin_unlock_irqrestore(&data_lock, flags);
-		goto out;
+		goto err;
 	}
 
 	mp->enabled = true;
@@ -1006,6 +1005,13 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 
 out:
 	mutex_unlock(&apply_lock);
+
+	return 0;
+
+err:
+	spin_unlock_irqrestore(&data_lock, flags);
+	mutex_unlock(&apply_lock);
+	return r;
 }
 
 void dss_mgr_disable(struct omap_overlay_manager *mgr)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index c6caf2f..f91eba3 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -170,7 +170,7 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
 void dss_start_update(struct omap_overlay_manager *mgr);
 int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
 
-void dss_mgr_enable(struct omap_overlay_manager *mgr);
+int dss_mgr_enable(struct omap_overlay_manager *mgr);
 void dss_mgr_disable(struct omap_overlay_manager *mgr);
 int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 63/65] OMAPDSS: APPLY: add checking of ovls/mgrs settings
From: Tomi Valkeinen @ 2011-11-22  9:22 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add checks for overlay and manager settings. The checks are a bit
complex, as we need to observe the bigger picture instead of overlays
and managers independently. Things like the used display and the zorder
of other overlays affect the validity of the settings.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 5d933b9..72afa85 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -166,6 +166,169 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
 	return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 }
 
+/* Check if overlay parameters are compatible with display */
+static int dss_ovl_check(struct omap_overlay *ovl,
+		struct omap_overlay_info *info, struct omap_dss_device *dssdev)
+{
+	u16 outw, outh;
+	u16 dw, dh;
+
+	if (dssdev = NULL)
+		return 0;
+
+	dssdev->driver->get_resolution(dssdev, &dw, &dh);
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) = 0) {
+		outw = info->width;
+		outh = info->height;
+	} else {
+		if (info->out_width = 0)
+			outw = info->width;
+		else
+			outw = info->out_width;
+
+		if (info->out_height = 0)
+			outh = info->height;
+		else
+			outh = info->out_height;
+	}
+
+	if (dw < info->pos_x + outw) {
+		DSSERR("overlay %d horizontally not inside the display area "
+				"(%d + %d >= %d)\n",
+				ovl->id, info->pos_x, outw, dw);
+		return -EINVAL;
+	}
+
+	if (dh < info->pos_y + outh) {
+		DSSERR("overlay %d vertically not inside the display area "
+				"(%d + %d >= %d)\n",
+				ovl->id, info->pos_y, outh, dh);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
+		struct omap_overlay_info **overlay_infos)
+{
+	struct omap_overlay *ovl1, *ovl2;
+	struct ovl_priv_data *op1, *op2;
+	struct omap_overlay_info *info1, *info2;
+
+	list_for_each_entry(ovl1, &mgr->overlays, list) {
+		op1 = get_ovl_priv(ovl1);
+		info1 = overlay_infos[ovl1->id];
+
+		if (info1 = NULL)
+			continue;
+
+		list_for_each_entry(ovl2, &mgr->overlays, list) {
+			if (ovl1 = ovl2)
+				continue;
+
+			op2 = get_ovl_priv(ovl2);
+			info2 = overlay_infos[ovl2->id];
+
+			if (info2 = NULL)
+				continue;
+
+			if (info1->zorder = info2->zorder) {
+				DSSERR("overlays %d and %d have the same "
+						"zorder %d\n",
+					ovl1->id, ovl2->id, info1->zorder);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int dss_mgr_check(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dssdev,
+		struct omap_overlay_manager_info *info,
+		struct omap_overlay_info **overlay_infos)
+{
+	struct omap_overlay *ovl;
+	int r;
+
+	if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
+		r = dss_mgr_check_zorder(mgr, overlay_infos);
+		if (r)
+			return r;
+	}
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		struct omap_overlay_info *oi;
+		int r;
+
+		oi = overlay_infos[ovl->id];
+
+		if (oi = NULL)
+			continue;
+
+		r = dss_ovl_check(ovl, oi, dssdev);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+static int dss_check_settings_low(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dssdev, bool applying)
+{
+	struct omap_overlay_info *oi;
+	struct omap_overlay_manager_info *mi;
+	struct omap_overlay *ovl;
+	struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
+	struct ovl_priv_data *op;
+	struct mgr_priv_data *mp;
+
+	mp = get_mgr_priv(mgr);
+
+	if (applying && mp->user_info_dirty)
+		mi = &mp->user_info;
+	else
+		mi = &mp->info;
+
+	/* collect the infos to be tested into the array */
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+
+		if (!op->enabled)
+			oi = NULL;
+		else if (applying && op->user_info_dirty)
+			oi = &op->user_info;
+		else
+			oi = &op->info;
+
+		ois[ovl->id] = oi;
+	}
+
+	return dss_mgr_check(mgr, dssdev, mi, ois);
+}
+
+/*
+ * check manager and overlay settings using overlay_info from data->info
+ */
+static int dss_check_settings(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dssdev)
+{
+	return dss_check_settings_low(mgr, dssdev, false);
+}
+
+/*
+ * check manager and overlay settings using overlay_info from ovl->info if
+ * dirty and from data->info otherwise
+ */
+static int dss_check_settings_apply(struct omap_overlay_manager *mgr,
+		struct omap_dss_device *dssdev)
+{
+	return dss_check_settings_low(mgr, dssdev, true);
+}
+
 static bool need_isr(void)
 {
 	const int num_mgrs = dss_feat_get_num_mgrs();
@@ -517,6 +680,7 @@ static void dss_write_regs(void)
 	for (i = 0; i < num_mgrs; ++i) {
 		struct omap_overlay_manager *mgr;
 		struct mgr_priv_data *mp;
+		int r;
 
 		mgr = omap_dss_get_overlay_manager(i);
 		mp = get_mgr_priv(mgr);
@@ -524,6 +688,13 @@ static void dss_write_regs(void)
 		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
 			continue;
 
+		r = dss_check_settings(mgr, mgr->device);
+		if (r) {
+			DSSERR("cannot write registers for manager %s: "
+					"illegal configuration\n", mgr->name);
+			continue;
+		}
+
 		dss_mgr_write_regs(mgr);
 
 		if (need_go(mgr)) {
@@ -541,11 +712,19 @@ void dss_start_update(struct omap_overlay_manager *mgr)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
+	int r;
 
 	spin_lock_irqsave(&data_lock, flags);
 
 	WARN_ON(mp->updating);
 
+	r = dss_check_settings(mgr, mgr->device);
+	if (r) {
+		DSSERR("cannot start manual update: illegal configuration\n");
+		spin_unlock_irqrestore(&data_lock, flags);
+		return;
+	}
+
 	dss_mgr_write_regs(mgr);
 
 	mp->updating = true;
@@ -690,11 +869,19 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 {
 	unsigned long flags;
 	struct omap_overlay *ovl;
+	int r;
 
 	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
 	spin_lock_irqsave(&data_lock, flags);
 
+	r = dss_check_settings_apply(mgr, mgr->device);
+	if (r) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("failed to apply settings: illegal configuration.\n");
+		return r;
+	}
+
 	/* Configure overlays */
 	list_for_each_entry(ovl, &mgr->overlays, list)
 		omap_dss_mgr_apply_ovl(ovl);
@@ -784,6 +971,7 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
+	int r;
 
 	mutex_lock(&apply_lock);
 
@@ -793,6 +981,16 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 	spin_lock_irqsave(&data_lock, flags);
 
 	mp->enabled = true;
+	r = dss_check_settings(mgr, mgr->device);
+	mp->enabled = false;
+	if (r) {
+		DSSERR("failed to enable manager %d: check_settings failed\n",
+				mgr->id);
+		spin_unlock_irqrestore(&data_lock, flags);
+		goto out;
+	}
+
+	mp->enabled = true;
 
 	dss_mgr_setup_fifos(mgr);
 
@@ -1142,16 +1340,25 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 
 	if (op->enabled) {
 		r = 0;
-		goto err;
+		goto err1;
 	}
 
 	if (ovl->manager = NULL || ovl->manager->device = NULL) {
 		r = -EINVAL;
-		goto err;
+		goto err1;
 	}
 
 	spin_lock_irqsave(&data_lock, flags);
 
+	op->enabled = true;
+	r = dss_check_settings(ovl->manager, ovl->manager->device);
+	op->enabled = false;
+	if (r) {
+		DSSERR("failed to enable overlay %d: check_settings failed\n",
+				ovl->id);
+		goto err2;
+	}
+
 	dss_apply_ovl_enable(ovl, true);
 
 	dss_ovl_setup_fifo(ovl);
@@ -1163,7 +1370,9 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 	mutex_unlock(&apply_lock);
 
 	return 0;
-err:
+err2:
+	spin_unlock_irqrestore(&data_lock, flags);
+err1:
 	mutex_unlock(&apply_lock);
 	return r;
 }
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 62/65] OMAPDSS: APPLY: add dss_mgr_simple_check()
From: Tomi Valkeinen @ 2011-11-22  9:22 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add dss_mgr_simple_check() which is used to check the validity of
certain manager attributes. Only attributes that can be checked
independently, without knowing the display being used, is done here
(thus "simple").

We can use this function in dss_mgr_set_info().

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index c1c4597..5d933b9 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -834,11 +834,35 @@ out:
 	mutex_unlock(&apply_lock);
 }
 
+static int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
+		const struct omap_overlay_manager_info *info)
+{
+	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
+		/*
+		 * OMAP3 supports only graphics source transparency color key
+		 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
+		 * Alpha Mode.
+		 */
+		if (info->partial_alpha_enabled && info->trans_enabled
+			&& info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
+			DSSERR("check_manager: illegal transparency key\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
+	int r;
+
+	r = dss_mgr_simple_check(mgr, info);
+	if (r)
+		return r;
 
 	spin_lock_irqsave(&data_lock, flags);
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 61/65] OMAPDSS: APPLY: add dss_ovl_simple_check()
From: Tomi Valkeinen @ 2011-11-22  9:22 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add dss_ovl_simple_check() which is used to check the validity of
certain overlay attributes. Only attributes that can be checked
independently, without knowing the display being used, is done here
(thus "simple").

We can use this function in dss_ovl_set_info().

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 6a50ee0..c1c4597 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -928,12 +928,52 @@ err:
 }
 
 
+static int dss_ovl_simple_check(struct omap_overlay *ovl,
+		const struct omap_overlay_info *info)
+{
+	if (info->paddr = 0) {
+		DSSERR("check_overlay: paddr cannot be 0\n");
+		return -EINVAL;
+	}
+
+	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) = 0) {
+		if (info->out_width != 0 && info->width != info->out_width) {
+			DSSERR("check_overlay: overlay %d doesn't support "
+					"scaling\n", ovl->id);
+			return -EINVAL;
+		}
+
+		if (info->out_height != 0 && info->height != info->out_height) {
+			DSSERR("check_overlay: overlay %d doesn't support "
+					"scaling\n", ovl->id);
+			return -EINVAL;
+		}
+	}
+
+	if ((ovl->supported_modes & info->color_mode) = 0) {
+		DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
+				ovl->id, info->color_mode);
+		return -EINVAL;
+	}
+
+	if (info->zorder >= omap_dss_get_num_overlays()) {
+		DSSERR("check_overlay: zorder %d too high\n", info->zorder);
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 int dss_ovl_set_info(struct omap_overlay *ovl,
 		struct omap_overlay_info *info)
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
+	int r;
+
+	r = dss_ovl_simple_check(ovl, info);
+	if (r)
+		return r;
 
 	spin_lock_irqsave(&data_lock, flags);
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 60/65] OMAPDSS: Add comments about blocking of ovl/mgr functions
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add comments specifying what ovl/mgr functions may block.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 include/video/omapdss.h |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 98fc026..39862b8 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -384,6 +384,17 @@ struct omap_overlay {
 	/* dynamic fields */
 	struct omap_overlay_manager *manager;
 
+	/*
+	 * The following functions do not block:
+	 *
+	 * is_enabled
+	 * set_overlay_info
+	 * get_overlay_info
+	 *
+	 * The rest of the functions may block and cannot be called from
+	 * interrupt context
+	 */
+
 	int (*enable)(struct omap_overlay *ovl);
 	int (*disable)(struct omap_overlay *ovl);
 	bool (*is_enabled)(struct omap_overlay *ovl);
@@ -426,6 +437,17 @@ struct omap_overlay_manager {
 	/* dynamic fields */
 	struct omap_dss_device *device;
 
+	/*
+	 * The following functions do not block:
+	 *
+	 * set_manager_info
+	 * get_manager_info
+	 * apply
+	 *
+	 * The rest of the functions may block and cannot be called from
+	 * interrupt context
+	 */
+
 	int (*set_device)(struct omap_overlay_manager *mgr,
 		struct omap_dss_device *dssdev);
 	int (*unset_device)(struct omap_overlay_manager *mgr);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 59/65] OMAPDSS: APPLY: remove runtime_get
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

apply.c no longer touches any registers if an output is not enabled.
This means that we don't need to do dispc_runtime_get() anymore, and the
calls can be removed.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 75db522..6a50ee0 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -688,16 +688,11 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 
 int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 {
-	int r;
 	unsigned long flags;
 	struct omap_overlay *ovl;
 
 	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
 	spin_lock_irqsave(&data_lock, flags);
 
 	/* Configure overlays */
@@ -711,9 +706,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
-	dispc_runtime_put();
-
-	return r;
+	return 0;
 }
 
 static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 58/65] OMAPDSS: APPLY: add wait_pending_extra_info_updates()
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add wait_pending_extra_info_updates() function which can be used to wait
until any extra_info changes have been taken into use by the hardware.
This can be only called when holding the apply mutex, so that other
threads cannot insert new extra_info changes.

This will be used to handle fifo-configurations.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 76b5b02..75db522 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -106,6 +106,7 @@ static struct {
 static spinlock_t data_lock;
 /* lock for blocking functions */
 static DEFINE_MUTEX(apply_lock);
+static DECLARE_COMPLETION(extra_updated_completion);
 
 static void dss_register_vsync_isr(void);
 
@@ -232,6 +233,70 @@ static bool need_go(struct omap_overlay_manager *mgr)
 	return false;
 }
 
+/* returns true if an extra_info field is currently being updated */
+static bool extra_info_update_ongoing(void)
+{
+	const int num_ovls = omap_dss_get_num_overlays();
+	struct ovl_priv_data *op;
+	struct omap_overlay *ovl;
+	struct mgr_priv_data *mp;
+	int i;
+	bool eid;
+
+	for (i = 0; i < num_ovls; ++i) {
+		ovl = omap_dss_get_overlay(i);
+		op = get_ovl_priv(ovl);
+
+		if (!op->enabled)
+			continue;
+
+		mp = get_mgr_priv(ovl->manager);
+
+		if (!mp->enabled)
+			continue;
+
+		eid = op->extra_info_dirty || op->shadow_extra_info_dirty;
+
+		if (!eid)
+			continue;
+
+		if (ovl_manual_update(ovl) && !mp->updating)
+			continue;
+
+		return true;
+	}
+
+	return false;
+}
+
+/* wait until no extra_info updates are pending */
+static void wait_pending_extra_info_updates(void)
+{
+	bool updating;
+	unsigned long flags;
+	unsigned long t;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	updating = extra_info_update_ongoing();
+
+	if (!updating) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		return;
+	}
+
+	init_completion(&extra_updated_completion);
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	t = msecs_to_jiffies(500);
+	wait_for_completion_timeout(&extra_updated_completion, t);
+
+	updating = extra_info_update_ongoing();
+
+	WARN_ON(updating);
+}
+
 int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
 	unsigned long timeout = msecs_to_jiffies(500);
@@ -553,6 +618,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 {
 	const int num_mgrs = dss_feat_get_num_mgrs();
 	int i;
+	bool extra_updating;
 
 	spin_lock(&data_lock);
 
@@ -582,6 +648,10 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 
 	dss_write_regs();
 
+	extra_updating = extra_info_update_ongoing();
+	if (!extra_updating)
+		complete_all(&extra_updated_completion);
+
 	if (!need_isr())
 		dss_unregister_vsync_isr();
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 57/65] OMAPDSS: APPLY: skip enable/disable if already enabled/disabled
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add checks to dss_mgr_enable, dss_mgr_disable, dss_ovl_enable,
dss_ovl_disable that check if the state is already the same as given in
the parameters, and exit if so.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index cfc17c0..76b5b02 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -724,6 +724,9 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 
 	mutex_lock(&apply_lock);
 
+	if (mp->enabled)
+		goto out;
+
 	spin_lock_irqsave(&data_lock, flags);
 
 	mp->enabled = true;
@@ -740,6 +743,7 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 	if (!mgr_manual_update(mgr))
 		dispc_mgr_enable(mgr->id, true);
 
+out:
 	mutex_unlock(&apply_lock);
 }
 
@@ -750,6 +754,9 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 
 	mutex_lock(&apply_lock);
 
+	if (!mp->enabled)
+		goto out;
+
 	if (!mgr_manual_update(mgr))
 		dispc_mgr_enable(mgr->id, false);
 
@@ -760,6 +767,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
+out:
 	mutex_unlock(&apply_lock);
 }
 
@@ -1005,6 +1013,11 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 
 	mutex_lock(&apply_lock);
 
+	if (op->enabled) {
+		r = 0;
+		goto err;
+	}
+
 	if (ovl->manager = NULL || ovl->manager->device = NULL) {
 		r = -EINVAL;
 		goto err;
@@ -1036,6 +1049,11 @@ int dss_ovl_disable(struct omap_overlay *ovl)
 
 	mutex_lock(&apply_lock);
 
+	if (!op->enabled) {
+		r = 0;
+		goto err;
+	}
+
 	if (ovl->manager = NULL || ovl->manager->device = NULL) {
 		r = -EINVAL;
 		goto err;
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 56/65] OMAPDSS: APPLY: add dss_apply_ovl_enable()
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add a helper function dss_apply_ovl_enable(), which is similar to the
main apply() function: dss_apply_ovl_enable() applies the given overlay
enable-status to ovl_priv_data, and sets the dirty flag.

The difference between the helper function and the previous direct use
of the fields is that the helper function will not do anything if the
enable state is already the same as given in the parameter.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 916acd7..cfc17c0 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -646,6 +646,19 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 	return r;
 }
 
+static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
+{
+	struct ovl_priv_data *op;
+
+	op = get_ovl_priv(ovl);
+
+	if (op->enabled = enable)
+		return;
+
+	op->enabled = enable;
+	op->extra_info_dirty = true;
+}
+
 static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -999,8 +1012,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	op->enabled = true;
-	op->extra_info_dirty = true;
+	dss_apply_ovl_enable(ovl, true);
 
 	dss_ovl_setup_fifo(ovl);
 
@@ -1031,8 +1043,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	op->enabled = false;
-	op->extra_info_dirty = true;
+	dss_apply_ovl_enable(ovl, false);
 
 	dss_write_regs();
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 55/65] OMAPDSS: APPLY: remove device_changed field
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

omap_overlay_manager contains device_changed field, which no longer has
any use. So remove the field and the few places where it is touched.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/apply.c |    7 -------
 include/video/omapdss.h         |    2 --
 2 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index fdd53b6..916acd7 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -608,11 +608,6 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 
 	mp = get_mgr_priv(mgr);
 
-	if (mgr->device_changed) {
-		mgr->device_changed = false;
-		mp->user_info_dirty  = true;
-	}
-
 	if (!mp->user_info_dirty)
 		return;
 
@@ -807,7 +802,6 @@ int dss_mgr_set_device(struct omap_overlay_manager *mgr,
 
 	dssdev->manager = mgr;
 	mgr->device = dssdev;
-	mgr->device_changed = true;
 
 	mutex_unlock(&apply_lock);
 
@@ -840,7 +834,6 @@ int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
 
 	mgr->device->manager = NULL;
 	mgr->device = NULL;
-	mgr->device_changed = true;
 
 	mutex_unlock(&apply_lock);
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index e629b0d..98fc026 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -426,8 +426,6 @@ struct omap_overlay_manager {
 	/* dynamic fields */
 	struct omap_dss_device *device;
 
-	bool device_changed;
-
 	int (*set_device)(struct omap_overlay_manager *mgr,
 		struct omap_dss_device *dssdev);
 	int (*unset_device)(struct omap_overlay_manager *mgr);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 54/65] OMAPDSS: APPLY: rename dirty & shadow_dirty
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Rename ovl_priv_data's and mgr_priv_data's dirty and shadow_dirty fields
to info_dirty and shadow_info_dirty to better reflect what they mean.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 0e93ae5..fdd53b6 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -31,8 +31,10 @@
  * We have 4 levels of cache for the dispc settings. First two are in SW and
  * the latter two in HW.
  *
+ *       set_info()
+ *          v
  * +--------------------+
- * |overlay/manager_info|
+ * |     user_info      |
  * +--------------------+
  *          v
  *        apply()
@@ -59,16 +61,11 @@ struct ovl_priv_data {
 	bool user_info_dirty;
 	struct omap_overlay_info user_info;
 
-	/* If true, cache changed, but not written to shadow registers. Set
-	 * in apply(), cleared when registers written. */
-	bool dirty;
-	/* If true, shadow registers contain changed values not yet in real
-	 * registers. Set when writing to shadow registers, cleared at
-	 * VSYNC/EVSYNC */
-	bool shadow_dirty;
-
+	bool info_dirty;
 	struct omap_overlay_info info;
 
+	bool shadow_info_dirty;
+
 	bool extra_info_dirty;
 	bool shadow_extra_info_dirty;
 
@@ -82,16 +79,11 @@ struct mgr_priv_data {
 	bool user_info_dirty;
 	struct omap_overlay_manager_info user_info;
 
-	/* If true, cache changed, but not written to shadow registers. Set
-	 * in apply(), cleared when registers written. */
-	bool dirty;
-	/* If true, shadow registers contain changed values not yet in real
-	 * registers. Set when writing to shadow registers, cleared at
-	 * VSYNC/EVSYNC */
-	bool shadow_dirty;
-
+	bool info_dirty;
 	struct omap_overlay_manager_info info;
 
+	bool shadow_info_dirty;
+
 	/* If true, GO bit is up and shadow registers cannot be written.
 	 * Never true for manual update displays */
 	bool busy;
@@ -199,7 +191,7 @@ static bool need_isr(void)
 				return true;
 
 			/* to write new values to registers */
-			if (mp->dirty)
+			if (mp->info_dirty)
 				return true;
 
 			list_for_each_entry(ovl, &mgr->overlays, list) {
@@ -211,7 +203,7 @@ static bool need_isr(void)
 					continue;
 
 				/* to write new values to registers */
-				if (op->dirty || op->extra_info_dirty)
+				if (op->info_dirty || op->extra_info_dirty)
 					return true;
 			}
 		}
@@ -228,12 +220,12 @@ static bool need_go(struct omap_overlay_manager *mgr)
 
 	mp = get_mgr_priv(mgr);
 
-	if (mp->shadow_dirty)
+	if (mp->shadow_info_dirty)
 		return true;
 
 	list_for_each_entry(ovl, &mgr->overlays, list) {
 		op = get_ovl_priv(ovl);
-		if (op->shadow_dirty || op->shadow_extra_info_dirty)
+		if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
 			return true;
 	}
 
@@ -264,8 +256,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 		bool shadow_dirty, dirty;
 
 		spin_lock_irqsave(&data_lock, flags);
-		dirty = mp->dirty;
-		shadow_dirty = mp->shadow_dirty;
+		dirty = mp->info_dirty;
+		shadow_dirty = mp->shadow_info_dirty;
 		spin_unlock_irqrestore(&data_lock, flags);
 
 		if (!dirty && !shadow_dirty) {
@@ -327,8 +319,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
 		bool shadow_dirty, dirty;
 
 		spin_lock_irqsave(&data_lock, flags);
-		dirty = op->dirty;
-		shadow_dirty = op->shadow_dirty;
+		dirty = op->info_dirty;
+		shadow_dirty = op->shadow_info_dirty;
 		spin_unlock_irqrestore(&data_lock, flags);
 
 		if (!dirty && !shadow_dirty) {
@@ -371,7 +363,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 
 	DSSDBGF("%d", ovl->id);
 
-	if (!op->enabled || !op->dirty)
+	if (!op->enabled || !op->info_dirty)
 		return;
 
 	oi = &op->info;
@@ -396,9 +388,9 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 
 	mp = get_mgr_priv(ovl->manager);
 
-	op->dirty = false;
+	op->info_dirty = false;
 	if (mp->updating)
-		op->shadow_dirty = true;
+		op->shadow_info_dirty = true;
 }
 
 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
@@ -443,12 +435,12 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 		dss_ovl_write_regs_extra(ovl);
 	}
 
-	if (mp->dirty) {
+	if (mp->info_dirty) {
 		dispc_mgr_setup(mgr->id, &mp->info);
 
-		mp->dirty = false;
+		mp->info_dirty = false;
 		if (mp->updating)
-			mp->shadow_dirty = true;
+			mp->shadow_info_dirty = true;
 	}
 }
 
@@ -548,11 +540,11 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
 	struct ovl_priv_data *op;
 
 	mp = get_mgr_priv(mgr);
-	mp->shadow_dirty = false;
+	mp->shadow_info_dirty = false;
 
 	list_for_each_entry(ovl, &mgr->overlays, list) {
 		op = get_ovl_priv(ovl);
-		op->shadow_dirty = false;
+		op->shadow_info_dirty = false;
 		op->shadow_extra_info_dirty = false;
 	}
 }
@@ -606,7 +598,7 @@ static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
 		return;
 
 	op->user_info_dirty = false;
-	op->dirty = true;
+	op->info_dirty = true;
 	op->info = op->user_info;
 }
 
@@ -625,7 +617,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 		return;
 
 	mp->user_info_dirty = false;
-	mp->dirty = true;
+	mp->info_dirty = true;
 	mp->info = mp->user_info;
 }
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 53/65] OMAPDSS: APPLY: move fifo thresholds to extra_info set
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Setting overlay's fifo thresholds is currently handled at the same time
as other overlay attributes. This is not right, as the normal attributes
should only affect one overlay and manager, but changing the fifo
thresholds are needed in cases like fifo-merge, where multiple managers
are affected.

This patch moves the channel field into the "extra_info" set, handled
together with channel and enabled-status.

This also lets us to calculate the fifos only when needed, specifically,
when an overlay or a manager is enabled.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 3e345d7..0e93ae5 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -69,14 +69,12 @@ struct ovl_priv_data {
 
 	struct omap_overlay_info info;
 
-	u32 fifo_low;
-	u32 fifo_high;
-
 	bool extra_info_dirty;
 	bool shadow_extra_info_dirty;
 
 	bool enabled;
 	enum omap_channel channel;
+	u32 fifo_low, fifo_high;
 };
 
 struct mgr_priv_data {
@@ -396,8 +394,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 		return;
 	}
 
-	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
-
 	mp = get_mgr_priv(ovl->manager);
 
 	op->dirty = false;
@@ -420,6 +416,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 
 	dispc_ovl_enable(ovl->id, op->enabled);
 	dispc_ovl_set_channel_out(ovl->id, op->channel);
+	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
 	mp = get_mgr_priv(ovl->manager);
 
@@ -632,13 +629,42 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 	mp->info = mp->user_info;
 }
 
-static void omap_dss_mgr_apply_ovl_fifos(struct omap_overlay *ovl)
+int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 {
-	struct ovl_priv_data *op;
+	int r;
+	unsigned long flags;
+	struct omap_overlay *ovl;
+
+	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	spin_lock_irqsave(&data_lock, flags);
+
+	/* Configure overlays */
+	list_for_each_entry(ovl, &mgr->overlays, list)
+		omap_dss_mgr_apply_ovl(ovl);
+
+	/* Configure manager */
+	omap_dss_mgr_apply_mgr(mgr);
+
+	dss_write_regs();
+
+	spin_unlock_irqrestore(&data_lock, flags);
+
+	dispc_runtime_put();
+
+	return r;
+}
+
+static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct omap_dss_device *dssdev;
 	u32 size, burst_size;
-
-	op = get_ovl_priv(ovl);
+	u32 fifo_low, fifo_high;
 
 	dssdev = ovl->manager->device;
 
@@ -653,53 +679,42 @@ static void omap_dss_mgr_apply_ovl_fifos(struct omap_overlay *ovl)
 	case OMAP_DISPLAY_TYPE_VENC:
 	case OMAP_DISPLAY_TYPE_HDMI:
 		default_get_overlay_fifo_thresholds(ovl->id, size,
-				burst_size, &op->fifo_low,
-				&op->fifo_high);
+				burst_size, &fifo_low, &fifo_high);
 		break;
 #ifdef CONFIG_OMAP2_DSS_DSI
 	case OMAP_DISPLAY_TYPE_DSI:
 		dsi_get_overlay_fifo_thresholds(ovl->id, size,
-				burst_size, &op->fifo_low,
-				&op->fifo_high);
+				burst_size, &fifo_low, &fifo_high);
 		break;
 #endif
 	default:
 		BUG();
 	}
+
+	op->fifo_low = fifo_low;
+	op->fifo_high = fifo_high;
+	op->extra_info_dirty = true;
 }
 
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
 {
-	int r;
-	unsigned long flags;
 	struct omap_overlay *ovl;
+	struct ovl_priv_data *op;
+	struct mgr_priv_data *mp;
 
-	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	spin_lock_irqsave(&data_lock, flags);
-
-	/* Configure overlays */
-	list_for_each_entry(ovl, &mgr->overlays, list)
-		omap_dss_mgr_apply_ovl(ovl);
-
-	/* Configure manager */
-	omap_dss_mgr_apply_mgr(mgr);
-
-	/* Configure overlay fifos */
-	list_for_each_entry(ovl, &mgr->overlays, list)
-		omap_dss_mgr_apply_ovl_fifos(ovl);
+	mp = get_mgr_priv(mgr);
 
-	dss_write_regs();
+	if (!mp->enabled)
+		return;
 
-	spin_unlock_irqrestore(&data_lock, flags);
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
 
-	dispc_runtime_put();
+		if (!op->enabled)
+			continue;
 
-	return r;
+		dss_ovl_setup_fifo(ovl);
+	}
 }
 
 void dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -713,6 +728,8 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 
 	mp->enabled = true;
 
+	dss_mgr_setup_fifos(mgr);
+
 	dss_write_regs();
 
 	if (!mgr_manual_update(mgr))
@@ -1000,6 +1017,8 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 	op->enabled = true;
 	op->extra_info_dirty = true;
 
+	dss_ovl_setup_fifo(ovl);
+
 	dss_write_regs();
 
 	spin_unlock_irqrestore(&data_lock, flags);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 52/65] OMAPDSS: APPLY: move channel-field to extra_info set
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Setting overlay's output channel is currently handled at the same time
as other overlay attributes. This is not right, as the normal attributes
should only affect one overlay and manager, but changing the channel
affects two managers.

This patch moves the channel field into the "extra_info" set, handled
together with enabled-status.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/apply.c |   21 +++++++--------------
 include/video/omapdss.h         |    2 --
 2 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index eac0041..3e345d7 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -69,8 +69,6 @@ struct ovl_priv_data {
 
 	struct omap_overlay_info info;
 
-	enum omap_channel channel;
-
 	u32 fifo_low;
 	u32 fifo_high;
 
@@ -78,7 +76,7 @@ struct ovl_priv_data {
 	bool shadow_extra_info_dirty;
 
 	bool enabled;
-
+	enum omap_channel channel;
 };
 
 struct mgr_priv_data {
@@ -384,8 +382,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 
 	ilace = ovl->manager->device->type = OMAP_DISPLAY_TYPE_VENC;
 
-	dispc_ovl_set_channel_out(ovl->id, op->channel);
-
 	r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
 	if (r) {
 		/*
@@ -423,6 +419,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 	 * disabled */
 
 	dispc_ovl_enable(ovl->id, op->enabled);
+	dispc_ovl_set_channel_out(ovl->id, op->channel);
 
 	mp = get_mgr_priv(ovl->manager);
 
@@ -608,19 +605,12 @@ static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
 
 	op = get_ovl_priv(ovl);
 
-	if (ovl->manager_changed) {
-		ovl->manager_changed = false;
-		op->user_info_dirty  = true;
-	}
-
 	if (!op->user_info_dirty)
 		return;
 
 	op->user_info_dirty = false;
 	op->dirty = true;
 	op->info = op->user_info;
-
-	op->channel = ovl->manager->id;
 }
 
 static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
@@ -910,9 +900,11 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
 		goto err;
 	}
 
+	op->channel = mgr->id;
+	op->extra_info_dirty = true;
+
 	ovl->manager = mgr;
 	list_add_tail(&ovl->list, &mgr->overlays);
-	ovl->manager_changed = true;
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
@@ -960,9 +952,10 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
 		goto err;
 	}
 
+	op->channel = -1;
+
 	ovl->manager = NULL;
 	list_del(&ovl->list);
-	ovl->manager_changed = true;
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 2e2c53f..e629b0d 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -384,8 +384,6 @@ struct omap_overlay {
 	/* dynamic fields */
 	struct omap_overlay_manager *manager;
 
-	bool manager_changed;
-
 	int (*enable)(struct omap_overlay *ovl);
 	int (*disable)(struct omap_overlay *ovl);
 	bool (*is_enabled)(struct omap_overlay *ovl);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 51/65] OMAPDSS: APPLY: move ovl->info to apply.c
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

struct omap_overlayr contains info and info_dirty fields, both of which
should be internal to apply.c.

This patch moves those fields into ovl_priv data, and names them
user_info and user_info_dirty.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/apply.c           |   51 ++++++++++++++++++++++++----
 drivers/video/omap2/dss/overlay.c         |   53 +++++++++++++++++++----------
 drivers/video/omap2/omapfb/omapfb-ioctl.c |   12 +++---
 drivers/video/omap2/omapfb/omapfb-main.c  |   12 ++++--
 include/video/omapdss.h                   |    3 --
 5 files changed, 93 insertions(+), 38 deletions(-)

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index de1ac24..eac0041 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -55,6 +55,10 @@
  */
 
 struct ovl_priv_data {
+
+	bool user_info_dirty;
+	struct omap_overlay_info user_info;
+
 	/* If true, cache changed, but not written to shadow registers. Set
 	 * in apply(), cleared when registers written. */
 	bool dirty;
@@ -129,7 +133,38 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
 
 void dss_apply_init(void)
 {
+	const int num_ovls = dss_feat_get_num_ovls();
+	int i;
+
 	spin_lock_init(&data_lock);
+
+	for (i = 0; i < num_ovls; ++i) {
+		struct ovl_priv_data *op;
+
+		op = &dss_data.ovl_priv_data_array[i];
+
+		op->info.global_alpha = 255;
+
+		switch (i) {
+		case 0:
+			op->info.zorder = 0;
+			break;
+		case 1:
+			op->info.zorder +				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
+			break;
+		case 2:
+			op->info.zorder +				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
+			break;
+		case 3:
+			op->info.zorder +				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
+			break;
+		}
+
+		op->user_info = op->info;
+	}
 }
 
 static bool ovl_manual_update(struct omap_overlay *ovl)
@@ -575,15 +610,15 @@ static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
 
 	if (ovl->manager_changed) {
 		ovl->manager_changed = false;
-		ovl->info_dirty  = true;
+		op->user_info_dirty  = true;
 	}
 
-	if (!ovl->info_dirty)
+	if (!op->user_info_dirty)
 		return;
 
-	ovl->info_dirty = false;
+	op->user_info_dirty = false;
 	op->dirty = true;
-	op->info = ovl->info;
+	op->info = op->user_info;
 
 	op->channel = ovl->manager->id;
 }
@@ -821,12 +856,13 @@ err:
 int dss_ovl_set_info(struct omap_overlay *ovl,
 		struct omap_overlay_info *info)
 {
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	ovl->info = *info;
-	ovl->info_dirty = true;
+	op->user_info = *info;
+	op->user_info_dirty = true;
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
@@ -836,11 +872,12 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
 void dss_ovl_get_info(struct omap_overlay *ovl,
 		struct omap_overlay_info *info)
 {
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	*info = ovl->info;
+	*info = op->user_info;
 
 	spin_unlock_irqrestore(&data_lock, flags);
 }
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 7d7cdf6..8d036e6 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -124,19 +124,31 @@ err:
 
 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
 {
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
 	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-			ovl->info.width, ovl->info.height);
+			info.width, info.height);
 }
 
 static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
 }
 
 static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
 {
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
 	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-			ovl->info.pos_x, ovl->info.pos_y);
+			info.pos_x, info.pos_y);
 }
 
 static ssize_t overlay_position_store(struct omap_overlay *ovl,
@@ -170,8 +182,12 @@ static ssize_t overlay_position_store(struct omap_overlay *ovl,
 
 static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
 {
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
 	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
-			ovl->info.out_width, ovl->info.out_height);
+			info.out_width, info.out_height);
 }
 
 static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
@@ -231,8 +247,12 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
 
 static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
 {
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-			ovl->info.global_alpha);
+			info.global_alpha);
 }
 
 static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
@@ -269,8 +289,12 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
 static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
 		char *buf)
 {
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-			ovl->info.pre_mult_alpha);
+			info.pre_mult_alpha);
 }
 
 static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
@@ -306,7 +330,11 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
 
 static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
+	struct omap_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
 }
 
 static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
@@ -456,29 +484,18 @@ void dss_init_overlays(struct platform_device *pdev)
 		case 0:
 			ovl->name = "gfx";
 			ovl->id = OMAP_DSS_GFX;
-			ovl->info.global_alpha = 255;
-			ovl->info.zorder = 0;
 			break;
 		case 1:
 			ovl->name = "vid1";
 			ovl->id = OMAP_DSS_VIDEO1;
-			ovl->info.global_alpha = 255;
-			ovl->info.zorder -				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
 			break;
 		case 2:
 			ovl->name = "vid2";
 			ovl->id = OMAP_DSS_VIDEO2;
-			ovl->info.global_alpha = 255;
-			ovl->info.zorder -				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
 			break;
 		case 3:
 			ovl->name = "vid3";
 			ovl->id = OMAP_DSS_VIDEO3;
-			ovl->info.global_alpha = 255;
-			ovl->info.zorder -				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
 			break;
 		}
 
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 562b5cc..16ba619 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -189,19 +189,19 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 		memset(pi, 0, sizeof(*pi));
 	} else {
 		struct omap_overlay *ovl;
-		struct omap_overlay_info *ovli;
+		struct omap_overlay_info ovli;
 
 		ovl = ofbi->overlays[0];
-		ovli = &ovl->info;
+		ovl->get_overlay_info(ovl, &ovli);
 
-		pi->pos_x = ovli->pos_x;
-		pi->pos_y = ovli->pos_y;
+		pi->pos_x = ovli.pos_x;
+		pi->pos_y = ovli.pos_y;
 		pi->enabled = ovl->is_enabled(ovl);
 		pi->channel_out = 0; /* xxx */
 		pi->mirror = 0;
 		pi->mem_idx = get_mem_idx(ofbi);
-		pi->out_width = ovli->out_width;
-		pi->out_height = ovli->out_height;
+		pi->out_width = ovli.out_width;
+		pi->out_height = ovli.out_height;
 	}
 
 	return 0;
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 91b49b5..46024ab 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -970,16 +970,20 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
 				outh = var->yres;
 			}
 		} else {
-			outw = ovl->info.out_width;
-			outh = ovl->info.out_height;
+			struct omap_overlay_info info;
+			ovl->get_overlay_info(ovl, &info);
+			outw = info.out_width;
+			outh = info.out_height;
 		}
 
 		if (init) {
 			posx = 0;
 			posy = 0;
 		} else {
-			posx = ovl->info.pos_x;
-			posy = ovl->info.pos_y;
+			struct omap_overlay_info info;
+			ovl->get_overlay_info(ovl, &info);
+			posx = info.pos_x;
+			posy = info.pos_y;
 		}
 
 		r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 0d5333f..2e2c53f 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -383,11 +383,8 @@ struct omap_overlay {
 
 	/* dynamic fields */
 	struct omap_overlay_manager *manager;
-	struct omap_overlay_info info;
 
 	bool manager_changed;
-	/* if true, info has been changed, but not applied() yet */
-	bool info_dirty;
 
 	int (*enable)(struct omap_overlay *ovl);
 	int (*disable)(struct omap_overlay *ovl);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 50/65] OMAPDSS: APPLY: move mgr->info to apply.c
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

struct omap_overlay_manager contains info and info_dirty fields, both of
which should be internal to apply.c.

This patch moves those fields into mgr_priv data, and names them
user_info and user_info_dirty.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/apply.c   |   20 +++++++++++++-------
 drivers/video/omap2/dss/manager.c |   35 +++++++++++++++++++++++++++++------
 include/video/omapdss.h           |    3 ---
 3 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 601dbc7..de1ac24 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -78,6 +78,10 @@ struct ovl_priv_data {
 };
 
 struct mgr_priv_data {
+
+	bool user_info_dirty;
+	struct omap_overlay_manager_info user_info;
+
 	/* If true, cache changed, but not written to shadow registers. Set
 	 * in apply(), cleared when registers written. */
 	bool dirty;
@@ -592,15 +596,15 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 
 	if (mgr->device_changed) {
 		mgr->device_changed = false;
-		mgr->info_dirty  = true;
+		mp->user_info_dirty  = true;
 	}
 
-	if (!mgr->info_dirty)
+	if (!mp->user_info_dirty)
 		return;
 
-	mgr->info_dirty = false;
+	mp->user_info_dirty = false;
 	mp->dirty = true;
-	mp->info = mgr->info;
+	mp->info = mp->user_info;
 }
 
 static void omap_dss_mgr_apply_ovl_fifos(struct omap_overlay *ovl)
@@ -720,12 +724,13 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info)
 {
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	mgr->info = *info;
-	mgr->info_dirty = true;
+	mp->user_info = *info;
+	mp->user_info_dirty = true;
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
@@ -735,11 +740,12 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 void dss_mgr_get_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info)
 {
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	*info = mgr->info;
+	*info = mp->user_info;
 
 	spin_unlock_irqrestore(&data_lock, flags);
 }
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index d7fd494..8c967ef 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -104,7 +104,11 @@ put_device:
 static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
 					  char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
 }
 
 static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@@ -142,8 +146,11 @@ static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
 					   char *buf)
 {
 	enum omap_dss_trans_key_type key_type;
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
 
-	key_type = mgr->info.trans_key_type;
+	key_type = info.trans_key_type;
 	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
@@ -183,7 +190,11 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
 static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
 					    char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
 }
 
 static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@@ -215,7 +226,11 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
 static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
 					      char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
 }
 
 static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
@@ -247,10 +262,14 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
 static ssize_t manager_alpha_blending_enabled_show(
 		struct omap_overlay_manager *mgr, char *buf)
 {
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
 	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-		mgr->info.partial_alpha_enabled);
+		info.partial_alpha_enabled);
 }
 
 static ssize_t manager_alpha_blending_enabled_store(
@@ -285,7 +304,11 @@ static ssize_t manager_alpha_blending_enabled_store(
 static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
 		char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable);
+	struct omap_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
 }
 
 static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 9d01ff6..0d5333f 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -430,11 +430,8 @@ struct omap_overlay_manager {
 
 	/* dynamic fields */
 	struct omap_dss_device *device;
-	struct omap_overlay_manager_info info;
 
 	bool device_changed;
-	/* if true, info has been changed but not applied() yet */
-	bool info_dirty;
 
 	int (*set_device)(struct omap_overlay_manager *mgr,
 		struct omap_dss_device *dssdev);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 49/65] OMAPDSS: APPLY: clean up isr_handler
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add a helper function mgr_clear_shadow_dirty(), which clears the
shadow_dirty flags for the given manager and for the overlays on that
manager.

This lets us simplify the code in the dss_apply_irq_handler().

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index b2c0462..601dbc7 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -508,47 +508,51 @@ static void dss_unregister_vsync_isr(void)
 	dss_data.irq_enabled = false;
 }
 
-static void dss_apply_irq_handler(void *data, u32 mask)
+static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
 {
 	struct omap_overlay *ovl;
-	struct omap_overlay_manager *mgr;
 	struct mgr_priv_data *mp;
 	struct ovl_priv_data *op;
-	const int num_ovls = dss_feat_get_num_ovls();
+
+	mp = get_mgr_priv(mgr);
+	mp->shadow_dirty = false;
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+		op->shadow_dirty = false;
+		op->shadow_extra_info_dirty = false;
+	}
+}
+
+static void dss_apply_irq_handler(void *data, u32 mask)
+{
 	const int num_mgrs = dss_feat_get_num_mgrs();
 	int i;
 
 	spin_lock(&data_lock);
 
+	/* clear busy, updating flags, shadow_dirty flags */
 	for (i = 0; i < num_mgrs; i++) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+
 		mgr = omap_dss_get_overlay_manager(i);
 		mp = get_mgr_priv(mgr);
 
-		mp->busy = dispc_mgr_go_busy(i);
-		mp->updating = dispc_mgr_is_enabled(i);
-	}
-
-	for (i = 0; i < num_ovls; ++i) {
-		ovl = omap_dss_get_overlay(i);
-		op = get_ovl_priv(ovl);
-
-		if (!op->enabled)
+		if (!mp->enabled)
 			continue;
 
-		mp = get_mgr_priv(ovl->manager);
-
-		if (!mp->busy) {
-			op->shadow_dirty = false;
-			op->shadow_extra_info_dirty = false;
-		}
-	}
+		mp->updating = dispc_mgr_is_enabled(i);
 
-	for (i = 0; i < num_mgrs; ++i) {
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
+		if (!mgr_manual_update(mgr)) {
+			mp->busy = dispc_mgr_go_busy(i);
 
-		if (!mp->busy)
-			mp->shadow_dirty = false;
+			if (!mp->busy)
+				mgr_clear_shadow_dirty(mgr);
+		} else {
+			if (!mp->updating)
+				mgr_clear_shadow_dirty(mgr);
+		}
 	}
 
 	dss_write_regs();
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 48/65] OMAPDSS: APPLY: add updating flag
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add "updating" flag to mgr_priv_data, which is used to track whether the
manager is currently actively working, i.e. updating the screen.

For auto-update displays updating is always true when the display is
enabled, but for manual update displays the flag is true only during
frame transfers.

The flag is used to manage registers properly, for example when updating
is false and a register for a manager is written, there's no need to set
shadow_dirty flag nor set the GO bit, as the settings will be taken into
use by the HW automatically when the output is enabled.

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index c4106b6..b2c0462 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -92,6 +92,9 @@ struct mgr_priv_data {
 	 * Never true for manual update displays */
 	bool busy;
 
+	/* If true, dispc output is enabled */
+	bool updating;
+
 	/* If true, a display is enabled using this manager */
 	bool enabled;
 };
@@ -151,28 +154,31 @@ static bool need_isr(void)
 		if (!mp->enabled)
 			continue;
 
-		if (mgr_manual_update(mgr))
-			continue;
-
-		/* to catch GO bit going down */
-		if (mp->busy)
-			return true;
+		if (mgr_manual_update(mgr)) {
+			/* to catch FRAMEDONE */
+			if (mp->updating)
+				return true;
+		} else {
+			/* to catch GO bit going down */
+			if (mp->busy)
+				return true;
 
-		/* to write new values to registers */
-		if (mp->dirty)
-			return true;
+			/* to write new values to registers */
+			if (mp->dirty)
+				return true;
 
-		list_for_each_entry(ovl, &mgr->overlays, list) {
-			struct ovl_priv_data *op;
+			list_for_each_entry(ovl, &mgr->overlays, list) {
+				struct ovl_priv_data *op;
 
-			op = get_ovl_priv(ovl);
+				op = get_ovl_priv(ovl);
 
-			if (!op->enabled)
-				continue;
+				if (!op->enabled)
+					continue;
 
-			/* to write new values to registers */
-			if (op->dirty || op->extra_info_dirty)
-				return true;
+				/* to write new values to registers */
+				if (op->dirty || op->extra_info_dirty)
+					return true;
+			}
 		}
 	}
 
@@ -325,6 +331,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct omap_overlay_info *oi;
 	bool ilace, replication;
+	struct mgr_priv_data *mp;
 	int r;
 
 	DSSDBGF("%d", ovl->id);
@@ -356,13 +363,17 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 
 	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
+	mp = get_mgr_priv(ovl->manager);
+
 	op->dirty = false;
-	op->shadow_dirty = true;
+	if (mp->updating)
+		op->shadow_dirty = true;
 }
 
 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	struct mgr_priv_data *mp;
 
 	DSSDBGF("%d", ovl->id);
 
@@ -374,8 +385,11 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 
 	dispc_ovl_enable(ovl->id, op->enabled);
 
+	mp = get_mgr_priv(ovl->manager);
+
 	op->extra_info_dirty = false;
-	op->shadow_extra_info_dirty = true;
+	if (mp->updating)
+		op->shadow_extra_info_dirty = true;
 }
 
 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
@@ -400,7 +414,8 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 		dispc_mgr_setup(mgr->id, &mp->info);
 
 		mp->dirty = false;
-		mp->shadow_dirty = true;
+		if (mp->updating)
+			mp->shadow_dirty = true;
 	}
 }
 
@@ -435,21 +450,18 @@ static void dss_write_regs(void)
 void dss_start_update(struct omap_overlay_manager *mgr)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
-	struct ovl_priv_data *op;
-	struct omap_overlay *ovl;
 	unsigned long flags;
 
 	spin_lock_irqsave(&data_lock, flags);
 
+	WARN_ON(mp->updating);
+
 	dss_mgr_write_regs(mgr);
 
-	list_for_each_entry(ovl, &mgr->overlays, list) {
-		op = get_ovl_priv(ovl);
-		op->shadow_dirty = false;
-		op->shadow_extra_info_dirty = false;
-	}
+	mp->updating = true;
 
-	mp->shadow_dirty = false;
+	if (!dss_data.irq_enabled && need_isr())
+		dss_register_vsync_isr();
 
 	dispc_mgr_enable(mgr->id, true);
 
@@ -468,6 +480,9 @@ static void dss_register_vsync_isr(void)
 	for (i = 0; i < num_mgrs; ++i)
 		mask |= dispc_mgr_get_vsync_irq(i);
 
+	for (i = 0; i < num_mgrs; ++i)
+		mask |= dispc_mgr_get_framedone_irq(i);
+
 	r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
 	WARN_ON(r);
 
@@ -484,6 +499,9 @@ static void dss_unregister_vsync_isr(void)
 	for (i = 0; i < num_mgrs; ++i)
 		mask |= dispc_mgr_get_vsync_irq(i);
 
+	for (i = 0; i < num_mgrs; ++i)
+		mask |= dispc_mgr_get_framedone_irq(i);
+
 	r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
 	WARN_ON(r);
 
@@ -507,6 +525,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 		mp = get_mgr_priv(mgr);
 
 		mp->busy = dispc_mgr_go_busy(i);
+		mp->updating = dispc_mgr_is_enabled(i);
 	}
 
 	for (i = 0; i < num_ovls; ++i) {
@@ -663,6 +682,9 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 
 	dss_write_regs();
 
+	if (!mgr_manual_update(mgr))
+		mp->updating = true;
+
 	spin_unlock_irqrestore(&data_lock, flags);
 
 	if (!mgr_manual_update(mgr))
@@ -683,6 +705,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 
 	spin_lock_irqsave(&data_lock, flags);
 
+	mp->updating = false;
 	mp->enabled = false;
 
 	spin_unlock_irqrestore(&data_lock, flags);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 47/65] OMAPDSS: DISPC: add dispc_mgr_get_framedone_irq
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

Add dispc_mgr_get_framedone_irq() which returns the irq number for
FRAMEDONE for the given channel.

Note that the function returns always 0 for DIGIT channel, even if OMAP4
does have FRAMEDONE_TV interrupt. The reason for this is that this
function is currently used only to track manual updates, and thus
FRAMEDONE_TV is not needed.

If there's need in the future to also get the FRAMEDONE_TV this needs
revisiting. However, as FRAMEDONE_TV doesn't exist on OMAP2/3, the use
of this function for that purpose needs some extra code to handle the
OMAP2/3 case.

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

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 27a2cff..8ce0c81 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -452,6 +452,20 @@ u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
 	}
 }
 
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
+{
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return DISPC_IRQ_FRAMEDONE;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return DISPC_IRQ_FRAMEDONE2;
+	case OMAP_DSS_CHANNEL_DIGIT:
+		return 0;
+	default:
+		BUG();
+	}
+}
+
 bool dispc_mgr_go_busy(enum omap_channel channel)
 {
 	int bit;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index b597485..c6caf2f 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -430,6 +430,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane,
 void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
 void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
 u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
 bool dispc_mgr_go_busy(enum omap_channel channel);
 void dispc_mgr_go(enum omap_channel channel);
 bool dispc_mgr_is_enabled(enum omap_channel channel);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 46/65] OMAPDSS: APPLY: rewrite register writing
From: Tomi Valkeinen @ 2011-11-22  9:21 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1321953724-6350-1-git-send-email-tomi.valkeinen@ti.com>

The functions writing to the DISPC registers in apply.c are more complex
than needed. This patch cleans things up.

Two helper functions are added: need_isr(), which returns if an isr for
VSYNC is needed, and need_go(), which tells if there has been a write to
the shadow registers and we need to set the GO bit.

The functions that call the actual dispc write functions will set the
dirty and shadow_dirty flags themselves, instead of that being done on
the caller side. The writing functions also check if the dirty flag is
even set, and return immediately if not.

This allows us to clean up dss_write_regs().

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

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 2c60e77..c4106b6 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -88,9 +88,6 @@ struct mgr_priv_data {
 
 	struct omap_overlay_manager_info info;
 
-	bool manual_update;
-	bool do_manual_update;
-
 	/* If true, GO bit is up and shadow registers cannot be written.
 	 * Never true for manual update displays */
 	bool busy;
@@ -111,6 +108,8 @@ static spinlock_t data_lock;
 /* lock for blocking functions */
 static DEFINE_MUTEX(apply_lock);
 
+static void dss_register_vsync_isr(void);
+
 static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
 {
 	return &dss_data.ovl_priv_data_array[ovl->id];
@@ -136,6 +135,70 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
 	return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 }
 
+static bool need_isr(void)
+{
+	const int num_mgrs = dss_feat_get_num_mgrs();
+	int i;
+
+	for (i = 0; i < num_mgrs; ++i) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+		struct omap_overlay *ovl;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mp->enabled)
+			continue;
+
+		if (mgr_manual_update(mgr))
+			continue;
+
+		/* to catch GO bit going down */
+		if (mp->busy)
+			return true;
+
+		/* to write new values to registers */
+		if (mp->dirty)
+			return true;
+
+		list_for_each_entry(ovl, &mgr->overlays, list) {
+			struct ovl_priv_data *op;
+
+			op = get_ovl_priv(ovl);
+
+			if (!op->enabled)
+				continue;
+
+			/* to write new values to registers */
+			if (op->dirty || op->extra_info_dirty)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+static bool need_go(struct omap_overlay_manager *mgr)
+{
+	struct omap_overlay *ovl;
+	struct mgr_priv_data *mp;
+	struct ovl_priv_data *op;
+
+	mp = get_mgr_priv(mgr);
+
+	if (mp->shadow_dirty)
+		return true;
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+		if (op->shadow_dirty || op->shadow_extra_info_dirty)
+			return true;
+	}
+
+	return false;
+}
+
 int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
 	unsigned long timeout = msecs_to_jiffies(500);
@@ -257,20 +320,19 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
 	return r;
 }
 
-static int dss_ovl_write_regs(struct omap_overlay *ovl)
+static void dss_ovl_write_regs(struct omap_overlay *ovl)
 {
-	struct ovl_priv_data *op;
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct omap_overlay_info *oi;
 	bool ilace, replication;
 	int r;
 
 	DSSDBGF("%d", ovl->id);
 
-	op = get_ovl_priv(ovl);
-	oi = &op->info;
+	if (!op->enabled || !op->dirty)
+		return;
 
-	if (!op->enabled)
-		return 0;
+	oi = &op->info;
 
 	replication = dss_use_replication(ovl->manager->device, oi->color_mode);
 
@@ -280,15 +342,22 @@ static int dss_ovl_write_regs(struct omap_overlay *ovl)
 
 	r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
 	if (r) {
-		/* this shouldn't happen */
+		/*
+		 * We can't do much here, as this function can be called from
+		 * vsync interrupt.
+		 */
 		DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
-		dispc_ovl_enable(ovl->id, 0);
-		return r;
+
+		/* This will leave fifo configurations in a nonoptimal state */
+		op->enabled = false;
+		dispc_ovl_enable(ovl->id, false);
+		return;
 	}
 
 	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
-	return 0;
+	op->dirty = false;
+	op->shadow_dirty = true;
 }
 
 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
@@ -297,141 +366,70 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 
 	DSSDBGF("%d", ovl->id);
 
+	if (!op->extra_info_dirty)
+		return;
+
 	/* note: write also when op->enabled = false, so that the ovl gets
 	 * disabled */
 
 	dispc_ovl_enable(ovl->id, op->enabled);
+
+	op->extra_info_dirty = false;
+	op->shadow_extra_info_dirty = true;
 }
 
 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 {
-	struct mgr_priv_data *mp;
-	struct omap_overlay_manager_info *mi;
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	struct omap_overlay *ovl;
 
 	DSSDBGF("%d", mgr->id);
 
-	mp = get_mgr_priv(mgr);
-	mi = &mp->info;
-
-	dispc_mgr_setup(mgr->id, mi);
-}
-
-/* dss_write_regs() tries to write values from cache to shadow registers.
- * It writes only to those managers/overlays that are not busy.
- * returns 0 if everything could be written to shadow registers.
- * returns 1 if not everything could be written to shadow registers. */
-static int dss_write_regs(void)
-{
-	struct omap_overlay *ovl;
-	struct omap_overlay_manager *mgr;
-	struct ovl_priv_data *op;
-	struct mgr_priv_data *mp;
-	const int num_ovls = dss_feat_get_num_ovls();
-	const int num_mgrs = dss_feat_get_num_mgrs();
-	int i;
-	int r;
-	bool mgr_go[MAX_DSS_MANAGERS] = { false };
-	bool busy;
+	if (!mp->enabled)
+		return;
 
-	r = 0;
-	busy = false;
+	WARN_ON(mp->busy);
 
 	/* Commit overlay settings */
-	for (i = 0; i < num_ovls; ++i) {
-		ovl = omap_dss_get_overlay(i);
-		op = get_ovl_priv(ovl);
-
-		if (!op->dirty)
-			continue;
-
-		mp = get_mgr_priv(ovl->manager);
-
-		if (mp->manual_update && !mp->do_manual_update)
-			continue;
-
-		if (mp->busy) {
-			busy = true;
-			continue;
-		}
-
-		r = dss_ovl_write_regs(ovl);
-		if (r)
-			DSSERR("dss_ovl_write_regs %d failed\n", i);
-
-		op->dirty = false;
-		op->shadow_dirty = true;
-		mgr_go[op->channel] = true;
-	}
-
-	for (i = 0; i < num_ovls; ++i) {
-		ovl = omap_dss_get_overlay(i);
-		op = get_ovl_priv(ovl);
-
-		if (!op->extra_info_dirty)
-			continue;
-
-		mp = get_mgr_priv(ovl->manager);
-
-		if (mp->manual_update && !mp->do_manual_update)
-			continue;
-
-		if (mp->busy) {
-			busy = true;
-			continue;
-		}
-
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		dss_ovl_write_regs(ovl);
 		dss_ovl_write_regs_extra(ovl);
-
-		op->extra_info_dirty = false;
-		op->shadow_extra_info_dirty = true;
-		mgr_go[op->channel] = true;
 	}
 
-	/* Commit manager settings */
-	for (i = 0; i < num_mgrs; ++i) {
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (!mp->dirty)
-			continue;
-
-		if (mp->manual_update && !mp->do_manual_update)
-			continue;
-
-		if (mp->busy) {
-			busy = true;
-			continue;
-		}
+	if (mp->dirty) {
+		dispc_mgr_setup(mgr->id, &mp->info);
 
-		dss_mgr_write_regs(mgr);
 		mp->dirty = false;
 		mp->shadow_dirty = true;
-		mgr_go[i] = true;
 	}
+}
+
+static void dss_write_regs(void)
+{
+	const int num_mgrs = omap_dss_get_num_overlay_managers();
+	int i;
 
-	/* set GO */
 	for (i = 0; i < num_mgrs; ++i) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+
 		mgr = omap_dss_get_overlay_manager(i);
 		mp = get_mgr_priv(mgr);
 
-		if (!mgr_go[i])
+		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
 			continue;
 
-		/* We don't need GO with manual update display. LCD iface will
-		 * always be turned off after frame, and new settings will be
-		 * taken in to use at next update */
-		if (!mp->manual_update) {
+		dss_mgr_write_regs(mgr);
+
+		if (need_go(mgr)) {
 			mp->busy = true;
-			dispc_mgr_go(i);
-		}
-	}
 
-	if (busy)
-		r = 1;
-	else
-		r = 0;
+			if (!dss_data.irq_enabled && need_isr())
+				dss_register_vsync_isr();
 
-	return r;
+			dispc_mgr_go(mgr->id);
+		}
+	}
 }
 
 void dss_start_update(struct omap_overlay_manager *mgr)
@@ -443,9 +441,7 @@ void dss_start_update(struct omap_overlay_manager *mgr)
 
 	spin_lock_irqsave(&data_lock, flags);
 
-	mp->do_manual_update = true;
-	dss_write_regs();
-	mp->do_manual_update = false;
+	dss_mgr_write_regs(mgr);
 
 	list_for_each_entry(ovl, &mgr->overlays, list) {
 		op = get_ovl_priv(ovl);
@@ -502,7 +498,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 	struct ovl_priv_data *op;
 	const int num_ovls = dss_feat_get_num_ovls();
 	const int num_mgrs = dss_feat_get_num_mgrs();
-	int i, r;
+	int i;
 
 	spin_lock(&data_lock);
 
@@ -536,31 +532,11 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 			mp->shadow_dirty = false;
 	}
 
-	r = dss_write_regs();
-	if (r = 1)
-		goto end;
-
-	/* re-read busy flags */
-	for (i = 0; i < num_mgrs; i++) {
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		mp->busy = dispc_mgr_go_busy(i);
-	}
-
-	/* keep running as long as there are busy managers, so that
-	 * we can collect overlay-applied information */
-	for (i = 0; i < num_mgrs; ++i) {
-		mgr = omap_dss_get_overlay_manager(i);
-		mp = get_mgr_priv(mgr);
-
-		if (mp->busy)
-			goto end;
-	}
+	dss_write_regs();
 
-	dss_unregister_vsync_isr();
+	if (!need_isr())
+		dss_unregister_vsync_isr();
 
-end:
 	spin_unlock(&data_lock);
 }
 
@@ -599,14 +575,9 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 	if (!mgr->info_dirty)
 		return;
 
-	if (!mgr->device)
-		return;
-
 	mgr->info_dirty = false;
 	mp->dirty = true;
 	mp->info = mgr->info;
-
-	mp->manual_update = mgr_manual_update(mgr);
 }
 
 static void omap_dss_mgr_apply_ovl_fifos(struct omap_overlay *ovl)
@@ -650,7 +621,6 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 	int r;
 	unsigned long flags;
 	struct omap_overlay *ovl;
-	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
 	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
@@ -671,13 +641,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 	list_for_each_entry(ovl, &mgr->overlays, list)
 		omap_dss_mgr_apply_ovl_fifos(ovl);
 
-	r = 0;
-	if (mp->enabled && !mgr_manual_update(mgr)) {
-		if (!dss_data.irq_enabled)
-			dss_register_vsync_isr();
-
-		dss_write_regs();
-	}
+	dss_write_regs();
 
 	spin_unlock_irqrestore(&data_lock, flags);
 
@@ -693,15 +657,17 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
 
 	mutex_lock(&apply_lock);
 
-	if (!mgr_manual_update(mgr))
-		dispc_mgr_enable(mgr->id, true);
-
 	spin_lock_irqsave(&data_lock, flags);
 
 	mp->enabled = true;
 
+	dss_write_regs();
+
 	spin_unlock_irqrestore(&data_lock, flags);
 
+	if (!mgr_manual_update(mgr))
+		dispc_mgr_enable(mgr->id, true);
+
 	mutex_unlock(&apply_lock);
 }
 
@@ -971,6 +937,8 @@ int dss_ovl_enable(struct omap_overlay *ovl)
 	op->enabled = true;
 	op->extra_info_dirty = true;
 
+	dss_write_regs();
+
 	spin_unlock_irqrestore(&data_lock, flags);
 
 	mutex_unlock(&apply_lock);
@@ -999,6 +967,8 @@ int dss_ovl_disable(struct omap_overlay *ovl)
 	op->enabled = false;
 	op->extra_info_dirty = true;
 
+	dss_write_regs();
+
 	spin_unlock_irqrestore(&data_lock, flags);
 
 	mutex_unlock(&apply_lock);
-- 
1.7.4.1


^ permalink raw reply related


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