1/* 2 * imx-ssi.c -- ALSA Soc Audio Layer 3 * 4 * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de> 5 * 6 * This code is based on code copyrighted by Freescale, 7 * Liam Girdwood, Javier Martin and probably others. 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 * 14 * 15 * The i.MX SSI core has some nasty limitations in AC97 mode. While most 16 * sane processor vendors have a FIFO per AC97 slot, the i.MX has only 17 * one FIFO which combines all valid receive slots. We cannot even select 18 * which slots we want to receive. The WM9712 with which this driver 19 * was developped with always sends GPIO status data in slot 12 which 20 * we receive in our (PCM-) data stream. The only chance we have is to 21 * manually skip this data in the FIQ handler. With sampling rates different 22 * from 48000Hz not every frame has valid receive data, so the ratio 23 * between pcm data and GPIO status data changes. Our FIQ handler is not 24 * able to handle this, hence this driver only works with 48000Hz sampling 25 * rate. 26 * Reading and writing AC97 registers is another challenge. The core 27 * provides us status bits when the read register is updated with *another* 28 * value. When we read the same register two times (and the register still 29 * contains the same value) these status bits are not set. We work 30 * around this by not polling these bits but only wait a fixed delay. 31 * 32 */ 33 34#include <linux/clk.h> 35#include <linux/delay.h> 36#include <linux/device.h> 37#include <linux/dma-mapping.h> 38#include <linux/init.h> 39#include <linux/interrupt.h> 40#include <linux/module.h> 41#include <linux/platform_device.h> 42#include <linux/slab.h> 43 44#include <sound/core.h> 45#include <sound/initval.h> 46#include <sound/pcm.h> 47#include <sound/pcm_params.h> 48#include <sound/soc.h> 49 50#include <mach/ssi.h> 51#include <mach/hardware.h> 52 53#include "imx-ssi.h" 54 55#define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) 56 57/* 58 * SSI Network Mode or TDM slots configuration. 59 * Should only be called when port is inactive (i.e. SSIEN = 0). 60 */ 61static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 62 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 63{ 64 struct imx_ssi *ssi = cpu_dai->private_data; 65 u32 sccr; 66 67 sccr = readl(ssi->base + SSI_STCCR); 68 sccr &= ~SSI_STCCR_DC_MASK; 69 sccr |= SSI_STCCR_DC(slots - 1); 70 writel(sccr, ssi->base + SSI_STCCR); 71 72 sccr = readl(ssi->base + SSI_SRCCR); 73 sccr &= ~SSI_STCCR_DC_MASK; 74 sccr |= SSI_STCCR_DC(slots - 1); 75 writel(sccr, ssi->base + SSI_SRCCR); 76 77 writel(tx_mask, ssi->base + SSI_STMSK); 78 writel(rx_mask, ssi->base + SSI_SRMSK); 79 80 return 0; 81} 82 83/* 84 * SSI DAI format configuration. 85 * Should only be called when port is inactive (i.e. SSIEN = 0). 86 */ 87static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) 88{ 89 struct imx_ssi *ssi = cpu_dai->private_data; 90 u32 strcr = 0, scr; 91 92 scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); 93 94 /* DAI mode */ 95 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 96 case SND_SOC_DAIFMT_I2S: 97 /* data on rising edge of bclk, frame low 1clk before data */ 98 strcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0; 99 scr |= SSI_SCR_NET; 100 if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) { 101 scr &= ~SSI_I2S_MODE_MASK; 102 scr |= SSI_SCR_I2S_MODE_SLAVE; 103 } 104 break; 105 case SND_SOC_DAIFMT_LEFT_J: 106 /* data on rising edge of bclk, frame high with data */ 107 strcr |= SSI_STCR_TXBIT0; 108 break; 109 case SND_SOC_DAIFMT_DSP_B: 110 /* data on rising edge of bclk, frame high with data */ 111 strcr |= SSI_STCR_TFSL; 112 break; 113 case SND_SOC_DAIFMT_DSP_A: 114 /* data on rising edge of bclk, frame high 1clk before data */ 115 strcr |= SSI_STCR_TFSL | SSI_STCR_TEFS; 116 break; 117 } 118 119 /* DAI clock inversion */ 120 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 121 case SND_SOC_DAIFMT_IB_IF: 122 strcr |= SSI_STCR_TFSI; 123 strcr &= ~SSI_STCR_TSCKP; 124 break; 125 case SND_SOC_DAIFMT_IB_NF: 126 strcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI); 127 break; 128 case SND_SOC_DAIFMT_NB_IF: 129 strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP; 130 break; 131 case SND_SOC_DAIFMT_NB_NF: 132 strcr &= ~SSI_STCR_TFSI; 133 strcr |= SSI_STCR_TSCKP; 134 break; 135 } 136 137 /* DAI clock master masks */ 138 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 139 case SND_SOC_DAIFMT_CBM_CFM: 140 break; 141 default: 142 /* Master mode not implemented, needs handling of clocks. */ 143 return -EINVAL; 144 } 145 146 strcr |= SSI_STCR_TFEN0; 147 148 if (ssi->flags & IMX_SSI_NET) 149 scr |= SSI_SCR_NET; 150 if (ssi->flags & IMX_SSI_SYN) 151 scr |= SSI_SCR_SYN; 152 153 writel(strcr, ssi->base + SSI_STCR); 154 writel(strcr, ssi->base + SSI_SRCR); 155 writel(scr, ssi->base + SSI_SCR); 156 157 return 0; 158} 159 160/* 161 * SSI system clock configuration. 162 * Should only be called when port is inactive (i.e. SSIEN = 0). 163 */ 164static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 165 int clk_id, unsigned int freq, int dir) 166{ 167 struct imx_ssi *ssi = cpu_dai->private_data; 168 u32 scr; 169 170 scr = readl(ssi->base + SSI_SCR); 171 172 switch (clk_id) { 173 case IMX_SSP_SYS_CLK: 174 if (dir == SND_SOC_CLOCK_OUT) 175 scr |= SSI_SCR_SYS_CLK_EN; 176 else 177 scr &= ~SSI_SCR_SYS_CLK_EN; 178 break; 179 default: 180 return -EINVAL; 181 } 182 183 writel(scr, ssi->base + SSI_SCR); 184 185 return 0; 186} 187 188/* 189 * SSI Clock dividers 190 * Should only be called when port is inactive (i.e. SSIEN = 0). 191 */ 192static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, 193 int div_id, int div) 194{ 195 struct imx_ssi *ssi = cpu_dai->private_data; 196 u32 stccr, srccr; 197 198 stccr = readl(ssi->base + SSI_STCCR); 199 srccr = readl(ssi->base + SSI_SRCCR); 200 201 switch (div_id) { 202 case IMX_SSI_TX_DIV_2: 203 stccr &= ~SSI_STCCR_DIV2; 204 stccr |= div; 205 break; 206 case IMX_SSI_TX_DIV_PSR: 207 stccr &= ~SSI_STCCR_PSR; 208 stccr |= div; 209 break; 210 case IMX_SSI_TX_DIV_PM: 211 stccr &= ~0xff; 212 stccr |= SSI_STCCR_PM(div); 213 break; 214 case IMX_SSI_RX_DIV_2: 215 stccr &= ~SSI_STCCR_DIV2; 216 stccr |= div; 217 break; 218 case IMX_SSI_RX_DIV_PSR: 219 stccr &= ~SSI_STCCR_PSR; 220 stccr |= div; 221 break; 222 case IMX_SSI_RX_DIV_PM: 223 stccr &= ~0xff; 224 stccr |= SSI_STCCR_PM(div); 225 break; 226 default: 227 return -EINVAL; 228 } 229 230 writel(stccr, ssi->base + SSI_STCCR); 231 writel(srccr, ssi->base + SSI_SRCCR); 232 233 return 0; 234} 235 236/* 237 * Should only be called when port is inactive (i.e. SSIEN = 0), 238 * although can be called multiple times by upper layers. 239 */ 240static int imx_ssi_hw_params(struct snd_pcm_substream *substream, 241 struct snd_pcm_hw_params *params, 242 struct snd_soc_dai *cpu_dai) 243{ 244 struct imx_ssi *ssi = cpu_dai->private_data; 245 struct imx_pcm_dma_params *dma_data; 246 u32 reg, sccr; 247 248 /* Tx/Rx config */ 249 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 250 reg = SSI_STCCR; 251 dma_data = &ssi->dma_params_tx; 252 } else { 253 reg = SSI_SRCCR; 254 dma_data = &ssi->dma_params_rx; 255 } 256 257 if (ssi->flags & IMX_SSI_SYN) 258 reg = SSI_STCCR; 259 260 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); 261 262 sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK; 263 264 /* DAI data (word) size */ 265 switch (params_format(params)) { 266 case SNDRV_PCM_FORMAT_S16_LE: 267 sccr |= SSI_SRCCR_WL(16); 268 break; 269 case SNDRV_PCM_FORMAT_S20_3LE: 270 sccr |= SSI_SRCCR_WL(20); 271 break; 272 case SNDRV_PCM_FORMAT_S24_LE: 273 sccr |= SSI_SRCCR_WL(24); 274 break; 275 } 276 277 writel(sccr, ssi->base + reg); 278 279 return 0; 280} 281 282static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, 283 struct snd_soc_dai *dai) 284{ 285 struct snd_soc_pcm_runtime *rtd = substream->private_data; 286 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 287 struct imx_ssi *ssi = cpu_dai->private_data; 288 unsigned int sier_bits, sier; 289 unsigned int scr; 290 291 scr = readl(ssi->base + SSI_SCR); 292 sier = readl(ssi->base + SSI_SIER); 293 294 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 295 if (ssi->flags & IMX_SSI_DMA) 296 sier_bits = SSI_SIER_TDMAE; 297 else 298 sier_bits = SSI_SIER_TIE | SSI_SIER_TFE0_EN; 299 } else { 300 if (ssi->flags & IMX_SSI_DMA) 301 sier_bits = SSI_SIER_RDMAE; 302 else 303 sier_bits = SSI_SIER_RIE | SSI_SIER_RFF0_EN; 304 } 305 306 switch (cmd) { 307 case SNDRV_PCM_TRIGGER_START: 308 case SNDRV_PCM_TRIGGER_RESUME: 309 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 310 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 311 scr |= SSI_SCR_TE; 312 else 313 scr |= SSI_SCR_RE; 314 sier |= sier_bits; 315 316 if (++ssi->enabled == 1) 317 scr |= SSI_SCR_SSIEN; 318 319 break; 320 321 case SNDRV_PCM_TRIGGER_STOP: 322 case SNDRV_PCM_TRIGGER_SUSPEND: 323 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 324 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 325 scr &= ~SSI_SCR_TE; 326 else 327 scr &= ~SSI_SCR_RE; 328 sier &= ~sier_bits; 329 330 if (--ssi->enabled == 0) 331 scr &= ~SSI_SCR_SSIEN; 332 333 break; 334 default: 335 return -EINVAL; 336 } 337 338 if (!(ssi->flags & IMX_SSI_USE_AC97)) 339 /* rx/tx are always enabled to access ac97 registers */ 340 writel(scr, ssi->base + SSI_SCR); 341 342 writel(sier, ssi->base + SSI_SIER); 343 344 return 0; 345} 346 347static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { 348 .hw_params = imx_ssi_hw_params, 349 .set_fmt = imx_ssi_set_dai_fmt, 350 .set_clkdiv = imx_ssi_set_dai_clkdiv, 351 .set_sysclk = imx_ssi_set_dai_sysclk, 352 .set_tdm_slot = imx_ssi_set_dai_tdm_slot, 353 .trigger = imx_ssi_trigger, 354}; 355 356static struct snd_soc_dai imx_ssi_dai = { 357 .playback = { 358 .channels_min = 2, 359 .channels_max = 2, 360 .rates = SNDRV_PCM_RATE_8000_96000, 361 .formats = SNDRV_PCM_FMTBIT_S16_LE, 362 }, 363 .capture = { 364 .channels_min = 2, 365 .channels_max = 2, 366 .rates = SNDRV_PCM_RATE_8000_96000, 367 .formats = SNDRV_PCM_FMTBIT_S16_LE, 368 }, 369 .ops = &imx_ssi_pcm_dai_ops, 370}; 371 372int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, 373 struct vm_area_struct *vma) 374{ 375 struct snd_pcm_runtime *runtime = substream->runtime; 376 int ret; 377 378 ret = dma_mmap_coherent(NULL, vma, runtime->dma_area, 379 runtime->dma_addr, runtime->dma_bytes); 380 381 pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, 382 runtime->dma_area, 383 runtime->dma_addr, 384 runtime->dma_bytes); 385 return ret; 386} 387 388static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 389{ 390 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 391 struct snd_dma_buffer *buf = &substream->dma_buffer; 392 size_t size = IMX_SSI_DMABUF_SIZE; 393 394 buf->dev.type = SNDRV_DMA_TYPE_DEV; 395 buf->dev.dev = pcm->card->dev; 396 buf->private_data = NULL; 397 buf->area = dma_alloc_writecombine(pcm->card->dev, size, 398 &buf->addr, GFP_KERNEL); 399 if (!buf->area) 400 return -ENOMEM; 401 buf->bytes = size; 402 403 return 0; 404} 405 406static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); 407 408int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 409 struct snd_pcm *pcm) 410{ 411 412 int ret = 0; 413 414 if (!card->dev->dma_mask) 415 card->dev->dma_mask = &imx_pcm_dmamask; 416 if (!card->dev->coherent_dma_mask) 417 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 418 if (dai->playback.channels_min) { 419 ret = imx_pcm_preallocate_dma_buffer(pcm, 420 SNDRV_PCM_STREAM_PLAYBACK); 421 if (ret) 422 goto out; 423 } 424 425 if (dai->capture.channels_min) { 426 ret = imx_pcm_preallocate_dma_buffer(pcm, 427 SNDRV_PCM_STREAM_CAPTURE); 428 if (ret) 429 goto out; 430 } 431 432out: 433 return ret; 434} 435 436void imx_pcm_free(struct snd_pcm *pcm) 437{ 438 struct snd_pcm_substream *substream; 439 struct snd_dma_buffer *buf; 440 int stream; 441 442 for (stream = 0; stream < 2; stream++) { 443 substream = pcm->streams[stream].substream; 444 if (!substream) 445 continue; 446 447 buf = &substream->dma_buffer; 448 if (!buf->area) 449 continue; 450 451 dma_free_writecombine(pcm->card->dev, buf->bytes, 452 buf->area, buf->addr); 453 buf->area = NULL; 454 } 455} 456 457struct snd_soc_platform imx_soc_platform = { 458 .name = "imx-audio", 459}; 460EXPORT_SYMBOL_GPL(imx_soc_platform); 461 462static struct snd_soc_dai imx_ac97_dai = { 463 .name = "AC97", 464 .ac97_control = 1, 465 .playback = { 466 .stream_name = "AC97 Playback", 467 .channels_min = 2, 468 .channels_max = 2, 469 .rates = SNDRV_PCM_RATE_48000, 470 .formats = SNDRV_PCM_FMTBIT_S16_LE, 471 }, 472 .capture = { 473 .stream_name = "AC97 Capture", 474 .channels_min = 2, 475 .channels_max = 2, 476 .rates = SNDRV_PCM_RATE_48000, 477 .formats = SNDRV_PCM_FMTBIT_S16_LE, 478 }, 479 .ops = &imx_ssi_pcm_dai_ops, 480}; 481 482static void setup_channel_to_ac97(struct imx_ssi *imx_ssi) 483{ 484 void __iomem *base = imx_ssi->base; 485 486 writel(0x0, base + SSI_SCR); 487 writel(0x0, base + SSI_STCR); 488 writel(0x0, base + SSI_SRCR); 489 490 writel(SSI_SCR_SYN | SSI_SCR_NET, base + SSI_SCR); 491 492 writel(SSI_SFCSR_RFWM0(8) | 493 SSI_SFCSR_TFWM0(8) | 494 SSI_SFCSR_RFWM1(8) | 495 SSI_SFCSR_TFWM1(8), base + SSI_SFCSR); 496 497 writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_STCCR); 498 writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_SRCCR); 499 500 writel(SSI_SCR_SYN | SSI_SCR_NET | SSI_SCR_SSIEN, base + SSI_SCR); 501 writel(SSI_SOR_WAIT(3), base + SSI_SOR); 502 503 writel(SSI_SCR_SYN | SSI_SCR_NET | SSI_SCR_SSIEN | 504 SSI_SCR_TE | SSI_SCR_RE, 505 base + SSI_SCR); 506 507 writel(SSI_SACNT_DEFAULT, base + SSI_SACNT); 508 writel(0xff, base + SSI_SACCDIS); 509 writel(0x300, base + SSI_SACCEN); 510} 511 512static struct imx_ssi *ac97_ssi; 513 514static void imx_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 515 unsigned short val) 516{ 517 struct imx_ssi *imx_ssi = ac97_ssi; 518 void __iomem *base = imx_ssi->base; 519 unsigned int lreg; 520 unsigned int lval; 521 522 if (reg > 0x7f) 523 return; 524 525 pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val); 526 527 lreg = reg << 12; 528 writel(lreg, base + SSI_SACADD); 529 530 lval = val << 4; 531 writel(lval , base + SSI_SACDAT); 532 533 writel(SSI_SACNT_DEFAULT | SSI_SACNT_WR, base + SSI_SACNT); 534 udelay(100); 535} 536 537static unsigned short imx_ssi_ac97_read(struct snd_ac97 *ac97, 538 unsigned short reg) 539{ 540 struct imx_ssi *imx_ssi = ac97_ssi; 541 void __iomem *base = imx_ssi->base; 542 543 unsigned short val = -1; 544 unsigned int lreg; 545 546 lreg = (reg & 0x7f) << 12 ; 547 writel(lreg, base + SSI_SACADD); 548 writel(SSI_SACNT_DEFAULT | SSI_SACNT_RD, base + SSI_SACNT); 549 550 udelay(100); 551 552 val = (readl(base + SSI_SACDAT) >> 4) & 0xffff; 553 554 pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val); 555 556 return val; 557} 558 559static void imx_ssi_ac97_reset(struct snd_ac97 *ac97) 560{ 561 struct imx_ssi *imx_ssi = ac97_ssi; 562 563 if (imx_ssi->ac97_reset) 564 imx_ssi->ac97_reset(ac97); 565} 566 567static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97) 568{ 569 struct imx_ssi *imx_ssi = ac97_ssi; 570 571 if (imx_ssi->ac97_warm_reset) 572 imx_ssi->ac97_warm_reset(ac97); 573} 574 575struct snd_ac97_bus_ops soc_ac97_ops = { 576 .read = imx_ssi_ac97_read, 577 .write = imx_ssi_ac97_write, 578 .reset = imx_ssi_ac97_reset, 579 .warm_reset = imx_ssi_ac97_warm_reset 580}; 581EXPORT_SYMBOL_GPL(soc_ac97_ops); 582 583struct snd_soc_dai imx_ssi_pcm_dai[2]; 584EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai); 585 586static int imx_ssi_probe(struct platform_device *pdev) 587{ 588 struct resource *res; 589 struct imx_ssi *ssi; 590 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; 591 struct snd_soc_platform *platform; 592 int ret = 0; 593 unsigned int val; 594 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; 595 596 if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai)) 597 return -EINVAL; 598 599 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); 600 if (!ssi) 601 return -ENOMEM; 602 603 if (pdata) { 604 ssi->ac97_reset = pdata->ac97_reset; 605 ssi->ac97_warm_reset = pdata->ac97_warm_reset; 606 ssi->flags = pdata->flags; 607 } 608 609 ssi->irq = platform_get_irq(pdev, 0); 610 611 ssi->clk = clk_get(&pdev->dev, NULL); 612 if (IS_ERR(ssi->clk)) { 613 ret = PTR_ERR(ssi->clk); 614 dev_err(&pdev->dev, "Cannot get the clock: %d\n", 615 ret); 616 goto failed_clk; 617 } 618 clk_enable(ssi->clk); 619 620 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 621 if (!res) { 622 ret = -ENODEV; 623 goto failed_get_resource; 624 } 625 626 if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { 627 dev_err(&pdev->dev, "request_mem_region failed\n"); 628 ret = -EBUSY; 629 goto failed_get_resource; 630 } 631 632 ssi->base = ioremap(res->start, resource_size(res)); 633 if (!ssi->base) { 634 dev_err(&pdev->dev, "ioremap failed\n"); 635 ret = -ENODEV; 636 goto failed_ioremap; 637 } 638 639 if (ssi->flags & IMX_SSI_USE_AC97) { 640 if (ac97_ssi) { 641 ret = -EBUSY; 642 goto failed_ac97; 643 } 644 ac97_ssi = ssi; 645 setup_channel_to_ac97(ssi); 646 memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); 647 } else 648 memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); 649 650 writel(0x0, ssi->base + SSI_SIER); 651 652 ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; 653 ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; 654 655 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); 656 if (res) 657 ssi->dma_params_tx.dma = res->start; 658 659 res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); 660 if (res) 661 ssi->dma_params_rx.dma = res->start; 662 663 dai->id = pdev->id; 664 dai->dev = &pdev->dev; 665 dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id); 666 dai->private_data = ssi; 667 668 if ((cpu_is_mx27() || cpu_is_mx21()) && 669 !(ssi->flags & IMX_SSI_USE_AC97) && 670 (ssi->flags & IMX_SSI_DMA)) { 671 ssi->flags |= IMX_SSI_DMA; 672 platform = imx_ssi_dma_mx2_init(pdev, ssi); 673 } else 674 platform = imx_ssi_fiq_init(pdev, ssi); 675 676 imx_soc_platform.pcm_ops = platform->pcm_ops; 677 imx_soc_platform.pcm_new = platform->pcm_new; 678 imx_soc_platform.pcm_free = platform->pcm_free; 679 680 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | 681 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); 682 writel(val, ssi->base + SSI_SFCSR); 683 684 ret = snd_soc_register_dai(dai); 685 if (ret) { 686 dev_err(&pdev->dev, "register DAI failed\n"); 687 goto failed_register; 688 } 689 690 platform_set_drvdata(pdev, ssi); 691 692 return 0; 693 694failed_register: 695failed_ac97: 696 iounmap(ssi->base); 697failed_ioremap: 698 release_mem_region(res->start, resource_size(res)); 699failed_get_resource: 700 clk_disable(ssi->clk); 701 clk_put(ssi->clk); 702failed_clk: 703 kfree(ssi); 704 705 return ret; 706} 707 708static int __devexit imx_ssi_remove(struct platform_device *pdev) 709{ 710 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 711 struct imx_ssi *ssi = platform_get_drvdata(pdev); 712 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id]; 713 714 snd_soc_unregister_dai(dai); 715 716 if (ssi->flags & IMX_SSI_USE_AC97) 717 ac97_ssi = NULL; 718 719 if (!(ssi->flags & IMX_SSI_DMA)) 720 imx_ssi_fiq_exit(pdev, ssi); 721 722 iounmap(ssi->base); 723 release_mem_region(res->start, resource_size(res)); 724 clk_disable(ssi->clk); 725 clk_put(ssi->clk); 726 kfree(ssi); 727 728 return 0; 729} 730 731static struct platform_driver imx_ssi_driver = { 732 .probe = imx_ssi_probe, 733 .remove = __devexit_p(imx_ssi_remove), 734 735 .driver = { 736 .name = DRV_NAME, 737 .owner = THIS_MODULE, 738 }, 739}; 740 741static int __init imx_ssi_init(void) 742{ 743 int ret; 744 745 ret = snd_soc_register_platform(&imx_soc_platform); 746 if (ret) { 747 pr_err("failed to register soc platform: %d\n", ret); 748 return ret; 749 } 750 751 ret = platform_driver_register(&imx_ssi_driver); 752 if (ret) { 753 snd_soc_unregister_platform(&imx_soc_platform); 754 return ret; 755 } 756 757 return 0; 758} 759 760static void __exit imx_ssi_exit(void) 761{ 762 platform_driver_unregister(&imx_ssi_driver); 763 snd_soc_unregister_platform(&imx_soc_platform); 764} 765 766module_init(imx_ssi_init); 767module_exit(imx_ssi_exit); 768 769/* Module information */ 770MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>"); 771MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface"); 772MODULE_LICENSE("GPL"); 773