Skip to contentSkip to conversation

Add cyclic DMA support to OMAP DMA engine driver

RFC New Russell King - ARM Linux 5 participants 13 messages Jun 22, 2012 – Jul 18, 2012 dmaengine

lore
Share & tools
lore
#0 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

These three patches add support for returning the residue and cyclic DMA support to the OMAP DMA engine driver.

As v3.5-rc is horribly broken on my OMAP platforms, I've had to back out all the sound/soc/omap changes from the last merge window to test this, inspite of Peter Ujfalusi maintaining that there is nothing wrong. I can't get working audio support on the OMAP4430SDP any other way.

I am planning no further work on this until OMAP ASoC support gets fixed; due to Peter and my plans this summer, this is likely to be late July/ August time.

This does not implement all of the weird and wonderfully different DMA setups which the OMAP ASoC driver appears to support (do we need soo much flexibility?) but it does support whatever is required for my OMAP4430SDP board.

These patches apply on top of the previously posted series of DMA patches.

I will be merging at least some of these down into the "dmaengine: add OMAP DMA engine driver" commit at some point.

 drivers/dma/omap-dma.c |  167 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 156 insertions(+), 11 deletions(-)
#1 lore raw

PATCH 1/3 dmaengine: omap: add support for returning residue in tx_state method

Add support for returning the residue for a particular descriptor by reading the current DMA address for the source or destination side of the transfer as appropriate, and walking the scatterlist until we find an entry containing the current DMA address.

---
 drivers/dma/omap-dma.c |   69 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 64 insertions(+), 5 deletions(-)
drivers/dma/omap-dma.c +64 -5
index 47d5e63..62b6a2b 100644
@@ -194,14 +194,73 @@ static void omap_dma_free_chan_resources(struct dma_chan *chan)
 	dev_info(c->vc.chan.device->dev, "freeing channel for %u\n", c->dma_sig);
 }
 
+static size_t omap_dma_sg_size(struct omap_sg *sg)
+{
+	return sg->en * sg->fn;
+}
+
+static size_t omap_dma_desc_size(struct omap_desc *d)
+{
+	unsigned i;
+	size_t size;
+
+	for (size = i = 0; i < d->sglen; i++)
+		size += omap_dma_sg_size(&d->sg[i]);
+
+	return size * es_bytes[d->es];
+}
+
+static size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr)
+{
+	unsigned i;
+	size_t size, es_size = es_bytes[d->es];
+
+	for (size = i = 0; i < d->sglen; i++) {
+		size_t this_size = omap_dma_sg_size(&d->sg[i]) * es_size;
+
+		if (size)
+			size += this_size;
+		else if (addr >= d->sg[i].addr &&
+			 addr < d->sg[i].addr + this_size)
+			size += d->sg[i].addr + this_size - addr;
+	}
+	return size;
+}
+
 static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
 	dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
-	/*
-	 * FIXME: do we need to return pending bytes?
-	 * We have no users of that info at the moment...
-	 */
-	return dma_cookie_status(chan, cookie, txstate);
+	struct omap_chan *c = to_omap_dma_chan(chan);
+	struct virt_dma_desc *vd;
+	enum dma_status ret;
+	unsigned long flags;
+
+	ret = dma_cookie_status(chan, cookie, txstate);
+	if (ret == DMA_SUCCESS || !txstate)
+		return ret;
+
+	spin_lock_irqsave(&c->vc.lock, flags);
+	vd = vchan_find_desc(&c->vc, cookie);
+	if (vd) {
+		txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx));
+	} else if (c->desc && c->desc->vd.tx.cookie == cookie) {
+		struct omap_desc *d = c->desc;
+		dma_addr_t pos;
+
+		if (d->dir == DMA_MEM_TO_DEV)
+			pos = omap_get_dma_src_pos(c->dma_ch);
+		else if (d->dir == DMA_DEV_TO_MEM)
+			pos = omap_get_dma_dst_pos(c->dma_ch);
+		else
+			pos = 0;
+
+		txstate->residue = omap_dma_desc_size_pos(d, pos);
+	} else {
+		txstate->residue = 0;
+	}
+	spin_unlock_irqrestore(&c->vc.lock, flags);
+
+	return ret;
 }
 
 static void omap_dma_issue_pending(struct dma_chan *chan)
Signature · 1 line
1.7.4.4
#2 lore raw

PATCH 2/3 dmaengine: omap: add support for setting fi

In reply to Russell King - ARM Linux
---
 drivers/dma/omap-dma.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/dma/omap-dma.c +3 -2
index 62b6a2b..e1a326d 100644
@@ -50,6 +50,7 @@ struct omap_desc {
 	enum dma_transfer_direction dir;
 	dma_addr_t dev_addr;
 
+	int16_t fi;		/* for OMAP_DMA_SYNC_PACKET */
 	uint8_t es;		/* element size */
 	uint8_t sync_mode;	/* OMAP_DMA_SYNC_xxx */
 	uint8_t sync_type;	/* OMAP_DMA_xxx_SYNC* */
@@ -120,10 +121,10 @@ static void omap_dma_start_desc(struct omap_chan *c)
 
 	if (d->dir == DMA_DEV_TO_MEM)
 		omap_set_dma_src_params(c->dma_ch, d->periph_port,
-			OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, 0);
+			OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi);
 	else
 		omap_set_dma_dest_params(c->dma_ch, d->periph_port,
-			OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, 0);
+			OMAP_DMA_AMODE_CONSTANT, d->dev_addr, 0, d->fi);
 
 	omap_dma_start_sg(c, d, 0);
 }
Signature · 1 line
1.7.4.4
#3 lore raw

PATCH 3/3 dmaengine: omap: add support for cyclic DMA

In reply to Russell King - ARM Linux

Add support for cyclic DMA to the OMAP DMA engine driver.

---
 drivers/dma/omap-dma.c |   93 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 89 insertions(+), 4 deletions(-)
drivers/dma/omap-dma.c +89 -4
index e1a326d..dae9c2c 100644
@@ -33,6 +33,7 @@ struct omap_chan {
 
 	struct dma_slave_config	cfg;
 	unsigned dma_sig;
+	bool cyclic;
 
 	int dma_ch;
 	struct omap_desc *desc;
@@ -138,11 +139,15 @@ static void omap_dma_callback(int ch, u16 status, void *data)
 	spin_lock_irqsave(&c->vc.lock, flags);
 	d = c->desc;
 	if (d) {
-		if (++c->sgidx < d->sglen) {
-			omap_dma_start_sg(c, d, c->sgidx);
+		if (!c->cyclic) {
+			if (++c->sgidx < d->sglen) {
+				omap_dma_start_sg(c, d, c->sgidx);
+			} else {
+				omap_dma_start_desc(c);
+				vchan_cookie_complete(&d->vd);
+			}
 		} else {
-			omap_dma_start_desc(c);
-			vchan_cookie_complete(&d->vd);
+			vchan_cyclic_callback(&d->vd);
 		}
 	}
 	spin_unlock_irqrestore(&c->vc.lock, flags);
@@ -358,6 +363,79 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 	return vchan_tx_prep(&c->vc, &d->vd, tx_flags);
 }
 
+static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
+	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+	size_t period_len, enum dma_transfer_direction dir, void *context)
+{
+	struct omap_chan *c = to_omap_dma_chan(chan);
+	enum dma_slave_buswidth dev_width;
+	struct omap_desc *d;
+	dma_addr_t dev_addr;
+	unsigned es, sync_type;
+	u32 burst;
+
+	if (dir == DMA_DEV_TO_MEM) {
+		dev_addr = c->cfg.src_addr;
+		dev_width = c->cfg.src_addr_width;
+		burst = c->cfg.src_maxburst;
+		sync_type = OMAP_DMA_SRC_SYNC;
+	} else if (dir == DMA_MEM_TO_DEV) {
+		dev_addr = c->cfg.dst_addr;
+		dev_width = c->cfg.dst_addr_width;
+		burst = c->cfg.dst_maxburst;
+		sync_type = OMAP_DMA_DST_SYNC;
+	} else {
+		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
+		return NULL;
+	}
+
+	/* Bus width translates to the element size (ES) */
+	switch (dev_width) {
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		es = OMAP_DMA_DATA_TYPE_S8;
+		break;
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		es = OMAP_DMA_DATA_TYPE_S16;
+		break;
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		es = OMAP_DMA_DATA_TYPE_S32;
+		break;
+	default: /* not reached */
+		return NULL;
+	}
+
+	/* Now allocate and setup the descriptor. */
+	d = kzalloc(sizeof(*d) + sizeof(d->sg[0]), GFP_ATOMIC);
+	if (!d)
+		return NULL;
+
+	d->dir = dir;
+	d->dev_addr = dev_addr;
+	d->fi = burst;
+	d->es = es;
+	d->sync_mode = OMAP_DMA_SYNC_PACKET;
+	d->sync_type = sync_type;
+	d->periph_port = OMAP_DMA_PORT_MPUI;
+	d->sg[0].addr = buf_addr;
+	d->sg[0].en = period_len / es_bytes[es];
+	d->sg[0].fn = buf_len / period_len;
+	d->sglen = 1;
+
+	if (!c->cyclic) {
+		c->cyclic = true;
+		omap_dma_link_lch(c->dma_ch, c->dma_ch);
+		omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ);
+		omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
+	}
+
+	if (!cpu_class_is_omap1()) {
+		omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
+		omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
+	}
+
+	return vchan_tx_prep(&c->vc, &d->vd, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+}
+
 static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg)
 {
 	if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
@@ -392,6 +470,11 @@ static int omap_dma_terminate_all(struct omap_chan *c)
 		omap_stop_dma(c->dma_ch);
 	}
 
+	if (c->cyclic) {
+		c->cyclic = false;
+		omap_dma_unlink_lch(c->dma_ch, c->dma_ch);
+	}
+
 	vchan_get_all_descriptors(&c->vc, &head);
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 	vchan_dma_desc_free_list(&c->vc, &head);
@@ -484,11 +567,13 @@ static int omap_dma_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
+	dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
 	od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources;
 	od->ddev.device_free_chan_resources = omap_dma_free_chan_resources;
 	od->ddev.device_tx_status = omap_dma_tx_status;
 	od->ddev.device_issue_pending = omap_dma_issue_pending;
 	od->ddev.device_prep_slave_sg = omap_dma_prep_slave_sg;
+	od->ddev.device_prep_dma_cyclic = omap_dma_prep_dma_cyclic;
 	od->ddev.device_control = omap_dma_control;
 	od->ddev.dev = &pdev->dev;
 	INIT_LIST_HEAD(&od->ddev.channels);
Signature · 1 line
1.7.4.4
#4 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

In reply to Russell King - ARM Linux
Quoted 12 lines · Russell King - ARM Linux

These three patches add support for returning the residue and cyclic DMA support to the OMAP DMA engine driver.

As v3.5-rc is horribly broken on my OMAP platforms, I've had to back out all the sound/soc/omap changes from the last merge window to test this, inspite of Peter Ujfalusi maintaining that there is nothing wrong. I can't get working audio support on the OMAP4430SDP any other way.

I am planning no further work on this until OMAP ASoC support gets fixed; due to Peter and my plans this summer, this is likely to be late July/ August time.

Quoted 6 lines

This does not implement all of the weird and wonderfully different DMA setups which the OMAP ASoC driver appears to support (do we need soo much flexibility?) but it does support whatever is required for my OMAP4430SDP board.

These patches apply on top of the previously posted series of DMA patches.

Actually, you will need to use this version of the DMA engine driver rather than the previously posted one - it contains a minor cleanup to allow the byte size of an element size to be more easily determined:

From: Russell King <[email protected]>
Subject: [PATCH] dmaengine: add OMAP DMA engine driver

---
 drivers/dma/Kconfig      |    6 +
 drivers/dma/Makefile     |    1 +
 drivers/dma/omap-dma.c   |  524 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/omap-dma.h |   24 ++
 4 files changed, 555 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dma/omap-dma.c
 create mode 100644 include/linux/omap-dma.h
drivers/dma/Kconfig +6 -0
index eb2b60e..8be3bf6 100644
@@ -261,6 +261,12 @@ config DMA_SA11X0
 	  SA-1110 SoCs.  This DMA engine can only be used with on-chip
 	  devices.
 
+config DMA_OMAP
+	tristate "OMAP DMA support"
+	depends on ARCH_OMAP
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+
 config DMA_ENGINE
 	bool
 
drivers/dma/Makefile +1 -0
index fc05f7d..ddc291a 100644
@@ -29,3 +29,4 @@ obj-$(CONFIG_PCH_DMA) += pch_dma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
 obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
 obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
+obj-$(CONFIG_DMA_OMAP) += omap-dma.o
drivers/dma/omap-dma.c new file +524 -0

524 lines not on this page · raw message

include/linux/omap-dma.h new file +24 -0
new file mode 100644
index 0000000..869534c
@@ -0,0 +1,24 @@
+/*
+ * OMAP DMA Engine support
+ *
+ * Copyright (C) 2012 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_OMAP_DMA_H
+#define __LINUX_OMAP_DMA_H
+
+struct dma_chan;
+
+#if defined(CONFIG_DMA_OMAP) || defined(CONFIG_DMA_OMAP_MODULE)
+bool omap_dma_filter_fn(struct dma_chan *, void *);
+#else
+static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d)
+{
+	return false;
+}
+#endif
+
+#endif
Signature · 1 line
1.7.4.4
#5 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

In reply to Russell King - ARM Linux
Quoted 4 lines · Russell King - ARM Linux

As v3.5-rc is horribly broken on my OMAP platforms, I've had to back out all the sound/soc/omap changes from the last merge window to test this, inspite of Peter Ujfalusi maintaining that there is nothing wrong. I can't get working audio support on the OMAP4430SDP any other way.

Do you have any details on what's wrong here? I've not seen any upstream reports but there's been precious little upstream work there so it should be simple to identify which changes caused the breakage and just drop them. There's been no public reports...

Quoted 3 lines

I am planning no further work on this until OMAP ASoC support gets fixed; due to Peter and my plans this summer, this is likely to be late July/ August time.

That's sounding like 3.5 is likely to go out work broken audio.

#6 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

Quoted 11 lines · Mark Brown
Quoted 4 lines · Russell King - ARM Linux

As v3.5-rc is horribly broken on my OMAP platforms, I've had to back out all the sound/soc/omap changes from the last merge window to test this, inspite of Peter Ujfalusi maintaining that there is nothing wrong. I can't get working audio support on the OMAP4430SDP any other way.

Do you have any details on what's wrong here? I've not seen any upstream reports but there's been precious little upstream work there so it should be simple to identify which changes caused the breakage and just drop them. There's been no public reports...

Peter took the thread off the mailing lists.

3.5-rc3 + Peter's blaze.aconf + aplay produces no audio but aplay appears to complete in about the right time.

3.5-rc3 + Peter's blaze.aconf + aplay + sound/soc/omap reverted back to v3.4 produces audio.

I have nothing further, other than "it produces no audio". As I have zero information on the SDP4430 hardware, if something doesn't work I just stop and post a bug report. I've no idea of the structure of the audio implementations on OMAP platforms. That information is kept from me.

I suspect the key difference is I run the uImage kernels on the SDP4430 without a DT blob. I suspect it's the DT conversion of sound/soc/omap that's buggered it up.

#7 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

Quoted 3 lines · Russell King - ARM Linux

I suspect the key difference is I run the uImage kernels on the SDP4430 without a DT blob. I suspect it's the DT conversion of sound/soc/omap that's buggered it up.

This sounds like the most likely explanation. There's not that many commits, would it be possible for you to try bisecting them (or just reverting them one at a time)? The most salient ones should be:

356bccbea17988bd32a016ada867dd6a53ba2796 ASoC: omap-abe-twl6040: Introduce driver data for runtime parameters 7d09f9e98956b29755f20d830252dec9300e7044 ASoC: omap-abe-twl6040: Move Digital Mic widget into dapm table c2f98956e3635a897737cc08a60539752aa00dd7 ASoC: omap-abe-twl6040: Keep only one snd_soc_dai_link structure

though it looks like a bisect of sound/soc/omap should be about as fast.
Like I say if we're talking late July or August there's a very good
chance that 3.5 will be broken so we should at least revert but it'd be
a shame to loose the HDMI stuff, I'd really expect that to be unrelated.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120622/6e1ce553/attachment.sig>

#8 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

Quoted 10 lines · Mark Brown
Quoted 3 lines · Russell King - ARM Linux

I suspect the key difference is I run the uImage kernels on the SDP4430 without a DT blob. I suspect it's the DT conversion of sound/soc/omap that's buggered it up.

This sounds like the most likely explanation. There's not that many commits, would it be possible for you to try bisecting them (or just reverting them one at a time)? The most salient ones should be:

Quoted 8 lines

356bccbea17988bd32a016ada867dd6a53ba2796 ASoC: omap-abe-twl6040: Introduce driver data for runtime parameters 7d09f9e98956b29755f20d830252dec9300e7044 ASoC: omap-abe-twl6040: Move Digital Mic widget into dapm table c2f98956e3635a897737cc08a60539752aa00dd7 ASoC: omap-abe-twl6040: Keep only one snd_soc_dai_link structure

though it looks like a bisect of sound/soc/omap should be about as fast. Like I say if we're talking late July or August there's a very good chance that 3.5 will be broken so we should at least revert but it'd be a shame to loose the HDMI stuff, I'd really expect that to be unrelated.

It appears to be something to do with the jack detection that's going wrong. If I start the audio with the jack disconnected, I never get anything out of the board. It requires the jack to be connected before the first use. The on-board speakers used to work without the jack plugged in at one time but they seem to be completely non-functional now.

Confused.

#9 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

Quoted 7 lines · Russell King - ARM Linux

It appears to be something to do with the jack detection that's going wrong. If I start the audio with the jack disconnected, I never get anything out of the board. It requires the jack to be connected before the first use. The on-board speakers used to work without the jack plugged in at one time but they seem to be completely non-functional now.

Confused.

Me too - there's nothing obvious in the code just from inspection that
would affect this.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120627/66482047/attachment.sig>

#10 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

+ Peter,

Quoted 8 lines · Mark Brown
Quoted 5 lines · Russell King - ARM Linux

It appears to be something to do with the jack detection that's going wrong. If I start the audio with the jack disconnected, I never get anything out of the board. It requires the jack to be connected before the first use. The on-board speakers used to work without the jack plugged in at one time but they seem to be completely non-functional now.

Quoted 4 lines
Quoted 1 line

Confused.

Me too - there's nothing obvious in the code just from inspection that would affect this.

Does audio work with $subject series after your mux fixes which you posted recently.

Regards
Santosh

#11 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

In reply to Russell King - ARM Linux

Hi Russell,

What is the status of the virtual dma and the series you have posted previously. Is it ready for merge?

I would be away for 10days starting coming Thursday. So please let me know

Quoted 29 lines · Russell King - ARM Linux

These three patches add support for returning the residue and cyclic DMA support to the OMAP DMA engine driver.

As v3.5-rc is horribly broken on my OMAP platforms, I've had to back out all the sound/soc/omap changes from the last merge window to test this, inspite of Peter Ujfalusi maintaining that there is nothing wrong. I can't get working audio support on the OMAP4430SDP any other way.

I am planning no further work on this until OMAP ASoC support gets fixed; due to Peter and my plans this summer, this is likely to be late July/ August time.

This does not implement all of the weird and wonderfully different DMA setups which the OMAP ASoC driver appears to support (do we need soo much flexibility?) but it does support whatever is required for my OMAP4430SDP board.

These patches apply on top of the previously posted series of DMA patches.

I will be merging at least some of these down into the "dmaengine: add OMAP DMA engine driver" commit at some point.

 drivers/dma/omap-dma.c |  167 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 156 insertions(+), 11 deletions(-)

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Signature · 1 line
~Vinod
#12 lore raw

cover Add cyclic DMA support to OMAP DMA engine driver

Quoted 7 lines · Vinod Koul

Hi Russell,

What is the status of the virtual dma and the series you have posted previously. Is it ready for merge?

I would be away for 10days starting coming Thursday. So please let me know

I have no idea.

I've just rebased all the DMA stuff onto -rc4, because -rc3 is just a whole load of problems for OMAP, and I'm still struggling with the stupid OMAP audio crap. And what with people who know how the SDP4430 works and/or OMAP audio works going on holiday too, I don't see much progress being made until August time.

I've found that the only way I can get any audio out of the SDP4430 platform is if I have something connected to the 3.5mm jack before powering up the board, and keep it connected. So provided I do that I can test the OMAP audio stuff.

Of course, finding out crap like that takes time away from my _one_ day a _week_ that I'm working on OMAP stuff...