~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to sound/soc/au1x/ac97c.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Au1000/Au1500/Au1100 AC97C controller driver for ASoC
 
3
 *
 
4
 * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
 
5
 *
 
6
 * based on the old ALSA driver originally written by
 
7
 *                      Charles Eidsness <charles@cooper-street.com>
 
8
 */
 
9
 
 
10
#include <linux/init.h>
 
11
#include <linux/module.h>
 
12
#include <linux/slab.h>
 
13
#include <linux/device.h>
 
14
#include <linux/delay.h>
 
15
#include <linux/mutex.h>
 
16
#include <linux/platform_device.h>
 
17
#include <linux/suspend.h>
 
18
#include <sound/core.h>
 
19
#include <sound/pcm.h>
 
20
#include <sound/initval.h>
 
21
#include <sound/soc.h>
 
22
#include <asm/mach-au1x00/au1000.h>
 
23
 
 
24
#include "psc.h"
 
25
 
 
26
/* register offsets and bits */
 
27
#define AC97_CONFIG     0x00
 
28
#define AC97_STATUS     0x04
 
29
#define AC97_DATA       0x08
 
30
#define AC97_CMDRESP    0x0c
 
31
#define AC97_ENABLE     0x10
 
32
 
 
33
#define CFG_RC(x)       (((x) & 0x3ff) << 13)   /* valid rx slots mask */
 
34
#define CFG_XS(x)       (((x) & 0x3ff) << 3)    /* valid tx slots mask */
 
35
#define CFG_SG          (1 << 2)        /* sync gate */
 
36
#define CFG_SN          (1 << 1)        /* sync control */
 
37
#define CFG_RS          (1 << 0)        /* acrst# control */
 
38
#define STAT_XU         (1 << 11)       /* tx underflow */
 
39
#define STAT_XO         (1 << 10)       /* tx overflow */
 
40
#define STAT_RU         (1 << 9)        /* rx underflow */
 
41
#define STAT_RO         (1 << 8)        /* rx overflow */
 
42
#define STAT_RD         (1 << 7)        /* codec ready */
 
43
#define STAT_CP         (1 << 6)        /* command pending */
 
44
#define STAT_TE         (1 << 4)        /* tx fifo empty */
 
45
#define STAT_TF         (1 << 3)        /* tx fifo full */
 
46
#define STAT_RE         (1 << 1)        /* rx fifo empty */
 
47
#define STAT_RF         (1 << 0)        /* rx fifo full */
 
48
#define CMD_SET_DATA(x) (((x) & 0xffff) << 16)
 
49
#define CMD_GET_DATA(x) ((x) & 0xffff)
 
50
#define CMD_READ        (1 << 7)
 
51
#define CMD_WRITE       (0 << 7)
 
52
#define CMD_IDX(x)      ((x) & 0x7f)
 
53
#define EN_D            (1 << 1)        /* DISable bit */
 
54
#define EN_CE           (1 << 0)        /* clock enable bit */
 
55
 
 
56
/* how often to retry failed codec register reads/writes */
 
57
#define AC97_RW_RETRIES 5
 
58
 
 
59
#define AC97_RATES      \
 
60
        SNDRV_PCM_RATE_CONTINUOUS
 
61
 
 
62
#define AC97_FMTS       \
 
63
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE)
 
64
 
 
65
/* instance data. There can be only one, MacLeod!!!!, fortunately there IS only
 
66
 * once AC97C on early Alchemy chips. The newer ones aren't so lucky.
 
67
 */
 
68
static struct au1xpsc_audio_data *ac97c_workdata;
 
69
#define ac97_to_ctx(x)          ac97c_workdata
 
70
 
 
71
static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg)
 
72
{
 
73
        return __raw_readl(ctx->mmio + reg);
 
74
}
 
75
 
 
76
static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v)
 
77
{
 
78
        __raw_writel(v, ctx->mmio + reg);
 
79
        wmb();
 
80
}
 
81
 
 
82
static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97,
 
83
                                          unsigned short r)
 
84
{
 
85
        struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
 
86
        unsigned int tmo, retry;
 
87
        unsigned long data;
 
88
 
 
89
        data = ~0;
 
90
        retry = AC97_RW_RETRIES;
 
91
        do {
 
92
                mutex_lock(&ctx->lock);
 
93
 
 
94
                tmo = 5;
 
95
                while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
 
96
                        udelay(21);     /* wait an ac97 frame time */
 
97
                if (!tmo) {
 
98
                        pr_debug("ac97rd timeout #1\n");
 
99
                        goto next;
 
100
                }
 
101
 
 
102
                WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ);
 
103
 
 
104
                /* stupid errata: data is only valid for 21us, so
 
105
                 * poll, Forrest, poll...
 
106
                 */
 
107
                tmo = 0x10000;
 
108
                while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
 
109
                        asm volatile ("nop");
 
110
                data = RD(ctx, AC97_CMDRESP);
 
111
 
 
112
                if (!tmo)
 
113
                        pr_debug("ac97rd timeout #2\n");
 
114
 
 
115
next:
 
116
                mutex_unlock(&ctx->lock);
 
117
        } while (--retry && !tmo);
 
118
 
 
119
        pr_debug("AC97RD %04x %04lx %d\n", r, data, retry);
 
120
 
 
121
        return retry ? data & 0xffff : 0xffff;
 
122
}
 
123
 
 
124
static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r,
 
125
                                 unsigned short v)
 
126
{
 
127
        struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
 
128
        unsigned int tmo, retry;
 
129
 
 
130
        retry = AC97_RW_RETRIES;
 
131
        do {
 
132
                mutex_lock(&ctx->lock);
 
133
 
 
134
                for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--)
 
135
                        udelay(21);
 
136
                if (!tmo) {
 
137
                        pr_debug("ac97wr timeout #1\n");
 
138
                        goto next;
 
139
                }
 
140
 
 
141
                WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v));
 
142
 
 
143
                for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--)
 
144
                        udelay(21);
 
145
                if (!tmo)
 
146
                        pr_debug("ac97wr timeout #2\n");
 
147
next:
 
148
                mutex_unlock(&ctx->lock);
 
149
        } while (--retry && !tmo);
 
150
 
 
151
        pr_debug("AC97WR %04x %04x %d\n", r, v, retry);
 
152
}
 
153
 
 
154
static void au1xac97c_ac97_warm_reset(struct snd_ac97 *ac97)
 
155
{
 
156
        struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
 
157
 
 
158
        WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG | CFG_SN);
 
159
        msleep(20);
 
160
        WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG);
 
161
        WR(ctx, AC97_CONFIG, ctx->cfg);
 
162
}
 
163
 
 
164
static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97)
 
165
{
 
166
        struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
 
167
        int i;
 
168
 
 
169
        WR(ctx, AC97_CONFIG, ctx->cfg | CFG_RS);
 
170
        msleep(500);
 
171
        WR(ctx, AC97_CONFIG, ctx->cfg);
 
172
 
 
173
        /* wait for codec ready */
 
174
        i = 50;
 
175
        while (((RD(ctx, AC97_STATUS) & STAT_RD) == 0) && --i)
 
176
                msleep(20);
 
177
        if (!i)
 
178
                printk(KERN_ERR "ac97c: codec not ready after cold reset\n");
 
179
}
 
180
 
 
181
/* AC97 controller operations */
 
182
struct snd_ac97_bus_ops soc_ac97_ops = {
 
183
        .read           = au1xac97c_ac97_read,
 
184
        .write          = au1xac97c_ac97_write,
 
185
        .reset          = au1xac97c_ac97_cold_reset,
 
186
        .warm_reset     = au1xac97c_ac97_warm_reset,
 
187
};
 
188
EXPORT_SYMBOL_GPL(soc_ac97_ops);        /* globals be gone! */
 
189
 
 
190
static int alchemy_ac97c_startup(struct snd_pcm_substream *substream,
 
191
                                 struct snd_soc_dai *dai)
 
192
{
 
193
        struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
 
194
        snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]);
 
195
        return 0;
 
196
}
 
197
 
 
198
static struct snd_soc_dai_ops alchemy_ac97c_ops = {
 
199
        .startup                = alchemy_ac97c_startup,
 
200
};
 
201
 
 
202
static int au1xac97c_dai_probe(struct snd_soc_dai *dai)
 
203
{
 
204
        return ac97c_workdata ? 0 : -ENODEV;
 
205
}
 
206
 
 
207
static struct snd_soc_dai_driver au1xac97c_dai_driver = {
 
208
        .name                   = "alchemy-ac97c",
 
209
        .ac97_control           = 1,
 
210
        .probe                  = au1xac97c_dai_probe,
 
211
        .playback = {
 
212
                .rates          = AC97_RATES,
 
213
                .formats        = AC97_FMTS,
 
214
                .channels_min   = 2,
 
215
                .channels_max   = 2,
 
216
        },
 
217
        .capture = {
 
218
                .rates          = AC97_RATES,
 
219
                .formats        = AC97_FMTS,
 
220
                .channels_min   = 2,
 
221
                .channels_max   = 2,
 
222
        },
 
223
        .ops                    = &alchemy_ac97c_ops,
 
224
};
 
225
 
 
226
static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 
227
{
 
228
        int ret;
 
229
        struct resource *iores, *dmares;
 
230
        struct au1xpsc_audio_data *ctx;
 
231
 
 
232
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 
233
        if (!ctx)
 
234
                return -ENOMEM;
 
235
 
 
236
        mutex_init(&ctx->lock);
 
237
 
 
238
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
239
        if (!iores) {
 
240
                ret = -ENODEV;
 
241
                goto out0;
 
242
        }
 
243
 
 
244
        ret = -EBUSY;
 
245
        if (!request_mem_region(iores->start, resource_size(iores),
 
246
                                pdev->name))
 
247
                goto out0;
 
248
 
 
249
        ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
 
250
        if (!ctx->mmio)
 
251
                goto out1;
 
252
 
 
253
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 
254
        if (!dmares)
 
255
                goto out2;
 
256
        ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
257
 
 
258
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 
259
        if (!dmares)
 
260
                goto out2;
 
261
        ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
262
 
 
263
        /* switch it on */
 
264
        WR(ctx, AC97_ENABLE, EN_D | EN_CE);
 
265
        WR(ctx, AC97_ENABLE, EN_CE);
 
266
 
 
267
        ctx->cfg = CFG_RC(3) | CFG_XS(3);
 
268
        WR(ctx, AC97_CONFIG, ctx->cfg);
 
269
 
 
270
        platform_set_drvdata(pdev, ctx);
 
271
 
 
272
        ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
 
273
        if (ret)
 
274
                goto out2;
 
275
 
 
276
        ac97c_workdata = ctx;
 
277
        return 0;
 
278
 
 
279
out2:
 
280
        iounmap(ctx->mmio);
 
281
out1:
 
282
        release_mem_region(iores->start, resource_size(iores));
 
283
out0:
 
284
        kfree(ctx);
 
285
        return ret;
 
286
}
 
287
 
 
288
static int __devexit au1xac97c_drvremove(struct platform_device *pdev)
 
289
{
 
290
        struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
 
291
        struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
292
 
 
293
        snd_soc_unregister_dai(&pdev->dev);
 
294
 
 
295
        WR(ctx, AC97_ENABLE, EN_D);     /* clock off, disable */
 
296
 
 
297
        iounmap(ctx->mmio);
 
298
        release_mem_region(r->start, resource_size(r));
 
299
        kfree(ctx);
 
300
 
 
301
        ac97c_workdata = NULL;  /* MDEV */
 
302
 
 
303
        return 0;
 
304
}
 
305
 
 
306
#ifdef CONFIG_PM
 
307
static int au1xac97c_drvsuspend(struct device *dev)
 
308
{
 
309
        struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
 
310
 
 
311
        WR(ctx, AC97_ENABLE, EN_D);     /* clock off, disable */
 
312
 
 
313
        return 0;
 
314
}
 
315
 
 
316
static int au1xac97c_drvresume(struct device *dev)
 
317
{
 
318
        struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
 
319
 
 
320
        WR(ctx, AC97_ENABLE, EN_D | EN_CE);
 
321
        WR(ctx, AC97_ENABLE, EN_CE);
 
322
        WR(ctx, AC97_CONFIG, ctx->cfg);
 
323
 
 
324
        return 0;
 
325
}
 
326
 
 
327
static const struct dev_pm_ops au1xpscac97_pmops = {
 
328
        .suspend        = au1xac97c_drvsuspend,
 
329
        .resume         = au1xac97c_drvresume,
 
330
};
 
331
 
 
332
#define AU1XPSCAC97_PMOPS (&au1xpscac97_pmops)
 
333
 
 
334
#else
 
335
 
 
336
#define AU1XPSCAC97_PMOPS NULL
 
337
 
 
338
#endif
 
339
 
 
340
static struct platform_driver au1xac97c_driver = {
 
341
        .driver = {
 
342
                .name   = "alchemy-ac97c",
 
343
                .owner  = THIS_MODULE,
 
344
                .pm     = AU1XPSCAC97_PMOPS,
 
345
        },
 
346
        .probe          = au1xac97c_drvprobe,
 
347
        .remove         = __devexit_p(au1xac97c_drvremove),
 
348
};
 
349
 
 
350
static int __init au1xac97c_load(void)
 
351
{
 
352
        ac97c_workdata = NULL;
 
353
        return platform_driver_register(&au1xac97c_driver);
 
354
}
 
355
 
 
356
static void __exit au1xac97c_unload(void)
 
357
{
 
358
        platform_driver_unregister(&au1xac97c_driver);
 
359
}
 
360
 
 
361
module_init(au1xac97c_load);
 
362
module_exit(au1xac97c_unload);
 
363
 
 
364
MODULE_LICENSE("GPL");
 
365
MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver");
 
366
MODULE_AUTHOR("Manuel Lauss");