diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-04 07:58:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-04 07:58:25 -0700 |
commit | 1046a2c428bedd64c960dcfd0c57cc69a82fea2f (patch) | |
tree | d34b83e0ac61b51305cece031f7ff49579e3fe76 /drivers/dma/ipu/ipu_idmac.c | |
parent | 46e85f5f1c2a1d106c1ec0fa2a06280276b8e052 (diff) | |
parent | b3f4e1eba45eda5d1213810ef3bc53e5247df2df (diff) | |
download | blackbird-op-linux-1046a2c428bedd64c960dcfd0c57cc69a82fea2f.tar.gz blackbird-op-linux-1046a2c428bedd64c960dcfd0c57cc69a82fea2f.zip |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (144 commits)
[media] saa7134.h: Suppress compiler warnings when CONFIG_VIDEO_SAA7134_RC is not set
[media] it913x [VER 1.07] Support for single ITE 9135 devices
[media] Support for Terratec G1
[media] cx25821: off by one in cx25821_vidioc_s_input()
[media] media: tea5764: reconcile Kconfig symbol and macro
[media] omap_vout: Add poll() support
[media] omap3isp: preview: Add crop support on the sink pad
[media] omap3isp: preview: Rename min/max input/output sizes defines
[media] omap3isp: preview: Remove horizontal averager support
[media] omap3isp: Report the ISP revision through the media controller API
[media] omap3isp: ccdc: remove redundant operation
[media] omap3isp: Fix memory leaks in initialization error paths
[media] omap3isp: Add missing mutex_destroy() calls
[media] omap3isp: Move *_init_entities() functions to the init/cleanup section
[media] omap3isp: Move media_entity_cleanup() from unregister() to cleanup()
[media] MFC: Change MFC firmware binary name
[media] vb2: add vb2_get_unmapped_area in vb2 core
[media] v4l: Add v4l2 subdev driver for S5K6AAFX sensor
[media] v4l: Add AUTO option for the V4L2_CID_POWER_LINE_FREQUENCY control
[media] media: ov6650: stylistic improvements
...
Diffstat (limited to 'drivers/dma/ipu/ipu_idmac.c')
-rw-r--r-- | drivers/dma/ipu/ipu_idmac.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 6815905a772f..ddc2a1331822 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1307,6 +1307,7 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) { callback = descnew->txd.callback; callback_param = descnew->txd.callback_param; + list_del_init(&descnew->list); spin_unlock(&ichan->lock); if (callback) callback(callback_param); @@ -1428,39 +1429,58 @@ static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac *idmac = to_idmac(chan->device); + struct ipu *ipu = to_ipu(idmac); + struct list_head *list, *tmp; unsigned long flags; int i; - /* Only supports DMA_TERMINATE_ALL */ - if (cmd != DMA_TERMINATE_ALL) - return -ENXIO; + switch (cmd) { + case DMA_PAUSE: + spin_lock_irqsave(&ipu->lock, flags); + ipu_ic_disable_task(ipu, chan->chan_id); - ipu_disable_channel(idmac, ichan, - ichan->status >= IPU_CHANNEL_ENABLED); + /* Return all descriptors into "prepared" state */ + list_for_each_safe(list, tmp, &ichan->queue) + list_del_init(list); - tasklet_disable(&to_ipu(idmac)->tasklet); + ichan->sg[0] = NULL; + ichan->sg[1] = NULL; - /* ichan->queue is modified in ISR, have to spinlock */ - spin_lock_irqsave(&ichan->lock, flags); - list_splice_init(&ichan->queue, &ichan->free_list); + spin_unlock_irqrestore(&ipu->lock, flags); - if (ichan->desc) - for (i = 0; i < ichan->n_tx_desc; i++) { - struct idmac_tx_desc *desc = ichan->desc + i; - if (list_empty(&desc->list)) - /* Descriptor was prepared, but not submitted */ - list_add(&desc->list, &ichan->free_list); + ichan->status = IPU_CHANNEL_INITIALIZED; + break; + case DMA_TERMINATE_ALL: + ipu_disable_channel(idmac, ichan, + ichan->status >= IPU_CHANNEL_ENABLED); - async_tx_clear_ack(&desc->txd); - } + tasklet_disable(&ipu->tasklet); - ichan->sg[0] = NULL; - ichan->sg[1] = NULL; - spin_unlock_irqrestore(&ichan->lock, flags); + /* ichan->queue is modified in ISR, have to spinlock */ + spin_lock_irqsave(&ichan->lock, flags); + list_splice_init(&ichan->queue, &ichan->free_list); - tasklet_enable(&to_ipu(idmac)->tasklet); + if (ichan->desc) + for (i = 0; i < ichan->n_tx_desc; i++) { + struct idmac_tx_desc *desc = ichan->desc + i; + if (list_empty(&desc->list)) + /* Descriptor was prepared, but not submitted */ + list_add(&desc->list, &ichan->free_list); - ichan->status = IPU_CHANNEL_INITIALIZED; + async_tx_clear_ack(&desc->txd); + } + + ichan->sg[0] = NULL; + ichan->sg[1] = NULL; + spin_unlock_irqrestore(&ichan->lock, flags); + + tasklet_enable(&ipu->tasklet); + + ichan->status = IPU_CHANNEL_INITIALIZED; + break; + default: + return -ENOSYS; + } return 0; } @@ -1663,7 +1683,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu) struct idmac_channel *ichan = ipu->channel + i; idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0); - idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0); } dma_async_device_unregister(&idmac->dma); |