0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/device.h>
0015 #include <linux/delay.h>
0016 #include <linux/mutex.h>
0017 #include <linux/suspend.h>
0018 #include <sound/core.h>
0019 #include <sound/pcm.h>
0020 #include <sound/initval.h>
0021 #include <sound/soc.h>
0022 #include <asm/mach-au1x00/au1000.h>
0023 #include <asm/mach-au1x00/au1xxx_psc.h>
0024
0025 #include "psc.h"
0026
0027
0028 #define AC97_RW_RETRIES 5
0029
0030 #define AC97_DIR \
0031 (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
0032
0033 #define AC97_RATES \
0034 SNDRV_PCM_RATE_8000_48000
0035
0036 #define AC97_FMTS \
0037 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
0038
0039 #define AC97PCR_START(stype) \
0040 ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
0041 #define AC97PCR_STOP(stype) \
0042 ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
0043 #define AC97PCR_CLRFIFO(stype) \
0044 ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
0045
0046 #define AC97STAT_BUSY(stype) \
0047 ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
0048
0049
0050 static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
0051
0052 #if 0
0053
0054
0055
0056
0057
0058 static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x)
0059 {
0060 struct snd_soc_card *c = x->bus->card->private_data;
0061 return snd_soc_dai_get_drvdata(c->asoc_rtd_to_cpu(rtd, 0));
0062 }
0063
0064 #else
0065
0066 #define ac97_to_pscdata(x) au1xpsc_ac97_workdata
0067
0068 #endif
0069
0070
0071 static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
0072 unsigned short reg)
0073 {
0074 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
0075 unsigned short retry, tmo;
0076 unsigned long data;
0077
0078 __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
0079 wmb();
0080
0081 retry = AC97_RW_RETRIES;
0082 do {
0083 mutex_lock(&pscdata->lock);
0084
0085 __raw_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
0086 AC97_CDC(pscdata));
0087 wmb();
0088
0089 tmo = 20;
0090 do {
0091 udelay(21);
0092 if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
0093 break;
0094 } while (--tmo);
0095
0096 data = __raw_readl(AC97_CDC(pscdata));
0097
0098 __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
0099 wmb();
0100
0101 mutex_unlock(&pscdata->lock);
0102
0103 if (reg != ((data >> 16) & 0x7f))
0104 tmo = 1;
0105
0106 } while (--retry && !tmo);
0107
0108 return retry ? data & 0xffff : 0xffff;
0109 }
0110
0111
0112 static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
0113 unsigned short val)
0114 {
0115 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
0116 unsigned int tmo, retry;
0117
0118 __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
0119 wmb();
0120
0121 retry = AC97_RW_RETRIES;
0122 do {
0123 mutex_lock(&pscdata->lock);
0124
0125 __raw_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
0126 AC97_CDC(pscdata));
0127 wmb();
0128
0129 tmo = 20;
0130 do {
0131 udelay(21);
0132 if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
0133 break;
0134 } while (--tmo);
0135
0136 __raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
0137 wmb();
0138
0139 mutex_unlock(&pscdata->lock);
0140 } while (--retry && !tmo);
0141 }
0142
0143
0144 static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
0145 {
0146 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
0147
0148 __raw_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
0149 wmb();
0150 msleep(10);
0151 __raw_writel(0, AC97_RST(pscdata));
0152 wmb();
0153 }
0154
0155 static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
0156 {
0157 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
0158 int i;
0159
0160
0161 __raw_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
0162 wmb();
0163 __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
0164 wmb();
0165
0166
0167 __raw_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
0168 wmb();
0169 msleep(500);
0170 __raw_writel(0, AC97_RST(pscdata));
0171 wmb();
0172
0173
0174 __raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
0175 wmb();
0176
0177
0178 i = 1000;
0179 while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
0180 msleep(1);
0181
0182 if (i == 0) {
0183 printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
0184 return;
0185 }
0186
0187
0188 __raw_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
0189 wmb();
0190
0191
0192 i = 1000;
0193 while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
0194 msleep(1);
0195 if (i == 0)
0196 printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
0197 }
0198
0199
0200 static struct snd_ac97_bus_ops psc_ac97_ops = {
0201 .read = au1xpsc_ac97_read,
0202 .write = au1xpsc_ac97_write,
0203 .reset = au1xpsc_ac97_cold_reset,
0204 .warm_reset = au1xpsc_ac97_warm_reset,
0205 };
0206
0207 static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
0208 struct snd_pcm_hw_params *params,
0209 struct snd_soc_dai *dai)
0210 {
0211 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
0212 unsigned long r, ro, stat;
0213 int chans, t, stype = substream->stream;
0214
0215 chans = params_channels(params);
0216
0217 r = ro = __raw_readl(AC97_CFG(pscdata));
0218 stat = __raw_readl(AC97_STAT(pscdata));
0219
0220
0221 if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
0222
0223 if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) ||
0224 (pscdata->rate != params_rate(params)))
0225 return -EINVAL;
0226 } else {
0227
0228
0229 r &= ~PSC_AC97CFG_LEN_MASK;
0230 r |= PSC_AC97CFG_SET_LEN(params->msbits);
0231
0232
0233 if (stype == SNDRV_PCM_STREAM_PLAYBACK) {
0234 r &= ~PSC_AC97CFG_TXSLOT_MASK;
0235 r |= PSC_AC97CFG_TXSLOT_ENA(3);
0236 r |= PSC_AC97CFG_TXSLOT_ENA(4);
0237 } else {
0238 r &= ~PSC_AC97CFG_RXSLOT_MASK;
0239 r |= PSC_AC97CFG_RXSLOT_ENA(3);
0240 r |= PSC_AC97CFG_RXSLOT_ENA(4);
0241 }
0242
0243
0244 if (!(r ^ ro))
0245 goto out;
0246
0247
0248 mutex_lock(&pscdata->lock);
0249
0250
0251 __raw_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
0252 wmb();
0253
0254
0255 t = 100;
0256 while ((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
0257 msleep(1);
0258
0259 if (!t)
0260 printk(KERN_ERR "PSC-AC97: can't disable!\n");
0261
0262
0263 __raw_writel(r, AC97_CFG(pscdata));
0264 wmb();
0265
0266
0267 __raw_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
0268 wmb();
0269
0270
0271 t = 100;
0272 while ((!(__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
0273 msleep(1);
0274
0275 if (!t)
0276 printk(KERN_ERR "PSC-AC97: can't enable!\n");
0277
0278 mutex_unlock(&pscdata->lock);
0279
0280 pscdata->cfg = r;
0281 pscdata->rate = params_rate(params);
0282 }
0283
0284 out:
0285 return 0;
0286 }
0287
0288 static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
0289 int cmd, struct snd_soc_dai *dai)
0290 {
0291 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
0292 int ret, stype = substream->stream;
0293
0294 ret = 0;
0295
0296 switch (cmd) {
0297 case SNDRV_PCM_TRIGGER_START:
0298 case SNDRV_PCM_TRIGGER_RESUME:
0299 __raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
0300 wmb();
0301 __raw_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
0302 wmb();
0303 break;
0304 case SNDRV_PCM_TRIGGER_STOP:
0305 case SNDRV_PCM_TRIGGER_SUSPEND:
0306 __raw_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
0307 wmb();
0308
0309 while (__raw_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
0310 asm volatile ("nop");
0311
0312 __raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
0313 wmb();
0314
0315 break;
0316 default:
0317 ret = -EINVAL;
0318 }
0319 return ret;
0320 }
0321
0322 static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream,
0323 struct snd_soc_dai *dai)
0324 {
0325 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
0326 snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
0327 return 0;
0328 }
0329
0330 static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
0331 {
0332 return au1xpsc_ac97_workdata ? 0 : -ENODEV;
0333 }
0334
0335 static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
0336 .startup = au1xpsc_ac97_startup,
0337 .trigger = au1xpsc_ac97_trigger,
0338 .hw_params = au1xpsc_ac97_hw_params,
0339 };
0340
0341 static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
0342 .probe = au1xpsc_ac97_probe,
0343 .playback = {
0344 .rates = AC97_RATES,
0345 .formats = AC97_FMTS,
0346 .channels_min = 2,
0347 .channels_max = 2,
0348 },
0349 .capture = {
0350 .rates = AC97_RATES,
0351 .formats = AC97_FMTS,
0352 .channels_min = 2,
0353 .channels_max = 2,
0354 },
0355 .ops = &au1xpsc_ac97_dai_ops,
0356 };
0357
0358 static const struct snd_soc_component_driver au1xpsc_ac97_component = {
0359 .name = "au1xpsc-ac97",
0360 .legacy_dai_naming = 1,
0361 };
0362
0363 static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
0364 {
0365 int ret;
0366 struct resource *dmares;
0367 unsigned long sel;
0368 struct au1xpsc_audio_data *wd;
0369
0370 wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),
0371 GFP_KERNEL);
0372 if (!wd)
0373 return -ENOMEM;
0374
0375 mutex_init(&wd->lock);
0376
0377 wd->mmio = devm_platform_ioremap_resource(pdev, 0);
0378 if (IS_ERR(wd->mmio))
0379 return PTR_ERR(wd->mmio);
0380
0381 dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
0382 if (!dmares)
0383 return -EBUSY;
0384 wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
0385
0386 dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
0387 if (!dmares)
0388 return -EBUSY;
0389 wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
0390
0391
0392 wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
0393 PSC_AC97CFG_DE_ENABLE;
0394
0395
0396 sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
0397 __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
0398 wmb();
0399 __raw_writel(0, PSC_SEL(wd));
0400 wmb();
0401 __raw_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
0402 wmb();
0403
0404
0405 memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
0406 sizeof(struct snd_soc_dai_driver));
0407 wd->dai_drv.name = dev_name(&pdev->dev);
0408
0409 platform_set_drvdata(pdev, wd);
0410
0411 ret = snd_soc_set_ac97_ops(&psc_ac97_ops);
0412 if (ret)
0413 return ret;
0414
0415 ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component,
0416 &wd->dai_drv, 1);
0417 if (ret)
0418 return ret;
0419
0420 au1xpsc_ac97_workdata = wd;
0421 return 0;
0422 }
0423
0424 static int au1xpsc_ac97_drvremove(struct platform_device *pdev)
0425 {
0426 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
0427
0428 snd_soc_unregister_component(&pdev->dev);
0429
0430
0431 __raw_writel(0, AC97_CFG(wd));
0432 wmb();
0433 __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
0434 wmb();
0435
0436 au1xpsc_ac97_workdata = NULL;
0437
0438 return 0;
0439 }
0440
0441 #ifdef CONFIG_PM
0442 static int au1xpsc_ac97_drvsuspend(struct device *dev)
0443 {
0444 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
0445
0446
0447 wd->pm[0] = __raw_readl(PSC_SEL(wd));
0448
0449 __raw_writel(0, AC97_CFG(wd));
0450 wmb();
0451 __raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
0452 wmb();
0453
0454 return 0;
0455 }
0456
0457 static int au1xpsc_ac97_drvresume(struct device *dev)
0458 {
0459 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
0460
0461
0462 __raw_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
0463 wmb();
0464
0465
0466
0467
0468
0469 return 0;
0470 }
0471
0472 static const struct dev_pm_ops au1xpscac97_pmops = {
0473 .suspend = au1xpsc_ac97_drvsuspend,
0474 .resume = au1xpsc_ac97_drvresume,
0475 };
0476
0477 #define AU1XPSCAC97_PMOPS &au1xpscac97_pmops
0478
0479 #else
0480
0481 #define AU1XPSCAC97_PMOPS NULL
0482
0483 #endif
0484
0485 static struct platform_driver au1xpsc_ac97_driver = {
0486 .driver = {
0487 .name = "au1xpsc_ac97",
0488 .pm = AU1XPSCAC97_PMOPS,
0489 },
0490 .probe = au1xpsc_ac97_drvprobe,
0491 .remove = au1xpsc_ac97_drvremove,
0492 };
0493
0494 module_platform_driver(au1xpsc_ac97_driver);
0495
0496 MODULE_LICENSE("GPL");
0497 MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
0498 MODULE_AUTHOR("Manuel Lauss");
0499