1 /*
2  * omap-mcbsp.c  --  OMAP ALSA SoC DAI driver using McBSP port
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  *
6  * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
7  *          Peter Ujfalusi <peter.ujfalusi@ti.com>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * version 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/device.h>
28 #include <sound/core.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/initval.h>
32 #include <sound/soc.h>
33 
34 #include <plat/dma.h>
35 #include <plat/mcbsp.h>
36 #include "omap-mcbsp.h"
37 #include "omap-pcm.h"
38 
39 #define OMAP_MCBSP_RATES	(SNDRV_PCM_RATE_8000_96000)
40 
41 #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
42 	xhandler_get, xhandler_put) \
43 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
44 	.info = omap_mcbsp_st_info_volsw, \
45 	.get = xhandler_get, .put = xhandler_put, \
46 	.private_value = (unsigned long) &(struct soc_mixer_control) \
47 	{.min = xmin, .max = xmax} }
48 
49 struct omap_mcbsp_data {
50 	unsigned int			bus_id;
51 	struct omap_mcbsp_reg_cfg	regs;
52 	unsigned int			fmt;
53 	/*
54 	 * Flags indicating is the bus already activated and configured by
55 	 * another substream
56 	 */
57 	int				active;
58 	int				configured;
59 	unsigned int			in_freq;
60 	int				clk_div;
61 	int				wlen;
62 };
63 
64 static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
65 
66 /*
67  * Stream DMA parameters. DMA request line and port address are set runtime
68  * since they are different between OMAP1 and later OMAPs
69  */
70 static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
71 
omap_mcbsp_set_threshold(struct snd_pcm_substream * substream)72 static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
73 {
74 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
75 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
76 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
77 	struct omap_pcm_dma_data *dma_data;
78 	int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
79 	int words;
80 
81 	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
82 
83 	/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
84 	if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
85 		/*
86 		 * Configure McBSP threshold based on either:
87 		 * packet_size, when the sDMA is in packet mode, or
88 		 * based on the period size.
89 		 */
90 		if (dma_data->packet_size)
91 			words = dma_data->packet_size;
92 		else
93 			words = snd_pcm_lib_period_bytes(substream) /
94 							(mcbsp_data->wlen / 8);
95 	else
96 		words = 1;
97 
98 	/* Configure McBSP internal buffer usage */
99 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
100 		omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
101 	else
102 		omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
103 }
104 
omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)105 static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
106 				    struct snd_pcm_hw_rule *rule)
107 {
108 	struct snd_interval *buffer_size = hw_param_interval(params,
109 					SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
110 	struct snd_interval *channels = hw_param_interval(params,
111 					SNDRV_PCM_HW_PARAM_CHANNELS);
112 	struct omap_mcbsp_data *mcbsp_data = rule->private;
113 	struct snd_interval frames;
114 	int size;
115 
116 	snd_interval_any(&frames);
117 	size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
118 
119 	frames.min = size / channels->min;
120 	frames.integer = 1;
121 	return snd_interval_refine(buffer_size, &frames);
122 }
123 
omap_mcbsp_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * cpu_dai)124 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
125 				  struct snd_soc_dai *cpu_dai)
126 {
127 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
128 	int bus_id = mcbsp_data->bus_id;
129 	int err = 0;
130 
131 	if (!cpu_dai->active)
132 		err = omap_mcbsp_request(bus_id);
133 
134 	/*
135 	 * OMAP3 McBSP FIFO is word structured.
136 	 * McBSP2 has 1024 + 256 = 1280 word long buffer,
137 	 * McBSP1,3,4,5 has 128 word long buffer
138 	 * This means that the size of the FIFO depends on the sample format.
139 	 * For example on McBSP3:
140 	 * 16bit samples: size is 128 * 2 = 256 bytes
141 	 * 32bit samples: size is 128 * 4 = 512 bytes
142 	 * It is simpler to place constraint for buffer and period based on
143 	 * channels.
144 	 * McBSP3 as example again (16 or 32 bit samples):
145 	 * 1 channel (mono): size is 128 frames (128 words)
146 	 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
147 	 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
148 	 */
149 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
150 		/*
151 		* Rule for the buffer size. We should not allow
152 		* smaller buffer than the FIFO size to avoid underruns
153 		*/
154 		snd_pcm_hw_rule_add(substream->runtime, 0,
155 				    SNDRV_PCM_HW_PARAM_CHANNELS,
156 				    omap_mcbsp_hwrule_min_buffersize,
157 				    mcbsp_data,
158 				    SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
159 
160 		/* Make sure, that the period size is always even */
161 		snd_pcm_hw_constraint_step(substream->runtime, 0,
162 					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
163 	}
164 
165 	return err;
166 }
167 
omap_mcbsp_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * cpu_dai)168 static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
169 				    struct snd_soc_dai *cpu_dai)
170 {
171 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
172 
173 	if (!cpu_dai->active) {
174 		omap_mcbsp_free(mcbsp_data->bus_id);
175 		mcbsp_data->configured = 0;
176 	}
177 }
178 
omap_mcbsp_dai_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * cpu_dai)179 static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
180 				  struct snd_soc_dai *cpu_dai)
181 {
182 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
183 	int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
184 
185 	switch (cmd) {
186 	case SNDRV_PCM_TRIGGER_START:
187 	case SNDRV_PCM_TRIGGER_RESUME:
188 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
189 		mcbsp_data->active++;
190 		omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
191 		break;
192 
193 	case SNDRV_PCM_TRIGGER_STOP:
194 	case SNDRV_PCM_TRIGGER_SUSPEND:
195 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
196 		omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
197 		mcbsp_data->active--;
198 		break;
199 	default:
200 		err = -EINVAL;
201 	}
202 
203 	return err;
204 }
205 
omap_mcbsp_dai_delay(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)206 static snd_pcm_sframes_t omap_mcbsp_dai_delay(
207 			struct snd_pcm_substream *substream,
208 			struct snd_soc_dai *dai)
209 {
210 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
211 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
212 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
213 	u16 fifo_use;
214 	snd_pcm_sframes_t delay;
215 
216 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
217 		fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
218 	else
219 		fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
220 
221 	/*
222 	 * Divide the used locations with the channel count to get the
223 	 * FIFO usage in samples (don't care about partial samples in the
224 	 * buffer).
225 	 */
226 	delay = fifo_use / substream->runtime->channels;
227 
228 	return delay;
229 }
230 
omap_mcbsp_dai_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * cpu_dai)231 static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
232 				    struct snd_pcm_hw_params *params,
233 				    struct snd_soc_dai *cpu_dai)
234 {
235 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
236 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
237 	struct omap_pcm_dma_data *dma_data;
238 	int dma, bus_id = mcbsp_data->bus_id;
239 	int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
240 	int pkt_size = 0;
241 	unsigned long port;
242 	unsigned int format, div, framesize, master;
243 
244 	dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
245 
246 	dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream);
247 	port = omap_mcbsp_dma_reg_params(bus_id, substream->stream);
248 
249 	switch (params_format(params)) {
250 	case SNDRV_PCM_FORMAT_S16_LE:
251 		dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
252 		wlen = 16;
253 		break;
254 	case SNDRV_PCM_FORMAT_S32_LE:
255 		dma_data->data_type = OMAP_DMA_DATA_TYPE_S32;
256 		wlen = 32;
257 		break;
258 	default:
259 		return -EINVAL;
260 	}
261 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
262 		dma_data->set_threshold = omap_mcbsp_set_threshold;
263 		/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
264 		if (omap_mcbsp_get_dma_op_mode(bus_id) ==
265 						MCBSP_DMA_MODE_THRESHOLD) {
266 			int period_words, max_thrsh;
267 
268 			period_words = params_period_bytes(params) / (wlen / 8);
269 			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
270 				max_thrsh = omap_mcbsp_get_max_tx_threshold(
271 							    mcbsp_data->bus_id);
272 			else
273 				max_thrsh = omap_mcbsp_get_max_rx_threshold(
274 							    mcbsp_data->bus_id);
275 			/*
276 			 * If the period contains less or equal number of words,
277 			 * we are using the original threshold mode setup:
278 			 * McBSP threshold = sDMA frame size = period_size
279 			 * Otherwise we switch to sDMA packet mode:
280 			 * McBSP threshold = sDMA packet size
281 			 * sDMA frame size = period size
282 			 */
283 			if (period_words > max_thrsh) {
284 				int divider = 0;
285 
286 				/*
287 				 * Look for the biggest threshold value, which
288 				 * divides the period size evenly.
289 				 */
290 				divider = period_words / max_thrsh;
291 				if (period_words % max_thrsh)
292 					divider++;
293 				while (period_words % divider &&
294 					divider < period_words)
295 					divider++;
296 				if (divider == period_words)
297 					return -EINVAL;
298 
299 				pkt_size = period_words / divider;
300 				sync_mode = OMAP_DMA_SYNC_PACKET;
301 			} else {
302 				sync_mode = OMAP_DMA_SYNC_FRAME;
303 			}
304 		}
305 	}
306 
307 	dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
308 	dma_data->dma_req = dma;
309 	dma_data->port_addr = port;
310 	dma_data->sync_mode = sync_mode;
311 	dma_data->packet_size = pkt_size;
312 
313 	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
314 
315 	if (mcbsp_data->configured) {
316 		/* McBSP already configured by another stream */
317 		return 0;
318 	}
319 
320 	regs->rcr2	&= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
321 	regs->xcr2	&= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
322 	regs->rcr1	&= ~(RFRLEN1(0x7f) | RWDLEN1(7));
323 	regs->xcr1	&= ~(XFRLEN1(0x7f) | XWDLEN1(7));
324 	format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
325 	wpf = channels = params_channels(params);
326 	if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
327 			      format == SND_SOC_DAIFMT_LEFT_J)) {
328 		/* Use dual-phase frames */
329 		regs->rcr2	|= RPHASE;
330 		regs->xcr2	|= XPHASE;
331 		/* Set 1 word per (McBSP) frame for phase1 and phase2 */
332 		wpf--;
333 		regs->rcr2	|= RFRLEN2(wpf - 1);
334 		regs->xcr2	|= XFRLEN2(wpf - 1);
335 	}
336 
337 	regs->rcr1	|= RFRLEN1(wpf - 1);
338 	regs->xcr1	|= XFRLEN1(wpf - 1);
339 
340 	switch (params_format(params)) {
341 	case SNDRV_PCM_FORMAT_S16_LE:
342 		/* Set word lengths */
343 		regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_16);
344 		regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_16);
345 		regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_16);
346 		regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_16);
347 		break;
348 	case SNDRV_PCM_FORMAT_S32_LE:
349 		/* Set word lengths */
350 		regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_32);
351 		regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_32);
352 		regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_32);
353 		regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_32);
354 		break;
355 	default:
356 		/* Unsupported PCM format */
357 		return -EINVAL;
358 	}
359 
360 	/* In McBSP master modes, FRAME (i.e. sample rate) is generated
361 	 * by _counting_ BCLKs. Calculate frame size in BCLKs */
362 	master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
363 	if (master ==	SND_SOC_DAIFMT_CBS_CFS) {
364 		div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
365 		framesize = (mcbsp_data->in_freq / div) / params_rate(params);
366 
367 		if (framesize < wlen * channels) {
368 			printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
369 					"channels\n", __func__);
370 			return -EINVAL;
371 		}
372 	} else
373 		framesize = wlen * channels;
374 
375 	/* Set FS period and length in terms of bit clock periods */
376 	regs->srgr2	&= ~FPER(0xfff);
377 	regs->srgr1	&= ~FWID(0xff);
378 	switch (format) {
379 	case SND_SOC_DAIFMT_I2S:
380 	case SND_SOC_DAIFMT_LEFT_J:
381 		regs->srgr2	|= FPER(framesize - 1);
382 		regs->srgr1	|= FWID((framesize >> 1) - 1);
383 		break;
384 	case SND_SOC_DAIFMT_DSP_A:
385 	case SND_SOC_DAIFMT_DSP_B:
386 		regs->srgr2	|= FPER(framesize - 1);
387 		regs->srgr1	|= FWID(0);
388 		break;
389 	}
390 
391 	omap_mcbsp_config(bus_id, &mcbsp_data->regs);
392 	mcbsp_data->wlen = wlen;
393 	mcbsp_data->configured = 1;
394 
395 	return 0;
396 }
397 
398 /*
399  * This must be called before _set_clkdiv and _set_sysclk since McBSP register
400  * cache is initialized here
401  */
omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai * cpu_dai,unsigned int fmt)402 static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
403 				      unsigned int fmt)
404 {
405 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
406 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
407 	bool inv_fs = false;
408 
409 	if (mcbsp_data->configured)
410 		return 0;
411 
412 	mcbsp_data->fmt = fmt;
413 	memset(regs, 0, sizeof(*regs));
414 	/* Generic McBSP register settings */
415 	regs->spcr2	|= XINTM(3) | FREE;
416 	regs->spcr1	|= RINTM(3);
417 	/* RFIG and XFIG are not defined in 34xx */
418 	if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) {
419 		regs->rcr2	|= RFIG;
420 		regs->xcr2	|= XFIG;
421 	}
422 	if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
423 		regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
424 		regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
425 	}
426 
427 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
428 	case SND_SOC_DAIFMT_I2S:
429 		/* 1-bit data delay */
430 		regs->rcr2	|= RDATDLY(1);
431 		regs->xcr2	|= XDATDLY(1);
432 		break;
433 	case SND_SOC_DAIFMT_LEFT_J:
434 		/* 0-bit data delay */
435 		regs->rcr2	|= RDATDLY(0);
436 		regs->xcr2	|= XDATDLY(0);
437 		regs->spcr1	|= RJUST(2);
438 		/* Invert FS polarity configuration */
439 		inv_fs = true;
440 		break;
441 	case SND_SOC_DAIFMT_DSP_A:
442 		/* 1-bit data delay */
443 		regs->rcr2      |= RDATDLY(1);
444 		regs->xcr2      |= XDATDLY(1);
445 		/* Invert FS polarity configuration */
446 		inv_fs = true;
447 		break;
448 	case SND_SOC_DAIFMT_DSP_B:
449 		/* 0-bit data delay */
450 		regs->rcr2      |= RDATDLY(0);
451 		regs->xcr2      |= XDATDLY(0);
452 		/* Invert FS polarity configuration */
453 		inv_fs = true;
454 		break;
455 	default:
456 		/* Unsupported data format */
457 		return -EINVAL;
458 	}
459 
460 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
461 	case SND_SOC_DAIFMT_CBS_CFS:
462 		/* McBSP master. Set FS and bit clocks as outputs */
463 		regs->pcr0	|= FSXM | FSRM |
464 				   CLKXM | CLKRM;
465 		/* Sample rate generator drives the FS */
466 		regs->srgr2	|= FSGM;
467 		break;
468 	case SND_SOC_DAIFMT_CBM_CFM:
469 		/* McBSP slave */
470 		break;
471 	default:
472 		/* Unsupported master/slave configuration */
473 		return -EINVAL;
474 	}
475 
476 	/* Set bit clock (CLKX/CLKR) and FS polarities */
477 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
478 	case SND_SOC_DAIFMT_NB_NF:
479 		/*
480 		 * Normal BCLK + FS.
481 		 * FS active low. TX data driven on falling edge of bit clock
482 		 * and RX data sampled on rising edge of bit clock.
483 		 */
484 		regs->pcr0	|= FSXP | FSRP |
485 				   CLKXP | CLKRP;
486 		break;
487 	case SND_SOC_DAIFMT_NB_IF:
488 		regs->pcr0	|= CLKXP | CLKRP;
489 		break;
490 	case SND_SOC_DAIFMT_IB_NF:
491 		regs->pcr0	|= FSXP | FSRP;
492 		break;
493 	case SND_SOC_DAIFMT_IB_IF:
494 		break;
495 	default:
496 		return -EINVAL;
497 	}
498 	if (inv_fs == true)
499 		regs->pcr0 ^= FSXP | FSRP;
500 
501 	return 0;
502 }
503 
omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai * cpu_dai,int div_id,int div)504 static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
505 				     int div_id, int div)
506 {
507 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
508 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
509 
510 	if (div_id != OMAP_MCBSP_CLKGDV)
511 		return -ENODEV;
512 
513 	mcbsp_data->clk_div = div;
514 	regs->srgr1	&= ~CLKGDV(0xff);
515 	regs->srgr1	|= CLKGDV(div - 1);
516 
517 	return 0;
518 }
519 
omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai * cpu_dai,int clk_id,unsigned int freq,int dir)520 static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
521 					 int clk_id, unsigned int freq,
522 					 int dir)
523 {
524 	struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
525 	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
526 	int err = 0;
527 
528 	if (mcbsp_data->active) {
529 		if (freq == mcbsp_data->in_freq)
530 			return 0;
531 		else
532 			return -EBUSY;
533 	}
534 
535 	/* The McBSP signal muxing functions are only available on McBSP1 */
536 	if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
537 	    clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
538 	    clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
539 	    clk_id == OMAP_MCBSP_FSR_SRC_FSX)
540 		if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
541 			return -EINVAL;
542 
543 	mcbsp_data->in_freq = freq;
544 	regs->srgr2	&= ~CLKSM;
545 	regs->pcr0	&= ~SCLKME;
546 
547 	switch (clk_id) {
548 	case OMAP_MCBSP_SYSCLK_CLK:
549 		regs->srgr2	|= CLKSM;
550 		break;
551 	case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
552 		if (cpu_class_is_omap1()) {
553 			err = -EINVAL;
554 			break;
555 		}
556 		err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
557 					       MCBSP_CLKS_PRCM_SRC);
558 		break;
559 	case OMAP_MCBSP_SYSCLK_CLKS_EXT:
560 		if (cpu_class_is_omap1()) {
561 			err = 0;
562 			break;
563 		}
564 		err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
565 					       MCBSP_CLKS_PAD_SRC);
566 		break;
567 
568 	case OMAP_MCBSP_SYSCLK_CLKX_EXT:
569 		regs->srgr2	|= CLKSM;
570 	case OMAP_MCBSP_SYSCLK_CLKR_EXT:
571 		regs->pcr0	|= SCLKME;
572 		break;
573 
574 
575 	case OMAP_MCBSP_CLKR_SRC_CLKR:
576 		if (cpu_class_is_omap1())
577 			break;
578 		omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
579 		break;
580 	case OMAP_MCBSP_CLKR_SRC_CLKX:
581 		if (cpu_class_is_omap1())
582 			break;
583 		omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
584 		break;
585 	case OMAP_MCBSP_FSR_SRC_FSR:
586 		if (cpu_class_is_omap1())
587 			break;
588 		omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
589 		break;
590 	case OMAP_MCBSP_FSR_SRC_FSX:
591 		if (cpu_class_is_omap1())
592 			break;
593 		omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
594 		break;
595 	default:
596 		err = -ENODEV;
597 	}
598 
599 	return err;
600 }
601 
602 static const struct snd_soc_dai_ops mcbsp_dai_ops = {
603 	.startup	= omap_mcbsp_dai_startup,
604 	.shutdown	= omap_mcbsp_dai_shutdown,
605 	.trigger	= omap_mcbsp_dai_trigger,
606 	.delay		= omap_mcbsp_dai_delay,
607 	.hw_params	= omap_mcbsp_dai_hw_params,
608 	.set_fmt	= omap_mcbsp_dai_set_dai_fmt,
609 	.set_clkdiv	= omap_mcbsp_dai_set_clkdiv,
610 	.set_sysclk	= omap_mcbsp_dai_set_dai_sysclk,
611 };
612 
mcbsp_dai_probe(struct snd_soc_dai * dai)613 static int mcbsp_dai_probe(struct snd_soc_dai *dai)
614 {
615 	mcbsp_data[dai->id].bus_id = dai->id;
616 	snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
617 	return 0;
618 }
619 
620 static struct snd_soc_dai_driver omap_mcbsp_dai = {
621 	.probe = mcbsp_dai_probe,
622 	.playback = {
623 		.channels_min = 1,
624 		.channels_max = 16,
625 		.rates = OMAP_MCBSP_RATES,
626 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
627 	},
628 	.capture = {
629 		.channels_min = 1,
630 		.channels_max = 16,
631 		.rates = OMAP_MCBSP_RATES,
632 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
633 	},
634 	.ops = &mcbsp_dai_ops,
635 };
636 
omap_mcbsp_st_info_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)637 static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
638 			struct snd_ctl_elem_info *uinfo)
639 {
640 	struct soc_mixer_control *mc =
641 		(struct soc_mixer_control *)kcontrol->private_value;
642 	int max = mc->max;
643 	int min = mc->min;
644 
645 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
646 	uinfo->count = 1;
647 	uinfo->value.integer.min = min;
648 	uinfo->value.integer.max = max;
649 	return 0;
650 }
651 
652 #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel)			\
653 static int								\
654 omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
655 					struct snd_ctl_elem_value *uc)	\
656 {									\
657 	struct soc_mixer_control *mc =					\
658 		(struct soc_mixer_control *)kc->private_value;		\
659 	int max = mc->max;						\
660 	int min = mc->min;						\
661 	int val = uc->value.integer.value[0];				\
662 									\
663 	if (val < min || val > max)					\
664 		return -EINVAL;						\
665 									\
666 	/* OMAP McBSP implementation uses index values 0..4 */		\
667 	return omap_st_set_chgain((id)-1, channel, val);		\
668 }
669 
670 #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel)			\
671 static int								\
672 omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
673 					struct snd_ctl_elem_value *uc)	\
674 {									\
675 	s16 chgain;							\
676 									\
677 	if (omap_st_get_chgain((id)-1, channel, &chgain))		\
678 		return -EAGAIN;						\
679 									\
680 	uc->value.integer.value[0] = chgain;				\
681 	return 0;							\
682 }
683 
684 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
685 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
686 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
687 OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
688 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
689 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
690 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
691 OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
692 
omap_mcbsp_st_put_mode(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)693 static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
694 				struct snd_ctl_elem_value *ucontrol)
695 {
696 	struct soc_mixer_control *mc =
697 		(struct soc_mixer_control *)kcontrol->private_value;
698 	u8 value = ucontrol->value.integer.value[0];
699 
700 	if (value == omap_st_is_enabled(mc->reg))
701 		return 0;
702 
703 	if (value)
704 		omap_st_enable(mc->reg);
705 	else
706 		omap_st_disable(mc->reg);
707 
708 	return 1;
709 }
710 
omap_mcbsp_st_get_mode(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)711 static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
712 				struct snd_ctl_elem_value *ucontrol)
713 {
714 	struct soc_mixer_control *mc =
715 		(struct soc_mixer_control *)kcontrol->private_value;
716 
717 	ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
718 	return 0;
719 }
720 
721 static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
722 	SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0,
723 			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
724 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
725 				      -32768, 32767,
726 				      omap_mcbsp2_get_st_ch0_volume,
727 				      omap_mcbsp2_set_st_ch0_volume),
728 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
729 				      -32768, 32767,
730 				      omap_mcbsp2_get_st_ch1_volume,
731 				      omap_mcbsp2_set_st_ch1_volume),
732 };
733 
734 static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
735 	SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0,
736 			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
737 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
738 				      -32768, 32767,
739 				      omap_mcbsp3_get_st_ch0_volume,
740 				      omap_mcbsp3_set_st_ch0_volume),
741 	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
742 				      -32768, 32767,
743 				      omap_mcbsp3_get_st_ch1_volume,
744 				      omap_mcbsp3_set_st_ch1_volume),
745 };
746 
omap_mcbsp_st_add_controls(struct snd_soc_codec * codec,int mcbsp_id)747 int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
748 {
749 	if (!cpu_is_omap34xx())
750 		return -ENODEV;
751 
752 	switch (mcbsp_id) {
753 	case 1: /* McBSP 2 */
754 		return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
755 					ARRAY_SIZE(omap_mcbsp2_st_controls));
756 	case 2: /* McBSP 3 */
757 		return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
758 					ARRAY_SIZE(omap_mcbsp3_st_controls));
759 	default:
760 		break;
761 	}
762 
763 	return -EINVAL;
764 }
765 EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
766 
asoc_mcbsp_probe(struct platform_device * pdev)767 static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
768 {
769 	return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
770 }
771 
asoc_mcbsp_remove(struct platform_device * pdev)772 static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
773 {
774 	snd_soc_unregister_dai(&pdev->dev);
775 	return 0;
776 }
777 
778 static struct platform_driver asoc_mcbsp_driver = {
779 	.driver = {
780 			.name = "omap-mcbsp-dai",
781 			.owner = THIS_MODULE,
782 	},
783 
784 	.probe = asoc_mcbsp_probe,
785 	.remove = __devexit_p(asoc_mcbsp_remove),
786 };
787 
788 module_platform_driver(asoc_mcbsp_driver);
789 
790 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
791 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
792 MODULE_LICENSE("GPL");
793