linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Archit Taneja <archit@ti.com>
To: tomi.valkeinen@ti.com
Cc: rohitkc@ti.com, linux-omap@vger.kernel.org,
	linux-fbdev@vger.kernel.org, Archit Taneja <archit@ti.com>
Subject: [RFC PATCH 05/29] OMAPDSS: APPLY/Writeback: Apply writeback configurations
Date: Tue, 27 Dec 2011 18:06:48 +0530	[thread overview]
Message-ID: <1324989432-3625-6-git-send-email-archit@ti.com> (raw)
In-Reply-To: <1324989432-3625-1-git-send-email-archit@ti.com>

The writeback pipeline has properties of both overlays and overlay managers.
It is like an overlay as it has programmable base addresses and contains blocks
like scalar, color conversion unit, truncation unit, DISPC DMA FIFO. It is like
a manager as enabling it immediately starts transfer to the memory, and it has
a GO bit to use a new writeback configuration. Hence, writeback is a separate
entity when it comes to applying configurations.

When it comes to applying user_info to the private info maintained by DSS2, the
writeback pipeline can be considered tightly coupled with the manager it is
connected to. This makes sense as in the current DSS2 design as writeback is
always connected to a manager in all its modes. In capture mode, writeback is
connected to the manager from which we are capturing the frames. In memory to
memory mode, we would either connected to a manager if we are capturing the
manager's output, or we would connect to a dummy writeback manager when we are
capturing data from just one overlay.Calling a manager's apply() calls
omap_dss_mgr_apply_wb(), which copies the user_info to the private info struct
only if that manager has writeback connected to it. Hence, copying user_info
to private info for writeback is similar to how it is done for overlays.

Unlike overlays, writeback configurations can't be totally governed by the state
of the manager. In capture mode, writeback registers are governed by the GO bit
of WB. Hence, a new configuration can be written to writeback shadow registers
even if the manager it is connected to is busy. Hence, copying of private info
to shadow register and setting GO bit for writeback is similar to how it is done
for managers.

We register to dss_apply_irq_handler() if writeback needs to write a pending
configuration or clear the busy and shadow_dirty status if the previous
configuration was transferred from the shadow registers successfully. This
isn't optimal for capture mode as a new/pending writeback configuration is
applied sometime later than the connected manager's VSYNC interrupt. The new
configuration is taken only after WBDELAYCOUNT lines(in time) are generated by
the manager after the VSYNC interrupt.

Since we don't have any interrupt to get this event. We currently register
to the manager's VSYNC interrupt itself. The correct approach would be to
generate a timer based interrupt event after approximately WBDELAYCOUNT lines
after we get the VSYNC interrupts. This is not done for now.

Create dummy dispc_wb_go/go_busy and wb_setup functions. These will be filled
up in a later commit.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/apply.c |  164 ++++++++++++++++++++++++++++++++++++++-
 drivers/video/omap2/dss/dispc.c |   15 ++++
 drivers/video/omap2/dss/dss.h   |    4 +
 3 files changed, 181 insertions(+), 2 deletions(-)

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 19120c1..f40f58c 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -105,6 +105,15 @@ struct wb_priv_data {
 
 	bool user_info_dirty;
 	struct omap_dss_writeback_info user_info;
+
+	bool info_dirty;
+	struct omap_dss_writeback_info info;
+
+	bool shadow_info_dirty;
+
+	/* If true, GO bit is up and shadow registers cannot be written.
+	 * Never true for writeback in memory to memory mode */
+	bool busy;
 };
 
 static struct {
@@ -250,6 +259,7 @@ static bool need_isr(void)
 		struct omap_overlay_manager *mgr;
 		struct mgr_priv_data *mp;
 		struct omap_overlay *ovl;
+		struct omap_dss_device *dssdev;
 
 		mgr = omap_dss_get_overlay_manager(i);
 		mp = get_mgr_priv(mgr);
@@ -304,13 +314,29 @@ static bool need_isr(void)
 				if (op->shadow_info_dirty)
 					return true;
 			}
+
+			dssdev = mgr->get_writeback(mgr);
+			if (dssdev) {
+				struct omap_dss_writeback *wb = dssdev->wbdev;
+				struct wb_priv_data *wp = get_wb_priv(wb);
+
+				if (wp->busy)
+					return true;
+
+				if (wp->info_dirty)
+					return true;
+
+				if (wp->shadow_info_dirty)
+					return true;
+
+			}
 		}
 	}
 
 	return false;
 }
 
-static bool need_go(struct omap_overlay_manager *mgr)
+static bool need_mgr_go(struct omap_overlay_manager *mgr)
 {
 	struct omap_overlay *ovl;
 	struct mgr_priv_data *mp;
@@ -330,6 +356,18 @@ static bool need_go(struct omap_overlay_manager *mgr)
 	return false;
 }
 
+static bool need_wb_go(struct omap_dss_writeback *wb)
+{
+	struct wb_priv_data *wp;
+
+	wp = get_wb_priv(wb);
+
+	if (wp->shadow_info_dirty)
+		return true;
+
+	return false;
+}
+
 /* returns true if an extra_info field is currently being updated */
 static bool extra_info_update_ongoing(void)
 {
@@ -577,6 +615,29 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 		op->shadow_extra_info_dirty = true;
 }
 
+static void dss_wb_write_regs(struct omap_dss_writeback *wb)
+{
+	struct wb_priv_data *wp = get_wb_priv(wb);
+	struct omap_dss_writeback_info *wi;
+	int r;
+
+	if (!wp->info_dirty)
+		return;
+
+	WARN_ON(wp->busy);
+
+	wi = &wp->info;
+
+	r = dispc_wb_setup(wb->id, wi);
+	if (r) {
+		DSSERR("dispc_wb_setup failed\n");
+		return;
+	}
+
+	wp->info_dirty = false;
+	wp->shadow_info_dirty = true;
+}
+
 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -607,6 +668,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 static void dss_write_regs(void)
 {
 	const int num_mgrs = omap_dss_get_num_overlay_managers();
+	const int num_wb = dss_feat_get_num_wb();
 	int i;
 
 	for (i = 0; i < num_mgrs; ++i) {
@@ -631,11 +693,30 @@ static void dss_write_regs(void)
 
 		dss_mgr_write_regs(mgr);
 	}
+
+	for (i = 0; i < num_wb; ++i) {
+		struct omap_dss_writeback *wb;
+		struct wb_priv_data *wp;
+		struct mgr_priv_data *mp;
+
+		wb = omap_dss_get_writeback(i);
+		wp = get_wb_priv(wb);
+		mp = get_mgr_priv(wb->dssdev->manager);
+
+		if (!mp->enabled)
+			continue;
+
+		if (wp->busy)
+			continue;
+
+		dss_wb_write_regs(wb);
+	}
 }
 
 static void dss_set_go_bits(void)
 {
 	const int num_mgrs = omap_dss_get_num_overlay_managers();
+	const int num_wb = dss_feat_get_num_wb();
 	int i;
 
 	for (i = 0; i < num_mgrs; ++i) {
@@ -648,7 +729,7 @@ static void dss_set_go_bits(void)
 		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
 			continue;
 
-		if (!need_go(mgr))
+		if (!need_mgr_go(mgr))
 			continue;
 
 		mp->busy = true;
@@ -659,6 +740,31 @@ static void dss_set_go_bits(void)
 		dispc_mgr_go(mgr->id);
 	}
 
+	for (i = 0; i < num_wb; ++i) {
+		struct omap_dss_writeback *wb;
+		struct wb_priv_data *wp;
+		struct mgr_priv_data *mp;
+
+		wb = omap_dss_get_writeback(i);
+		wp = get_wb_priv(wb);
+		mp = get_mgr_priv(wb->dssdev->manager);
+
+		if (!mp->enabled)
+			continue;
+
+		if (wp->busy)
+			continue;
+
+		if (!need_wb_go(wb))
+			continue;
+
+		wp->busy = true;
+
+		if (!dss_data.irq_enabled && need_isr())
+			dss_register_vsync_isr();
+
+		dispc_wb_go(wb->id);
+	}
 }
 
 void dss_mgr_start_update(struct omap_overlay_manager *mgr)
@@ -749,9 +855,18 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
 	}
 }
 
+static void wb_clear_shadow_dirty(struct omap_dss_writeback *wb)
+{
+	struct wb_priv_data *wp;
+
+	wp = get_wb_priv(wb);
+	wp->shadow_info_dirty = false;
+}
+
 static void dss_apply_irq_handler(void *data, u32 mask)
 {
 	const int num_mgrs = dss_feat_get_num_mgrs();
+	const int num_wb = dss_feat_get_num_wb();
 	int i;
 	bool extra_updating;
 
@@ -784,6 +899,32 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 		}
 	}
 
+
+	for (i = 0; i < num_wb; i++) {
+		struct omap_dss_writeback *wb;
+		struct wb_priv_data *wp;
+		bool was_busy;
+
+		wb = omap_dss_get_writeback(i);
+		wp = get_wb_priv(wb);
+
+		was_busy = wp->busy;
+		wp->busy = dispc_wb_go_busy(i);
+
+		/*
+		 * In writeback capture mode, the GO bit doesn't get reset
+		 * at the manager's VSYNC interrupt. It takes an extra
+		 * 'WBDELAYCOUNTER' time after VSYNC when the writeback
+		 * FIFOs are flushed and the shadow registers are taken in.
+		 * There isn't any DSS interrupt to notify this point in time.
+		 * The correct solution would be to set off a timer here which
+		 * generates an interrupt approximately after WBDELAYCOUNTER
+		 * time.
+		 */
+		if (was_busy && !wp->busy)
+			wb_clear_shadow_dirty(wb);
+	}
+
 	dss_write_regs();
 	dss_set_go_bits();
 
@@ -825,6 +966,20 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 	mp->info = mp->user_info;
 }
 
+static void omap_dss_mgr_apply_wb(struct omap_dss_writeback *wb)
+{
+	struct wb_priv_data *wp;
+
+	wp = get_wb_priv(wb);
+
+	if (!wp->user_info_dirty)
+		return;
+
+	wp->user_info_dirty = false;
+	wp->info_dirty = true;
+	wp->info = wp->user_info;
+}
+
 int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 {
 	unsigned long flags;
@@ -852,6 +1007,11 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 	/* Configure manager */
 	omap_dss_mgr_apply_mgr(mgr);
 
+	/* Configure writeback */
+	dssdev = mgr->get_writeback(mgr);
+	if (dssdev)
+		omap_dss_mgr_apply_wb(dssdev->wbdev);
+
 	dss_write_regs();
 	dss_set_go_bits();
 
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b228e05..d98905f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -508,6 +508,16 @@ void dispc_mgr_go(enum omap_channel channel)
 		REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
 }
 
+bool dispc_wb_go_busy(int id)
+{
+	return false;
+}
+
+void dispc_wb_go(int id)
+{
+	return;
+}
+
 static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
 {
 	dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
@@ -1888,6 +1898,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
 	return 0;
 }
 
+int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi)
+{
+	return 0;
+}
+
 int dispc_ovl_enable(enum omap_plane plane, bool enable)
 {
 	DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 9b3b93c..556bc7c 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -476,6 +476,10 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
 void dispc_mgr_setup(enum omap_channel channel,
 		struct omap_overlay_manager_info *info);
 
+bool dispc_wb_go_busy(int id);
+void dispc_wb_go(int id);
+int dispc_wb_setup(int id, struct omap_dss_writeback_info *wi);
+
 /* VENC */
 #ifdef CONFIG_OMAP2_DSS_VENC
 int venc_init_platform_driver(void);
-- 
1.7.4.1


  parent reply	other threads:[~2011-12-27 12:38 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-27 12:36 [RFC PATCH 00/29] OMAPDSS: Initial Writeback Capture mode support Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 01/29] omapdss/omapfb/omap_vout: Introduce manager output struct Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 02/29] OMAPDSS: Add writeback to omap_dss_mgr_output Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 03/29] OMAPDSS: Writeback: Add writeback interface and panel driver Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 04/29] OMAPDSS: APPLY/Writeback: Add writeback_info Archit Taneja
2011-12-27 12:36 ` Archit Taneja [this message]
2011-12-27 12:36 ` [RFC PATCH 06/29] OMAPDSS: APPLY: Add writeback enable/disable functions Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 07/29] OMAPDSS: APPLY: Add extra_info for writeback Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 08/29] OMAPDSS: APPLY: Modify manager unset device op Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 09/29] OMAPDSS: APPLY: Allow manager set/unset_device ops to set/unset writeback Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 10/29] OMAPDSS: APPLY: Calculate channel_in for writeback Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 11/29] OMAPDSS: DISPC: Add writeback as a new plane Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 12/29] OMAPDSS: Writeback: Add check for color_mode in dss_wb_simple_check() Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 13/29] OMAPDSS: APPLY: Configure writeback FIFOs Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 14/29] OMAPDSS: DISPC: Allow both upscaling and downscaling of chroma Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 15/29] OMAPDSS: DISPC: Pass overlay caps as a parameter to DISPC overlay related functions Archit Taneja
2011-12-27 12:36 ` [RFC PATCH 16/29] OMAPDSS: OVERLAY: Add position and replication as overlay caps Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 17/29] OMAPDSS: DISPC: Make dispc_ovl_setup call dispc_plane_setup Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 18/29] OMAPDSS: DISPC: Make chroma_upscale an argument to dispc_plane_setup Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 19/29] OMAPDSS: DISPC: Don't set chroma resampling bit for writeback Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 20/29] OMAPDSS: Writeback: Add writeback capabilities Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 21/29] OMAPDSS: DISPC: Configure overlay-like parameters in dispc_wb_setup Archit Taneja
2012-08-02 10:10   ` Chandrabhanu Mahapatra
2011-12-27 12:37 ` [RFC PATCH 22/29] OMAPDSS: DISPC: Setup writeback go, enable and channel_in functions Archit Taneja
2012-08-02  9:55   ` Mahapatra, Chandrabhanu
2011-12-27 12:37 ` [RFC PATCH 23/29] OMAPDSS: Writeback: Configure writeback specific parameters Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 24/29] OMAPDSS: Writeback: Use panel driver ops to configure mirroring rotation and buffer size Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 25/29] OMAPDSS: Writeback: Add sysfs attributes to writeback panel Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 26/29] OMAPDSS: DISPLAY: Add a manager apply to sysfs store attributes for writeback Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 27/29] OMAPDSS: MANAGER: Split manager_display_store into smaller functions Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 28/29] OMAPDSS: MANAGER: Add writeback as a sysfs attribute Archit Taneja
2011-12-27 12:37 ` [RFC PATCH 29/29] OMAPDSS: FEATURES: Allow WB panels to attach to managers Archit Taneja

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1324989432-3625-6-git-send-email-archit@ti.com \
    --to=archit@ti.com \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=rohitkc@ti.com \
    --cc=tomi.valkeinen@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).