aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap/omap-mcbsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap/omap-mcbsp.c')
-rw-r--r--sound/soc/omap/omap-mcbsp.c359
1 files changed, 108 insertions, 251 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 86f213905e2c..07b772357244 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -4,7 +4,7 @@
4 * Copyright (C) 2008 Nokia Corporation 4 * Copyright (C) 2008 Nokia Corporation
5 * 5 *
6 * Contact: Jarkko Nikula <jhnikula@gmail.com> 6 * Contact: Jarkko Nikula <jhnikula@gmail.com>
7 * Peter Ujfalusi <peter.ujfalusi@nokia.com> 7 * Peter Ujfalusi <peter.ujfalusi@ti.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
@@ -31,7 +31,6 @@
31#include <sound/initval.h> 31#include <sound/initval.h>
32#include <sound/soc.h> 32#include <sound/soc.h>
33 33
34#include <plat/control.h>
35#include <plat/dma.h> 34#include <plat/dma.h>
36#include <plat/mcbsp.h> 35#include <plat/mcbsp.h>
37#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
@@ -62,8 +61,6 @@ struct omap_mcbsp_data {
62 int wlen; 61 int wlen;
63}; 62};
64 63
65#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
66
67static struct omap_mcbsp_data mcbsp_data[NUM_LINKS]; 64static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
68 65
69/* 66/*
@@ -72,94 +69,16 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
72 */ 69 */
73static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2]; 70static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
74 71
75#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
76static const int omap1_dma_reqs[][2] = {
77 { OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
78 { OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
79 { OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
80};
81static const unsigned long omap1_mcbsp_port[][2] = {
82 { OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
83 OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
84 { OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
85 OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
86 { OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
87 OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
88};
89#else
90static const int omap1_dma_reqs[][2] = {};
91static const unsigned long omap1_mcbsp_port[][2] = {};
92#endif
93
94#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
95static const int omap24xx_dma_reqs[][2] = {
96 { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
97 { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
98#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
99 { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
100 { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
101 { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
102#endif
103};
104#else
105static const int omap24xx_dma_reqs[][2] = {};
106#endif
107
108#if defined(CONFIG_ARCH_OMAP2420)
109static const unsigned long omap2420_mcbsp_port[][2] = {
110 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
111 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
112 { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
113 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
114};
115#else
116static const unsigned long omap2420_mcbsp_port[][2] = {};
117#endif
118
119#if defined(CONFIG_ARCH_OMAP2430)
120static const unsigned long omap2430_mcbsp_port[][2] = {
121 { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
122 OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
123 { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
124 OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
125 { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
126 OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
127 { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
128 OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
129 { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
130 OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
131};
132#else
133static const unsigned long omap2430_mcbsp_port[][2] = {};
134#endif
135
136#if defined(CONFIG_ARCH_OMAP3)
137static const unsigned long omap34xx_mcbsp_port[][2] = {
138 { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
139 OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
140 { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
141 OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
142 { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
143 OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
144 { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
145 OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
146 { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
147 OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
148};
149#else
150static const unsigned long omap34xx_mcbsp_port[][2] = {};
151#endif
152
153static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) 72static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
154{ 73{
155 struct snd_soc_pcm_runtime *rtd = substream->private_data; 74 struct snd_soc_pcm_runtime *rtd = substream->private_data;
156 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 75 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
157 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 76 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
158 struct omap_pcm_dma_data *dma_data; 77 struct omap_pcm_dma_data *dma_data;
159 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); 78 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
160 int words; 79 int words;
161 80
162 dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 81 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
163 82
164 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ 83 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
165 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) 84 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
@@ -203,11 +122,9 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
203} 122}
204 123
205static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 124static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
206 struct snd_soc_dai *dai) 125 struct snd_soc_dai *cpu_dai)
207{ 126{
208 struct snd_soc_pcm_runtime *rtd = substream->private_data; 127 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
209 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
210 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
211 int bus_id = mcbsp_data->bus_id; 128 int bus_id = mcbsp_data->bus_id;
212 int err = 0; 129 int err = 0;
213 130
@@ -229,7 +146,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
229 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) 146 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
230 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) 147 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
231 */ 148 */
232 if (cpu_is_omap343x()) { 149 if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
233 /* 150 /*
234 * Rule for the buffer size. We should not allow 151 * Rule for the buffer size. We should not allow
235 * smaller buffer than the FIFO size to avoid underruns 152 * smaller buffer than the FIFO size to avoid underruns
@@ -249,11 +166,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
249} 166}
250 167
251static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, 168static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
252 struct snd_soc_dai *dai) 169 struct snd_soc_dai *cpu_dai)
253{ 170{
254 struct snd_soc_pcm_runtime *rtd = substream->private_data; 171 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
255 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
256 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
257 172
258 if (!cpu_dai->active) { 173 if (!cpu_dai->active) {
259 omap_mcbsp_free(mcbsp_data->bus_id); 174 omap_mcbsp_free(mcbsp_data->bus_id);
@@ -262,11 +177,9 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
262} 177}
263 178
264static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, 179static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
265 struct snd_soc_dai *dai) 180 struct snd_soc_dai *cpu_dai)
266{ 181{
267 struct snd_soc_pcm_runtime *rtd = substream->private_data; 182 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
268 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
269 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
270 int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 183 int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
271 184
272 switch (cmd) { 185 switch (cmd) {
@@ -295,8 +208,8 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
295 struct snd_soc_dai *dai) 208 struct snd_soc_dai *dai)
296{ 209{
297 struct snd_soc_pcm_runtime *rtd = substream->private_data; 210 struct snd_soc_pcm_runtime *rtd = substream->private_data;
298 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 211 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
299 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 212 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
300 u16 fifo_use; 213 u16 fifo_use;
301 snd_pcm_sframes_t delay; 214 snd_pcm_sframes_t delay;
302 215
@@ -317,11 +230,9 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
317 230
318static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, 231static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
319 struct snd_pcm_hw_params *params, 232 struct snd_pcm_hw_params *params,
320 struct snd_soc_dai *dai) 233 struct snd_soc_dai *cpu_dai)
321{ 234{
322 struct snd_soc_pcm_runtime *rtd = substream->private_data; 235 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
323 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
324 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
325 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 236 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
326 struct omap_pcm_dma_data *dma_data; 237 struct omap_pcm_dma_data *dma_data;
327 int dma, bus_id = mcbsp_data->bus_id; 238 int dma, bus_id = mcbsp_data->bus_id;
@@ -331,21 +242,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
331 unsigned int format, div, framesize, master; 242 unsigned int format, div, framesize, master;
332 243
333 dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; 244 dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
334 if (cpu_class_is_omap1()) { 245
335 dma = omap1_dma_reqs[bus_id][substream->stream]; 246 dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream);
336 port = omap1_mcbsp_port[bus_id][substream->stream]; 247 port = omap_mcbsp_dma_reg_params(bus_id, substream->stream);
337 } else if (cpu_is_omap2420()) { 248
338 dma = omap24xx_dma_reqs[bus_id][substream->stream];
339 port = omap2420_mcbsp_port[bus_id][substream->stream];
340 } else if (cpu_is_omap2430()) {
341 dma = omap24xx_dma_reqs[bus_id][substream->stream];
342 port = omap2430_mcbsp_port[bus_id][substream->stream];
343 } else if (cpu_is_omap343x()) {
344 dma = omap24xx_dma_reqs[bus_id][substream->stream];
345 port = omap34xx_mcbsp_port[bus_id][substream->stream];
346 } else {
347 return -ENODEV;
348 }
349 switch (params_format(params)) { 249 switch (params_format(params)) {
350 case SNDRV_PCM_FORMAT_S16_LE: 250 case SNDRV_PCM_FORMAT_S16_LE:
351 dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; 251 dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
@@ -358,7 +258,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
358 default: 258 default:
359 return -EINVAL; 259 return -EINVAL;
360 } 260 }
361 if (cpu_is_omap343x()) { 261 if (cpu_is_omap34xx()) {
362 dma_data->set_threshold = omap_mcbsp_set_threshold; 262 dma_data->set_threshold = omap_mcbsp_set_threshold;
363 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ 263 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
364 if (omap_mcbsp_get_dma_op_mode(bus_id) == 264 if (omap_mcbsp_get_dma_op_mode(bus_id) ==
@@ -496,7 +396,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
496static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, 396static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
497 unsigned int fmt) 397 unsigned int fmt)
498{ 398{
499 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 399 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
500 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 400 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
501 unsigned int temp_fmt = fmt; 401 unsigned int temp_fmt = fmt;
502 402
@@ -509,11 +409,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
509 regs->spcr2 |= XINTM(3) | FREE; 409 regs->spcr2 |= XINTM(3) | FREE;
510 regs->spcr1 |= RINTM(3); 410 regs->spcr1 |= RINTM(3);
511 /* RFIG and XFIG are not defined in 34xx */ 411 /* RFIG and XFIG are not defined in 34xx */
512 if (!cpu_is_omap34xx()) { 412 if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) {
513 regs->rcr2 |= RFIG; 413 regs->rcr2 |= RFIG;
514 regs->xcr2 |= XFIG; 414 regs->xcr2 |= XFIG;
515 } 415 }
516 if (cpu_is_omap2430() || cpu_is_omap34xx()) { 416 if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
517 regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; 417 regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
518 regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; 418 regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
519 } 419 }
@@ -596,7 +496,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
596static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, 496static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
597 int div_id, int div) 497 int div_id, int div)
598{ 498{
599 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 499 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
600 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 500 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
601 501
602 if (div_id != OMAP_MCBSP_CLKGDV) 502 if (div_id != OMAP_MCBSP_CLKGDV)
@@ -608,101 +508,22 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
608 return 0; 508 return 0;
609} 509}
610 510
611static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
612 int clk_id)
613{
614 int sel_bit;
615 u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
616
617 if (cpu_class_is_omap1()) {
618 /* OMAP1's can use only external source clock */
619 if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
620 return -EINVAL;
621 else
622 return 0;
623 }
624
625 if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
626 return -EINVAL;
627
628 if (cpu_is_omap343x())
629 reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
630
631 switch (mcbsp_data->bus_id) {
632 case 0:
633 reg = OMAP2_CONTROL_DEVCONF0;
634 sel_bit = 2;
635 break;
636 case 1:
637 reg = OMAP2_CONTROL_DEVCONF0;
638 sel_bit = 6;
639 break;
640 case 2:
641 reg = reg_devconf1;
642 sel_bit = 0;
643 break;
644 case 3:
645 reg = reg_devconf1;
646 sel_bit = 2;
647 break;
648 case 4:
649 reg = reg_devconf1;
650 sel_bit = 4;
651 break;
652 default:
653 return -EINVAL;
654 }
655
656 if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
657 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
658 else
659 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
660
661 return 0;
662}
663
664static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
665 int clk_id)
666{
667 int sel_bit, set = 0;
668 u16 reg = OMAP2_CONTROL_DEVCONF0;
669
670 if (cpu_class_is_omap1())
671 return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
672 if (mcbsp_data->bus_id != 0)
673 return -EINVAL;
674
675 switch (clk_id) {
676 case OMAP_MCBSP_CLKR_SRC_CLKX:
677 set = 1;
678 case OMAP_MCBSP_CLKR_SRC_CLKR:
679 sel_bit = 3;
680 break;
681 case OMAP_MCBSP_FSR_SRC_FSX:
682 set = 1;
683 case OMAP_MCBSP_FSR_SRC_FSR:
684 sel_bit = 4;
685 break;
686 default:
687 return -EINVAL;
688 }
689
690 if (set)
691 omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
692 else
693 omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
694
695 return 0;
696}
697
698static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 511static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
699 int clk_id, unsigned int freq, 512 int clk_id, unsigned int freq,
700 int dir) 513 int dir)
701{ 514{
702 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 515 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
703 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 516 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
704 int err = 0; 517 int err = 0;
705 518
519 /* The McBSP signal muxing functions are only available on McBSP1 */
520 if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
521 clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
522 clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
523 clk_id == OMAP_MCBSP_FSR_SRC_FSX)
524 if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
525 return -EINVAL;
526
706 mcbsp_data->in_freq = freq; 527 mcbsp_data->in_freq = freq;
707 528
708 switch (clk_id) { 529 switch (clk_id) {
@@ -710,8 +531,20 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
710 regs->srgr2 |= CLKSM; 531 regs->srgr2 |= CLKSM;
711 break; 532 break;
712 case OMAP_MCBSP_SYSCLK_CLKS_FCLK: 533 case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
534 if (cpu_class_is_omap1()) {
535 err = -EINVAL;
536 break;
537 }
538 err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
539 MCBSP_CLKS_PRCM_SRC);
540 break;
713 case OMAP_MCBSP_SYSCLK_CLKS_EXT: 541 case OMAP_MCBSP_SYSCLK_CLKS_EXT:
714 err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id); 542 if (cpu_class_is_omap1()) {
543 err = 0;
544 break;
545 }
546 err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
547 MCBSP_CLKS_PAD_SRC);
715 break; 548 break;
716 549
717 case OMAP_MCBSP_SYSCLK_CLKX_EXT: 550 case OMAP_MCBSP_SYSCLK_CLKX_EXT:
@@ -720,11 +553,26 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
720 regs->pcr0 |= SCLKME; 553 regs->pcr0 |= SCLKME;
721 break; 554 break;
722 555
556
723 case OMAP_MCBSP_CLKR_SRC_CLKR: 557 case OMAP_MCBSP_CLKR_SRC_CLKR:
558 if (cpu_class_is_omap1())
559 break;
560 omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
561 break;
724 case OMAP_MCBSP_CLKR_SRC_CLKX: 562 case OMAP_MCBSP_CLKR_SRC_CLKX:
563 if (cpu_class_is_omap1())
564 break;
565 omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
566 break;
725 case OMAP_MCBSP_FSR_SRC_FSR: 567 case OMAP_MCBSP_FSR_SRC_FSR:
568 if (cpu_class_is_omap1())
569 break;
570 omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
571 break;
726 case OMAP_MCBSP_FSR_SRC_FSX: 572 case OMAP_MCBSP_FSR_SRC_FSX:
727 err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id); 573 if (cpu_class_is_omap1())
574 break;
575 omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
728 break; 576 break;
729 default: 577 default:
730 err = -ENODEV; 578 err = -ENODEV;
@@ -733,7 +581,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
733 return err; 581 return err;
734} 582}
735 583
736static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { 584static struct snd_soc_dai_ops mcbsp_dai_ops = {
737 .startup = omap_mcbsp_dai_startup, 585 .startup = omap_mcbsp_dai_startup,
738 .shutdown = omap_mcbsp_dai_shutdown, 586 .shutdown = omap_mcbsp_dai_shutdown,
739 .trigger = omap_mcbsp_dai_trigger, 587 .trigger = omap_mcbsp_dai_trigger,
@@ -744,43 +592,32 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
744 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, 592 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
745}; 593};
746 594
747#define OMAP_MCBSP_DAI_BUILDER(link_id) \ 595static int mcbsp_dai_probe(struct snd_soc_dai *dai)
748{ \ 596{
749 .name = "omap-mcbsp-dai-"#link_id, \ 597 mcbsp_data[dai->id].bus_id = dai->id;
750 .id = (link_id), \ 598 snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
751 .playback = { \ 599 return 0;
752 .channels_min = 1, \
753 .channels_max = 16, \
754 .rates = OMAP_MCBSP_RATES, \
755 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
756 SNDRV_PCM_FMTBIT_S32_LE, \
757 }, \
758 .capture = { \
759 .channels_min = 1, \
760 .channels_max = 16, \
761 .rates = OMAP_MCBSP_RATES, \
762 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
763 SNDRV_PCM_FMTBIT_S32_LE, \
764 }, \
765 .ops = &omap_mcbsp_dai_ops, \
766 .private_data = &mcbsp_data[(link_id)].bus_id, \
767} 600}
768 601
769struct snd_soc_dai omap_mcbsp_dai[] = { 602static struct snd_soc_dai_driver omap_mcbsp_dai =
770 OMAP_MCBSP_DAI_BUILDER(0), 603{
771 OMAP_MCBSP_DAI_BUILDER(1), 604 .probe = mcbsp_dai_probe,
772#if NUM_LINKS >= 3 605 .playback = {
773 OMAP_MCBSP_DAI_BUILDER(2), 606 .channels_min = 1,
774#endif 607 .channels_max = 16,
775#if NUM_LINKS == 5 608 .rates = OMAP_MCBSP_RATES,
776 OMAP_MCBSP_DAI_BUILDER(3), 609 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
777 OMAP_MCBSP_DAI_BUILDER(4), 610 },
778#endif 611 .capture = {
612 .channels_min = 1,
613 .channels_max = 16,
614 .rates = OMAP_MCBSP_RATES,
615 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
616 },
617 .ops = &mcbsp_dai_ops,
779}; 618};
780 619
781EXPORT_SYMBOL_GPL(omap_mcbsp_dai); 620static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
782
783int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_info *uinfo) 621 struct snd_ctl_elem_info *uinfo)
785{ 622{
786 struct soc_mixer_control *mc = 623 struct soc_mixer_control *mc =
@@ -910,16 +747,36 @@ int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
910} 747}
911EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); 748EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
912 749
750static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
751{
752 return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
753}
754
755static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
756{
757 snd_soc_unregister_dai(&pdev->dev);
758 return 0;
759}
760
761static struct platform_driver asoc_mcbsp_driver = {
762 .driver = {
763 .name = "omap-mcbsp-dai",
764 .owner = THIS_MODULE,
765 },
766
767 .probe = asoc_mcbsp_probe,
768 .remove = __devexit_p(asoc_mcbsp_remove),
769};
770
913static int __init snd_omap_mcbsp_init(void) 771static int __init snd_omap_mcbsp_init(void)
914{ 772{
915 return snd_soc_register_dais(omap_mcbsp_dai, 773 return platform_driver_register(&asoc_mcbsp_driver);
916 ARRAY_SIZE(omap_mcbsp_dai));
917} 774}
918module_init(snd_omap_mcbsp_init); 775module_init(snd_omap_mcbsp_init);
919 776
920static void __exit snd_omap_mcbsp_exit(void) 777static void __exit snd_omap_mcbsp_exit(void)
921{ 778{
922 snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); 779 platform_driver_unregister(&asoc_mcbsp_driver);
923} 780}
924module_exit(snd_omap_mcbsp_exit); 781module_exit(snd_omap_mcbsp_exit);
925 782