Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
imx-ssi.c
Go to the documentation of this file.
1 /*
2  * imx-ssi.c -- ALSA Soc Audio Layer
3  *
4  * Copyright 2009 Sascha Hauer <[email protected]>
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 developed 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 
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  */
61 static 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 = snd_soc_dai_get_drvdata(cpu_dai);
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  */
87 static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
88 {
89  struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
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 */
99  scr |= SSI_SCR_NET;
100  if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) {
103  }
104  break;
106  /* data on rising edge of bclk, frame high with data */
107  strcr |= SSI_STCR_TXBIT0;
108  break;
110  /* data on rising edge of bclk, frame high with data */
111  strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0;
112  break;
114  /* data on rising edge of bclk, frame high 1clk before data */
116  break;
117  }
118 
119  /* DAI clock inversion */
120  switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
122  strcr |= SSI_STCR_TFSI;
123  strcr &= ~SSI_STCR_TSCKP;
124  break;
126  strcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI);
127  break;
129  strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
130  break;
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) {
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  */
164 static 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 = snd_soc_dai_get_drvdata(cpu_dai);
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  */
192 static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
193  int div_id, int div)
194 {
195  struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
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 static int imx_ssi_startup(struct snd_pcm_substream *substream,
237  struct snd_soc_dai *cpu_dai)
238 {
239  struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
240  struct imx_pcm_dma_params *dma_data;
241 
242  /* Tx/Rx config */
243  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
244  dma_data = &ssi->dma_params_tx;
245  else
246  dma_data = &ssi->dma_params_rx;
247 
248  snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
249 
250  return 0;
251 }
252 
253 /*
254  * Should only be called when port is inactive (i.e. SSIEN = 0),
255  * although can be called multiple times by upper layers.
256  */
257 static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
258  struct snd_pcm_hw_params *params,
259  struct snd_soc_dai *cpu_dai)
260 {
261  struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
262  u32 reg, sccr;
263 
264  /* Tx/Rx config */
265  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
266  reg = SSI_STCCR;
267  else
268  reg = SSI_SRCCR;
269 
270  if (ssi->flags & IMX_SSI_SYN)
271  reg = SSI_STCCR;
272 
273  sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
274 
275  /* DAI data (word) size */
276  switch (params_format(params)) {
278  sccr |= SSI_SRCCR_WL(16);
279  break;
281  sccr |= SSI_SRCCR_WL(20);
282  break;
284  sccr |= SSI_SRCCR_WL(24);
285  break;
286  }
287 
288  writel(sccr, ssi->base + reg);
289 
290  return 0;
291 }
292 
293 static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
294  struct snd_soc_dai *dai)
295 {
296  struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai);
297  unsigned int sier_bits, sier;
298  unsigned int scr;
299 
300  scr = readl(ssi->base + SSI_SCR);
301  sier = readl(ssi->base + SSI_SIER);
302 
303  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
304  if (ssi->flags & IMX_SSI_DMA)
305  sier_bits = SSI_SIER_TDMAE;
306  else
307  sier_bits = SSI_SIER_TIE | SSI_SIER_TFE0_EN;
308  } else {
309  if (ssi->flags & IMX_SSI_DMA)
310  sier_bits = SSI_SIER_RDMAE;
311  else
312  sier_bits = SSI_SIER_RIE | SSI_SIER_RFF0_EN;
313  }
314 
315  switch (cmd) {
319  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
320  scr |= SSI_SCR_TE;
321  else
322  scr |= SSI_SCR_RE;
323  sier |= sier_bits;
324 
325  if (++ssi->enabled == 1)
326  scr |= SSI_SCR_SSIEN;
327 
328  break;
329 
333  if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
334  scr &= ~SSI_SCR_TE;
335  else
336  scr &= ~SSI_SCR_RE;
337  sier &= ~sier_bits;
338 
339  if (--ssi->enabled == 0)
340  scr &= ~SSI_SCR_SSIEN;
341 
342  break;
343  default:
344  return -EINVAL;
345  }
346 
347  if (!(ssi->flags & IMX_SSI_USE_AC97))
348  /* rx/tx are always enabled to access ac97 registers */
349  writel(scr, ssi->base + SSI_SCR);
350 
351  writel(sier, ssi->base + SSI_SIER);
352 
353  return 0;
354 }
355 
356 static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
357  .startup = imx_ssi_startup,
358  .hw_params = imx_ssi_hw_params,
359  .set_fmt = imx_ssi_set_dai_fmt,
360  .set_clkdiv = imx_ssi_set_dai_clkdiv,
361  .set_sysclk = imx_ssi_set_dai_sysclk,
362  .set_tdm_slot = imx_ssi_set_dai_tdm_slot,
363  .trigger = imx_ssi_trigger,
364 };
365 
366 static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
367 {
368  struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
369  uint32_t val;
370 
371  snd_soc_dai_set_drvdata(dai, ssi);
372 
373  val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
374  SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
375  writel(val, ssi->base + SSI_SFCSR);
376 
377  return 0;
378 }
379 
380 static struct snd_soc_dai_driver imx_ssi_dai = {
381  .probe = imx_ssi_dai_probe,
382  .playback = {
383  .channels_min = 1,
384  .channels_max = 2,
385  .rates = SNDRV_PCM_RATE_8000_96000,
386  .formats = SNDRV_PCM_FMTBIT_S16_LE,
387  },
388  .capture = {
389  .channels_min = 1,
390  .channels_max = 2,
391  .rates = SNDRV_PCM_RATE_8000_96000,
392  .formats = SNDRV_PCM_FMTBIT_S16_LE,
393  },
394  .ops = &imx_ssi_pcm_dai_ops,
395 };
396 
397 static struct snd_soc_dai_driver imx_ac97_dai = {
398  .probe = imx_ssi_dai_probe,
399  .ac97_control = 1,
400  .playback = {
401  .stream_name = "AC97 Playback",
402  .channels_min = 2,
403  .channels_max = 2,
404  .rates = SNDRV_PCM_RATE_48000,
405  .formats = SNDRV_PCM_FMTBIT_S16_LE,
406  },
407  .capture = {
408  .stream_name = "AC97 Capture",
409  .channels_min = 2,
410  .channels_max = 2,
411  .rates = SNDRV_PCM_RATE_48000,
412  .formats = SNDRV_PCM_FMTBIT_S16_LE,
413  },
414  .ops = &imx_ssi_pcm_dai_ops,
415 };
416 
417 static void setup_channel_to_ac97(struct imx_ssi *imx_ssi)
418 {
419  void __iomem *base = imx_ssi->base;
420 
421  writel(0x0, base + SSI_SCR);
422  writel(0x0, base + SSI_STCR);
423  writel(0x0, base + SSI_SRCR);
424 
426 
428  SSI_SFCSR_TFWM0(8) |
429  SSI_SFCSR_RFWM1(8) |
430  SSI_SFCSR_TFWM1(8), base + SSI_SFCSR);
431 
432  writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_STCCR);
433  writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_SRCCR);
434 
436  writel(SSI_SOR_WAIT(3), base + SSI_SOR);
437 
440  base + SSI_SCR);
441 
443  writel(0xff, base + SSI_SACCDIS);
444  writel(0x300, base + SSI_SACCEN);
445 }
446 
447 static struct imx_ssi *ac97_ssi;
448 
449 static void imx_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
450  unsigned short val)
451 {
452  struct imx_ssi *imx_ssi = ac97_ssi;
453  void __iomem *base = imx_ssi->base;
454  unsigned int lreg;
455  unsigned int lval;
456 
457  if (reg > 0x7f)
458  return;
459 
460  pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val);
461 
462  lreg = reg << 12;
463  writel(lreg, base + SSI_SACADD);
464 
465  lval = val << 4;
466  writel(lval , base + SSI_SACDAT);
467 
469  udelay(100);
470 }
471 
472 static unsigned short imx_ssi_ac97_read(struct snd_ac97 *ac97,
473  unsigned short reg)
474 {
475  struct imx_ssi *imx_ssi = ac97_ssi;
476  void __iomem *base = imx_ssi->base;
477 
478  unsigned short val = -1;
479  unsigned int lreg;
480 
481  lreg = (reg & 0x7f) << 12 ;
482  writel(lreg, base + SSI_SACADD);
484 
485  udelay(100);
486 
487  val = (readl(base + SSI_SACDAT) >> 4) & 0xffff;
488 
489  pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val);
490 
491  return val;
492 }
493 
494 static void imx_ssi_ac97_reset(struct snd_ac97 *ac97)
495 {
496  struct imx_ssi *imx_ssi = ac97_ssi;
497 
498  if (imx_ssi->ac97_reset)
499  imx_ssi->ac97_reset(ac97);
500 }
501 
502 static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
503 {
504  struct imx_ssi *imx_ssi = ac97_ssi;
505 
506  if (imx_ssi->ac97_warm_reset)
507  imx_ssi->ac97_warm_reset(ac97);
508 }
509 
511  .read = imx_ssi_ac97_read,
512  .write = imx_ssi_ac97_write,
513  .reset = imx_ssi_ac97_reset,
514  .warm_reset = imx_ssi_ac97_warm_reset
515 };
516 EXPORT_SYMBOL_GPL(soc_ac97_ops);
517 
518 static int imx_ssi_probe(struct platform_device *pdev)
519 {
520  struct resource *res;
521  struct imx_ssi *ssi;
522  struct imx_ssi_platform_data *pdata = pdev->dev.platform_data;
523  int ret = 0;
524  struct snd_soc_dai_driver *dai;
525 
526  ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
527  if (!ssi)
528  return -ENOMEM;
529  dev_set_drvdata(&pdev->dev, ssi);
530 
531  if (pdata) {
532  ssi->ac97_reset = pdata->ac97_reset;
533  ssi->ac97_warm_reset = pdata->ac97_warm_reset;
534  ssi->flags = pdata->flags;
535  }
536 
537  ssi->irq = platform_get_irq(pdev, 0);
538 
539  ssi->clk = devm_clk_get(&pdev->dev, NULL);
540  if (IS_ERR(ssi->clk)) {
541  ret = PTR_ERR(ssi->clk);
542  dev_err(&pdev->dev, "Cannot get the clock: %d\n",
543  ret);
544  goto failed_clk;
545  }
546  clk_prepare_enable(ssi->clk);
547 
548  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
549  if (!res) {
550  ret = -ENODEV;
551  goto failed_get_resource;
552  }
553 
554  ssi->base = devm_request_and_ioremap(&pdev->dev, res);
555  if (!ssi->base) {
556  dev_err(&pdev->dev, "ioremap failed\n");
557  ret = -ENODEV;
558  goto failed_register;
559  }
560 
561  if (ssi->flags & IMX_SSI_USE_AC97) {
562  if (ac97_ssi) {
563  dev_err(&pdev->dev, "AC'97 SSI already registered\n");
564  ret = -EBUSY;
565  goto failed_register;
566  }
567  ac97_ssi = ssi;
568  setup_channel_to_ac97(ssi);
569  dai = &imx_ac97_dai;
570  } else
571  dai = &imx_ssi_dai;
572 
573  writel(0x0, ssi->base + SSI_SIER);
574 
575  ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0;
576  ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
577 
578  ssi->dma_params_tx.burstsize = 6;
579  ssi->dma_params_rx.burstsize = 4;
580 
581  res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
582  if (res)
583  ssi->dma_params_tx.dma = res->start;
584 
585  res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0");
586  if (res)
587  ssi->dma_params_rx.dma = res->start;
588 
589  platform_set_drvdata(pdev, ssi);
590 
591  ret = snd_soc_register_dai(&pdev->dev, dai);
592  if (ret) {
593  dev_err(&pdev->dev, "register DAI failed\n");
594  goto failed_register;
595  }
596 
597  ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
598  if (!ssi->soc_platform_pdev_fiq) {
599  ret = -ENOMEM;
600  goto failed_pdev_fiq_alloc;
601  }
602 
603  platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi);
605  if (ret) {
606  dev_err(&pdev->dev, "failed to add platform device\n");
607  goto failed_pdev_fiq_add;
608  }
609 
610  ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id);
611  if (!ssi->soc_platform_pdev) {
612  ret = -ENOMEM;
613  goto failed_pdev_alloc;
614  }
615 
616  platform_set_drvdata(ssi->soc_platform_pdev, ssi);
618  if (ret) {
619  dev_err(&pdev->dev, "failed to add platform device\n");
620  goto failed_pdev_add;
621  }
622 
623  return 0;
624 
625 failed_pdev_add:
627 failed_pdev_alloc:
629 failed_pdev_fiq_add:
631 failed_pdev_fiq_alloc:
632  snd_soc_unregister_dai(&pdev->dev);
633 failed_register:
634  release_mem_region(res->start, resource_size(res));
635 failed_get_resource:
636  clk_disable_unprepare(ssi->clk);
637 failed_clk:
638 
639  return ret;
640 }
641 
642 static int __devexit imx_ssi_remove(struct platform_device *pdev)
643 {
644  struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
645  struct imx_ssi *ssi = platform_get_drvdata(pdev);
646 
649 
650  snd_soc_unregister_dai(&pdev->dev);
651 
652  if (ssi->flags & IMX_SSI_USE_AC97)
653  ac97_ssi = NULL;
654 
655  release_mem_region(res->start, resource_size(res));
656  clk_disable_unprepare(ssi->clk);
657 
658  return 0;
659 }
660 
661 static struct platform_driver imx_ssi_driver = {
662  .probe = imx_ssi_probe,
663  .remove = __devexit_p(imx_ssi_remove),
664 
665  .driver = {
666  .name = "imx-ssi",
667  .owner = THIS_MODULE,
668  },
669 };
670 
671 module_platform_driver(imx_ssi_driver);
672 
673 /* Module information */
674 MODULE_AUTHOR("Sascha Hauer, <[email protected]>");
675 MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface");
676 MODULE_LICENSE("GPL");
677 MODULE_ALIAS("platform:imx-ssi");