aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt2
-rw-r--r--sound/soc/davinci/davinci-mcasp.c124
-rw-r--r--sound/soc/davinci/davinci-mcasp.h11
3 files changed, 136 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index 60ca07996458..46bc9829c71a 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -32,7 +32,7 @@ Optional properties:
32- rx-num-evt : FIFO levels. 32- rx-num-evt : FIFO levels.
33- sram-size-playback : size of sram to be allocated during playback 33- sram-size-playback : size of sram to be allocated during playback
34- sram-size-capture : size of sram to be allocated during capture 34- sram-size-capture : size of sram to be allocated during capture
35- interrupts : Interrupt numbers for McASP, currently not used by the driver 35- interrupts : Interrupt numbers for McASP
36- interrupt-names : Known interrupt names are "tx" and "rx" 36- interrupt-names : Known interrupt names are "tx" and "rx"
37- pinctrl-0: Should specify pin control group used for this controller. 37- pinctrl-0: Should specify pin control group used for this controller.
38- pinctrl-names: Should contain only one value - "default", for more details 38- pinctrl-names: Should contain only one value - "default", for more details
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index a9822c7bbb0b..e460f97c514e 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -70,6 +70,7 @@ struct davinci_mcasp {
70 void __iomem *base; 70 void __iomem *base;
71 u32 fifo_base; 71 u32 fifo_base;
72 struct device *dev; 72 struct device *dev;
73 struct snd_pcm_substream *substreams[2];
73 74
74 /* McASP specific data */ 75 /* McASP specific data */
75 int tdm_slots; 76 int tdm_slots;
@@ -80,6 +81,7 @@ struct davinci_mcasp {
80 u8 bclk_div; 81 u8 bclk_div;
81 u16 bclk_lrclk_ratio; 82 u16 bclk_lrclk_ratio;
82 int streams; 83 int streams;
84 u32 irq_request[2];
83 85
84 int sysclk_freq; 86 int sysclk_freq;
85 bool bclk_master; 87 bool bclk_master;
@@ -185,6 +187,10 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
185 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); 187 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
186 if (mcasp_is_synchronous(mcasp)) 188 if (mcasp_is_synchronous(mcasp))
187 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); 189 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
190
191 /* enable receive IRQs */
192 mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG,
193 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]);
188} 194}
189 195
190static void mcasp_start_tx(struct davinci_mcasp *mcasp) 196static void mcasp_start_tx(struct davinci_mcasp *mcasp)
@@ -214,6 +220,10 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
214 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); 220 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
215 /* Release Frame Sync generator */ 221 /* Release Frame Sync generator */
216 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); 222 mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
223
224 /* enable transmit IRQs */
225 mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
226 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
217} 227}
218 228
219static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream) 229static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
@@ -228,6 +238,10 @@ static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
228 238
229static void mcasp_stop_rx(struct davinci_mcasp *mcasp) 239static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
230{ 240{
241 /* disable IRQ sources */
242 mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG,
243 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]);
244
231 /* 245 /*
232 * In synchronous mode stop the TX clocks if no other stream is 246 * In synchronous mode stop the TX clocks if no other stream is
233 * running 247 * running
@@ -249,6 +263,10 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
249{ 263{
250 u32 val = 0; 264 u32 val = 0;
251 265
266 /* disable IRQ sources */
267 mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
268 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
269
252 /* 270 /*
253 * In synchronous mode keep TX clocks running if the capture stream is 271 * In synchronous mode keep TX clocks running if the capture stream is
254 * still running. 272 * still running.
@@ -276,6 +294,76 @@ static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
276 mcasp_stop_rx(mcasp); 294 mcasp_stop_rx(mcasp);
277} 295}
278 296
297static irqreturn_t davinci_mcasp_tx_irq_handler(int irq, void *data)
298{
299 struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
300 struct snd_pcm_substream *substream;
301 u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK];
302 u32 handled_mask = 0;
303 u32 stat;
304
305 stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG);
306 if (stat & XUNDRN & irq_mask) {
307 dev_warn(mcasp->dev, "Transmit buffer underflow\n");
308 handled_mask |= XUNDRN;
309
310 substream = mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK];
311 if (substream) {
312 snd_pcm_stream_lock_irq(substream);
313 if (snd_pcm_running(substream))
314 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
315 snd_pcm_stream_unlock_irq(substream);
316 }
317 }
318
319 if (!handled_mask)
320 dev_warn(mcasp->dev, "unhandled tx event. txstat: 0x%08x\n",
321 stat);
322
323 if (stat & XRERR)
324 handled_mask |= XRERR;
325
326 /* Ack the handled event only */
327 mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, handled_mask);
328
329 return IRQ_RETVAL(handled_mask);
330}
331
332static irqreturn_t davinci_mcasp_rx_irq_handler(int irq, void *data)
333{
334 struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
335 struct snd_pcm_substream *substream;
336 u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE];
337 u32 handled_mask = 0;
338 u32 stat;
339
340 stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG);
341 if (stat & ROVRN & irq_mask) {
342 dev_warn(mcasp->dev, "Receive buffer overflow\n");
343 handled_mask |= ROVRN;
344
345 substream = mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE];
346 if (substream) {
347 snd_pcm_stream_lock_irq(substream);
348 if (snd_pcm_running(substream))
349 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
350 snd_pcm_stream_unlock_irq(substream);
351 }
352 }
353
354 if (!handled_mask)
355 dev_warn(mcasp->dev, "unhandled rx event. rxstat: 0x%08x\n",
356 stat);
357
358 if (stat & XRERR)
359 handled_mask |= XRERR;
360
361 /* Ack the handled event only */
362 mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, handled_mask);
363
364 return IRQ_RETVAL(handled_mask);
365}
366
279static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, 367static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
280 unsigned int fmt) 368 unsigned int fmt)
281{ 369{
@@ -869,6 +957,8 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
869 u32 max_channels = 0; 957 u32 max_channels = 0;
870 int i, dir; 958 int i, dir;
871 959
960 mcasp->substreams[substream->stream] = substream;
961
872 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) 962 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
873 return 0; 963 return 0;
874 964
@@ -907,6 +997,8 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream,
907{ 997{
908 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); 998 struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
909 999
1000 mcasp->substreams[substream->stream] = NULL;
1001
910 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) 1002 if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
911 return; 1003 return;
912 1004
@@ -1256,6 +1348,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
1256 struct resource *mem, *ioarea, *res, *dat; 1348 struct resource *mem, *ioarea, *res, *dat;
1257 struct davinci_mcasp_pdata *pdata; 1349 struct davinci_mcasp_pdata *pdata;
1258 struct davinci_mcasp *mcasp; 1350 struct davinci_mcasp *mcasp;
1351 char *irq_name;
1352 int irq;
1259 int ret; 1353 int ret;
1260 1354
1261 if (!pdev->dev.platform_data && !pdev->dev.of_node) { 1355 if (!pdev->dev.platform_data && !pdev->dev.of_node) {
@@ -1336,6 +1430,36 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
1336 1430
1337 mcasp->dev = &pdev->dev; 1431 mcasp->dev = &pdev->dev;
1338 1432
1433 irq = platform_get_irq_byname(pdev, "rx");
1434 if (irq >= 0) {
1435 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx\n",
1436 dev_name(&pdev->dev));
1437 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
1438 davinci_mcasp_rx_irq_handler,
1439 IRQF_ONESHOT, irq_name, mcasp);
1440 if (ret) {
1441 dev_err(&pdev->dev, "RX IRQ request failed\n");
1442 goto err;
1443 }
1444
1445 mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN;
1446 }
1447
1448 irq = platform_get_irq_byname(pdev, "tx");
1449 if (irq >= 0) {
1450 irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx\n",
1451 dev_name(&pdev->dev));
1452 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
1453 davinci_mcasp_tx_irq_handler,
1454 IRQF_ONESHOT, irq_name, mcasp);
1455 if (ret) {
1456 dev_err(&pdev->dev, "TX IRQ request failed\n");
1457 goto err;
1458 }
1459
1460 mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN;
1461 }
1462
1339 dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); 1463 dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
1340 if (dat) 1464 if (dat)
1341 mcasp->dat_port = true; 1465 mcasp->dat_port = true;
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 9737108f0305..79dc511180bf 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -256,6 +256,7 @@
256 * DAVINCI_MCASP_TXSTAT_REG - Transmitter Status Register Bits 256 * DAVINCI_MCASP_TXSTAT_REG - Transmitter Status Register Bits
257 * DAVINCI_MCASP_RXSTAT_REG - Receiver Status Register Bits 257 * DAVINCI_MCASP_RXSTAT_REG - Receiver Status Register Bits
258 */ 258 */
259#define XRERR BIT(8) /* Transmit/Receive error */
259#define XRDATA BIT(5) /* Transmit/Receive data ready */ 260#define XRDATA BIT(5) /* Transmit/Receive data ready */
260 261
261/* 262/*
@@ -285,6 +286,16 @@
285#define TXDATADMADIS BIT(0) 286#define TXDATADMADIS BIT(0)
286 287
287/* 288/*
289 * DAVINCI_MCASP_EVTCTLR_REG - Receiver Interrupt Control Register Bits
290 */
291#define ROVRN BIT(0)
292
293/*
294 * DAVINCI_MCASP_EVTCTLX_REG - Transmitter Interrupt Control Register Bits
295 */
296#define XUNDRN BIT(0)
297
298/*
288 * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits 299 * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
289 */ 300 */
290#define FIFO_ENABLE BIT(16) 301#define FIFO_ENABLE BIT(16)