linux/sound/soc/au1x/psc-ac97.c
<<
>>
Prefs
   1/*
   2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
   3 *
   4 * (c) 2007-2009 MSC Vertriebsges.m.b.H.,
   5 *      Manuel Lauss <manuel.lauss@gmail.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * Au1xxx-PSC AC97 glue.
  12 *
  13 * NOTE: all of these drivers can only work with a SINGLE instance
  14 *       of a PSC. Multiple independent audio devices are impossible
  15 *       with ASoC v1.
  16 */
  17
  18#include <linux/init.h>
  19#include <linux/module.h>
  20#include <linux/device.h>
  21#include <linux/delay.h>
  22#include <linux/mutex.h>
  23#include <linux/suspend.h>
  24#include <sound/core.h>
  25#include <sound/pcm.h>
  26#include <sound/initval.h>
  27#include <sound/soc.h>
  28#include <asm/mach-au1x00/au1000.h>
  29#include <asm/mach-au1x00/au1xxx_psc.h>
  30
  31#include "psc.h"
  32
  33/* how often to retry failed codec register reads/writes */
  34#define AC97_RW_RETRIES 5
  35
  36#define AC97_DIR        \
  37        (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
  38
  39#define AC97_RATES      \
  40        SNDRV_PCM_RATE_8000_48000
  41
  42#define AC97_FMTS       \
  43        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
  44
  45#define AC97PCR_START(stype)    \
  46        ((stype) == PCM_TX ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
  47#define AC97PCR_STOP(stype)     \
  48        ((stype) == PCM_TX ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
  49#define AC97PCR_CLRFIFO(stype)  \
  50        ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
  51
  52#define AC97STAT_BUSY(stype)    \
  53        ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
  54
  55/* instance data. There can be only one, MacLeod!!!! */
  56static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
  57
  58/* AC97 controller reads codec register */
  59static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
  60                                        unsigned short reg)
  61{
  62        /* FIXME */
  63        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
  64        unsigned short data, retry, tmo;
  65
  66        au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
  67        au_sync();
  68
  69        retry = AC97_RW_RETRIES;
  70        do {
  71                mutex_lock(&pscdata->lock);
  72
  73                au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
  74                          AC97_CDC(pscdata));
  75                au_sync();
  76
  77                tmo = 2000;
  78                while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
  79                        && --tmo)
  80                        udelay(2);
  81
  82                data = au_readl(AC97_CDC(pscdata)) & 0xffff;
  83
  84                au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
  85                au_sync();
  86
  87                mutex_unlock(&pscdata->lock);
  88        } while (--retry && !tmo);
  89
  90        return retry ? data : 0xffff;
  91}
  92
  93/* AC97 controller writes to codec register */
  94static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
  95                                unsigned short val)
  96{
  97        /* FIXME */
  98        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
  99        unsigned int tmo, retry;
 100
 101        au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
 102        au_sync();
 103
 104        retry = AC97_RW_RETRIES;
 105        do {
 106                mutex_lock(&pscdata->lock);
 107
 108                au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
 109                          AC97_CDC(pscdata));
 110                au_sync();
 111
 112                tmo = 2000;
 113                while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
 114                       && --tmo)
 115                        udelay(2);
 116
 117                au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
 118                au_sync();
 119
 120                mutex_unlock(&pscdata->lock);
 121        } while (--retry && !tmo);
 122}
 123
 124/* AC97 controller asserts a warm reset */
 125static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
 126{
 127        /* FIXME */
 128        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
 129
 130        au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
 131        au_sync();
 132        msleep(10);
 133        au_writel(0, AC97_RST(pscdata));
 134        au_sync();
 135}
 136
 137static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
 138{
 139        /* FIXME */
 140        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
 141        int i;
 142
 143        /* disable PSC during cold reset */
 144        au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
 145        au_sync();
 146        au_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
 147        au_sync();
 148
 149        /* issue cold reset */
 150        au_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
 151        au_sync();
 152        msleep(500);
 153        au_writel(0, AC97_RST(pscdata));
 154        au_sync();
 155
 156        /* enable PSC */
 157        au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
 158        au_sync();
 159
 160        /* wait for PSC to indicate it's ready */
 161        i = 1000;
 162        while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
 163                msleep(1);
 164
 165        if (i == 0) {
 166                printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
 167                return;
 168        }
 169
 170        /* enable the ac97 function */
 171        au_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
 172        au_sync();
 173
 174        /* wait for AC97 core to become ready */
 175        i = 1000;
 176        while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
 177                msleep(1);
 178        if (i == 0)
 179                printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
 180}
 181
 182/* AC97 controller operations */
 183struct snd_ac97_bus_ops soc_ac97_ops = {
 184        .read           = au1xpsc_ac97_read,
 185        .write          = au1xpsc_ac97_write,
 186        .reset          = au1xpsc_ac97_cold_reset,
 187        .warm_reset     = au1xpsc_ac97_warm_reset,
 188};
 189EXPORT_SYMBOL_GPL(soc_ac97_ops);
 190
 191static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
 192                                  struct snd_pcm_hw_params *params,
 193                                  struct snd_soc_dai *dai)
 194{
 195        /* FIXME */
 196        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
 197        unsigned long r, ro, stat;
 198        int chans, stype = SUBSTREAM_TYPE(substream);
 199
 200        chans = params_channels(params);
 201
 202        r = ro = au_readl(AC97_CFG(pscdata));
 203        stat = au_readl(AC97_STAT(pscdata));
 204
 205        /* already active? */
 206        if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
 207                /* reject parameters not currently set up */
 208                if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) ||
 209                    (pscdata->rate != params_rate(params)))
 210                        return -EINVAL;
 211        } else {
 212
 213                /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */
 214                r &= ~PSC_AC97CFG_LEN_MASK;
 215                r |= PSC_AC97CFG_SET_LEN(params->msbits);
 216
 217                /* channels: enable slots for front L/R channel */
 218                if (stype == PCM_TX) {
 219                        r &= ~PSC_AC97CFG_TXSLOT_MASK;
 220                        r |= PSC_AC97CFG_TXSLOT_ENA(3);
 221                        r |= PSC_AC97CFG_TXSLOT_ENA(4);
 222                } else {
 223                        r &= ~PSC_AC97CFG_RXSLOT_MASK;
 224                        r |= PSC_AC97CFG_RXSLOT_ENA(3);
 225                        r |= PSC_AC97CFG_RXSLOT_ENA(4);
 226                }
 227
 228                /* do we need to poke the hardware? */
 229                if (!(r ^ ro))
 230                        goto out;
 231
 232                /* ac97 engine is about to be disabled */
 233                mutex_lock(&pscdata->lock);
 234
 235                /* disable AC97 device controller first... */
 236                au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
 237                au_sync();
 238
 239                /* ...wait for it... */
 240                while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)
 241                        asm volatile ("nop");
 242
 243                /* ...write config... */
 244                au_writel(r, AC97_CFG(pscdata));
 245                au_sync();
 246
 247                /* ...enable the AC97 controller again... */
 248                au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
 249                au_sync();
 250
 251                /* ...and wait for ready bit */
 252                while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR))
 253                        asm volatile ("nop");
 254
 255                mutex_unlock(&pscdata->lock);
 256
 257                pscdata->cfg = r;
 258                pscdata->rate = params_rate(params);
 259        }
 260
 261out:
 262        return 0;
 263}
 264
 265static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
 266                                int cmd, struct snd_soc_dai *dai)
 267{
 268        /* FIXME */
 269        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
 270        int ret, stype = SUBSTREAM_TYPE(substream);
 271
 272        ret = 0;
 273
 274        switch (cmd) {
 275        case SNDRV_PCM_TRIGGER_START:
 276        case SNDRV_PCM_TRIGGER_RESUME:
 277                au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
 278                au_sync();
 279                au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
 280                au_sync();
 281                break;
 282        case SNDRV_PCM_TRIGGER_STOP:
 283        case SNDRV_PCM_TRIGGER_SUSPEND:
 284                au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
 285                au_sync();
 286
 287                while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
 288                        asm volatile ("nop");
 289
 290                au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
 291                au_sync();
 292
 293                break;
 294        default:
 295                ret = -EINVAL;
 296        }
 297        return ret;
 298}
 299
 300static int au1xpsc_ac97_probe(struct platform_device *pdev,
 301                              struct snd_soc_dai *dai)
 302{
 303        int ret;
 304        struct resource *r;
 305        unsigned long sel;
 306
 307        if (au1xpsc_ac97_workdata)
 308                return -EBUSY;
 309
 310        au1xpsc_ac97_workdata =
 311                kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
 312        if (!au1xpsc_ac97_workdata)
 313                return -ENOMEM;
 314
 315        mutex_init(&au1xpsc_ac97_workdata->lock);
 316
 317        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 318        if (!r) {
 319                ret = -ENODEV;
 320                goto out0;
 321        }
 322
 323        ret = -EBUSY;
 324        au1xpsc_ac97_workdata->ioarea =
 325                request_mem_region(r->start, r->end - r->start + 1,
 326                                        "au1xpsc_ac97");
 327        if (!au1xpsc_ac97_workdata->ioarea)
 328                goto out0;
 329
 330        au1xpsc_ac97_workdata->mmio = ioremap(r->start, 0xffff);
 331        if (!au1xpsc_ac97_workdata->mmio)
 332                goto out1;
 333
 334        /* configuration: max dma trigger threshold, enable ac97 */
 335        au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 |
 336                                     PSC_AC97CFG_TT_FIFO8 |
 337                                     PSC_AC97CFG_DE_ENABLE;
 338
 339        /* preserve PSC clock source set up by platform (dev.platform_data
 340         * is already occupied by soc layer)
 341         */
 342        sel = au_readl(PSC_SEL(au1xpsc_ac97_workdata)) & PSC_SEL_CLK_MASK;
 343        au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
 344        au_sync();
 345        au_writel(0, PSC_SEL(au1xpsc_ac97_workdata));
 346        au_sync();
 347        au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(au1xpsc_ac97_workdata));
 348        au_sync();
 349        /* next up: cold reset.  Dont check for PSC-ready now since
 350         * there may not be any codec clock yet.
 351         */
 352
 353        return 0;
 354
 355out1:
 356        release_resource(au1xpsc_ac97_workdata->ioarea);
 357        kfree(au1xpsc_ac97_workdata->ioarea);
 358out0:
 359        kfree(au1xpsc_ac97_workdata);
 360        au1xpsc_ac97_workdata = NULL;
 361        return ret;
 362}
 363
 364static void au1xpsc_ac97_remove(struct platform_device *pdev,
 365                                struct snd_soc_dai *dai)
 366{
 367        /* disable PSC completely */
 368        au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
 369        au_sync();
 370        au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
 371        au_sync();
 372
 373        iounmap(au1xpsc_ac97_workdata->mmio);
 374        release_resource(au1xpsc_ac97_workdata->ioarea);
 375        kfree(au1xpsc_ac97_workdata->ioarea);
 376        kfree(au1xpsc_ac97_workdata);
 377        au1xpsc_ac97_workdata = NULL;
 378}
 379
 380static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai)
 381{
 382        /* save interesting registers and disable PSC */
 383        au1xpsc_ac97_workdata->pm[0] =
 384                        au_readl(PSC_SEL(au1xpsc_ac97_workdata));
 385
 386        au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
 387        au_sync();
 388        au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
 389        au_sync();
 390
 391        return 0;
 392}
 393
 394static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
 395{
 396        /* restore PSC clock config */
 397        au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
 398                        PSC_SEL(au1xpsc_ac97_workdata));
 399        au_sync();
 400
 401        /* after this point the ac97 core will cold-reset the codec.
 402         * During cold-reset the PSC is reinitialized and the last
 403         * configuration set up in hw_params() is restored.
 404         */
 405        return 0;
 406}
 407
 408static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
 409        .trigger        = au1xpsc_ac97_trigger,
 410        .hw_params      = au1xpsc_ac97_hw_params,
 411};
 412
 413struct snd_soc_dai au1xpsc_ac97_dai = {
 414        .name                   = "au1xpsc_ac97",
 415        .ac97_control           = 1,
 416        .probe                  = au1xpsc_ac97_probe,
 417        .remove                 = au1xpsc_ac97_remove,
 418        .suspend                = au1xpsc_ac97_suspend,
 419        .resume                 = au1xpsc_ac97_resume,
 420        .playback = {
 421                .rates          = AC97_RATES,
 422                .formats        = AC97_FMTS,
 423                .channels_min   = 2,
 424                .channels_max   = 2,
 425        },
 426        .capture = {
 427                .rates          = AC97_RATES,
 428                .formats        = AC97_FMTS,
 429                .channels_min   = 2,
 430                .channels_max   = 2,
 431        },
 432        .ops = &au1xpsc_ac97_dai_ops,
 433};
 434EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
 435
 436static int __init au1xpsc_ac97_init(void)
 437{
 438        au1xpsc_ac97_workdata = NULL;
 439        return snd_soc_register_dai(&au1xpsc_ac97_dai);
 440}
 441
 442static void __exit au1xpsc_ac97_exit(void)
 443{
 444        snd_soc_unregister_dai(&au1xpsc_ac97_dai);
 445}
 446
 447module_init(au1xpsc_ac97_init);
 448module_exit(au1xpsc_ac97_exit);
 449
 450MODULE_LICENSE("GPL");
 451MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
 452MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>");
 453