• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/sound/soc/omap/
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 <jhnikula@gmail.com>
7 *          Peter Ujfalusi <peter.ujfalusi@nokia.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/control.h>
35#include <plat/dma.h>
36#include <plat/mcbsp.h>
37#include "omap-mcbsp.h"
38#include "omap-pcm.h"
39
40#define OMAP_MCBSP_RATES	(SNDRV_PCM_RATE_8000_96000)
41
42#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
43	xhandler_get, xhandler_put) \
44{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
45	.info = omap_mcbsp_st_info_volsw, \
46	.get = xhandler_get, .put = xhandler_put, \
47	.private_value = (unsigned long) &(struct soc_mixer_control) \
48	{.min = xmin, .max = xmax} }
49
50struct omap_mcbsp_data {
51	unsigned int			bus_id;
52	struct omap_mcbsp_reg_cfg	regs;
53	unsigned int			fmt;
54	/*
55	 * Flags indicating is the bus already activated and configured by
56	 * another substream
57	 */
58	int				active;
59	int				configured;
60	unsigned int			in_freq;
61	int				clk_div;
62	int				wlen;
63};
64
65#define to_mcbsp(priv)	container_of((priv), struct omap_mcbsp_data, bus_id)
66
67static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
68
69/*
70 * Stream DMA parameters. DMA request line and port address are set runtime
71 * since they are different between OMAP1 and later OMAPs
72 */
73static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
74
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)
154{
155	struct snd_soc_pcm_runtime *rtd = substream->private_data;
156	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
157	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
158	struct omap_pcm_dma_data *dma_data;
159	int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
160	int words;
161
162	dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
163
164	/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
165	if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
166		/*
167		 * Configure McBSP threshold based on either:
168		 * packet_size, when the sDMA is in packet mode, or
169		 * based on the period size.
170		 */
171		if (dma_data->packet_size)
172			words = dma_data->packet_size;
173		else
174			words = snd_pcm_lib_period_bytes(substream) /
175							(mcbsp_data->wlen / 8);
176	else
177		words = 1;
178
179	/* Configure McBSP internal buffer usage */
180	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
181		omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
182	else
183		omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
184}
185
186static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
187				    struct snd_pcm_hw_rule *rule)
188{
189	struct snd_interval *buffer_size = hw_param_interval(params,
190					SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
191	struct snd_interval *channels = hw_param_interval(params,
192					SNDRV_PCM_HW_PARAM_CHANNELS);
193	struct omap_mcbsp_data *mcbsp_data = rule->private;
194	struct snd_interval frames;
195	int size;
196
197	snd_interval_any(&frames);
198	size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
199
200	frames.min = size / channels->min;
201	frames.integer = 1;
202	return snd_interval_refine(buffer_size, &frames);
203}
204
205static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
206				  struct snd_soc_dai *dai)
207{
208	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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;
212	int err = 0;
213
214	if (!cpu_dai->active)
215		err = omap_mcbsp_request(bus_id);
216
217	/*
218	 * OMAP3 McBSP FIFO is word structured.
219	 * McBSP2 has 1024 + 256 = 1280 word long buffer,
220	 * McBSP1,3,4,5 has 128 word long buffer
221	 * This means that the size of the FIFO depends on the sample format.
222	 * For example on McBSP3:
223	 * 16bit samples: size is 128 * 2 = 256 bytes
224	 * 32bit samples: size is 128 * 4 = 512 bytes
225	 * It is simpler to place constraint for buffer and period based on
226	 * channels.
227	 * McBSP3 as example again (16 or 32 bit samples):
228	 * 1 channel (mono): size is 128 frames (128 words)
229	 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
230	 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
231	 */
232	if (cpu_is_omap343x()) {
233		/*
234		* Rule for the buffer size. We should not allow
235		* smaller buffer than the FIFO size to avoid underruns
236		*/
237		snd_pcm_hw_rule_add(substream->runtime, 0,
238				    SNDRV_PCM_HW_PARAM_CHANNELS,
239				    omap_mcbsp_hwrule_min_buffersize,
240				    mcbsp_data,
241				    SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
242
243		/* Make sure, that the period size is always even */
244		snd_pcm_hw_constraint_step(substream->runtime, 0,
245					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
246	}
247
248	return err;
249}
250
251static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
252				    struct snd_soc_dai *dai)
253{
254	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
258	if (!cpu_dai->active) {
259		omap_mcbsp_free(mcbsp_data->bus_id);
260		mcbsp_data->configured = 0;
261	}
262}
263
264static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
265				  struct snd_soc_dai *dai)
266{
267	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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);
271
272	switch (cmd) {
273	case SNDRV_PCM_TRIGGER_START:
274	case SNDRV_PCM_TRIGGER_RESUME:
275	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
276		mcbsp_data->active++;
277		omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
278		break;
279
280	case SNDRV_PCM_TRIGGER_STOP:
281	case SNDRV_PCM_TRIGGER_SUSPEND:
282	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
283		omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
284		mcbsp_data->active--;
285		break;
286	default:
287		err = -EINVAL;
288	}
289
290	return err;
291}
292
293static snd_pcm_sframes_t omap_mcbsp_dai_delay(
294			struct snd_pcm_substream *substream,
295			struct snd_soc_dai *dai)
296{
297	struct snd_soc_pcm_runtime *rtd = substream->private_data;
298	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
299	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
300	u16 fifo_use;
301	snd_pcm_sframes_t delay;
302
303	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
304		fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
305	else
306		fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
307
308	/*
309	 * Divide the used locations with the channel count to get the
310	 * FIFO usage in samples (don't care about partial samples in the
311	 * buffer).
312	 */
313	delay = fifo_use / substream->runtime->channels;
314
315	return delay;
316}
317
318static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
319				    struct snd_pcm_hw_params *params,
320				    struct snd_soc_dai *dai)
321{
322	struct snd_soc_pcm_runtime *rtd = substream->private_data;
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;
326	struct omap_pcm_dma_data *dma_data;
327	int dma, bus_id = mcbsp_data->bus_id;
328	int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
329	int pkt_size = 0;
330	unsigned long port;
331	unsigned int format, div, framesize, master;
332
333	dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
334	if (cpu_class_is_omap1()) {
335		dma = omap1_dma_reqs[bus_id][substream->stream];
336		port = omap1_mcbsp_port[bus_id][substream->stream];
337	} else if (cpu_is_omap2420()) {
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)) {
350	case SNDRV_PCM_FORMAT_S16_LE:
351		dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
352		wlen = 16;
353		break;
354	case SNDRV_PCM_FORMAT_S32_LE:
355		dma_data->data_type = OMAP_DMA_DATA_TYPE_S32;
356		wlen = 32;
357		break;
358	default:
359		return -EINVAL;
360	}
361	if (cpu_is_omap343x()) {
362		dma_data->set_threshold = omap_mcbsp_set_threshold;
363		/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
364		if (omap_mcbsp_get_dma_op_mode(bus_id) ==
365						MCBSP_DMA_MODE_THRESHOLD) {
366			int period_words, max_thrsh;
367
368			period_words = params_period_bytes(params) / (wlen / 8);
369			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
370				max_thrsh = omap_mcbsp_get_max_tx_threshold(
371							    mcbsp_data->bus_id);
372			else
373				max_thrsh = omap_mcbsp_get_max_rx_threshold(
374							    mcbsp_data->bus_id);
375			/*
376			 * If the period contains less or equal number of words,
377			 * we are using the original threshold mode setup:
378			 * McBSP threshold = sDMA frame size = period_size
379			 * Otherwise we switch to sDMA packet mode:
380			 * McBSP threshold = sDMA packet size
381			 * sDMA frame size = period size
382			 */
383			if (period_words > max_thrsh) {
384				int divider = 0;
385
386				/*
387				 * Look for the biggest threshold value, which
388				 * divides the period size evenly.
389				 */
390				divider = period_words / max_thrsh;
391				if (period_words % max_thrsh)
392					divider++;
393				while (period_words % divider &&
394					divider < period_words)
395					divider++;
396				if (divider == period_words)
397					return -EINVAL;
398
399				pkt_size = period_words / divider;
400				sync_mode = OMAP_DMA_SYNC_PACKET;
401			} else {
402				sync_mode = OMAP_DMA_SYNC_FRAME;
403			}
404		}
405	}
406
407	dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
408	dma_data->dma_req = dma;
409	dma_data->port_addr = port;
410	dma_data->sync_mode = sync_mode;
411	dma_data->packet_size = pkt_size;
412
413	snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
414
415	if (mcbsp_data->configured) {
416		/* McBSP already configured by another stream */
417		return 0;
418	}
419
420	format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
421	wpf = channels = params_channels(params);
422	if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
423			      format == SND_SOC_DAIFMT_LEFT_J)) {
424		/* Use dual-phase frames */
425		regs->rcr2	|= RPHASE;
426		regs->xcr2	|= XPHASE;
427		/* Set 1 word per (McBSP) frame for phase1 and phase2 */
428		wpf--;
429		regs->rcr2	|= RFRLEN2(wpf - 1);
430		regs->xcr2	|= XFRLEN2(wpf - 1);
431	}
432
433	regs->rcr1	|= RFRLEN1(wpf - 1);
434	regs->xcr1	|= XFRLEN1(wpf - 1);
435
436	switch (params_format(params)) {
437	case SNDRV_PCM_FORMAT_S16_LE:
438		/* Set word lengths */
439		regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_16);
440		regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_16);
441		regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_16);
442		regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_16);
443		break;
444	case SNDRV_PCM_FORMAT_S32_LE:
445		/* Set word lengths */
446		regs->rcr2	|= RWDLEN2(OMAP_MCBSP_WORD_32);
447		regs->rcr1	|= RWDLEN1(OMAP_MCBSP_WORD_32);
448		regs->xcr2	|= XWDLEN2(OMAP_MCBSP_WORD_32);
449		regs->xcr1	|= XWDLEN1(OMAP_MCBSP_WORD_32);
450		break;
451	default:
452		/* Unsupported PCM format */
453		return -EINVAL;
454	}
455
456	/* In McBSP master modes, FRAME (i.e. sample rate) is generated
457	 * by _counting_ BCLKs. Calculate frame size in BCLKs */
458	master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
459	if (master ==	SND_SOC_DAIFMT_CBS_CFS) {
460		div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
461		framesize = (mcbsp_data->in_freq / div) / params_rate(params);
462
463		if (framesize < wlen * channels) {
464			printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
465					"channels\n", __func__);
466			return -EINVAL;
467		}
468	} else
469		framesize = wlen * channels;
470
471	/* Set FS period and length in terms of bit clock periods */
472	switch (format) {
473	case SND_SOC_DAIFMT_I2S:
474	case SND_SOC_DAIFMT_LEFT_J:
475		regs->srgr2	|= FPER(framesize - 1);
476		regs->srgr1	|= FWID((framesize >> 1) - 1);
477		break;
478	case SND_SOC_DAIFMT_DSP_A:
479	case SND_SOC_DAIFMT_DSP_B:
480		regs->srgr2	|= FPER(framesize - 1);
481		regs->srgr1	|= FWID(0);
482		break;
483	}
484
485	omap_mcbsp_config(bus_id, &mcbsp_data->regs);
486	mcbsp_data->wlen = wlen;
487	mcbsp_data->configured = 1;
488
489	return 0;
490}
491
492/*
493 * This must be called before _set_clkdiv and _set_sysclk since McBSP register
494 * cache is initialized here
495 */
496static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
497				      unsigned int fmt)
498{
499	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
500	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
501	unsigned int temp_fmt = fmt;
502
503	if (mcbsp_data->configured)
504		return 0;
505
506	mcbsp_data->fmt = fmt;
507	memset(regs, 0, sizeof(*regs));
508	/* Generic McBSP register settings */
509	regs->spcr2	|= XINTM(3) | FREE;
510	regs->spcr1	|= RINTM(3);
511	/* RFIG and XFIG are not defined in 34xx */
512	if (!cpu_is_omap34xx()) {
513		regs->rcr2	|= RFIG;
514		regs->xcr2	|= XFIG;
515	}
516	if (cpu_is_omap2430() || cpu_is_omap34xx()) {
517		regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
518		regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
519	}
520
521	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
522	case SND_SOC_DAIFMT_I2S:
523		/* 1-bit data delay */
524		regs->rcr2	|= RDATDLY(1);
525		regs->xcr2	|= XDATDLY(1);
526		break;
527	case SND_SOC_DAIFMT_LEFT_J:
528		/* 0-bit data delay */
529		regs->rcr2	|= RDATDLY(0);
530		regs->xcr2	|= XDATDLY(0);
531		regs->spcr1	|= RJUST(2);
532		/* Invert FS polarity configuration */
533		temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
534		break;
535	case SND_SOC_DAIFMT_DSP_A:
536		/* 1-bit data delay */
537		regs->rcr2      |= RDATDLY(1);
538		regs->xcr2      |= XDATDLY(1);
539		/* Invert FS polarity configuration */
540		temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
541		break;
542	case SND_SOC_DAIFMT_DSP_B:
543		/* 0-bit data delay */
544		regs->rcr2      |= RDATDLY(0);
545		regs->xcr2      |= XDATDLY(0);
546		/* Invert FS polarity configuration */
547		temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
548		break;
549	default:
550		/* Unsupported data format */
551		return -EINVAL;
552	}
553
554	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
555	case SND_SOC_DAIFMT_CBS_CFS:
556		/* McBSP master. Set FS and bit clocks as outputs */
557		regs->pcr0	|= FSXM | FSRM |
558				   CLKXM | CLKRM;
559		/* Sample rate generator drives the FS */
560		regs->srgr2	|= FSGM;
561		break;
562	case SND_SOC_DAIFMT_CBM_CFM:
563		/* McBSP slave */
564		break;
565	default:
566		/* Unsupported master/slave configuration */
567		return -EINVAL;
568	}
569
570	/* Set bit clock (CLKX/CLKR) and FS polarities */
571	switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
572	case SND_SOC_DAIFMT_NB_NF:
573		/*
574		 * Normal BCLK + FS.
575		 * FS active low. TX data driven on falling edge of bit clock
576		 * and RX data sampled on rising edge of bit clock.
577		 */
578		regs->pcr0	|= FSXP | FSRP |
579				   CLKXP | CLKRP;
580		break;
581	case SND_SOC_DAIFMT_NB_IF:
582		regs->pcr0	|= CLKXP | CLKRP;
583		break;
584	case SND_SOC_DAIFMT_IB_NF:
585		regs->pcr0	|= FSXP | FSRP;
586		break;
587	case SND_SOC_DAIFMT_IB_IF:
588		break;
589	default:
590		return -EINVAL;
591	}
592
593	return 0;
594}
595
596static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
597				     int div_id, int div)
598{
599	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
600	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
601
602	if (div_id != OMAP_MCBSP_CLKGDV)
603		return -ENODEV;
604
605	mcbsp_data->clk_div = div;
606	regs->srgr1	|= CLKGDV(div - 1);
607
608	return 0;
609}
610
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,
699					 int clk_id, unsigned int freq,
700					 int dir)
701{
702	struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
703	struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
704	int err = 0;
705
706	mcbsp_data->in_freq = freq;
707
708	switch (clk_id) {
709	case OMAP_MCBSP_SYSCLK_CLK:
710		regs->srgr2	|= CLKSM;
711		break;
712	case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
713	case OMAP_MCBSP_SYSCLK_CLKS_EXT:
714		err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
715		break;
716
717	case OMAP_MCBSP_SYSCLK_CLKX_EXT:
718		regs->srgr2	|= CLKSM;
719	case OMAP_MCBSP_SYSCLK_CLKR_EXT:
720		regs->pcr0	|= SCLKME;
721		break;
722
723	case OMAP_MCBSP_CLKR_SRC_CLKR:
724	case OMAP_MCBSP_CLKR_SRC_CLKX:
725	case OMAP_MCBSP_FSR_SRC_FSR:
726	case OMAP_MCBSP_FSR_SRC_FSX:
727		err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
728		break;
729	default:
730		err = -ENODEV;
731	}
732
733	return err;
734}
735
736static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
737	.startup	= omap_mcbsp_dai_startup,
738	.shutdown	= omap_mcbsp_dai_shutdown,
739	.trigger	= omap_mcbsp_dai_trigger,
740	.delay		= omap_mcbsp_dai_delay,
741	.hw_params	= omap_mcbsp_dai_hw_params,
742	.set_fmt	= omap_mcbsp_dai_set_dai_fmt,
743	.set_clkdiv	= omap_mcbsp_dai_set_clkdiv,
744	.set_sysclk	= omap_mcbsp_dai_set_dai_sysclk,
745};
746
747#define OMAP_MCBSP_DAI_BUILDER(link_id)				\
748{								\
749	.name = "omap-mcbsp-dai-"#link_id,			\
750	.id = (link_id),					\
751	.playback = {						\
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}
768
769struct snd_soc_dai omap_mcbsp_dai[] = {
770	OMAP_MCBSP_DAI_BUILDER(0),
771	OMAP_MCBSP_DAI_BUILDER(1),
772#if NUM_LINKS >= 3
773	OMAP_MCBSP_DAI_BUILDER(2),
774#endif
775#if NUM_LINKS == 5
776	OMAP_MCBSP_DAI_BUILDER(3),
777	OMAP_MCBSP_DAI_BUILDER(4),
778#endif
779};
780
781EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
782
783int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
784			struct snd_ctl_elem_info *uinfo)
785{
786	struct soc_mixer_control *mc =
787		(struct soc_mixer_control *)kcontrol->private_value;
788	int max = mc->max;
789	int min = mc->min;
790
791	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
792	uinfo->count = 1;
793	uinfo->value.integer.min = min;
794	uinfo->value.integer.max = max;
795	return 0;
796}
797
798#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel)			\
799static int								\
800omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
801					struct snd_ctl_elem_value *uc)	\
802{									\
803	struct soc_mixer_control *mc =					\
804		(struct soc_mixer_control *)kc->private_value;		\
805	int max = mc->max;						\
806	int min = mc->min;						\
807	int val = uc->value.integer.value[0];				\
808									\
809	if (val < min || val > max)					\
810		return -EINVAL;						\
811									\
812	/* OMAP McBSP implementation uses index values 0..4 */		\
813	return omap_st_set_chgain((id)-1, channel, val);		\
814}
815
816#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel)			\
817static int								\
818omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc,	\
819					struct snd_ctl_elem_value *uc)	\
820{									\
821	s16 chgain;							\
822									\
823	if (omap_st_get_chgain((id)-1, channel, &chgain))		\
824		return -EAGAIN;						\
825									\
826	uc->value.integer.value[0] = chgain;				\
827	return 0;							\
828}
829
830OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
831OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
832OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
833OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
834OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
835OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
836OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
837OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
838
839static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
840				struct snd_ctl_elem_value *ucontrol)
841{
842	struct soc_mixer_control *mc =
843		(struct soc_mixer_control *)kcontrol->private_value;
844	u8 value = ucontrol->value.integer.value[0];
845
846	if (value == omap_st_is_enabled(mc->reg))
847		return 0;
848
849	if (value)
850		omap_st_enable(mc->reg);
851	else
852		omap_st_disable(mc->reg);
853
854	return 1;
855}
856
857static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
858				struct snd_ctl_elem_value *ucontrol)
859{
860	struct soc_mixer_control *mc =
861		(struct soc_mixer_control *)kcontrol->private_value;
862
863	ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
864	return 0;
865}
866
867static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
868	SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0,
869			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
870	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
871				      -32768, 32767,
872				      omap_mcbsp2_get_st_ch0_volume,
873				      omap_mcbsp2_set_st_ch0_volume),
874	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
875				      -32768, 32767,
876				      omap_mcbsp2_get_st_ch1_volume,
877				      omap_mcbsp2_set_st_ch1_volume),
878};
879
880static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
881	SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0,
882			omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
883	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
884				      -32768, 32767,
885				      omap_mcbsp3_get_st_ch0_volume,
886				      omap_mcbsp3_set_st_ch0_volume),
887	OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
888				      -32768, 32767,
889				      omap_mcbsp3_get_st_ch1_volume,
890				      omap_mcbsp3_set_st_ch1_volume),
891};
892
893int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
894{
895	if (!cpu_is_omap34xx())
896		return -ENODEV;
897
898	switch (mcbsp_id) {
899	case 1: /* McBSP 2 */
900		return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
901					ARRAY_SIZE(omap_mcbsp2_st_controls));
902	case 2: /* McBSP 3 */
903		return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
904					ARRAY_SIZE(omap_mcbsp3_st_controls));
905	default:
906		break;
907	}
908
909	return -EINVAL;
910}
911EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
912
913static int __init snd_omap_mcbsp_init(void)
914{
915	return snd_soc_register_dais(omap_mcbsp_dai,
916				     ARRAY_SIZE(omap_mcbsp_dai));
917}
918module_init(snd_omap_mcbsp_init);
919
920static void __exit snd_omap_mcbsp_exit(void)
921{
922	snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
923}
924module_exit(snd_omap_mcbsp_exit);
925
926MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
927MODULE_DESCRIPTION("OMAP I2S SoC Interface");
928MODULE_LICENSE("GPL");
929