[PATCH 00/65] OMAPDSS: manager/apply improvements

STALE5420d

91 messages, 3 authors, 2011-12-13 · page 2 of 2 · open the first message on its own page

Re: [PATCH 41/65] OMAPDSS: APPLY: add missing uses of spinlock

From: Archit Taneja <hidden>
Date: 2011-11-23 09:57:36

On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted hunk
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.

The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.

The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.

apply.c already contains a spinlock, which has been used to protect
(badly) the dss_data. This patch adds locks/unlocks of the spinlock to
the missing places, and the lock should now properly protect dss_data.

Signed-off-by: Tomi Valkeinen<redacted>
---
  drivers/video/omap2/dss/apply.c |   29 +++++++++++++++++++++++++++++
  1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index fb6d3c2..9ad2a36 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -405,6 +405,9 @@ 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);

  	mp->do_manual_update = true;
  	dss_write_regs();
@@ -418,6 +421,8 @@ void dss_start_update(struct omap_overlay_manager *mgr)
  	mp->shadow_dirty = false;

  	dispc_mgr_enable(mgr->id, true);
+
+	spin_unlock_irqrestore(&data_lock, flags);
  }

  static void dss_apply_irq_handler(void *data, u32 mask);
@@ -662,16 +667,28 @@ 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)
  {
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
  	mgr->info = *info;
  	mgr->info_dirty = true;

+	spin_unlock_irqrestore(&data_lock, flags);
+
  	return 0;
  }

  void dss_mgr_get_info(struct omap_overlay_manager *mgr,
  		struct omap_overlay_manager_info *info)
  {
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
  	*info = mgr->info;
+
+	spin_unlock_irqrestore(&data_lock, flags);
  }

  int dss_mgr_set_device(struct omap_overlay_manager *mgr,
@@ -745,16 +762,28 @@ err:
  int dss_ovl_set_info(struct omap_overlay *ovl,
  		struct omap_overlay_info *info)
  {
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
  	ovl->info = *info;
  	ovl->info_dirty = true;

+	spin_unlock_irqrestore(&data_lock, flags);
+
  	return 0;
  }

  void dss_ovl_get_info(struct omap_overlay *ovl,
  		struct omap_overlay_info *info)
  {
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
  	*info = ovl->info;
+
+	spin_unlock_irqrestore(&data_lock, flags);
  }
The get/set info functions for overlays and managers only modify the 
omap_overlay_info or manager_info structs, these aren't really a part of 
'dss_data', they only become a part of dss_data only when we call 
mgr->apply().

So, are we protecting these functions so that 2 users of the same 
overlay don't see incorrect info values?

Archit
  int dss_ovl_set_manager(struct omap_overlay *ovl,

Re: [PATCH 41/65] OMAPDSS: APPLY: add missing uses of spinlock

From: Tomi Valkeinen <hidden>
Date: 2011-11-23 10:12:23

On Wed, 2011-11-23 at 15:26 +0530, Archit Taneja wrote:
On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted
  int dss_mgr_set_device(struct omap_overlay_manager *mgr,
@@ -745,16 +762,28 @@ err:
  int dss_ovl_set_info(struct omap_overlay *ovl,
  		struct omap_overlay_info *info)
  {
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
  	ovl->info = *info;
  	ovl->info_dirty = true;

+	spin_unlock_irqrestore(&data_lock, flags);
+
  	return 0;
  }

  void dss_ovl_get_info(struct omap_overlay *ovl,
  		struct omap_overlay_info *info)
  {
+	unsigned long flags;
+
+	spin_lock_irqsave(&data_lock, flags);
+
  	*info = ovl->info;
+
+	spin_unlock_irqrestore(&data_lock, flags);
  }
The get/set info functions for overlays and managers only modify the 
omap_overlay_info or manager_info structs, these aren't really a part of 
'dss_data', they only become a part of dss_data only when we call 
mgr->apply().

So, are we protecting these functions so that 2 users of the same 
overlay don't see incorrect info values?
True, at this point the data_lock is a bit vague, and is protecting also
the info fields in omap_overlay and omap_overlay_manager.

A lock is needed, though, as otherwise the info struct may be only
partial. E.g. somebody calls set_info, which is half way copying the
values, and somebody else calls apply or get_info.

In the next patches the infos will be moved into the dss_data, and then
using dss_lock spin lock makes more sense.

 Tomi

Re: [PATCH 40/65] OMAPDSS: APPLY: add mutex

From: Tomi Valkeinen <hidden>
Date: 2011-11-23 10:17:00

On Wed, 2011-11-23 at 15:18 +0530, Archit Taneja wrote:
Hi,

On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted
The functions in apply.c, called mostly via function pointers in overlay
and overlay_manager structs, will be divided into two groups. The other
group will not sleep and can be called from interrupts, and the other
group may sleep.
Small sentence issue above, both groups are called the 'other group'.
Thanks, fixed.
quoted
The idea is that the non-sleeping functions may only change certain
settings in overlays and managers, and those settings may only affect
the particular overlay/manager. For example, set the base address of the
overlay.

The blocking functions, however, will handle more complex configuration
changes. For example, when an overlay is enabled and fifo-merge feature
is used, we need to do the enable in multiple steps, waiting in between,
and the change affects multiple overlays and managers.

This patch adds the mutex which is used in the blocking functions to
have exclusive access to overlays and overlay managers.
Previously, when we changed the links between 'overlay->managers' and 
'manager->devices', it wasn't protected by a lock. Why is it needed now?
Previously many places were missing a lock =).
As an example, suppose we are changing a manager's device to some other 
display. Is this lock preventing someone else to get the older 
'mgr->device' rather than the new one?
Hmm. We need some lock there, that's for sure, as set/unset manager are
changing the manager's list of overlays. However, it is also protected
by the spinlock, so in that sense mutex is not necessary.

I have to say I'm not sure if mutex is needed at this point. However,
consider the end result when fifo-merge is used:

dss_ovl_enable() will take the mutex, then it does the configuration in
multiple steps, doing multiple spin_lock & spin_unlocks, waiting in
between.

If we had only a spinlock in set/unset_manager, the manager could be
changed while dss_ovl_enable is doing the process of enabling the
overlay.

So I may have added mutexes or spinlocks a bit early in the series to
some places, but I don't see any harm in that. It'd be rather difficult
to try to find the exact spots where a lock becomes a requirement.

 Tomi

Re: [PATCH 42/65] OMAPDSS: DSI: call mgr_enable/disable for cmd mode

From: Archit Taneja <hidden>
Date: 2011-11-23 10:22:20

On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
The current code uses dsi_video_mode_enable/disable functions to
enable/disable DISPC output for video mode displays. For command mode
displays we have no notion in the DISPC side of whether the panel is
enabled, except when a dss_start_update() call is made.

However, to properly maintain the DISPC state in apply.c, we need to
know if a manager used for a manual update display is currently in use.

This patch achieves that by changing dsi_video_mode_enable/disable to
dsi_enable/disable_video_output, which is called by both video and
command mode displays. For video mode displays it starts the actual
pixel stream, as it did before. For command mode displays it doesn't do
anything else than mark that the manager is currently in use.
dsi_video_mode_enable() doesn't only enable the DISPC output, it also 
sends the long packet header to start video mode transfer.

I think it would be better if we had 2 separate functions, one which 
starts/stops DSI video mode, and the other which enables/disables the 
DISPC video port.

This way, a manual update panel would need to call only 
dsi_enable/disable_video_output(which just enables or disables the 
manager), whereas a video mode panel will need to call both.

This is just a suggestion though. It's probably okay to have both in the 
same function too. We might have to separate them out later if we were 
planning to standardise mipi dsi across SoCs.

Archit
quoted hunk
Signed-off-by: Tomi Valkeinen<redacted>
---
  drivers/video/omap2/displays/panel-taal.c |    6 ++
  drivers/video/omap2/dss/apply.c           |    6 ++-
  drivers/video/omap2/dss/dsi.c             |   73 +++++++++++++++-------------
  include/video/omapdss.h                   |    4 +-
  4 files changed, 51 insertions(+), 38 deletions(-)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index dd64bd1..00c5c61 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1182,6 +1182,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
  	if (r)
  		goto err;

+	r = dsi_enable_video_output(dssdev, td->channel);
+	if (r)
+		goto err;
+
  	td->enabled = 1;

  	if (!td->intro_printed) {
@@ -1211,6 +1215,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
  	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
  	int r;

+	dsi_disable_video_output(dssdev, td->channel);
+
  	r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
  	if (!r)
  		r = taal_sleep_in(td);
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 9ad2a36..66f4c56 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -648,7 +648,8 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr)
  {
  	mutex_lock(&apply_lock);

-	dispc_mgr_enable(mgr->id, true);
+	if (!mgr_manual_update(mgr))
+		dispc_mgr_enable(mgr->id, true);
  	mgr->enabled = true;

  	mutex_unlock(&apply_lock);
@@ -658,7 +659,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
  {
  	mutex_lock(&apply_lock);

-	dispc_mgr_enable(mgr->id, false);
+	if (!mgr_manual_update(mgr))
+		dispc_mgr_enable(mgr->id, false);
  	mgr->enabled = false;

  	mutex_unlock(&apply_lock);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 08d3de90..a35f3fb 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3939,65 +3939,70 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
  	}
  }

-int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel)
+int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
  {
  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
  	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
  	u8 data_type;
  	u16 word_count;

-	switch (dssdev->panel.dsi_pix_fmt) {
-	case OMAP_DSS_DSI_FMT_RGB888:
-		data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
-		break;
-	case OMAP_DSS_DSI_FMT_RGB666:
-		data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
-		break;
-	case OMAP_DSS_DSI_FMT_RGB666_PACKED:
-		data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
-		break;
-	case OMAP_DSS_DSI_FMT_RGB565:
-		data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
-		break;
-	default:
-		BUG();
-	};
+	if (dssdev->panel.dsi_mode = OMAP_DSS_DSI_VIDEO_MODE) {
+		switch (dssdev->panel.dsi_pix_fmt) {
+		case OMAP_DSS_DSI_FMT_RGB888:
+			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+			break;
+		case OMAP_DSS_DSI_FMT_RGB666:
+			data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+			break;
+		case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+			break;
+		case OMAP_DSS_DSI_FMT_RGB565:
+			data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+			break;
+		default:
+			BUG();
+		};

-	dsi_if_enable(dsidev, false);
-	dsi_vc_enable(dsidev, channel, false);
+		dsi_if_enable(dsidev, false);
+		dsi_vc_enable(dsidev, channel, false);

-	/* MODE, 1 = video mode */
-	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
+		/* MODE, 1 = video mode */
+		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);

-	word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
+		word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);

-	dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0);
+		dsi_vc_write_long_header(dsidev, channel, data_type,
+				word_count, 0);

-	dsi_vc_enable(dsidev, channel, true);
-	dsi_if_enable(dsidev, true);
+		dsi_vc_enable(dsidev, channel, true);
+		dsi_if_enable(dsidev, true);
+	}

  	dss_mgr_enable(dssdev->manager);

  	return 0;
  }
-EXPORT_SYMBOL(dsi_video_mode_enable);
+EXPORT_SYMBOL(dsi_enable_video_output);

-void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel)
+void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
  {
  	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);

-	dsi_if_enable(dsidev, false);
-	dsi_vc_enable(dsidev, channel, false);
+	if (dssdev->panel.dsi_mode = OMAP_DSS_DSI_VIDEO_MODE) {
+		dsi_if_enable(dsidev, false);
+		dsi_vc_enable(dsidev, channel, false);

-	/* MODE, 0 = command mode */
-	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
+		/* MODE, 0 = command mode */
+		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);

-	dsi_vc_enable(dsidev, channel, true);
-	dsi_if_enable(dsidev, true);
+		dsi_vc_enable(dsidev, channel, true);
+		dsi_if_enable(dsidev, true);
+	}

  	dss_mgr_disable(dssdev->manager);
  }
-EXPORT_SYMBOL(dsi_video_mode_disable);
+EXPORT_SYMBOL(dsi_disable_video_output);

  static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
  		u16 w, u16 h)
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index eaeca89..25ef771 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -294,8 +294,8 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
  		u16 len);
  int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
  int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
-int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel);
-void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel);
+int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
+void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);

  /* Board specific data */
  struct omap_dss_board_info {

Re: [PATCH 35/65] OMAPDSS: APPLY: move spinlock outside the struct

From: Sergey Kibrik <hidden>
Date: 2011-11-23 10:29:27

On 11/22/2011 11:21 AM, Tomi Valkeinen wrote:
dss_cache struct contains a spinlock used to protect the struct. A more
logical place for the spinlock is outside the struct that it is
protecting. So move it there.
a small question: isn't it clearer to keep lock inside struct, so it would be easier to read code? Say, if we meet
spin_lock_irqsave(&dss_cache.lock, flags);
in code we already aware of what struct being actually protected, and in case of external lock it's not that obvious

-- 
regards,
Sergey

Re: [PATCH 42/65] OMAPDSS: DSI: call mgr_enable/disable for cmd

From: Tomi Valkeinen <hidden>
Date: 2011-11-23 10:42:57

On Wed, 2011-11-23 at 15:40 +0530, Archit Taneja wrote:
On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted
The current code uses dsi_video_mode_enable/disable functions to
enable/disable DISPC output for video mode displays. For command mode
displays we have no notion in the DISPC side of whether the panel is
enabled, except when a dss_start_update() call is made.

However, to properly maintain the DISPC state in apply.c, we need to
know if a manager used for a manual update display is currently in use.

This patch achieves that by changing dsi_video_mode_enable/disable to
dsi_enable/disable_video_output, which is called by both video and
command mode displays. For video mode displays it starts the actual
pixel stream, as it did before. For command mode displays it doesn't do
anything else than mark that the manager is currently in use.
dsi_video_mode_enable() doesn't only enable the DISPC output, it also 
sends the long packet header to start video mode transfer.

I think it would be better if we had 2 separate functions, one which 
starts/stops DSI video mode, and the other which enables/disables the 
DISPC video port.

This way, a manual update panel would need to call only 
dsi_enable/disable_video_output(which just enables or disables the 
manager), whereas a video mode panel will need to call both.

This is just a suggestion though. It's probably okay to have both in the 
same function too. We might have to separate them out later if we were 
planning to standardise mipi dsi across SoCs.
If you think from the panel driver's point of view, it doesn't know
about DISPC. It just wants to enable the video stream (on video mode
displays).

If we had two functions, could only the first be used? I.e. is it
possible to just enable the video mode transfer, without enabling DISPC?
If not, I'm not sure what would be the use for two separate functions.
And even if it can, I'm not sure what use it would be to enable only the
video mode output without the actual pixel data from DISPC.

It is true that the function in thsi patch is not the best one. For
command mode display it's more about reserving the ovl manager for use
than actually enabling it. Then again, how I thought the function's
purpose was that it enables the DSI video output, but because for
command mode there's need to trigger the actual frame transfer later,
the function doesn't start the pixel feed for command mode displays. It
just "prepares" the output.

But even if we had the functions separated, the function called by video
mode and command mode displays would be different, as for the former one
it enables the pixel stream, and for latter one it just reserves the
output.

So, I'm fine with changing the function, but the reasoning for what
functions we have and what they do should come from the panel driver's
perspective, not because of OMAP DSS's HW details.

 Tomi

Re: [PATCH 35/65] OMAPDSS: APPLY: move spinlock outside the struct

From: Tomi Valkeinen <hidden>
Date: 2011-11-23 10:47:33

On Wed, 2011-11-23 at 12:29 +0200, Sergey Kibrik wrote:
On 11/22/2011 11:21 AM, Tomi Valkeinen wrote:
quoted
dss_cache struct contains a spinlock used to protect the struct. A more
logical place for the spinlock is outside the struct that it is
protecting. So move it there.
a small question: isn't it clearer to keep lock inside struct, so it would be easier to read code? Say, if we meet
quoted
spin_lock_irqsave(&dss_cache.lock, flags);
in code we already aware of what struct being actually protected, and in case of external lock it's not that obvious
But if you meet code like:

op = get_ovl_priv(ovl);

You don't see that the data is inside the struct protected with the
spinlock. So you still need to understand what it protects, and what the
above function returns.

But I see your point. I'm not sure which way is better. I thought it
like this: the lock protects a struct, but if the lock is inside the
struct, the lock would protect also itself. Which it doesn't.

That said, I'm fine with both ways. It doesn't matter much. I didn't
really look for any established patterns for this in the kernel code,
but if everybody else have their locks inside the structs they protect,
then obviously we should also.

 Tomi

Re: [PATCH 42/65] OMAPDSS: DSI: call mgr_enable/disable for cmd mode

From: Archit Taneja <hidden>
Date: 2011-11-23 11:20:58

On Wednesday 23 November 2011 04:12 PM, Tomi Valkeinen wrote:
On Wed, 2011-11-23 at 15:40 +0530, Archit Taneja wrote:
quoted
On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted
The current code uses dsi_video_mode_enable/disable functions to
enable/disable DISPC output for video mode displays. For command mode
displays we have no notion in the DISPC side of whether the panel is
enabled, except when a dss_start_update() call is made.

However, to properly maintain the DISPC state in apply.c, we need to
know if a manager used for a manual update display is currently in use.

This patch achieves that by changing dsi_video_mode_enable/disable to
dsi_enable/disable_video_output, which is called by both video and
command mode displays. For video mode displays it starts the actual
pixel stream, as it did before. For command mode displays it doesn't do
anything else than mark that the manager is currently in use.
dsi_video_mode_enable() doesn't only enable the DISPC output, it also
sends the long packet header to start video mode transfer.

I think it would be better if we had 2 separate functions, one which
starts/stops DSI video mode, and the other which enables/disables the
DISPC video port.

This way, a manual update panel would need to call only
dsi_enable/disable_video_output(which just enables or disables the
manager), whereas a video mode panel will need to call both.

This is just a suggestion though. It's probably okay to have both in the
same function too. We might have to separate them out later if we were
planning to standardise mipi dsi across SoCs.
If you think from the panel driver's point of view, it doesn't know
about DISPC. It just wants to enable the video stream (on video mode
displays).

If we had two functions, could only the first be used? I.e. is it
possible to just enable the video mode transfer, without enabling DISPC?
If not, I'm not sure what would be the use for two separate functions.
And even if it can, I'm not sure what use it would be to enable only the
video mode output without the actual pixel data from DISPC.

It is true that the function in thsi patch is not the best one. For
command mode display it's more about reserving the ovl manager for use
than actually enabling it. Then again, how I thought the function's
purpose was that it enables the DSI video output, but because for
command mode there's need to trigger the actual frame transfer later,
the function doesn't start the pixel feed for command mode displays. It
just "prepares" the output.

But even if we had the functions separated, the function called by video
mode and command mode displays would be different, as for the former one
it enables the pixel stream, and for latter one it just reserves the
output.

So, I'm fine with changing the function, but the reasoning for what
functions we have and what they do should come from the panel driver's
perspective, not because of OMAP DSS's HW details.
If you look from the panel driver's perspective, we shouldn't split this.

I think it would be best to stuff the 'video mode enabling and manager 
enabling' functionality in omapdss_dsi_display_enable() itself, the 
panel driver shouldn't need to call a function separately to enable 
video mode for the panel. This way we would be more along the lines of 
the dpi driver, where dpi_display_enable() enables the manager in the end.

I guess we can leave this the way you are doing it currently, and move 
this code into dsi_display_enable() code later on.

Archit
  Tomi

Re: [PATCH 42/65] OMAPDSS: DSI: call mgr_enable/disable for cmd

From: Tomi Valkeinen <hidden>
Date: 2011-11-23 11:27:32

On Wed, 2011-11-23 at 16:38 +0530, Archit Taneja wrote:
I think it would be best to stuff the 'video mode enabling and
manager 
enabling' functionality in omapdss_dsi_display_enable() itself, the 
panel driver shouldn't need to call a function separately to enable 
video mode for the panel. This way we would be more along the lines
of 
the dpi driver, where dpi_display_enable() enables the manager in the
end. 
But we need to configure the panel between enabling the DSI interface
and enabling the video output, so we can't combine those two functions.

For DPI things are simpler, as enabling the interface and the video
output are more or less the same thing.

 Tomi

Re: [PATCH 42/65] OMAPDSS: DSI: call mgr_enable/disable for cmd mode

From: Archit Taneja <hidden>
Date: 2011-11-23 12:25:45

On Wednesday 23 November 2011 04:57 PM, Tomi Valkeinen wrote:
On Wed, 2011-11-23 at 16:38 +0530, Archit Taneja wrote:
quoted
I think it would be best to stuff the 'video mode enabling and
manager
enabling' functionality in omapdss_dsi_display_enable() itself, the
panel driver shouldn't need to call a function separately to enable
video mode for the panel. This way we would be more along the lines
of
the dpi driver, where dpi_display_enable() enables the manager in the
end.
But we need to configure the panel between enabling the DSI interface
and enabling the video output, so we can't combine those two functions.
Oh okay, that's right, we can't start video mode before preparing the panel.

Archit
For DPI things are simpler, as enabling the interface and the video
output are more or less the same thing.

  Tomi

Re: [PATCH 58/65] OMAPDSS: APPLY: add

From: Tomi Valkeinen <hidden>
Date: 2011-12-07 13:15:10

On Wed, 2011-12-07 at 18:37 +0530, Archit Taneja wrote:
On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted
+/* 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);
+}
This function isn't used, are you planning to use it later?
Yes, it's used with the fifo-merge stuff. It could be added later, but
as it's related to the extra_info stuff, I think it fits better here
than with the fifo merge series.

 Tomi

Re: [PATCH 63/65] OMAPDSS: APPLY: add checking of ovls/mgrs settings

From: Archit Taneja <hidden>
Date: 2011-12-07 13:17:51

Hi,

On Tuesday 22 November 2011 02:52 PM, Tomi Valkeinen wrote:
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.
Minor comment:

dss_ovl_check, dss_mgr_check and dss_mgr_check_zorder don't really 
qualify as functions which do actual applying of configurations, they 
could be moved from apply.c to manager.c and overlay.c.

Archit
quoted hunk
Signed-off-by: Tomi Valkeinen<redacted>
---
  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;
  }

Re: [PATCH 58/65] OMAPDSS: APPLY: add wait_pending_extra_info_updates()

From: Archit Taneja <hidden>
Date: 2011-12-07 13:19:42

On Tuesday 22 November 2011 02:51 PM, Tomi Valkeinen wrote:
quoted hunk
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<redacted>
---
  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);
+}
This function isn't used, are you planning to use it later?

Archit
quoted hunk
+
  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();

Re: [PATCH 63/65] OMAPDSS: APPLY: add checking of ovls/mgrs

From: Tomi Valkeinen <hidden>
Date: 2011-12-08 08:29:25

On Wed, 2011-12-07 at 18:35 +0530, Archit Taneja wrote:
Hi,

On Tuesday 22 November 2011 02:52 PM, Tomi Valkeinen wrote:
quoted
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.
Minor comment:

dss_ovl_check, dss_mgr_check and dss_mgr_check_zorder don't really 
qualify as functions which do actual applying of configurations, they 
could be moved from apply.c to manager.c and overlay.c.
I had the check functions in apply.c because they used apply.c's
internal datastructures.

However, looking the functions now, only dss_mgr_check_zorder() used the
internal datas, and the function doesn't even use those variables for
anything =).

So you're right, they can be moved to manager.c and overlay.c, thanks.

 Tomi

Re: [PATCH 63/65] OMAPDSS: APPLY: add checking of ovls/mgrs settings

From: Archit Taneja <hidden>
Date: 2011-12-13 10:14:29

Hi,

On Thursday 08 December 2011 01:59 PM, Tomi Valkeinen wrote:
On Wed, 2011-12-07 at 18:35 +0530, Archit Taneja wrote:
quoted
Hi,

On Tuesday 22 November 2011 02:52 PM, Tomi Valkeinen wrote:
quoted
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.
Minor comment:

dss_ovl_check, dss_mgr_check and dss_mgr_check_zorder don't really
qualify as functions which do actual applying of configurations, they
could be moved from apply.c to manager.c and overlay.c.
I had the check functions in apply.c because they used apply.c's
internal datastructures.

However, looking the functions now, only dss_mgr_check_zorder() used the
internal datas, and the function doesn't even use those variables for
anything =).
Also, the function dss_mgr_check() takes 'struct 
omap_overlay_manager_info *info' as a parameter but doesn't use it. We 
might want to remove that too.

Archit
So you're right, they can be moved to manager.c and overlay.c, thanks.

  Tomi

Re: [PATCH 63/65] OMAPDSS: APPLY: add checking of ovls/mgrs

From: Tomi Valkeinen <hidden>
Date: 2011-12-13 11:16:21

On Tue, 2011-12-13 at 15:32 +0530, Archit Taneja wrote:
Hi,

On Thursday 08 December 2011 01:59 PM, Tomi Valkeinen wrote:
quoted
On Wed, 2011-12-07 at 18:35 +0530, Archit Taneja wrote:
quoted
Hi,

On Tuesday 22 November 2011 02:52 PM, Tomi Valkeinen wrote:
quoted
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.
Minor comment:

dss_ovl_check, dss_mgr_check and dss_mgr_check_zorder don't really
qualify as functions which do actual applying of configurations, they
could be moved from apply.c to manager.c and overlay.c.
I had the check functions in apply.c because they used apply.c's
internal datastructures.

However, looking the functions now, only dss_mgr_check_zorder() used the
internal datas, and the function doesn't even use those variables for
anything =).
Also, the function dss_mgr_check() takes 'struct 
omap_overlay_manager_info *info' as a parameter but doesn't use it. We 
might want to remove that too.
Right. And the dss_ovl/mgr_simple_check() functions could also be moved
outside apply.c.

 Tomi

Previous page

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help