linux/sound/soc/pxa/pxa2xx-i2s.c
<<
>>
Prefs
   1/*
   2 * pxa2xx-i2s.c  --  ALSA Soc Audio Layer
   3 *
   4 * Copyright 2005 Wolfson Microelectronics PLC.
   5 * Author: Liam Girdwood
   6 *         lrg@slimlogic.co.uk
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 */
  13
  14#include <linux/init.h>
  15#include <linux/module.h>
  16#include <linux/device.h>
  17#include <linux/delay.h>
  18#include <linux/clk.h>
  19#include <linux/platform_device.h>
  20#include <sound/core.h>
  21#include <sound/pcm.h>
  22#include <sound/initval.h>
  23#include <sound/soc.h>
  24#include <sound/pxa2xx-lib.h>
  25
  26#include <mach/hardware.h>
  27#include <mach/dma.h>
  28#include <mach/audio.h>
  29
  30#include "pxa2xx-pcm.h"
  31#include "pxa2xx-i2s.h"
  32
  33/*
  34 * I2S Controller Register and Bit Definitions
  35 */
  36#define SACR0           __REG(0x40400000)  /* Global Control Register */
  37#define SACR1           __REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
  38#define SASR0           __REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
  39#define SAIMR           __REG(0x40400014)  /* Serial Audio Interrupt Mask Register */
  40#define SAICR           __REG(0x40400018)  /* Serial Audio Interrupt Clear Register */
  41#define SADIV           __REG(0x40400060)  /* Audio Clock Divider Register. */
  42#define SADR            __REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
  43
  44#define SACR0_RFTH(x)   ((x) << 12)     /* Rx FIFO Interrupt or DMA Trigger Threshold */
  45#define SACR0_TFTH(x)   ((x) << 8)      /* Tx FIFO Interrupt or DMA Trigger Threshold */
  46#define SACR0_STRF      (1 << 5)        /* FIFO Select for EFWR Special Function */
  47#define SACR0_EFWR      (1 << 4)        /* Enable EFWR Function  */
  48#define SACR0_RST       (1 << 3)        /* FIFO, i2s Register Reset */
  49#define SACR0_BCKD      (1 << 2)        /* Bit Clock Direction */
  50#define SACR0_ENB       (1 << 0)        /* Enable I2S Link */
  51#define SACR1_ENLBF     (1 << 5)        /* Enable Loopback */
  52#define SACR1_DRPL      (1 << 4)        /* Disable Replaying Function */
  53#define SACR1_DREC      (1 << 3)        /* Disable Recording Function */
  54#define SACR1_AMSL      (1 << 0)        /* Specify Alternate Mode */
  55
  56#define SASR0_I2SOFF    (1 << 7)        /* Controller Status */
  57#define SASR0_ROR       (1 << 6)        /* Rx FIFO Overrun */
  58#define SASR0_TUR       (1 << 5)        /* Tx FIFO Underrun */
  59#define SASR0_RFS       (1 << 4)        /* Rx FIFO Service Request */
  60#define SASR0_TFS       (1 << 3)        /* Tx FIFO Service Request */
  61#define SASR0_BSY       (1 << 2)        /* I2S Busy */
  62#define SASR0_RNE       (1 << 1)        /* Rx FIFO Not Empty */
  63#define SASR0_TNF       (1 << 0)        /* Tx FIFO Not Empty */
  64
  65#define SAICR_ROR       (1 << 6)        /* Clear Rx FIFO Overrun Interrupt */
  66#define SAICR_TUR       (1 << 5)        /* Clear Tx FIFO Underrun Interrupt */
  67
  68#define SAIMR_ROR       (1 << 6)        /* Enable Rx FIFO Overrun Condition Interrupt */
  69#define SAIMR_TUR       (1 << 5)        /* Enable Tx FIFO Underrun Condition Interrupt */
  70#define SAIMR_RFS       (1 << 4)        /* Enable Rx FIFO Service Interrupt */
  71#define SAIMR_TFS       (1 << 3)        /* Enable Tx FIFO Service Interrupt */
  72
  73struct pxa_i2s_port {
  74        u32 sadiv;
  75        u32 sacr0;
  76        u32 sacr1;
  77        u32 saimr;
  78        int master;
  79        u32 fmt;
  80};
  81static struct pxa_i2s_port pxa_i2s;
  82static struct clk *clk_i2s;
  83
  84static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
  85        .name                   = "I2S PCM Stereo out",
  86        .dev_addr               = __PREG(SADR),
  87        .drcmr                  = &DRCMR(3),
  88        .dcmd                   = DCMD_INCSRCADDR | DCMD_FLOWTRG |
  89                                  DCMD_BURST32 | DCMD_WIDTH4,
  90};
  91
  92static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
  93        .name                   = "I2S PCM Stereo in",
  94        .dev_addr               = __PREG(SADR),
  95        .drcmr                  = &DRCMR(2),
  96        .dcmd                   = DCMD_INCTRGADDR | DCMD_FLOWSRC |
  97                                  DCMD_BURST32 | DCMD_WIDTH4,
  98};
  99
 100static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
 101                              struct snd_soc_dai *dai)
 102{
 103        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 104        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 105
 106        if (IS_ERR(clk_i2s))
 107                return PTR_ERR(clk_i2s);
 108
 109        if (!cpu_dai->active)
 110                SACR0 = 0;
 111
 112        return 0;
 113}
 114
 115/* wait for I2S controller to be ready */
 116static int pxa_i2s_wait(void)
 117{
 118        int i;
 119
 120        /* flush the Rx FIFO */
 121        for(i = 0; i < 16; i++)
 122                SADR;
 123        return 0;
 124}
 125
 126static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 127                unsigned int fmt)
 128{
 129        /* interface format */
 130        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 131        case SND_SOC_DAIFMT_I2S:
 132                pxa_i2s.fmt = 0;
 133                break;
 134        case SND_SOC_DAIFMT_LEFT_J:
 135                pxa_i2s.fmt = SACR1_AMSL;
 136                break;
 137        }
 138
 139        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 140        case SND_SOC_DAIFMT_CBS_CFS:
 141                pxa_i2s.master = 1;
 142                break;
 143        case SND_SOC_DAIFMT_CBM_CFS:
 144                pxa_i2s.master = 0;
 145                break;
 146        default:
 147                break;
 148        }
 149        return 0;
 150}
 151
 152static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 153                int clk_id, unsigned int freq, int dir)
 154{
 155        if (clk_id != PXA2XX_I2S_SYSCLK)
 156                return -ENODEV;
 157
 158        return 0;
 159}
 160
 161static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
 162                                struct snd_pcm_hw_params *params,
 163                                struct snd_soc_dai *dai)
 164{
 165        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 166        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 167
 168        BUG_ON(IS_ERR(clk_i2s));
 169        clk_enable(clk_i2s);
 170        dai->private_data = dai;
 171        pxa_i2s_wait();
 172
 173        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 174                cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
 175        else
 176                cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
 177
 178        /* is port used by another stream */
 179        if (!(SACR0 & SACR0_ENB)) {
 180                SACR0 = 0;
 181                if (pxa_i2s.master)
 182                        SACR0 |= SACR0_BCKD;
 183
 184                SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
 185                SACR1 |= pxa_i2s.fmt;
 186        }
 187        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 188                SAIMR |= SAIMR_TFS;
 189        else
 190                SAIMR |= SAIMR_RFS;
 191
 192        switch (params_rate(params)) {
 193        case 8000:
 194                SADIV = 0x48;
 195                break;
 196        case 11025:
 197                SADIV = 0x34;
 198                break;
 199        case 16000:
 200                SADIV = 0x24;
 201                break;
 202        case 22050:
 203                SADIV = 0x1a;
 204                break;
 205        case 44100:
 206                SADIV = 0xd;
 207                break;
 208        case 48000:
 209                SADIV = 0xc;
 210                break;
 211        case 96000: /* not in manual and possibly slightly inaccurate */
 212                SADIV = 0x6;
 213                break;
 214        }
 215
 216        return 0;
 217}
 218
 219static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 220                              struct snd_soc_dai *dai)
 221{
 222        int ret = 0;
 223
 224        switch (cmd) {
 225        case SNDRV_PCM_TRIGGER_START:
 226                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 227                        SACR1 &= ~SACR1_DRPL;
 228                else
 229                        SACR1 &= ~SACR1_DREC;
 230                SACR0 |= SACR0_ENB;
 231                break;
 232        case SNDRV_PCM_TRIGGER_RESUME:
 233        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 234        case SNDRV_PCM_TRIGGER_STOP:
 235        case SNDRV_PCM_TRIGGER_SUSPEND:
 236        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 237                break;
 238        default:
 239                ret = -EINVAL;
 240        }
 241
 242        return ret;
 243}
 244
 245static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
 246                                struct snd_soc_dai *dai)
 247{
 248        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 249                SACR1 |= SACR1_DRPL;
 250                SAIMR &= ~SAIMR_TFS;
 251        } else {
 252                SACR1 |= SACR1_DREC;
 253                SAIMR &= ~SAIMR_RFS;
 254        }
 255
 256        if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
 257                SACR0 &= ~SACR0_ENB;
 258                pxa_i2s_wait();
 259                if (dai->private_data != NULL) {
 260                        clk_disable(clk_i2s);
 261                        dai->private_data = NULL;
 262                }
 263        }
 264}
 265
 266#ifdef CONFIG_PM
 267static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
 268{
 269        /* store registers */
 270        pxa_i2s.sacr0 = SACR0;
 271        pxa_i2s.sacr1 = SACR1;
 272        pxa_i2s.saimr = SAIMR;
 273        pxa_i2s.sadiv = SADIV;
 274
 275        /* deactivate link */
 276        SACR0 &= ~SACR0_ENB;
 277        pxa_i2s_wait();
 278        return 0;
 279}
 280
 281static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
 282{
 283        pxa_i2s_wait();
 284
 285        SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
 286        SACR1 = pxa_i2s.sacr1;
 287        SAIMR = pxa_i2s.saimr;
 288        SADIV = pxa_i2s.sadiv;
 289
 290        SACR0 = pxa_i2s.sacr0;
 291
 292        return 0;
 293}
 294
 295#else
 296#define pxa2xx_i2s_suspend      NULL
 297#define pxa2xx_i2s_resume       NULL
 298#endif
 299
 300#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
 301                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
 302                SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 303
 304static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
 305        .startup        = pxa2xx_i2s_startup,
 306        .shutdown       = pxa2xx_i2s_shutdown,
 307        .trigger        = pxa2xx_i2s_trigger,
 308        .hw_params      = pxa2xx_i2s_hw_params,
 309        .set_fmt        = pxa2xx_i2s_set_dai_fmt,
 310        .set_sysclk     = pxa2xx_i2s_set_dai_sysclk,
 311};
 312
 313struct snd_soc_dai pxa_i2s_dai = {
 314        .name = "pxa2xx-i2s",
 315        .id = 0,
 316        .suspend = pxa2xx_i2s_suspend,
 317        .resume = pxa2xx_i2s_resume,
 318        .playback = {
 319                .channels_min = 2,
 320                .channels_max = 2,
 321                .rates = PXA2XX_I2S_RATES,
 322                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 323        .capture = {
 324                .channels_min = 2,
 325                .channels_max = 2,
 326                .rates = PXA2XX_I2S_RATES,
 327                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
 328        .ops = &pxa_i2s_dai_ops,
 329        .symmetric_rates = 1,
 330};
 331
 332EXPORT_SYMBOL_GPL(pxa_i2s_dai);
 333
 334static int pxa2xx_i2s_probe(struct platform_device *dev)
 335{
 336        int ret;
 337
 338        clk_i2s = clk_get(&dev->dev, "I2SCLK");
 339        if (IS_ERR(clk_i2s))
 340                return PTR_ERR(clk_i2s);
 341
 342        pxa_i2s_dai.dev = &dev->dev;
 343        pxa_i2s_dai.private_data = NULL;
 344        ret = snd_soc_register_dai(&pxa_i2s_dai);
 345        if (ret != 0)
 346                clk_put(clk_i2s);
 347
 348        /*
 349         * PXA Developer's Manual:
 350         * If SACR0[ENB] is toggled in the middle of a normal operation,
 351         * the SACR0[RST] bit must also be set and cleared to reset all
 352         * I2S controller registers.
 353         */
 354        SACR0 = SACR0_RST;
 355        SACR0 = 0;
 356        /* Make sure RPL and REC are disabled */
 357        SACR1 = SACR1_DRPL | SACR1_DREC;
 358        /* Along with FIFO servicing */
 359        SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
 360
 361        return ret;
 362}
 363
 364static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
 365{
 366        snd_soc_unregister_dai(&pxa_i2s_dai);
 367        clk_put(clk_i2s);
 368        clk_i2s = ERR_PTR(-ENOENT);
 369        return 0;
 370}
 371
 372static struct platform_driver pxa2xx_i2s_driver = {
 373        .probe = pxa2xx_i2s_probe,
 374        .remove = __devexit_p(pxa2xx_i2s_remove),
 375
 376        .driver = {
 377                .name = "pxa2xx-i2s",
 378                .owner = THIS_MODULE,
 379        },
 380};
 381
 382static int __init pxa2xx_i2s_init(void)
 383{
 384        clk_i2s = ERR_PTR(-ENOENT);
 385        return platform_driver_register(&pxa2xx_i2s_driver);
 386}
 387
 388static void __exit pxa2xx_i2s_exit(void)
 389{
 390        platform_driver_unregister(&pxa2xx_i2s_driver);
 391}
 392
 393module_init(pxa2xx_i2s_init);
 394module_exit(pxa2xx_i2s_exit);
 395
 396/* Module information */
 397MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 398MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
 399MODULE_LICENSE("GPL");
 400