935 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor4 *5 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>6 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>7 *8 * DT support (c) 2016 Petr Kulhavy, Barix AG <petr@barix.com>9 * based on davinci-mcasp.c DT support10 *11 * TODO:12 * on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers13 */14 15#include <linux/init.h>16#include <linux/module.h>17#include <linux/device.h>18#include <linux/slab.h>19#include <linux/delay.h>20#include <linux/io.h>21#include <linux/clk.h>22 23#include <sound/core.h>24#include <sound/pcm.h>25#include <sound/pcm_params.h>26#include <sound/initval.h>27#include <sound/soc.h>28#include <sound/dmaengine_pcm.h>29 30#include "edma-pcm.h"31#include "davinci-i2s.h"32 33#define DRV_NAME "davinci-i2s"34 35/*36 * NOTE: terminology here is confusing.37 *38 * - This driver supports the "Audio Serial Port" (ASP),39 * found on dm6446, dm355, and other DaVinci chips.40 *41 * - But it labels it a "Multi-channel Buffered Serial Port"42 * (McBSP) as on older chips like the dm642 ... which was43 * backward-compatible, possibly explaining that confusion.44 *45 * - OMAP chips have a controller called McBSP, which is46 * incompatible with the DaVinci flavor of McBSP.47 *48 * - Newer DaVinci chips have a controller called McASP,49 * incompatible with ASP and with either McBSP.50 *51 * In short: this uses ASP to implement I2S, not McBSP.52 * And it won't be the only DaVinci implemention of I2S.53 */54#define DAVINCI_MCBSP_DRR_REG 0x0055#define DAVINCI_MCBSP_DXR_REG 0x0456#define DAVINCI_MCBSP_SPCR_REG 0x0857#define DAVINCI_MCBSP_RCR_REG 0x0c58#define DAVINCI_MCBSP_XCR_REG 0x1059#define DAVINCI_MCBSP_SRGR_REG 0x1460#define DAVINCI_MCBSP_PCR_REG 0x2461 62#define DAVINCI_MCBSP_SPCR_RRST (1 << 0)63#define DAVINCI_MCBSP_SPCR_RINTM(v) ((v) << 4)64#define DAVINCI_MCBSP_SPCR_RJUST(v) ((v) << 13)65#define DAVINCI_MCBSP_SPCR_RJUST_Z_LE DAVINCI_MCBSP_SPCR_RJUST(0)66#define DAVINCI_MCBSP_SPCR_RJUST_S_LE DAVINCI_MCBSP_SPCR_RJUST(1)67#define DAVINCI_MCBSP_SPCR_XRST (1 << 16)68#define DAVINCI_MCBSP_SPCR_XINTM(v) ((v) << 20)69#define DAVINCI_MCBSP_SPCR_GRST (1 << 22)70#define DAVINCI_MCBSP_SPCR_FRST (1 << 23)71#define DAVINCI_MCBSP_SPCR_FREE (1 << 25)72 73#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5)74#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8)75#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16)76#define DAVINCI_MCBSP_RCR_RFIG (1 << 18)77#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21)78#define DAVINCI_MCBSP_RCR_RFRLEN2(v) ((v) << 24)79#define DAVINCI_MCBSP_RCR_RPHASE BIT(31)80 81#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5)82#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8)83#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16)84#define DAVINCI_MCBSP_XCR_XFIG (1 << 18)85#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21)86#define DAVINCI_MCBSP_XCR_XFRLEN2(v) ((v) << 24)87#define DAVINCI_MCBSP_XCR_XPHASE BIT(31)88 89#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8)90#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16)91#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28)92#define DAVINCI_MCBSP_SRGR_CLKSM BIT(29)93 94#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0)95#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)96#define DAVINCI_MCBSP_PCR_FSRP (1 << 2)97#define DAVINCI_MCBSP_PCR_FSXP (1 << 3)98#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7)99#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8)100#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9)101#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)102#define DAVINCI_MCBSP_PCR_FSXM (1 << 11)103 104enum {105 DAVINCI_MCBSP_WORD_8 = 0,106 DAVINCI_MCBSP_WORD_12,107 DAVINCI_MCBSP_WORD_16,108 DAVINCI_MCBSP_WORD_20,109 DAVINCI_MCBSP_WORD_24,110 DAVINCI_MCBSP_WORD_32,111};112 113static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = {114 [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8,115 [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16,116 [SNDRV_PCM_FORMAT_S24_LE] = DAVINCI_MCBSP_WORD_24,117 [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32,118};119 120static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {121 [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE,122 [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE,123};124 125struct davinci_mcbsp_dev {126 struct device *dev;127 struct snd_dmaengine_dai_dma_data dma_data[2];128 int dma_request[2];129 void __iomem *base;130#define MOD_DSP_A 0131#define MOD_DSP_B 1132 int mode;133 u32 pcr;134 struct clk *clk;135 struct clk *ext_clk;136 /*137 * Combining both channels into 1 element will at least double the138 * amount of time between servicing the dma channel, increase139 * effiency, and reduce the chance of overrun/underrun. But,140 * it will result in the left & right channels being swapped.141 *142 * If relabeling the left and right channels is not possible,143 * you may want to let the codec know to swap them back.144 *145 * It may allow x10 the amount of time to service dma requests,146 * if the codec is master and is using an unnecessarily fast bit clock147 * (ie. tlvaic23b), independent of the sample rate. So, having an148 * entire frame at once means it can be serviced at the sample rate149 * instead of the bit clock rate.150 *151 * In the now unlikely case that an underrun still152 * occurs, both the left and right samples will be repeated153 * so that no pops are heard, and the left and right channels154 * won't end up being swapped because of the underrun.155 */156 unsigned enable_channel_combine:1;157 158 unsigned int fmt;159 int clk_div;160 bool i2s_accurate_sck;161 162 int tdm_slots;163 int slot_width;164 165 bool tx_framing_bit;166 bool rx_framing_bit;167};168 169static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,170 int reg, u32 val)171{172 __raw_writel(val, dev->base + reg);173}174 175static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)176{177 return __raw_readl(dev->base + reg);178}179 180static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)181{182 u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;183 /* The clock needs to toggle to complete reset.184 * So, fake it by toggling the clk polarity.185 */186 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);187 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);188}189 190static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,191 struct snd_pcm_substream *substream)192{193 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);194 u32 spcr;195 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;196 197 /* Enable transmitter or receiver */198 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);199 spcr |= mask;200 201 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {202 /* Start frame sync */203 spcr |= DAVINCI_MCBSP_SPCR_FRST;204 }205 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);206}207 208static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)209{210 u32 spcr;211 212 /* Reset transmitter/receiver and sample rate/frame sync generators */213 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);214 spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);215 spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;216 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);217 toggle_clock(dev, playback);218}219 220static int davinci_i2s_tdm_word_length(int tdm_slot_width)221{222 switch (tdm_slot_width) {223 case 8:224 return DAVINCI_MCBSP_WORD_8;225 case 12:226 return DAVINCI_MCBSP_WORD_12;227 case 16:228 return DAVINCI_MCBSP_WORD_16;229 case 20:230 return DAVINCI_MCBSP_WORD_20;231 case 24:232 return DAVINCI_MCBSP_WORD_24;233 case 32:234 return DAVINCI_MCBSP_WORD_32;235 default:236 return -EINVAL;237 }238}239 240static int davinci_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,241 unsigned int tx_mask,242 unsigned int rx_mask,243 int slots, int slot_width)244{245 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);246 247 dev_dbg(dev->dev, "slots %d, slot_width %d\n", slots, slot_width);248 249 if (slots > 128 || !slots) {250 dev_err(dev->dev, "Invalid number of slots\n");251 return -EINVAL;252 }253 254 if (rx_mask != (1 << slots) - 1) {255 dev_err(dev->dev, "Invalid RX mask (0x%08x) : all slots must be used by McBSP\n",256 rx_mask);257 return -EINVAL;258 }259 260 if (tx_mask != (1 << slots) - 1) {261 dev_err(dev->dev, "Invalid TX mask (0x%08x) : all slots must be used by McBSP\n",262 tx_mask);263 return -EINVAL;264 }265 266 if (davinci_i2s_tdm_word_length(slot_width) < 0) {267 dev_err(dev->dev, "%s: Unsupported slot_width %d\n", __func__, slot_width);268 return -EINVAL;269 }270 271 dev->tdm_slots = slots;272 dev->slot_width = slot_width;273 274 return 0;275}276 277#define DEFAULT_BITPERSAMPLE 16278 279static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,280 unsigned int fmt)281{282 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);283 unsigned int pcr;284 unsigned int spcr;285 unsigned int srgr;286 bool inv_fs = false;287 /* Attention srgr is updated by hw_params! */288 srgr = DAVINCI_MCBSP_SRGR_FSGM |289 DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |290 DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);291 292 dev->fmt = fmt;293 294 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);295 switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {296 case SND_SOC_DAIFMT_CONT:297 spcr |= DAVINCI_MCBSP_SPCR_FREE;298 dev_dbg(dev->dev, "Free-running mode ON\n");299 break;300 case SND_SOC_DAIFMT_GATED:301 spcr &= ~DAVINCI_MCBSP_SPCR_FREE;302 dev_dbg(dev->dev, "Free-running mode OFF\n");303 break;304 default:305 dev_err(dev->dev, "Invalid clock gating\n");306 return -EINVAL;307 }308 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);309 310 /* set master/slave audio interface */311 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {312 case SND_SOC_DAIFMT_BP_FP:313 /* cpu is master */314 pcr = DAVINCI_MCBSP_PCR_FSXM |315 DAVINCI_MCBSP_PCR_FSRM |316 DAVINCI_MCBSP_PCR_CLKXM |317 DAVINCI_MCBSP_PCR_CLKRM;318 break;319 case SND_SOC_DAIFMT_BC_FP:320 if (dev->tdm_slots || dev->slot_width) {321 dev_err(dev->dev, "TDM is not supported for BC_FP format\n");322 return -EINVAL;323 }324 325 /*326 * McBSP CLKR pin is the input for the Sample Rate Generator.327 * McBSP FSR and FSX are driven by the Sample Rate Generator.328 */329 pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;330 pcr |= DAVINCI_MCBSP_PCR_SCLKME;331 break;332 case SND_SOC_DAIFMT_BP_FC:333 /* cpu is bitclock provider */334 pcr = DAVINCI_MCBSP_PCR_CLKXM |335 DAVINCI_MCBSP_PCR_CLKRM;336 break;337 338 case SND_SOC_DAIFMT_BC_FC:339 if (dev->tdm_slots || dev->slot_width) {340 dev_err(dev->dev, "TDM is not supported for BC_FC format\n");341 return -EINVAL;342 }343 344 /* codec is master */345 pcr = 0;346 break;347 default:348 printk(KERN_ERR "%s:bad master\n", __func__);349 return -EINVAL;350 }351 352 /* interface format */353 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {354 case SND_SOC_DAIFMT_I2S:355 /* Davinci doesn't support TRUE I2S, but some codecs will have356 * the left and right channels contiguous. This allows357 * dsp_a mode to be used with an inverted normal frame clk.358 * If your codec is master and does not have contiguous359 * channels, then you will have sound on only one channel.360 * Try using a different mode, or codec as slave.361 *362 * The TLV320AIC33 is an example of a codec where this works.363 * It has a variable bit clock frequency allowing it to have364 * valid data on every bit clock.365 *366 * The TLV320AIC23 is an example of a codec where this does not367 * work. It has a fixed bit clock frequency with progressively368 * more empty bit clock slots between channels as the sample369 * rate is lowered.370 */371 inv_fs = true;372 fallthrough;373 case SND_SOC_DAIFMT_DSP_A:374 dev->mode = MOD_DSP_A;375 break;376 case SND_SOC_DAIFMT_DSP_B:377 dev->mode = MOD_DSP_B;378 break;379 default:380 printk(KERN_ERR "%s:bad format\n", __func__);381 return -EINVAL;382 }383 384 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {385 case SND_SOC_DAIFMT_NB_NF:386 /* CLKRP Receive clock polarity,387 * 1 - sampled on rising edge of CLKR388 * valid on rising edge389 * CLKXP Transmit clock polarity,390 * 1 - clocked on falling edge of CLKX391 * valid on rising edge392 * FSRP Receive frame sync pol, 0 - active high393 * FSXP Transmit frame sync pol, 0 - active high394 */395 pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP);396 break;397 case SND_SOC_DAIFMT_IB_IF:398 /* CLKRP Receive clock polarity,399 * 0 - sampled on falling edge of CLKR400 * valid on falling edge401 * CLKXP Transmit clock polarity,402 * 0 - clocked on rising edge of CLKX403 * valid on falling edge404 * FSRP Receive frame sync pol, 1 - active low405 * FSXP Transmit frame sync pol, 1 - active low406 */407 pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);408 break;409 case SND_SOC_DAIFMT_NB_IF:410 /* CLKRP Receive clock polarity,411 * 1 - sampled on rising edge of CLKR412 * valid on rising edge413 * CLKXP Transmit clock polarity,414 * 1 - clocked on falling edge of CLKX415 * valid on rising edge416 * FSRP Receive frame sync pol, 1 - active low417 * FSXP Transmit frame sync pol, 1 - active low418 */419 pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP |420 DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);421 break;422 case SND_SOC_DAIFMT_IB_NF:423 /* CLKRP Receive clock polarity,424 * 0 - sampled on falling edge of CLKR425 * valid on falling edge426 * CLKXP Transmit clock polarity,427 * 0 - clocked on rising edge of CLKX428 * valid on falling edge429 * FSRP Receive frame sync pol, 0 - active high430 * FSXP Transmit frame sync pol, 0 - active high431 */432 break;433 default:434 return -EINVAL;435 }436 if (inv_fs == true)437 pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);438 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);439 dev->pcr = pcr;440 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);441 return 0;442}443 444static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,445 int div_id, int div)446{447 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);448 449 if (div_id != DAVINCI_MCBSP_CLKGDV)450 return -ENODEV;451 452 dev->clk_div = div;453 return 0;454}455 456static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,457 struct snd_pcm_hw_params *params,458 struct snd_soc_dai *dai)459{460 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);461 struct snd_interval *i = NULL;462 int mcbsp_word_length, master;463 unsigned int clk_div, freq, framesize;464 unsigned int srgr = 0;465 unsigned int rcr = 0;466 unsigned int xcr = 0;467 u32 spcr;468 snd_pcm_format_t fmt;469 unsigned element_cnt = 1;470 471 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);472 473 /* Determine xfer data type */474 fmt = params_format(params);475 switch (fmt) {476 case SNDRV_PCM_FORMAT_S16_LE:477 case SNDRV_PCM_FORMAT_S32_LE:478 break;479 case SNDRV_PCM_FORMAT_S24_LE:480 spcr |= DAVINCI_MCBSP_SPCR_RJUST_S_LE;481 break;482 default:483 dev_warn(dev->dev, "davinci-i2s: unsupported PCM format\n");484 return -EINVAL;485 }486 487 /* general line settings */488 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {489 spcr |= DAVINCI_MCBSP_SPCR_RINTM(3);490 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);491 } else {492 spcr |= DAVINCI_MCBSP_SPCR_XINTM(3);493 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);494 }495 496 master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;497 fmt = params_format(params);498 if (dev->slot_width)499 mcbsp_word_length = davinci_i2s_tdm_word_length(dev->slot_width);500 else501 mcbsp_word_length = asp_word_length[fmt];502 503 if (mcbsp_word_length < 0)504 return mcbsp_word_length;505 506 switch (master) {507 case SND_SOC_DAIFMT_BP_FP:508 if (dev->ext_clk) {509 freq = clk_get_rate(dev->ext_clk);510 } else {511 freq = clk_get_rate(dev->clk);512 srgr = DAVINCI_MCBSP_SRGR_CLKSM;513 }514 srgr |= DAVINCI_MCBSP_SRGR_FSGM;515 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *516 8 - 1);517 if (dev->i2s_accurate_sck) {518 clk_div = 256;519 do {520 framesize = (freq / (--clk_div)) /521 params->rate_num *522 params->rate_den;523 } while (((framesize < 33) || (framesize > 4095)) &&524 (clk_div));525 clk_div--;526 srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);527 } else {528 /* symmetric waveforms */529 clk_div = freq / (mcbsp_word_length * 16) /530 params->rate_num * params->rate_den;531 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *532 16 - 1);533 }534 clk_div &= 0xFF;535 srgr |= clk_div;536 break;537 case SND_SOC_DAIFMT_BC_FP:538 srgr = DAVINCI_MCBSP_SRGR_FSGM;539 clk_div = dev->clk_div - 1;540 srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);541 srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);542 clk_div &= 0xFF;543 srgr |= clk_div;544 break;545 case SND_SOC_DAIFMT_BP_FC:546 if (dev->ext_clk) {547 freq = clk_get_rate(dev->ext_clk);548 } else {549 freq = clk_get_rate(dev->clk);550 srgr = DAVINCI_MCBSP_SRGR_CLKSM;551 }552 if (dev->tdm_slots && dev->slot_width) {553 clk_div = freq / (params->rate_num * params->rate_den)554 / (dev->tdm_slots * dev->slot_width) - 1;555 } else {556 clk_div = freq / (mcbsp_word_length * 16) /557 params->rate_num * params->rate_den;558 }559 clk_div &= 0xFF;560 srgr |= clk_div;561 break;562 case SND_SOC_DAIFMT_BC_FC:563 /* Clock and frame sync given from external sources */564 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);565 srgr = DAVINCI_MCBSP_SRGR_FSGM;566 srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);567 pr_debug("%s - %d FWID set: re-read srgr = %X\n",568 __func__, __LINE__, snd_interval_value(i) - 1);569 570 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);571 srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);572 break;573 default:574 return -EINVAL;575 }576 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);577 578 if (dev->mode == MOD_DSP_B) {579 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);580 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);581 } else {582 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);583 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);584 }585 586 if (dev->tx_framing_bit) {587 xcr &= ~DAVINCI_MCBSP_XCR_XDATDLY(1);588 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(2);589 }590 if (dev->rx_framing_bit) {591 rcr &= ~DAVINCI_MCBSP_RCR_RDATDLY(1);592 rcr |= DAVINCI_MCBSP_RCR_RDATDLY(2);593 }594 595 if (params_channels(params) == 2) {596 element_cnt = 2;597 if (double_fmt[fmt] && dev->enable_channel_combine) {598 element_cnt = 1;599 fmt = double_fmt[fmt];600 }601 switch (master) {602 case SND_SOC_DAIFMT_BP_FP:603 case SND_SOC_DAIFMT_BP_FC:604 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0);605 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0);606 rcr |= DAVINCI_MCBSP_RCR_RPHASE;607 xcr |= DAVINCI_MCBSP_XCR_XPHASE;608 break;609 case SND_SOC_DAIFMT_BC_FC:610 case SND_SOC_DAIFMT_BC_FP:611 rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);612 xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);613 break;614 default:615 return -EINVAL;616 }617 }618 619 switch (master) {620 case SND_SOC_DAIFMT_BP_FP:621 case SND_SOC_DAIFMT_BP_FC:622 if (dev->tdm_slots > 0) {623 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(dev->tdm_slots - 1);624 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(dev->tdm_slots - 1);625 } else {626 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);627 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);628 }629 break;630 case SND_SOC_DAIFMT_BC_FC:631 case SND_SOC_DAIFMT_BC_FP:632 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);633 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);634 break;635 default:636 return -EINVAL;637 }638 639 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |640 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);641 xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |642 DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);643 644 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)645 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);646 else647 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);648 649 pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr);650 pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr);651 pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr);652 return 0;653}654 655static int davinci_i2s_prepare(struct snd_pcm_substream *substream,656 struct snd_soc_dai *dai)657{658 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);659 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);660 u32 spcr;661 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;662 663 davinci_mcbsp_stop(dev, playback);664 665 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);666 if (spcr & mask) {667 /* start off disabled */668 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,669 spcr & ~mask);670 toggle_clock(dev, playback);671 }672 if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |673 DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {674 /* Start the sample generator */675 spcr |= DAVINCI_MCBSP_SPCR_GRST;676 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);677 }678 679 if (playback) {680 /* Enable the transmitter */681 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);682 spcr |= DAVINCI_MCBSP_SPCR_XRST;683 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);684 685 /* wait for any unexpected frame sync error to occur */686 udelay(100);687 688 /* Disable the transmitter to clear any outstanding XSYNCERR */689 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);690 spcr &= ~DAVINCI_MCBSP_SPCR_XRST;691 davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);692 toggle_clock(dev, playback);693 }694 695 return 0;696}697 698static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,699 struct snd_soc_dai *dai)700{701 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);702 int ret = 0;703 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);704 705 switch (cmd) {706 case SNDRV_PCM_TRIGGER_START:707 case SNDRV_PCM_TRIGGER_RESUME:708 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:709 davinci_mcbsp_start(dev, substream);710 break;711 case SNDRV_PCM_TRIGGER_STOP:712 case SNDRV_PCM_TRIGGER_SUSPEND:713 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:714 davinci_mcbsp_stop(dev, playback);715 break;716 default:717 ret = -EINVAL;718 }719 return ret;720}721 722static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,723 struct snd_soc_dai *dai)724{725 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);726 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);727 davinci_mcbsp_stop(dev, playback);728}729 730#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000731#define DAVINCI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \732 SNDRV_PCM_FMTBIT_S24_LE | \733 SNDRV_PCM_FMTBIT_S32_LE)734 735static int davinci_i2s_dai_probe(struct snd_soc_dai *dai)736{737 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);738 int stream;739 740 for_each_pcm_streams(stream)741 snd_soc_dai_dma_data_set(dai, stream, &dev->dma_data[stream]);742 743 return 0;744}745 746static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {747 .probe = davinci_i2s_dai_probe,748 .shutdown = davinci_i2s_shutdown,749 .prepare = davinci_i2s_prepare,750 .trigger = davinci_i2s_trigger,751 .hw_params = davinci_i2s_hw_params,752 .set_fmt = davinci_i2s_set_dai_fmt,753 .set_clkdiv = davinci_i2s_dai_set_clkdiv,754 .set_tdm_slot = davinci_i2s_set_tdm_slot,755 756};757 758static struct snd_soc_dai_driver davinci_i2s_dai = {759 .playback = {760 .channels_min = 2,761 .channels_max = 128,762 .rates = DAVINCI_I2S_RATES,763 .formats = DAVINCI_I2S_FORMATS,764 },765 .capture = {766 .channels_min = 2,767 .channels_max = 128,768 .rates = DAVINCI_I2S_RATES,769 .formats = DAVINCI_I2S_FORMATS,770 },771 .ops = &davinci_i2s_dai_ops,772 773};774 775static const struct snd_soc_component_driver davinci_i2s_component = {776 .name = DRV_NAME,777 .legacy_dai_naming = 1,778};779 780static int davinci_i2s_probe(struct platform_device *pdev)781{782 struct snd_dmaengine_dai_dma_data *dma_data;783 struct davinci_mcbsp_dev *dev;784 struct resource *mem, *res;785 void __iomem *io_base;786 int *dma;787 int ret;788 789 mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");790 if (!mem) {791 dev_warn(&pdev->dev,792 "\"mpu\" mem resource not found, using index 0\n");793 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);794 if (!mem) {795 dev_err(&pdev->dev, "no mem resource?\n");796 return -ENODEV;797 }798 }799 800 io_base = devm_ioremap_resource(&pdev->dev, mem);801 if (IS_ERR(io_base))802 return PTR_ERR(io_base);803 804 dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev),805 GFP_KERNEL);806 if (!dev)807 return -ENOMEM;808 809 dev->base = io_base;810 811 dev->tx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-tx");812 dev->rx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-rx");813 814 /* setup DMA, first TX, then RX */815 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];816 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);817 818 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);819 if (res) {820 dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];821 *dma = res->start;822 dma_data->filter_data = dma;823 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {824 dma_data->filter_data = "tx";825 } else {826 dev_err(&pdev->dev, "Missing DMA tx resource\n");827 return -ENODEV;828 }829 830 dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];831 dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);832 833 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);834 if (res) {835 dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];836 *dma = res->start;837 dma_data->filter_data = dma;838 } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {839 dma_data->filter_data = "rx";840 } else {841 dev_err(&pdev->dev, "Missing DMA rx resource\n");842 return -ENODEV;843 }844 845 /*846 * The optional is there for backward compatibility.847 * If 'fck' is not present, the clk_get(dev, NULL) that follows may find something848 */849 dev->clk = devm_clk_get_optional(&pdev->dev, "fck");850 if (IS_ERR(dev->clk))851 return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), "Invalid functional clock\n");852 if (!dev->clk) {853 dev->clk = devm_clk_get(&pdev->dev, NULL);854 if (IS_ERR(dev->clk))855 return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk),856 "Missing functional clock\n");857 }858 859 dev->ext_clk = devm_clk_get_optional(&pdev->dev, "clks");860 if (IS_ERR(dev->ext_clk))861 return dev_err_probe(&pdev->dev, PTR_ERR(dev->ext_clk), "Invalid external clock\n");862 863 ret = clk_prepare_enable(dev->clk);864 if (ret)865 return ret;866 867 if (dev->ext_clk) {868 dev_dbg(&pdev->dev, "External clock used for sample rate generator\n");869 ret = clk_prepare_enable(dev->ext_clk);870 if (ret) {871 dev_err_probe(&pdev->dev, ret, "Failed to enable external clock\n");872 goto err_disable_clk;873 }874 }875 876 dev->dev = &pdev->dev;877 dev_set_drvdata(&pdev->dev, dev);878 879 ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,880 &davinci_i2s_dai, 1);881 if (ret != 0)882 goto err_disable_ext_clk;883 884 ret = edma_pcm_platform_register(&pdev->dev);885 if (ret) {886 dev_err_probe(&pdev->dev, ret, "register PCM failed\n");887 goto err_unregister_component;888 }889 890 return 0;891 892err_unregister_component:893 snd_soc_unregister_component(&pdev->dev);894err_disable_ext_clk:895 if (dev->ext_clk)896 clk_disable_unprepare(dev->ext_clk);897err_disable_clk:898 clk_disable_unprepare(dev->clk);899 900 return ret;901}902 903static void davinci_i2s_remove(struct platform_device *pdev)904{905 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);906 907 snd_soc_unregister_component(&pdev->dev);908 909 clk_disable_unprepare(dev->clk);910 911 if (dev->ext_clk)912 clk_disable_unprepare(dev->ext_clk);913}914 915static const struct of_device_id davinci_i2s_match[] __maybe_unused = {916 { .compatible = "ti,da850-mcbsp" },917 {},918};919MODULE_DEVICE_TABLE(of, davinci_i2s_match);920 921static struct platform_driver davinci_mcbsp_driver = {922 .probe = davinci_i2s_probe,923 .remove = davinci_i2s_remove,924 .driver = {925 .name = "davinci-mcbsp",926 .of_match_table = of_match_ptr(davinci_i2s_match),927 },928};929 930module_platform_driver(davinci_mcbsp_driver);931 932MODULE_AUTHOR("Vladimir Barinov");933MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");934MODULE_LICENSE("GPL");935