aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ipu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/ipu')
-rw-r--r--drivers/dma/ipu/ipu_idmac.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 7ce0e25266dc..90773844cc89 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1442,8 +1442,8 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan
1442 unsigned long flags; 1442 unsigned long flags;
1443 1443
1444 /* We only can handle these three channels so far */ 1444 /* We only can handle these three channels so far */
1445 if (ichan->dma_chan.chan_id != IDMAC_SDC_0 && ichan->dma_chan.chan_id != IDMAC_SDC_1 && 1445 if (chan->chan_id != IDMAC_SDC_0 && chan->chan_id != IDMAC_SDC_1 &&
1446 ichan->dma_chan.chan_id != IDMAC_IC_7) 1446 chan->chan_id != IDMAC_IC_7)
1447 return NULL; 1447 return NULL;
1448 1448
1449 if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) { 1449 if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) {
@@ -1484,7 +1484,7 @@ static void idmac_issue_pending(struct dma_chan *chan)
1484 1484
1485 /* This is not always needed, but doesn't hurt either */ 1485 /* This is not always needed, but doesn't hurt either */
1486 spin_lock_irqsave(&ipu->lock, flags); 1486 spin_lock_irqsave(&ipu->lock, flags);
1487 ipu_select_buffer(ichan->dma_chan.chan_id, ichan->active_buffer); 1487 ipu_select_buffer(chan->chan_id, ichan->active_buffer);
1488 spin_unlock_irqrestore(&ipu->lock, flags); 1488 spin_unlock_irqrestore(&ipu->lock, flags);
1489 1489
1490 /* 1490 /*
@@ -1541,6 +1541,28 @@ static void idmac_terminate_all(struct dma_chan *chan)
1541 mutex_unlock(&ichan->chan_mutex); 1541 mutex_unlock(&ichan->chan_mutex);
1542} 1542}
1543 1543
1544#ifdef DEBUG
1545static irqreturn_t ic_sof_irq(int irq, void *dev_id)
1546{
1547 struct idmac_channel *ichan = dev_id;
1548 printk(KERN_DEBUG "Got SOF IRQ %d on Channel %d\n",
1549 irq, ichan->dma_chan.chan_id);
1550 disable_irq(irq);
1551 return IRQ_HANDLED;
1552}
1553
1554static irqreturn_t ic_eof_irq(int irq, void *dev_id)
1555{
1556 struct idmac_channel *ichan = dev_id;
1557 printk(KERN_DEBUG "Got EOF IRQ %d on Channel %d\n",
1558 irq, ichan->dma_chan.chan_id);
1559 disable_irq(irq);
1560 return IRQ_HANDLED;
1561}
1562
1563static int ic_sof = -EINVAL, ic_eof = -EINVAL;
1564#endif
1565
1544static int idmac_alloc_chan_resources(struct dma_chan *chan) 1566static int idmac_alloc_chan_resources(struct dma_chan *chan)
1545{ 1567{
1546 struct idmac_channel *ichan = to_idmac_chan(chan); 1568 struct idmac_channel *ichan = to_idmac_chan(chan);
@@ -1554,7 +1576,7 @@ static int idmac_alloc_chan_resources(struct dma_chan *chan)
1554 chan->cookie = 1; 1576 chan->cookie = 1;
1555 ichan->completed = -ENXIO; 1577 ichan->completed = -ENXIO;
1556 1578
1557 ret = ipu_irq_map(ichan->dma_chan.chan_id); 1579 ret = ipu_irq_map(chan->chan_id);
1558 if (ret < 0) 1580 if (ret < 0)
1559 goto eimap; 1581 goto eimap;
1560 1582
@@ -1575,17 +1597,28 @@ static int idmac_alloc_chan_resources(struct dma_chan *chan)
1575 if (ret < 0) 1597 if (ret < 0)
1576 goto erirq; 1598 goto erirq;
1577 1599
1600#ifdef DEBUG
1601 if (chan->chan_id == IDMAC_IC_7) {
1602 ic_sof = ipu_irq_map(69);
1603 if (ic_sof > 0)
1604 request_irq(ic_sof, ic_sof_irq, 0, "IC SOF", ichan);
1605 ic_eof = ipu_irq_map(70);
1606 if (ic_eof > 0)
1607 request_irq(ic_eof, ic_eof_irq, 0, "IC EOF", ichan);
1608 }
1609#endif
1610
1578 ichan->status = IPU_CHANNEL_INITIALIZED; 1611 ichan->status = IPU_CHANNEL_INITIALIZED;
1579 1612
1580 dev_dbg(&ichan->dma_chan.dev->device, "Found channel 0x%x, irq %d\n", 1613 dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
1581 ichan->dma_chan.chan_id, ichan->eof_irq); 1614 chan->chan_id, ichan->eof_irq);
1582 1615
1583 return ret; 1616 return ret;
1584 1617
1585erirq: 1618erirq:
1586 ipu_uninit_channel(idmac, ichan); 1619 ipu_uninit_channel(idmac, ichan);
1587eichan: 1620eichan:
1588 ipu_irq_unmap(ichan->dma_chan.chan_id); 1621 ipu_irq_unmap(chan->chan_id);
1589eimap: 1622eimap:
1590 return ret; 1623 return ret;
1591} 1624}
@@ -1600,8 +1633,22 @@ static void idmac_free_chan_resources(struct dma_chan *chan)
1600 __idmac_terminate_all(chan); 1633 __idmac_terminate_all(chan);
1601 1634
1602 if (ichan->status > IPU_CHANNEL_FREE) { 1635 if (ichan->status > IPU_CHANNEL_FREE) {
1636#ifdef DEBUG
1637 if (chan->chan_id == IDMAC_IC_7) {
1638 if (ic_sof > 0) {
1639 free_irq(ic_sof, ichan);
1640 ipu_irq_unmap(69);
1641 ic_sof = -EINVAL;
1642 }
1643 if (ic_eof > 0) {
1644 free_irq(ic_eof, ichan);
1645 ipu_irq_unmap(70);
1646 ic_eof = -EINVAL;
1647 }
1648 }
1649#endif
1603 free_irq(ichan->eof_irq, ichan); 1650 free_irq(ichan->eof_irq, ichan);
1604 ipu_irq_unmap(ichan->dma_chan.chan_id); 1651 ipu_irq_unmap(chan->chan_id);
1605 } 1652 }
1606 1653
1607 ichan->status = IPU_CHANNEL_FREE; 1654 ichan->status = IPU_CHANNEL_FREE;
@@ -1663,7 +1710,7 @@ static int __init ipu_idmac_init(struct ipu *ipu)
1663 dma_chan->device = &idmac->dma; 1710 dma_chan->device = &idmac->dma;
1664 dma_chan->cookie = 1; 1711 dma_chan->cookie = 1;
1665 dma_chan->chan_id = i; 1712 dma_chan->chan_id = i;
1666 list_add_tail(&ichan->dma_chan.device_node, &dma->channels); 1713 list_add_tail(&dma_chan->device_node, &dma->channels);
1667 } 1714 }
1668 1715
1669 idmac_write_icreg(ipu, 0x00000070, IDMAC_CONF); 1716 idmac_write_icreg(ipu, 0x00000070, IDMAC_CONF);