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