ASoC: omap-mcbsp: Use the common interrupt line if supported by the SoC
authorPeter Ujfalusi <peter.ujfalusi@ti.com>
Mon, 19 Mar 2012 15:05:39 +0000 (17:05 +0200)
committerLiam Girdwood <lrg@ti.com>
Tue, 22 May 2012 16:33:19 +0000 (17:33 +0100)
With the common irq the driver only needs to use one interrupt line, and
it provides better debugging possibilites compared to the legacy TX/RX
interrupt lines.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@ti.com>
sound/soc/omap/mcbsp.c
sound/soc/omap/mcbsp.h

index ec6832cc296db658b9a0c537baf899a8b7def4b0..34835e8a9160ce16b1d074a1f8495d1124e5eac8 100644 (file)
@@ -109,6 +109,47 @@ static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
        dev_dbg(mcbsp->dev, "***********************\n");
 }
 
+static irqreturn_t omap_mcbsp_irq_handler(int irq, void *dev_id)
+{
+       struct omap_mcbsp *mcbsp = dev_id;
+       u16 irqst;
+
+       irqst = MCBSP_READ(mcbsp, IRQST);
+       dev_dbg(mcbsp->dev, "IRQ callback : 0x%x\n", irqst);
+
+       if (irqst & RSYNCERREN)
+               dev_err(mcbsp->dev, "RX Frame Sync Error!\n");
+       if (irqst & RFSREN)
+               dev_dbg(mcbsp->dev, "RX Frame Sync\n");
+       if (irqst & REOFEN)
+               dev_dbg(mcbsp->dev, "RX End Of Frame\n");
+       if (irqst & RRDYEN)
+               dev_dbg(mcbsp->dev, "RX Buffer Threshold Reached\n");
+       if (irqst & RUNDFLEN)
+               dev_err(mcbsp->dev, "RX Buffer Underflow!\n");
+       if (irqst & ROVFLEN)
+               dev_err(mcbsp->dev, "RX Buffer Overflow!\n");
+
+       if (irqst & XSYNCERREN)
+               dev_err(mcbsp->dev, "TX Frame Sync Error!\n");
+       if (irqst & XFSXEN)
+               dev_dbg(mcbsp->dev, "TX Frame Sync\n");
+       if (irqst & XEOFEN)
+               dev_dbg(mcbsp->dev, "TX End Of Frame\n");
+       if (irqst & XRDYEN)
+               dev_dbg(mcbsp->dev, "TX Buffer threshold Reached\n");
+       if (irqst & XUNDFLEN)
+               dev_err(mcbsp->dev, "TX Buffer Underflow!\n");
+       if (irqst & XOVFLEN)
+               dev_err(mcbsp->dev, "TX Buffer Overflow!\n");
+       if (irqst & XEMPTYEOFEN)
+               dev_dbg(mcbsp->dev, "TX Buffer empty at end of frame\n");
+
+       MCBSP_WRITE(mcbsp, IRQST, irqst);
+
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
 {
        struct omap_mcbsp *mcbsp_tx = dev_id;
@@ -176,6 +217,10 @@ void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
        /* Enable wakeup behavior */
        if (mcbsp->pdata->has_wakeup)
                MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
+
+       /* Enable TX/RX sync error interrupts by default */
+       if (mcbsp->irq)
+               MCBSP_WRITE(mcbsp, IRQEN, RSYNCERREN | XSYNCERREN);
 }
 
 /**
@@ -489,23 +534,25 @@ int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
        MCBSP_WRITE(mcbsp, SPCR1, 0);
        MCBSP_WRITE(mcbsp, SPCR2, 0);
 
-       err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
-                               0, "McBSP", (void *)mcbsp);
-       if (err != 0) {
-               dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
-                               "for McBSP%d\n", mcbsp->tx_irq,
-                               mcbsp->id);
-               goto err_clk_disable;
-       }
+       if (mcbsp->irq) {
+               err = request_irq(mcbsp->irq, omap_mcbsp_irq_handler, 0,
+                                 "McBSP", (void *)mcbsp);
+               if (err != 0) {
+                       dev_err(mcbsp->dev, "Unable to request IRQ\n");
+                       goto err_clk_disable;
+               }
+       } else {
+               err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0,
+                                 "McBSP TX", (void *)mcbsp);
+               if (err != 0) {
+                       dev_err(mcbsp->dev, "Unable to request TX IRQ\n");
+                       goto err_clk_disable;
+               }
 
-       if (mcbsp->rx_irq) {
-               err = request_irq(mcbsp->rx_irq,
-                               omap_mcbsp_rx_irq_handler,
-                               0, "McBSP", (void *)mcbsp);
+               err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0,
+                                 "McBSP RX", (void *)mcbsp);
                if (err != 0) {
-                       dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
-                                       "for McBSP%d\n", mcbsp->rx_irq,
-                                       mcbsp->id);
+                       dev_err(mcbsp->dev, "Unable to request RX IRQ\n");
                        goto err_free_irq;
                }
        }
@@ -542,9 +589,16 @@ void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
        if (mcbsp->pdata->has_wakeup)
                MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 
-       if (mcbsp->rx_irq)
+       /* Disable interrupt requests */
+       if (mcbsp->irq)
+               MCBSP_WRITE(mcbsp, IRQEN, 0);
+
+       if (mcbsp->irq) {
+               free_irq(mcbsp->irq, (void *)mcbsp);
+       } else {
                free_irq(mcbsp->rx_irq, (void *)mcbsp);
-       free_irq(mcbsp->tx_irq, (void *)mcbsp);
+               free_irq(mcbsp->tx_irq, (void *)mcbsp);
+       }
 
        reg_cache = mcbsp->reg_cache;
 
@@ -949,13 +1003,24 @@ int __devinit omap_mcbsp_init(struct platform_device *pdev)
        else
                mcbsp->phys_dma_base = res->start;
 
-       mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
-       mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
-
-       /* From OMAP4 there will be a single irq line */
-       if (mcbsp->tx_irq == -ENXIO) {
-               mcbsp->tx_irq = platform_get_irq(pdev, 0);
-               mcbsp->rx_irq = 0;
+       /*
+        * OMAP1, 2 uses two interrupt lines: TX, RX
+        * OMAP2430, OMAP3 SoC have combined IRQ line as well.
+        * OMAP4 and newer SoC only have the combined IRQ line.
+        * Use the combined IRQ if available since it gives better debugging
+        * possibilities.
+        */
+       mcbsp->irq = platform_get_irq_byname(pdev, "common");
+       if (mcbsp->irq == -ENXIO) {
+               mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
+
+               if (mcbsp->tx_irq == -ENXIO) {
+                       mcbsp->irq = platform_get_irq(pdev, 0);
+                       mcbsp->tx_irq = 0;
+               } else {
+                       mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
+                       mcbsp->irq = 0;
+               }
        }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
index 179a822c7238fd58e02fd76fea8f4979e15a013d..262a6152111fe67badda011198c875974e76d377 100644 (file)
@@ -218,15 +218,19 @@ enum {
 #define MCBSP_DMA_MODE_ELEMENT         0
 #define MCBSP_DMA_MODE_THRESHOLD       1
 
-/********************** McBSP WAKEUPEN bit definitions *********************/
+/********************** McBSP WAKEUPEN/IRQST/IRQEN bit definitions *********/
 #define RSYNCERREN             BIT(0)
 #define RFSREN                 BIT(1)
 #define REOFEN                 BIT(2)
 #define RRDYEN                 BIT(3)
+#define RUNDFLEN               BIT(4)
+#define ROVFLEN                        BIT(5)
 #define XSYNCERREN             BIT(7)
 #define XFSXEN                 BIT(8)
 #define XEOFEN                 BIT(9)
 #define XRDYEN                 BIT(10)
+#define XUNDFLEN               BIT(11)
+#define XOVFLEN                        BIT(12)
 #define XEMPTYEOFEN            BIT(14)
 
 /* Clock signal muxing options */
@@ -294,6 +298,7 @@ struct omap_mcbsp {
        int configured;
        u8 free;
 
+       int irq;
        int rx_irq;
        int tx_irq;