aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2012-03-19 11:05:39 -0400
committerLiam Girdwood <lrg@ti.com>2012-05-22 12:33:19 -0400
commit35d210faa17e46897771fcf0d78df7f952b0f9b0 (patch)
tree0fa607e334f8d74822b252fd8cb82739c7f3b733 /sound/soc
parent09fa37ac8f8be7cf57f24cfd5291c591b79957f1 (diff)
ASoC: omap-mcbsp: Use the common interrupt line if supported by the SoC
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>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/omap/mcbsp.c113
-rw-r--r--sound/soc/omap/mcbsp.h7
2 files changed, 95 insertions, 25 deletions
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index ec6832cc296d..34835e8a9160 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -109,6 +109,47 @@ static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
109 dev_dbg(mcbsp->dev, "***********************\n"); 109 dev_dbg(mcbsp->dev, "***********************\n");
110} 110}
111 111
112static irqreturn_t omap_mcbsp_irq_handler(int irq, void *dev_id)
113{
114 struct omap_mcbsp *mcbsp = dev_id;
115 u16 irqst;
116
117 irqst = MCBSP_READ(mcbsp, IRQST);
118 dev_dbg(mcbsp->dev, "IRQ callback : 0x%x\n", irqst);
119
120 if (irqst & RSYNCERREN)
121 dev_err(mcbsp->dev, "RX Frame Sync Error!\n");
122 if (irqst & RFSREN)
123 dev_dbg(mcbsp->dev, "RX Frame Sync\n");
124 if (irqst & REOFEN)
125 dev_dbg(mcbsp->dev, "RX End Of Frame\n");
126 if (irqst & RRDYEN)
127 dev_dbg(mcbsp->dev, "RX Buffer Threshold Reached\n");
128 if (irqst & RUNDFLEN)
129 dev_err(mcbsp->dev, "RX Buffer Underflow!\n");
130 if (irqst & ROVFLEN)
131 dev_err(mcbsp->dev, "RX Buffer Overflow!\n");
132
133 if (irqst & XSYNCERREN)
134 dev_err(mcbsp->dev, "TX Frame Sync Error!\n");
135 if (irqst & XFSXEN)
136 dev_dbg(mcbsp->dev, "TX Frame Sync\n");
137 if (irqst & XEOFEN)
138 dev_dbg(mcbsp->dev, "TX End Of Frame\n");
139 if (irqst & XRDYEN)
140 dev_dbg(mcbsp->dev, "TX Buffer threshold Reached\n");
141 if (irqst & XUNDFLEN)
142 dev_err(mcbsp->dev, "TX Buffer Underflow!\n");
143 if (irqst & XOVFLEN)
144 dev_err(mcbsp->dev, "TX Buffer Overflow!\n");
145 if (irqst & XEMPTYEOFEN)
146 dev_dbg(mcbsp->dev, "TX Buffer empty at end of frame\n");
147
148 MCBSP_WRITE(mcbsp, IRQST, irqst);
149
150 return IRQ_HANDLED;
151}
152
112static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) 153static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
113{ 154{
114 struct omap_mcbsp *mcbsp_tx = dev_id; 155 struct omap_mcbsp *mcbsp_tx = dev_id;
@@ -176,6 +217,10 @@ void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
176 /* Enable wakeup behavior */ 217 /* Enable wakeup behavior */
177 if (mcbsp->pdata->has_wakeup) 218 if (mcbsp->pdata->has_wakeup)
178 MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); 219 MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
220
221 /* Enable TX/RX sync error interrupts by default */
222 if (mcbsp->irq)
223 MCBSP_WRITE(mcbsp, IRQEN, RSYNCERREN | XSYNCERREN);
179} 224}
180 225
181/** 226/**
@@ -489,23 +534,25 @@ int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
489 MCBSP_WRITE(mcbsp, SPCR1, 0); 534 MCBSP_WRITE(mcbsp, SPCR1, 0);
490 MCBSP_WRITE(mcbsp, SPCR2, 0); 535 MCBSP_WRITE(mcbsp, SPCR2, 0);
491 536
492 err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 537 if (mcbsp->irq) {
493 0, "McBSP", (void *)mcbsp); 538 err = request_irq(mcbsp->irq, omap_mcbsp_irq_handler, 0,
494 if (err != 0) { 539 "McBSP", (void *)mcbsp);
495 dev_err(mcbsp->dev, "Unable to request TX IRQ %d " 540 if (err != 0) {
496 "for McBSP%d\n", mcbsp->tx_irq, 541 dev_err(mcbsp->dev, "Unable to request IRQ\n");
497 mcbsp->id); 542 goto err_clk_disable;
498 goto err_clk_disable; 543 }
499 } 544 } else {
545 err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0,
546 "McBSP TX", (void *)mcbsp);
547 if (err != 0) {
548 dev_err(mcbsp->dev, "Unable to request TX IRQ\n");
549 goto err_clk_disable;
550 }
500 551
501 if (mcbsp->rx_irq) { 552 err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0,
502 err = request_irq(mcbsp->rx_irq, 553 "McBSP RX", (void *)mcbsp);
503 omap_mcbsp_rx_irq_handler,
504 0, "McBSP", (void *)mcbsp);
505 if (err != 0) { 554 if (err != 0) {
506 dev_err(mcbsp->dev, "Unable to request RX IRQ %d " 555 dev_err(mcbsp->dev, "Unable to request RX IRQ\n");
507 "for McBSP%d\n", mcbsp->rx_irq,
508 mcbsp->id);
509 goto err_free_irq; 556 goto err_free_irq;
510 } 557 }
511 } 558 }
@@ -542,9 +589,16 @@ void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
542 if (mcbsp->pdata->has_wakeup) 589 if (mcbsp->pdata->has_wakeup)
543 MCBSP_WRITE(mcbsp, WAKEUPEN, 0); 590 MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
544 591
545 if (mcbsp->rx_irq) 592 /* Disable interrupt requests */
593 if (mcbsp->irq)
594 MCBSP_WRITE(mcbsp, IRQEN, 0);
595
596 if (mcbsp->irq) {
597 free_irq(mcbsp->irq, (void *)mcbsp);
598 } else {
546 free_irq(mcbsp->rx_irq, (void *)mcbsp); 599 free_irq(mcbsp->rx_irq, (void *)mcbsp);
547 free_irq(mcbsp->tx_irq, (void *)mcbsp); 600 free_irq(mcbsp->tx_irq, (void *)mcbsp);
601 }
548 602
549 reg_cache = mcbsp->reg_cache; 603 reg_cache = mcbsp->reg_cache;
550 604
@@ -949,13 +1003,24 @@ int __devinit omap_mcbsp_init(struct platform_device *pdev)
949 else 1003 else
950 mcbsp->phys_dma_base = res->start; 1004 mcbsp->phys_dma_base = res->start;
951 1005
952 mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); 1006 /*
953 mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); 1007 * OMAP1, 2 uses two interrupt lines: TX, RX
954 1008 * OMAP2430, OMAP3 SoC have combined IRQ line as well.
955 /* From OMAP4 there will be a single irq line */ 1009 * OMAP4 and newer SoC only have the combined IRQ line.
956 if (mcbsp->tx_irq == -ENXIO) { 1010 * Use the combined IRQ if available since it gives better debugging
957 mcbsp->tx_irq = platform_get_irq(pdev, 0); 1011 * possibilities.
958 mcbsp->rx_irq = 0; 1012 */
1013 mcbsp->irq = platform_get_irq_byname(pdev, "common");
1014 if (mcbsp->irq == -ENXIO) {
1015 mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
1016
1017 if (mcbsp->tx_irq == -ENXIO) {
1018 mcbsp->irq = platform_get_irq(pdev, 0);
1019 mcbsp->tx_irq = 0;
1020 } else {
1021 mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
1022 mcbsp->irq = 0;
1023 }
959 } 1024 }
960 1025
961 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); 1026 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index 179a822c7238..262a6152111f 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -218,15 +218,19 @@ enum {
218#define MCBSP_DMA_MODE_ELEMENT 0 218#define MCBSP_DMA_MODE_ELEMENT 0
219#define MCBSP_DMA_MODE_THRESHOLD 1 219#define MCBSP_DMA_MODE_THRESHOLD 1
220 220
221/********************** McBSP WAKEUPEN bit definitions *********************/ 221/********************** McBSP WAKEUPEN/IRQST/IRQEN bit definitions *********/
222#define RSYNCERREN BIT(0) 222#define RSYNCERREN BIT(0)
223#define RFSREN BIT(1) 223#define RFSREN BIT(1)
224#define REOFEN BIT(2) 224#define REOFEN BIT(2)
225#define RRDYEN BIT(3) 225#define RRDYEN BIT(3)
226#define RUNDFLEN BIT(4)
227#define ROVFLEN BIT(5)
226#define XSYNCERREN BIT(7) 228#define XSYNCERREN BIT(7)
227#define XFSXEN BIT(8) 229#define XFSXEN BIT(8)
228#define XEOFEN BIT(9) 230#define XEOFEN BIT(9)
229#define XRDYEN BIT(10) 231#define XRDYEN BIT(10)
232#define XUNDFLEN BIT(11)
233#define XOVFLEN BIT(12)
230#define XEMPTYEOFEN BIT(14) 234#define XEMPTYEOFEN BIT(14)
231 235
232/* Clock signal muxing options */ 236/* Clock signal muxing options */
@@ -294,6 +298,7 @@ struct omap_mcbsp {
294 int configured; 298 int configured;
295 u8 free; 299 u8 free;
296 300
301 int irq;
297 int rx_irq; 302 int rx_irq;
298 int tx_irq; 303 int tx_irq;
299 304