1 /* 2 * Freescale ESAI ALSA SoC Digital Audio Interface (DAI) driver 3 * 4 * Copyright (C) 2014 Freescale Semiconductor, Inc. 5 * 6 * This file is licensed under the terms of the GNU General Public License 7 * version 2. This program is licensed "as is" without any warranty of any 8 * kind, whether express or implied. 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/dmaengine.h> 13 #include <linux/module.h> 14 #include <linux/of_irq.h> 15 #include <linux/of_platform.h> 16 #include <sound/dmaengine_pcm.h> 17 #include <sound/pcm_params.h> 18 19 #include "fsl_esai.h" 20 #include "imx-pcm.h" 21 22 #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 23 #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 24 SNDRV_PCM_FMTBIT_S16_LE | \ 25 SNDRV_PCM_FMTBIT_S20_3LE | \ 26 SNDRV_PCM_FMTBIT_S24_LE) 27 28 /** 29 * fsl_esai: ESAI private data 30 * 31 * @dma_params_rx: DMA parameters for receive channel 32 * @dma_params_tx: DMA parameters for transmit channel 33 * @pdev: platform device pointer 34 * @regmap: regmap handler 35 * @coreclk: clock source to access register 36 * @extalclk: esai clock source to derive HCK, SCK and FS 37 * @fsysclk: system clock source to derive HCK, SCK and FS 38 * @fifo_depth: depth of tx/rx FIFO 39 * @slot_width: width of each DAI slot 40 * @hck_rate: clock rate of desired HCKx clock 41 * @sck_div: if using PSR/PM dividers for SCKx clock 42 * @slave_mode: if fully using DAI slave mode 43 * @synchronous: if using tx/rx synchronous mode 44 * @name: driver name 45 */ 46 struct fsl_esai { 47 struct snd_dmaengine_dai_dma_data dma_params_rx; 48 struct snd_dmaengine_dai_dma_data dma_params_tx; 49 struct platform_device *pdev; 50 struct regmap *regmap; 51 struct clk *coreclk; 52 struct clk *extalclk; 53 struct clk *fsysclk; 54 u32 fifo_depth; 55 u32 slot_width; 56 u32 hck_rate[2]; 57 bool sck_div[2]; 58 bool slave_mode; 59 bool synchronous; 60 char name[32]; 61 }; 62 63 static irqreturn_t esai_isr(int irq, void *devid) 64 { 65 struct fsl_esai *esai_priv = (struct fsl_esai *)devid; 66 struct platform_device *pdev = esai_priv->pdev; 67 u32 esr; 68 69 regmap_read(esai_priv->regmap, REG_ESAI_ESR, &esr); 70 71 if (esr & ESAI_ESR_TINIT_MASK) 72 dev_dbg(&pdev->dev, "isr: Transmition Initialized\n"); 73 74 if (esr & ESAI_ESR_RFF_MASK) 75 dev_warn(&pdev->dev, "isr: Receiving overrun\n"); 76 77 if (esr & ESAI_ESR_TFE_MASK) 78 dev_warn(&pdev->dev, "isr: Transmition underrun\n"); 79 80 if (esr & ESAI_ESR_TLS_MASK) 81 dev_dbg(&pdev->dev, "isr: Just transmitted the last slot\n"); 82 83 if (esr & ESAI_ESR_TDE_MASK) 84 dev_dbg(&pdev->dev, "isr: Transmition data exception\n"); 85 86 if (esr & ESAI_ESR_TED_MASK) 87 dev_dbg(&pdev->dev, "isr: Transmitting even slots\n"); 88 89 if (esr & ESAI_ESR_TD_MASK) 90 dev_dbg(&pdev->dev, "isr: Transmitting data\n"); 91 92 if (esr & ESAI_ESR_RLS_MASK) 93 dev_dbg(&pdev->dev, "isr: Just received the last slot\n"); 94 95 if (esr & ESAI_ESR_RDE_MASK) 96 dev_dbg(&pdev->dev, "isr: Receiving data exception\n"); 97 98 if (esr & ESAI_ESR_RED_MASK) 99 dev_dbg(&pdev->dev, "isr: Receiving even slots\n"); 100 101 if (esr & ESAI_ESR_RD_MASK) 102 dev_dbg(&pdev->dev, "isr: Receiving data\n"); 103 104 return IRQ_HANDLED; 105 } 106 107 /** 108 * This function is used to calculate the divisors of psr, pm, fp and it is 109 * supposed to be called in set_dai_sysclk() and set_bclk(). 110 * 111 * @ratio: desired overall ratio for the paticipating dividers 112 * @usefp: for HCK setting, there is no need to set fp divider 113 * @fp: bypass other dividers by setting fp directly if fp != 0 114 * @tx: current setting is for playback or capture 115 */ 116 static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio, 117 bool usefp, u32 fp) 118 { 119 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 120 u32 psr, pm = 999, maxfp, prod, sub, savesub, i, j; 121 122 maxfp = usefp ? 16 : 1; 123 124 if (usefp && fp) 125 goto out_fp; 126 127 if (ratio > 2 * 8 * 256 * maxfp || ratio < 2) { 128 dev_err(dai->dev, "the ratio is out of range (2 ~ %d)\n", 129 2 * 8 * 256 * maxfp); 130 return -EINVAL; 131 } else if (ratio % 2) { 132 dev_err(dai->dev, "the raio must be even if using upper divider\n"); 133 return -EINVAL; 134 } 135 136 ratio /= 2; 137 138 psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8; 139 140 /* Set the max fluctuation -- 0.1% of the max devisor */ 141 savesub = (psr ? 1 : 8) * 256 * maxfp / 1000; 142 143 /* Find the best value for PM */ 144 for (i = 1; i <= 256; i++) { 145 for (j = 1; j <= maxfp; j++) { 146 /* PSR (1 or 8) * PM (1 ~ 256) * FP (1 ~ 16) */ 147 prod = (psr ? 1 : 8) * i * j; 148 149 if (prod == ratio) 150 sub = 0; 151 else if (prod / ratio == 1) 152 sub = prod - ratio; 153 else if (ratio / prod == 1) 154 sub = ratio - prod; 155 else 156 continue; 157 158 /* Calculate the fraction */ 159 sub = sub * 1000 / ratio; 160 if (sub < savesub) { 161 savesub = sub; 162 pm = i; 163 fp = j; 164 } 165 166 /* We are lucky */ 167 if (savesub == 0) 168 goto out; 169 } 170 } 171 172 if (pm == 999) { 173 dev_err(dai->dev, "failed to calculate proper divisors\n"); 174 return -EINVAL; 175 } 176 177 out: 178 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx), 179 ESAI_xCCR_xPSR_MASK | ESAI_xCCR_xPM_MASK, 180 psr | ESAI_xCCR_xPM(pm)); 181 182 out_fp: 183 /* Bypass fp if not being required */ 184 if (maxfp <= 1) 185 return 0; 186 187 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx), 188 ESAI_xCCR_xFP_MASK, ESAI_xCCR_xFP(fp)); 189 190 return 0; 191 } 192 193 /** 194 * This function mainly configures the clock frequency of MCLK (HCKT/HCKR) 195 * 196 * @Parameters: 197 * clk_id: The clock source of HCKT/HCKR 198 * (Input from outside; output from inside, FSYS or EXTAL) 199 * freq: The required clock rate of HCKT/HCKR 200 * dir: The clock direction of HCKT/HCKR 201 * 202 * Note: If the direction is input, we do not care about clk_id. 203 */ 204 static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, 205 unsigned int freq, int dir) 206 { 207 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 208 struct clk *clksrc = esai_priv->extalclk; 209 bool tx = clk_id <= ESAI_HCKT_EXTAL; 210 bool in = dir == SND_SOC_CLOCK_IN; 211 u32 ret, ratio, ecr = 0; 212 unsigned long clk_rate; 213 214 /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */ 215 esai_priv->sck_div[tx] = true; 216 217 /* Set the direction of HCKT/HCKR pins */ 218 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCCR(tx), 219 ESAI_xCCR_xHCKD, in ? 0 : ESAI_xCCR_xHCKD); 220 221 if (in) 222 goto out; 223 224 switch (clk_id) { 225 case ESAI_HCKT_FSYS: 226 case ESAI_HCKR_FSYS: 227 clksrc = esai_priv->fsysclk; 228 break; 229 case ESAI_HCKT_EXTAL: 230 ecr |= ESAI_ECR_ETI; 231 case ESAI_HCKR_EXTAL: 232 ecr |= ESAI_ECR_ERI; 233 break; 234 default: 235 return -EINVAL; 236 } 237 238 if (IS_ERR(clksrc)) { 239 dev_err(dai->dev, "no assigned %s clock\n", 240 clk_id % 2 ? "extal" : "fsys"); 241 return PTR_ERR(clksrc); 242 } 243 clk_rate = clk_get_rate(clksrc); 244 245 ratio = clk_rate / freq; 246 if (ratio * freq > clk_rate) 247 ret = ratio * freq - clk_rate; 248 else if (ratio * freq < clk_rate) 249 ret = clk_rate - ratio * freq; 250 else 251 ret = 0; 252 253 /* Block if clock source can not be divided into the required rate */ 254 if (ret != 0 && clk_rate / ret < 1000) { 255 dev_err(dai->dev, "failed to derive required HCK%c rate\n", 256 tx ? 'T' : 'R'); 257 return -EINVAL; 258 } 259 260 if (ratio == 1) { 261 /* Bypass all the dividers if not being needed */ 262 ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO; 263 goto out; 264 } 265 266 ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0); 267 if (ret) 268 return ret; 269 270 esai_priv->sck_div[tx] = false; 271 272 out: 273 esai_priv->hck_rate[tx] = freq; 274 275 regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, 276 tx ? ESAI_ECR_ETI | ESAI_ECR_ETO : 277 ESAI_ECR_ERI | ESAI_ECR_ERO, ecr); 278 279 return 0; 280 } 281 282 /** 283 * This function configures the related dividers according to the bclk rate 284 */ 285 static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) 286 { 287 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 288 u32 hck_rate = esai_priv->hck_rate[tx]; 289 u32 sub, ratio = hck_rate / freq; 290 291 /* Don't apply for fully slave mode*/ 292 if (esai_priv->slave_mode) 293 return 0; 294 295 if (ratio * freq > hck_rate) 296 sub = ratio * freq - hck_rate; 297 else if (ratio * freq < hck_rate) 298 sub = hck_rate - ratio * freq; 299 else 300 sub = 0; 301 302 /* Block if clock source can not be divided into the required rate */ 303 if (sub != 0 && hck_rate / sub < 1000) { 304 dev_err(dai->dev, "failed to derive required SCK%c rate\n", 305 tx ? 'T' : 'R'); 306 return -EINVAL; 307 } 308 309 if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) { 310 dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n"); 311 return -EINVAL; 312 } 313 314 return fsl_esai_divisor_cal(dai, tx, ratio, true, 315 esai_priv->sck_div[tx] ? 0 : ratio); 316 } 317 318 static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, 319 u32 rx_mask, int slots, int slot_width) 320 { 321 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 322 323 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, 324 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); 325 326 regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA, 327 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask)); 328 regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB, 329 ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask)); 330 331 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, 332 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots)); 333 334 regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA, 335 ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask)); 336 regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB, 337 ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask)); 338 339 esai_priv->slot_width = slot_width; 340 341 return 0; 342 } 343 344 static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 345 { 346 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 347 u32 xcr = 0, xccr = 0, mask; 348 349 /* DAI mode */ 350 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 351 case SND_SOC_DAIFMT_I2S: 352 /* Data on rising edge of bclk, frame low, 1clk before data */ 353 xcr |= ESAI_xCR_xFSR; 354 xccr |= ESAI_xCCR_xFSP | ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; 355 break; 356 case SND_SOC_DAIFMT_LEFT_J: 357 /* Data on rising edge of bclk, frame high */ 358 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; 359 break; 360 case SND_SOC_DAIFMT_RIGHT_J: 361 /* Data on rising edge of bclk, frame high, right aligned */ 362 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCR_xWA; 363 break; 364 case SND_SOC_DAIFMT_DSP_A: 365 /* Data on rising edge of bclk, frame high, 1clk before data */ 366 xcr |= ESAI_xCR_xFSL | ESAI_xCR_xFSR; 367 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; 368 break; 369 case SND_SOC_DAIFMT_DSP_B: 370 /* Data on rising edge of bclk, frame high */ 371 xcr |= ESAI_xCR_xFSL; 372 xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; 373 break; 374 default: 375 return -EINVAL; 376 } 377 378 /* DAI clock inversion */ 379 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 380 case SND_SOC_DAIFMT_NB_NF: 381 /* Nothing to do for both normal cases */ 382 break; 383 case SND_SOC_DAIFMT_IB_NF: 384 /* Invert bit clock */ 385 xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; 386 break; 387 case SND_SOC_DAIFMT_NB_IF: 388 /* Invert frame clock */ 389 xccr ^= ESAI_xCCR_xFSP; 390 break; 391 case SND_SOC_DAIFMT_IB_IF: 392 /* Invert both clocks */ 393 xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP; 394 break; 395 default: 396 return -EINVAL; 397 } 398 399 esai_priv->slave_mode = false; 400 401 /* DAI clock master masks */ 402 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 403 case SND_SOC_DAIFMT_CBM_CFM: 404 esai_priv->slave_mode = true; 405 break; 406 case SND_SOC_DAIFMT_CBS_CFM: 407 xccr |= ESAI_xCCR_xCKD; 408 break; 409 case SND_SOC_DAIFMT_CBM_CFS: 410 xccr |= ESAI_xCCR_xFSD; 411 break; 412 case SND_SOC_DAIFMT_CBS_CFS: 413 xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD; 414 break; 415 default: 416 return -EINVAL; 417 } 418 419 mask = ESAI_xCR_xFSL | ESAI_xCR_xFSR; 420 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, xcr); 421 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCR, mask, xcr); 422 423 mask = ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP | 424 ESAI_xCCR_xFSD | ESAI_xCCR_xCKD | ESAI_xCR_xWA; 425 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, mask, xccr); 426 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, mask, xccr); 427 428 return 0; 429 } 430 431 static int fsl_esai_startup(struct snd_pcm_substream *substream, 432 struct snd_soc_dai *dai) 433 { 434 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 435 436 /* 437 * Some platforms might use the same bit to gate all three or two of 438 * clocks, so keep all clocks open/close at the same time for safety 439 */ 440 clk_prepare_enable(esai_priv->coreclk); 441 if (!IS_ERR(esai_priv->extalclk)) 442 clk_prepare_enable(esai_priv->extalclk); 443 if (!IS_ERR(esai_priv->fsysclk)) 444 clk_prepare_enable(esai_priv->fsysclk); 445 446 if (!dai->active) { 447 /* Reset Port C */ 448 regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, 449 ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); 450 regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, 451 ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); 452 453 /* Set synchronous mode */ 454 regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR, 455 ESAI_SAICR_SYNC, esai_priv->synchronous ? 456 ESAI_SAICR_SYNC : 0); 457 458 /* Set a default slot number -- 2 */ 459 regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, 460 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2)); 461 regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, 462 ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2)); 463 } 464 465 return 0; 466 } 467 468 static int fsl_esai_hw_params(struct snd_pcm_substream *substream, 469 struct snd_pcm_hw_params *params, 470 struct snd_soc_dai *dai) 471 { 472 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 473 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 474 u32 width = snd_pcm_format_width(params_format(params)); 475 u32 channels = params_channels(params); 476 u32 bclk, mask, val, ret; 477 478 bclk = params_rate(params) * esai_priv->slot_width * 2; 479 480 ret = fsl_esai_set_bclk(dai, tx, bclk); 481 if (ret) 482 return ret; 483 484 /* Use Normal mode to support monaural audio */ 485 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 486 ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ? 487 ESAI_xCR_xMOD_NETWORK : 0); 488 489 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 490 ESAI_xFCR_xFR_MASK, ESAI_xFCR_xFR); 491 492 mask = ESAI_xFCR_xFR_MASK | ESAI_xFCR_xWA_MASK | ESAI_xFCR_xFWM_MASK | 493 (tx ? ESAI_xFCR_TE_MASK | ESAI_xFCR_TIEN : ESAI_xFCR_RE_MASK); 494 val = ESAI_xFCR_xWA(width) | ESAI_xFCR_xFWM(esai_priv->fifo_depth) | 495 (tx ? ESAI_xFCR_TE(channels) | ESAI_xFCR_TIEN : ESAI_xFCR_RE(channels)); 496 497 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); 498 499 mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0); 500 val = ESAI_xCR_xSWS(esai_priv->slot_width, width) | (tx ? ESAI_xCR_PADC : 0); 501 502 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val); 503 504 return 0; 505 } 506 507 static void fsl_esai_shutdown(struct snd_pcm_substream *substream, 508 struct snd_soc_dai *dai) 509 { 510 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 511 512 if (!IS_ERR(esai_priv->fsysclk)) 513 clk_disable_unprepare(esai_priv->fsysclk); 514 if (!IS_ERR(esai_priv->extalclk)) 515 clk_disable_unprepare(esai_priv->extalclk); 516 clk_disable_unprepare(esai_priv->coreclk); 517 } 518 519 static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd, 520 struct snd_soc_dai *dai) 521 { 522 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 523 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 524 u8 i, channels = substream->runtime->channels; 525 526 switch (cmd) { 527 case SNDRV_PCM_TRIGGER_START: 528 case SNDRV_PCM_TRIGGER_RESUME: 529 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 530 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 531 ESAI_xFCR_xFEN_MASK, ESAI_xFCR_xFEN); 532 533 /* Write initial words reqiured by ESAI as normal procedure */ 534 for (i = 0; tx && i < channels; i++) 535 regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0); 536 537 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 538 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 539 tx ? ESAI_xCR_TE(channels) : ESAI_xCR_RE(channels)); 540 break; 541 case SNDRV_PCM_TRIGGER_SUSPEND: 542 case SNDRV_PCM_TRIGGER_STOP: 543 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 544 regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), 545 tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0); 546 547 /* Disable and reset FIFO */ 548 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 549 ESAI_xFCR_xFR | ESAI_xFCR_xFEN, ESAI_xFCR_xFR); 550 regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), 551 ESAI_xFCR_xFR, 0); 552 break; 553 default: 554 return -EINVAL; 555 } 556 557 return 0; 558 } 559 560 static struct snd_soc_dai_ops fsl_esai_dai_ops = { 561 .startup = fsl_esai_startup, 562 .shutdown = fsl_esai_shutdown, 563 .trigger = fsl_esai_trigger, 564 .hw_params = fsl_esai_hw_params, 565 .set_sysclk = fsl_esai_set_dai_sysclk, 566 .set_fmt = fsl_esai_set_dai_fmt, 567 .set_tdm_slot = fsl_esai_set_dai_tdm_slot, 568 }; 569 570 static int fsl_esai_dai_probe(struct snd_soc_dai *dai) 571 { 572 struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); 573 574 snd_soc_dai_init_dma_data(dai, &esai_priv->dma_params_tx, 575 &esai_priv->dma_params_rx); 576 577 return 0; 578 } 579 580 static struct snd_soc_dai_driver fsl_esai_dai = { 581 .probe = fsl_esai_dai_probe, 582 .playback = { 583 .channels_min = 1, 584 .channels_max = 12, 585 .rates = FSL_ESAI_RATES, 586 .formats = FSL_ESAI_FORMATS, 587 }, 588 .capture = { 589 .channels_min = 1, 590 .channels_max = 8, 591 .rates = FSL_ESAI_RATES, 592 .formats = FSL_ESAI_FORMATS, 593 }, 594 .ops = &fsl_esai_dai_ops, 595 }; 596 597 static const struct snd_soc_component_driver fsl_esai_component = { 598 .name = "fsl-esai", 599 }; 600 601 static bool fsl_esai_readable_reg(struct device *dev, unsigned int reg) 602 { 603 switch (reg) { 604 case REG_ESAI_ERDR: 605 case REG_ESAI_ECR: 606 case REG_ESAI_ESR: 607 case REG_ESAI_TFCR: 608 case REG_ESAI_TFSR: 609 case REG_ESAI_RFCR: 610 case REG_ESAI_RFSR: 611 case REG_ESAI_RX0: 612 case REG_ESAI_RX1: 613 case REG_ESAI_RX2: 614 case REG_ESAI_RX3: 615 case REG_ESAI_SAISR: 616 case REG_ESAI_SAICR: 617 case REG_ESAI_TCR: 618 case REG_ESAI_TCCR: 619 case REG_ESAI_RCR: 620 case REG_ESAI_RCCR: 621 case REG_ESAI_TSMA: 622 case REG_ESAI_TSMB: 623 case REG_ESAI_RSMA: 624 case REG_ESAI_RSMB: 625 case REG_ESAI_PRRC: 626 case REG_ESAI_PCRC: 627 return true; 628 default: 629 return false; 630 } 631 } 632 633 static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) 634 { 635 switch (reg) { 636 case REG_ESAI_ETDR: 637 case REG_ESAI_ECR: 638 case REG_ESAI_TFCR: 639 case REG_ESAI_RFCR: 640 case REG_ESAI_TX0: 641 case REG_ESAI_TX1: 642 case REG_ESAI_TX2: 643 case REG_ESAI_TX3: 644 case REG_ESAI_TX4: 645 case REG_ESAI_TX5: 646 case REG_ESAI_TSR: 647 case REG_ESAI_SAICR: 648 case REG_ESAI_TCR: 649 case REG_ESAI_TCCR: 650 case REG_ESAI_RCR: 651 case REG_ESAI_RCCR: 652 case REG_ESAI_TSMA: 653 case REG_ESAI_TSMB: 654 case REG_ESAI_RSMA: 655 case REG_ESAI_RSMB: 656 case REG_ESAI_PRRC: 657 case REG_ESAI_PCRC: 658 return true; 659 default: 660 return false; 661 } 662 } 663 664 static const struct regmap_config fsl_esai_regmap_config = { 665 .reg_bits = 32, 666 .reg_stride = 4, 667 .val_bits = 32, 668 669 .max_register = REG_ESAI_PCRC, 670 .readable_reg = fsl_esai_readable_reg, 671 .writeable_reg = fsl_esai_writeable_reg, 672 }; 673 674 static int fsl_esai_probe(struct platform_device *pdev) 675 { 676 struct device_node *np = pdev->dev.of_node; 677 struct fsl_esai *esai_priv; 678 struct resource *res; 679 const uint32_t *iprop; 680 void __iomem *regs; 681 int irq, ret; 682 683 esai_priv = devm_kzalloc(&pdev->dev, sizeof(*esai_priv), GFP_KERNEL); 684 if (!esai_priv) 685 return -ENOMEM; 686 687 esai_priv->pdev = pdev; 688 strcpy(esai_priv->name, np->name); 689 690 /* Get the addresses and IRQ */ 691 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 692 regs = devm_ioremap_resource(&pdev->dev, res); 693 if (IS_ERR(regs)) 694 return PTR_ERR(regs); 695 696 esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, 697 "core", regs, &fsl_esai_regmap_config); 698 if (IS_ERR(esai_priv->regmap)) { 699 dev_err(&pdev->dev, "failed to init regmap: %ld\n", 700 PTR_ERR(esai_priv->regmap)); 701 return PTR_ERR(esai_priv->regmap); 702 } 703 704 esai_priv->coreclk = devm_clk_get(&pdev->dev, "core"); 705 if (IS_ERR(esai_priv->coreclk)) { 706 dev_err(&pdev->dev, "failed to get core clock: %ld\n", 707 PTR_ERR(esai_priv->coreclk)); 708 return PTR_ERR(esai_priv->coreclk); 709 } 710 711 esai_priv->extalclk = devm_clk_get(&pdev->dev, "extal"); 712 if (IS_ERR(esai_priv->extalclk)) 713 dev_warn(&pdev->dev, "failed to get extal clock: %ld\n", 714 PTR_ERR(esai_priv->extalclk)); 715 716 esai_priv->fsysclk = devm_clk_get(&pdev->dev, "fsys"); 717 if (IS_ERR(esai_priv->fsysclk)) 718 dev_warn(&pdev->dev, "failed to get fsys clock: %ld\n", 719 PTR_ERR(esai_priv->fsysclk)); 720 721 irq = platform_get_irq(pdev, 0); 722 if (irq < 0) { 723 dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); 724 return irq; 725 } 726 727 ret = devm_request_irq(&pdev->dev, irq, esai_isr, 0, 728 esai_priv->name, esai_priv); 729 if (ret) { 730 dev_err(&pdev->dev, "failed to claim irq %u\n", irq); 731 return ret; 732 } 733 734 /* Set a default slot size */ 735 esai_priv->slot_width = 32; 736 737 /* Set a default master/slave state */ 738 esai_priv->slave_mode = true; 739 740 /* Determine the FIFO depth */ 741 iprop = of_get_property(np, "fsl,fifo-depth", NULL); 742 if (iprop) 743 esai_priv->fifo_depth = be32_to_cpup(iprop); 744 else 745 esai_priv->fifo_depth = 64; 746 747 esai_priv->dma_params_tx.maxburst = 16; 748 esai_priv->dma_params_rx.maxburst = 16; 749 esai_priv->dma_params_tx.addr = res->start + REG_ESAI_ETDR; 750 esai_priv->dma_params_rx.addr = res->start + REG_ESAI_ERDR; 751 752 esai_priv->synchronous = 753 of_property_read_bool(np, "fsl,esai-synchronous"); 754 755 /* Implement full symmetry for synchronous mode */ 756 if (esai_priv->synchronous) { 757 fsl_esai_dai.symmetric_rates = 1; 758 fsl_esai_dai.symmetric_channels = 1; 759 fsl_esai_dai.symmetric_samplebits = 1; 760 } 761 762 dev_set_drvdata(&pdev->dev, esai_priv); 763 764 /* Reset ESAI unit */ 765 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ERST); 766 if (ret) { 767 dev_err(&pdev->dev, "failed to reset ESAI: %d\n", ret); 768 return ret; 769 } 770 771 /* 772 * We need to enable ESAI so as to access some of its registers. 773 * Otherwise, we would fail to dump regmap from user space. 774 */ 775 ret = regmap_write(esai_priv->regmap, REG_ESAI_ECR, ESAI_ECR_ESAIEN); 776 if (ret) { 777 dev_err(&pdev->dev, "failed to enable ESAI: %d\n", ret); 778 return ret; 779 } 780 781 ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component, 782 &fsl_esai_dai, 1); 783 if (ret) { 784 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); 785 return ret; 786 } 787 788 ret = imx_pcm_dma_init(pdev); 789 if (ret) 790 dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); 791 792 return ret; 793 } 794 795 static const struct of_device_id fsl_esai_dt_ids[] = { 796 { .compatible = "fsl,imx35-esai", }, 797 {} 798 }; 799 MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); 800 801 static struct platform_driver fsl_esai_driver = { 802 .probe = fsl_esai_probe, 803 .driver = { 804 .name = "fsl-esai-dai", 805 .owner = THIS_MODULE, 806 .of_match_table = fsl_esai_dt_ids, 807 }, 808 }; 809 810 module_platform_driver(fsl_esai_driver); 811 812 MODULE_AUTHOR("Freescale Semiconductor, Inc."); 813 MODULE_DESCRIPTION("Freescale ESAI CPU DAI driver"); 814 MODULE_LICENSE("GPL v2"); 815 MODULE_ALIAS("platform:fsl-esai-dai"); 816