]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/allwinner/a10_codec.c
if_emac: Before generating a random MAC address, try using the SID rootkey
[FreeBSD/FreeBSD.git] / sys / arm / allwinner / a10_codec.c
1 /*-
2  * Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 /*
30  * Allwinner A10/A20 Audio Codec
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/bus.h>
39 #include <sys/rman.h>
40 #include <sys/condvar.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/gpio.h>
44
45 #include <machine/bus.h>
46
47 #include <dev/sound/pcm/sound.h>
48 #include <dev/sound/chip.h>
49
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
52
53 #include <dev/extres/clk/clk.h>
54
55 #include "sunxi_dma_if.h"
56 #include "mixer_if.h"
57 #include "gpio_if.h"
58
59 #define TX_TRIG_LEVEL   0xf
60 #define RX_TRIG_LEVEL   0x7
61 #define DRQ_CLR_CNT     0x3
62
63 #define AC_DAC_DPC      0x00
64 #define  DAC_DPC_EN_DA                  0x80000000
65 #define AC_DAC_FIFOC    0x04
66 #define  DAC_FIFOC_FS_SHIFT             29
67 #define  DAC_FIFOC_FS_MASK              (7U << DAC_FIFOC_FS_SHIFT)
68 #define   DAC_FS_48KHZ                  0
69 #define   DAC_FS_32KHZ                  1
70 #define   DAC_FS_24KHZ                  2
71 #define   DAC_FS_16KHZ                  3
72 #define   DAC_FS_12KHZ                  4
73 #define   DAC_FS_8KHZ                   5
74 #define   DAC_FS_192KHZ                 6
75 #define   DAC_FS_96KHZ                  7
76 #define  DAC_FIFOC_FIFO_MODE_SHIFT      24
77 #define  DAC_FIFOC_FIFO_MODE_MASK       (3U << DAC_FIFOC_FIFO_MODE_SHIFT)
78 #define   FIFO_MODE_24_31_8             0
79 #define   FIFO_MODE_16_31_16            0
80 #define   FIFO_MODE_16_15_0             1
81 #define  DAC_FIFOC_DRQ_CLR_CNT_SHIFT    21
82 #define  DAC_FIFOC_DRQ_CLR_CNT_MASK     (3U << DAC_FIFOC_DRQ_CLR_CNT_SHIFT)
83 #define  DAC_FIFOC_TX_TRIG_LEVEL_SHIFT  8
84 #define  DAC_FIFOC_TX_TRIG_LEVEL_MASK   (0x7f << DAC_FIFOC_TX_TRIG_LEVEL_SHIFT)
85 #define  DAC_FIFOC_MONO_EN              (1U << 6)
86 #define  DAC_FIFOC_TX_BITS              (1U << 5)
87 #define  DAC_FIFOC_DRQ_EN               (1U << 4)
88 #define  DAC_FIFOC_FIFO_FLUSH           (1U << 0)
89 #define AC_DAC_FIFOS    0x08
90 #define AC_DAC_TXDATA   0x0c
91 #define AC_DAC_ACTL     0x10
92 #define  DAC_ACTL_DACAREN               (1U << 31)
93 #define  DAC_ACTL_DACALEN               (1U << 30)
94 #define  DAC_ACTL_MIXEN                 (1U << 29)
95 #define  DAC_ACTL_DACPAS                (1U << 8)
96 #define  DAC_ACTL_PAMUTE                (1U << 6)
97 #define  DAC_ACTL_PAVOL_SHIFT           0
98 #define  DAC_ACTL_PAVOL_MASK            (0x3f << DAC_ACTL_PAVOL_SHIFT)
99 #define AC_ADC_FIFOC    0x1c
100 #define  ADC_FIFOC_FS_SHIFT             29
101 #define  ADC_FIFOC_FS_MASK              (7U << ADC_FIFOC_FS_SHIFT)
102 #define   ADC_FS_48KHZ          0
103 #define  ADC_FIFOC_EN_AD                (1U << 28)
104 #define  ADC_FIFOC_RX_FIFO_MODE         (1U << 24)
105 #define  ADC_FIFOC_RX_TRIG_LEVEL_SHIFT  8
106 #define  ADC_FIFOC_RX_TRIG_LEVEL_MASK   (0x1f << ADC_FIFOC_RX_TRIG_LEVEL_SHIFT)
107 #define  ADC_FIFOC_MONO_EN              (1U << 7)
108 #define  ADC_FIFOC_RX_BITS              (1U << 6)
109 #define  ADC_FIFOC_DRQ_EN               (1U << 4)
110 #define  ADC_FIFOC_FIFO_FLUSH           (1U << 1)
111 #define AC_ADC_FIFOS    0x20
112 #define AC_ADC_RXDATA   0x24
113 #define AC_ADC_ACTL     0x28
114 #define  ADC_ACTL_ADCREN                (1U << 31)
115 #define  ADC_ACTL_ADCLEN                (1U << 30)
116 #define  ADC_ACTL_PREG1EN               (1U << 29)
117 #define  ADC_ACTL_PREG2EN               (1U << 28)
118 #define  ADC_ACTL_VMICEN                (1U << 27)
119 #define  ADC_ACTL_ADCG_SHIFT            20
120 #define  ADC_ACTL_ADCG_MASK             (7U << ADC_ACTL_ADCG_SHIFT)
121 #define  ADC_ACTL_ADCIS_SHIFT           17
122 #define  ADC_ACTL_ADCIS_MASK            (7U << ADC_ACTL_ADCIS_SHIFT)
123 #define   ADC_IS_LINEIN                 0
124 #define   ADC_IS_FMIN                   1
125 #define   ADC_IS_MIC1                   2
126 #define   ADC_IS_MIC2                   3
127 #define   ADC_IS_MIC1_L_MIC2_R          4
128 #define   ADC_IS_MIC1_LR_MIC2_LR        5
129 #define   ADC_IS_OMIX                   6
130 #define   ADC_IS_LINEIN_L_MIC1_R        7
131 #define  ADC_ACTL_LNRDF                 (1U << 16)
132 #define  ADC_ACTL_LNPREG_SHIFT          13
133 #define  ADC_ACTL_LNPREG_MASK           (7U << ADC_ACTL_LNPREG_SHIFT)
134 #define  ADC_ACTL_PA_EN                 (1U << 4)
135 #define  ADC_ACTL_DDE                   (1U << 3)
136 #define AC_DAC_CNT      0x30
137 #define AC_ADC_CNT      0x34
138
139 static uint32_t a10codec_fmt[] = {
140         SND_FORMAT(AFMT_S16_LE, 1, 0),
141         SND_FORMAT(AFMT_S16_LE, 2, 0),
142         0
143 };
144
145 static struct pcmchan_caps a10codec_pcaps = { 8000, 192000, a10codec_fmt, 0 };
146 static struct pcmchan_caps a10codec_rcaps = { 8000, 48000, a10codec_fmt, 0 };
147
148 struct a10codec_info;
149
150 struct a10codec_chinfo {
151         struct snd_dbuf         *buffer;
152         struct pcm_channel      *channel;       
153         struct a10codec_info    *parent;
154         bus_dmamap_t            dmamap;
155         void                    *dmaaddr;
156         bus_addr_t              physaddr;
157         bus_size_t              fifo;
158         device_t                dmac;
159         void                    *dmachan;
160
161         int                     dir;
162         int                     run;
163         uint32_t                pos;
164         uint32_t                format;
165         uint32_t                blocksize;
166         uint32_t                speed;
167 };
168
169 struct a10codec_info {
170         device_t                dev;
171         struct resource         *res[2];
172         struct mtx              *lock;
173         bus_dma_tag_t           dmat;
174         unsigned                dmasize;
175         void                    *ih;
176
177         unsigned                drqtype_codec;
178         unsigned                drqtype_sdram;
179
180         struct a10codec_chinfo  play;
181         struct a10codec_chinfo  rec;
182 };
183
184 static struct resource_spec a10codec_spec[] = {
185         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
186         { SYS_RES_IRQ,          0,      RF_ACTIVE },
187         { -1, 0 }
188 };
189
190 #define CODEC_READ(sc, reg)             bus_read_4((sc)->res[0], (reg))
191 #define CODEC_WRITE(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
192
193 /*
194  * Mixer interface
195  */
196
197 static int
198 a10codec_mixer_init(struct snd_mixer *m)
199 {
200         struct a10codec_info *sc = mix_getdevinfo(m);
201         pcell_t prop[4];
202         phandle_t node;
203         device_t gpio;
204         uint32_t val;
205         ssize_t len;
206         int pin;
207
208         mix_setdevs(m, SOUND_MASK_VOLUME | SOUND_MASK_LINE | SOUND_MASK_RECLEV);
209         mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC);
210
211         /* Unmute input source to PA */
212         val = CODEC_READ(sc, AC_DAC_ACTL);
213         val |= DAC_ACTL_PAMUTE;
214         CODEC_WRITE(sc, AC_DAC_ACTL, val);
215
216         /* Enable PA */
217         val = CODEC_READ(sc, AC_ADC_ACTL);
218         val |= ADC_ACTL_PA_EN;
219         CODEC_WRITE(sc, AC_ADC_ACTL, val);
220
221         /* Unmute PA */
222         node = ofw_bus_get_node(sc->dev);
223         len = OF_getencprop(node, "allwinner,pa-gpios", prop, sizeof(prop));
224         if (len > 0 && (len / sizeof(prop[0])) == 4) {
225                 gpio = OF_device_from_xref(prop[0]);
226                 if (gpio != NULL) {
227                         pin = prop[1] * 32 + prop[2];
228                         GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
229                         GPIO_PIN_SET(gpio, pin, GPIO_PIN_LOW);
230                 }
231         }
232
233         return (0);
234 }
235
236 static const struct a10codec_mixer {
237         unsigned reg;
238         unsigned mask;
239         unsigned shift;
240 } a10codec_mixers[SOUND_MIXER_NRDEVICES] = {
241         [SOUND_MIXER_VOLUME]    = { AC_DAC_ACTL, DAC_ACTL_PAVOL_MASK,
242                                     DAC_ACTL_PAVOL_SHIFT },
243         [SOUND_MIXER_LINE]      = { AC_ADC_ACTL, ADC_ACTL_LNPREG_MASK,
244                                     ADC_ACTL_LNPREG_SHIFT },
245         [SOUND_MIXER_RECLEV]    = { AC_ADC_ACTL, ADC_ACTL_ADCG_MASK,
246                                     ADC_ACTL_ADCG_SHIFT },
247 }; 
248
249 static int
250 a10codec_mixer_set(struct snd_mixer *m, unsigned dev, unsigned left,
251     unsigned right)
252 {
253         struct a10codec_info *sc = mix_getdevinfo(m);
254         uint32_t val;
255         unsigned nvol, max;
256
257         max = a10codec_mixers[dev].mask >> a10codec_mixers[dev].shift;
258         nvol = (left * max) / 100;
259
260         val = CODEC_READ(sc, a10codec_mixers[dev].reg);
261         val &= ~a10codec_mixers[dev].mask;
262         val |= (nvol << a10codec_mixers[dev].shift);
263         CODEC_WRITE(sc, a10codec_mixers[dev].reg, val);
264
265         left = right = (left * 100) / max;
266         return (left | (right << 8));
267 }
268
269 static uint32_t
270 a10codec_mixer_setrecsrc(struct snd_mixer *m, uint32_t src)
271 {
272         struct a10codec_info *sc = mix_getdevinfo(m);
273         uint32_t val;
274
275         val = CODEC_READ(sc, AC_ADC_ACTL);
276
277         switch (src) {
278         case SOUND_MASK_LINE:   /* line-in */
279                 val &= ~ADC_ACTL_ADCIS_MASK;
280                 val |= (ADC_IS_LINEIN << ADC_ACTL_ADCIS_SHIFT);
281                 break;
282         case SOUND_MASK_MIC:    /* MIC1 */
283                 val &= ~ADC_ACTL_ADCIS_MASK;
284                 val |= (ADC_IS_MIC1 << ADC_ACTL_ADCIS_SHIFT);
285                 break;
286         case SOUND_MASK_LINE1:  /* MIC2 */
287                 val &= ~ADC_ACTL_ADCIS_MASK;
288                 val |= (ADC_IS_MIC2 << ADC_ACTL_ADCIS_SHIFT);
289                 break;
290         default:
291                 break;
292         }
293
294         CODEC_WRITE(sc, AC_ADC_ACTL, val);
295
296         switch ((val & ADC_ACTL_ADCIS_MASK) >> ADC_ACTL_ADCIS_SHIFT) {
297         case ADC_IS_LINEIN:
298                 return (SOUND_MASK_LINE);
299         case ADC_IS_MIC1:
300                 return (SOUND_MASK_MIC);
301         case ADC_IS_MIC2:
302                 return (SOUND_MASK_LINE1);
303         default:
304                 return (0);
305         }
306 }
307
308 static kobj_method_t a10codec_mixer_methods[] = {
309         KOBJMETHOD(mixer_init,          a10codec_mixer_init),
310         KOBJMETHOD(mixer_set,           a10codec_mixer_set),
311         KOBJMETHOD(mixer_setrecsrc,     a10codec_mixer_setrecsrc),
312         KOBJMETHOD_END
313 };
314 MIXER_DECLARE(a10codec_mixer);
315
316
317 /*
318  * Channel interface
319  */
320
321 static void
322 a10codec_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
323 {
324         struct a10codec_chinfo *ch = arg;
325
326         if (error != 0)
327                 return;
328
329         ch->physaddr = segs[0].ds_addr;
330 }
331
332 static void
333 a10codec_transfer(struct a10codec_chinfo *ch)
334 {
335         bus_addr_t src, dst;
336         int error;
337
338         if (ch->dir == PCMDIR_PLAY) {
339                 src = ch->physaddr + ch->pos;
340                 dst = ch->fifo;
341         } else {
342                 src = ch->fifo;
343                 dst = ch->physaddr + ch->pos;
344         }
345
346         error = SUNXI_DMA_TRANSFER(ch->dmac, ch->dmachan, src, dst,
347             ch->blocksize);
348         if (error) {
349                 ch->run = 0;
350                 device_printf(ch->parent->dev, "DMA transfer failed: %d\n",
351                     error);
352         }
353 }
354
355 static void
356 a10codec_dmaconfig(struct a10codec_chinfo *ch)
357 {
358         struct a10codec_info *sc = ch->parent;
359         struct sunxi_dma_config conf;
360
361         memset(&conf, 0, sizeof(conf));
362         conf.src_width = conf.dst_width = 16;
363         conf.src_burst_len = conf.dst_burst_len = 4;
364
365         if (ch->dir == PCMDIR_PLAY) {
366                 conf.dst_noincr = true;
367                 conf.src_drqtype = sc->drqtype_sdram;
368                 conf.dst_drqtype = sc->drqtype_codec;
369         } else {
370                 conf.src_noincr = true;
371                 conf.src_drqtype = sc->drqtype_codec;
372                 conf.dst_drqtype = sc->drqtype_sdram;
373         }
374
375         SUNXI_DMA_SET_CONFIG(ch->dmac, ch->dmachan, &conf);
376 }
377
378 static void
379 a10codec_dmaintr(void *priv)
380 {
381         struct a10codec_chinfo *ch = priv;
382         unsigned bufsize;
383
384         bufsize = sndbuf_getsize(ch->buffer);
385
386         ch->pos += ch->blocksize;
387         if (ch->pos >= bufsize)
388                 ch->pos -= bufsize;
389
390         if (ch->run) {
391                 chn_intr(ch->channel);
392                 a10codec_transfer(ch);
393         }
394 }
395
396 static unsigned
397 a10codec_fs(struct a10codec_chinfo *ch)
398 {
399         switch (ch->speed) {
400         case 48000:
401                 return (DAC_FS_48KHZ);
402         case 24000:
403                 return (DAC_FS_24KHZ);
404         case 12000:
405                 return (DAC_FS_12KHZ);
406         case 192000:
407                 return (DAC_FS_192KHZ);
408         case 32000:
409                 return (DAC_FS_32KHZ);
410         case 16000:
411                 return (DAC_FS_16KHZ);
412         case 8000:
413                 return (DAC_FS_8KHZ);
414         case 96000:
415                 return (DAC_FS_96KHZ);
416         default:
417                 return (DAC_FS_48KHZ);
418         }
419 }
420
421 static void
422 a10codec_start(struct a10codec_chinfo *ch)
423 {
424         struct a10codec_info *sc = ch->parent;
425         uint32_t val;
426
427         ch->pos = 0;
428
429         if (ch->dir == PCMDIR_PLAY) {
430                 /* Flush DAC FIFO */
431                 CODEC_WRITE(sc, AC_DAC_FIFOC, DAC_FIFOC_FIFO_FLUSH);
432
433                 /* Clear DAC FIFO status */
434                 CODEC_WRITE(sc, AC_DAC_FIFOS, CODEC_READ(sc, AC_DAC_FIFOS));
435
436                 /* Enable DAC analog left/right channels and output mixer */
437                 val = CODEC_READ(sc, AC_DAC_ACTL);
438                 val |= DAC_ACTL_DACAREN;
439                 val |= DAC_ACTL_DACALEN;
440                 val |= DAC_ACTL_DACPAS;
441                 CODEC_WRITE(sc, AC_DAC_ACTL, val);
442
443                 /* Configure DAC DMA channel */
444                 a10codec_dmaconfig(ch);
445
446                 /* Configure DAC FIFO */
447                 CODEC_WRITE(sc, AC_DAC_FIFOC,
448                     (AFMT_CHANNEL(ch->format) == 1 ? DAC_FIFOC_MONO_EN : 0) |
449                     (a10codec_fs(ch) << DAC_FIFOC_FS_SHIFT) |
450                     (FIFO_MODE_16_15_0 << DAC_FIFOC_FIFO_MODE_SHIFT) |
451                     (DRQ_CLR_CNT << DAC_FIFOC_DRQ_CLR_CNT_SHIFT) |
452                     (TX_TRIG_LEVEL << DAC_FIFOC_TX_TRIG_LEVEL_SHIFT));
453
454                 /* Enable DAC DRQ */
455                 val = CODEC_READ(sc, AC_DAC_FIFOC);
456                 val |= DAC_FIFOC_DRQ_EN;
457                 CODEC_WRITE(sc, AC_DAC_FIFOC, val);
458         } else {
459                 /* Flush ADC FIFO */
460                 CODEC_WRITE(sc, AC_ADC_FIFOC, ADC_FIFOC_FIFO_FLUSH);
461
462                 /* Clear ADC FIFO status */
463                 CODEC_WRITE(sc, AC_ADC_FIFOS, CODEC_READ(sc, AC_ADC_FIFOS));
464
465                 /* Enable ADC analog left/right channels, MIC1 preamp,
466                  * and VMIC pin voltage
467                  */
468                 val = CODEC_READ(sc, AC_ADC_ACTL);
469                 val |= ADC_ACTL_ADCREN;
470                 val |= ADC_ACTL_ADCLEN;
471                 val |= ADC_ACTL_PREG1EN;
472                 val |= ADC_ACTL_VMICEN;
473                 CODEC_WRITE(sc, AC_ADC_ACTL, val);
474
475                 /* Configure ADC DMA channel */
476                 a10codec_dmaconfig(ch);
477
478                 /* Configure ADC FIFO */
479                 CODEC_WRITE(sc, AC_ADC_FIFOC,
480                     ADC_FIFOC_EN_AD |
481                     ADC_FIFOC_RX_FIFO_MODE |
482                     (AFMT_CHANNEL(ch->format) == 1 ? ADC_FIFOC_MONO_EN : 0) |
483                     (a10codec_fs(ch) << ADC_FIFOC_FS_SHIFT) |
484                     (RX_TRIG_LEVEL << ADC_FIFOC_RX_TRIG_LEVEL_SHIFT));
485
486                 /* Enable ADC DRQ */
487                 val = CODEC_READ(sc, AC_ADC_FIFOC);
488                 val |= ADC_FIFOC_DRQ_EN;
489                 CODEC_WRITE(sc, AC_ADC_FIFOC, val);
490         }
491
492         /* Start DMA transfer */
493         a10codec_transfer(ch);
494 }
495
496 static void
497 a10codec_stop(struct a10codec_chinfo *ch)
498 {
499         struct a10codec_info *sc = ch->parent;
500         uint32_t val;
501
502         /* Disable DMA channel */
503         SUNXI_DMA_HALT(ch->dmac, ch->dmachan);
504
505         if (ch->dir == PCMDIR_PLAY) {
506                 /* Disable DAC analog left/right channels and output mixer */
507                 val = CODEC_READ(sc, AC_DAC_ACTL);
508                 val &= ~DAC_ACTL_DACAREN;
509                 val &= ~DAC_ACTL_DACALEN;
510                 val &= ~DAC_ACTL_DACPAS;
511                 CODEC_WRITE(sc, AC_DAC_ACTL, val);
512
513                 /* Disable DAC DRQ */
514                 CODEC_WRITE(sc, AC_DAC_FIFOC, 0);
515         } else {
516                 /* Disable ADC analog left/right channels, MIC1 preamp,
517                  * and VMIC pin voltage
518                  */
519                 val = CODEC_READ(sc, AC_ADC_ACTL);
520                 val &= ~ADC_ACTL_ADCREN;
521                 val &= ~ADC_ACTL_ADCLEN;
522                 val &= ~ADC_ACTL_PREG1EN;
523                 val &= ~ADC_ACTL_VMICEN;
524                 CODEC_WRITE(sc, AC_ADC_ACTL, val);
525
526                 /* Disable ADC DRQ */
527                 CODEC_WRITE(sc, AC_ADC_FIFOC, 0);
528         }
529 }
530
531 static void *
532 a10codec_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
533     struct pcm_channel *c, int dir)
534 {
535         struct a10codec_info *sc = devinfo;
536         struct a10codec_chinfo *ch = dir == PCMDIR_PLAY ? &sc->play : &sc->rec;
537         int error;
538
539         ch->parent = sc;
540         ch->channel = c;
541         ch->buffer = b;
542         ch->dir = dir;
543         ch->fifo = rman_get_start(sc->res[0]) +
544             (dir == PCMDIR_REC ? AC_ADC_RXDATA : AC_DAC_TXDATA);
545
546         ch->dmac = devclass_get_device(devclass_find("a10dmac"), 0);
547         if (ch->dmac == NULL) {
548                 device_printf(sc->dev, "cannot find DMA controller\n");
549                 return (NULL);
550         }
551         ch->dmachan = SUNXI_DMA_ALLOC(ch->dmac, false, a10codec_dmaintr, ch);
552         if (ch->dmachan == NULL) {
553                 device_printf(sc->dev, "cannot allocate DMA channel\n");
554                 return (NULL);
555         }
556
557         error = bus_dmamem_alloc(sc->dmat, &ch->dmaaddr,
558             BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &ch->dmamap);
559         if (error != 0) {
560                 device_printf(sc->dev, "cannot allocate channel buffer\n");
561                 return (NULL);
562         }
563         error = bus_dmamap_load(sc->dmat, ch->dmamap, ch->dmaaddr,
564             sc->dmasize, a10codec_dmamap_cb, ch, BUS_DMA_NOWAIT);
565         if (error != 0) {
566                 device_printf(sc->dev, "cannot load DMA map\n");
567                 return (NULL);
568         }
569         memset(ch->dmaaddr, 0, sc->dmasize);
570
571         if (sndbuf_setup(ch->buffer, ch->dmaaddr, sc->dmasize) != 0) {
572                 device_printf(sc->dev, "cannot setup sndbuf\n");
573                 return (NULL);
574         }
575
576         return (ch);
577 }
578
579 static int
580 a10codec_chan_free(kobj_t obj, void *data)
581 {
582         struct a10codec_chinfo *ch = data;
583         struct a10codec_info *sc = ch->parent;
584
585         SUNXI_DMA_FREE(ch->dmac, ch->dmachan);
586         bus_dmamap_unload(sc->dmat, ch->dmamap);
587         bus_dmamem_free(sc->dmat, ch->dmaaddr, ch->dmamap);
588
589         return (0);
590 }
591
592 static int
593 a10codec_chan_setformat(kobj_t obj, void *data, uint32_t format)
594 {
595         struct a10codec_chinfo *ch = data;
596
597         ch->format = format;
598
599         return (0);
600 }
601
602 static uint32_t
603 a10codec_chan_setspeed(kobj_t obj, void *data, uint32_t speed)
604 {
605         struct a10codec_chinfo *ch = data;
606
607         /*
608          * The codec supports full duplex operation but both DAC and ADC
609          * use the same source clock (PLL2). Limit the available speeds to
610          * those supported by a 24576000 Hz input.
611          */
612         switch (speed) {
613         case 8000:
614         case 12000:
615         case 16000:
616         case 24000:
617         case 32000:
618         case 48000:
619                 ch->speed = speed;
620                 break;
621         case 96000:
622         case 192000:
623                 /* 96 KHz / 192 KHz mode only supported for playback */
624                 if (ch->dir == PCMDIR_PLAY) {
625                         ch->speed = speed;
626                 } else {
627                         ch->speed = 48000;
628                 }
629                 break;
630         case 44100:
631                 ch->speed = 48000;
632                 break;
633         case 22050:
634                 ch->speed = 24000;
635                 break;
636         case 11025:
637                 ch->speed = 12000;
638                 break;
639         default:
640                 ch->speed = 48000;
641                 break;
642         }
643
644         return (ch->speed);
645 }
646
647 static uint32_t
648 a10codec_chan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
649 {
650         struct a10codec_chinfo *ch = data;
651
652         ch->blocksize = blocksize & ~3;
653
654         return (ch->blocksize);
655 }
656
657 static int
658 a10codec_chan_trigger(kobj_t obj, void *data, int go)
659 {
660         struct a10codec_chinfo *ch = data;
661         struct a10codec_info *sc = ch->parent;
662
663         if (!PCMTRIG_COMMON(go))
664                 return (0);
665
666         snd_mtxlock(sc->lock);
667         switch (go) {
668         case PCMTRIG_START:
669                 ch->run = 1;
670                 a10codec_start(ch);
671                 break;
672         case PCMTRIG_STOP:
673         case PCMTRIG_ABORT:
674                 ch->run = 0;
675                 a10codec_stop(ch);
676                 break;
677         default:
678                 break;
679         }
680         snd_mtxunlock(sc->lock);
681
682         return (0);
683 }
684
685 static uint32_t
686 a10codec_chan_getptr(kobj_t obj, void *data)
687 {
688         struct a10codec_chinfo *ch = data;
689
690         return (ch->pos);
691 }
692
693 static struct pcmchan_caps *
694 a10codec_chan_getcaps(kobj_t obj, void *data)
695 {
696         struct a10codec_chinfo *ch = data;
697
698         if (ch->dir == PCMDIR_PLAY) {
699                 return (&a10codec_pcaps);
700         } else {
701                 return (&a10codec_rcaps);
702         }
703 }
704
705 static kobj_method_t a10codec_chan_methods[] = {
706         KOBJMETHOD(channel_init,                a10codec_chan_init),
707         KOBJMETHOD(channel_free,                a10codec_chan_free),
708         KOBJMETHOD(channel_setformat,           a10codec_chan_setformat),
709         KOBJMETHOD(channel_setspeed,            a10codec_chan_setspeed),
710         KOBJMETHOD(channel_setblocksize,        a10codec_chan_setblocksize),
711         KOBJMETHOD(channel_trigger,             a10codec_chan_trigger),
712         KOBJMETHOD(channel_getptr,              a10codec_chan_getptr),
713         KOBJMETHOD(channel_getcaps,             a10codec_chan_getcaps),
714         KOBJMETHOD_END
715 };
716 CHANNEL_DECLARE(a10codec_chan);
717
718
719 /*
720  * Device interface
721  */
722
723 static struct ofw_compat_data compat_data[] = {
724         {"allwinner,sun4i-a10-codec", 1},
725         {"allwinner,sun7i-a20-codec", 1},
726         {NULL, 0},
727 };
728
729 static int
730 a10codec_probe(device_t dev)
731 {
732         if (!ofw_bus_status_okay(dev))
733                 return (ENXIO);
734
735         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
736                 return (ENXIO);
737
738         device_set_desc(dev, "Allwinner Audio Codec");
739         return (BUS_PROBE_DEFAULT);
740 }
741
742 static int
743 a10codec_attach(device_t dev)
744 {
745         struct a10codec_info *sc;
746         char status[SND_STATUSLEN];
747         clk_t clk_apb, clk_codec;
748         uint32_t val;
749         int error;
750
751         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
752         sc->dev = dev;
753         sc->lock = snd_mtxcreate(device_get_nameunit(dev), "a10codec softc");
754
755         if (bus_alloc_resources(dev, a10codec_spec, sc->res)) {
756                 device_printf(dev, "cannot allocate resources for device\n");
757                 error = ENXIO;
758                 goto fail;
759         }
760
761         /* XXX DRQ types should come from FDT, but how? */
762         if (ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-codec") ||
763             ofw_bus_is_compatible(dev, "allwinner,sun7i-a20-codec")) {
764                 sc->drqtype_codec = 19;
765                 sc->drqtype_sdram = 22;
766         } else {
767                 device_printf(dev, "DRQ types not known for this SoC\n");
768                 error = ENXIO;
769                 goto fail;
770         }
771
772         sc->dmasize = 131072;
773         error = bus_dma_tag_create(
774             bus_get_dma_tag(dev),
775             4, sc->dmasize,             /* alignment, boundary */
776             BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
777             BUS_SPACE_MAXADDR,          /* highaddr */
778             NULL, NULL,                 /* filter, filterarg */
779             sc->dmasize, 1,             /* maxsize, nsegs */
780             sc->dmasize, 0,             /* maxsegsize, flags */
781             NULL, NULL,                 /* lockfunc, lockarg */
782             &sc->dmat);
783         if (error != 0) {
784                 device_printf(dev, "cannot create DMA tag\n");
785                 goto fail;
786         }
787
788         /* Get clocks */
789         error = clk_get_by_ofw_name(dev, 0, "apb", &clk_apb);
790         if (error != 0) {
791                 device_printf(dev, "cannot find apb clock\n");
792                 goto fail;
793         }
794         error = clk_get_by_ofw_name(dev, 0, "codec", &clk_codec);
795         if (error != 0) {
796                 device_printf(dev, "cannot find codec clock\n");
797                 goto fail;
798         }
799
800         /* Gating APB clock for codec */
801         error = clk_enable(clk_apb);
802         if (error != 0) {
803                 device_printf(dev, "cannot enable apb clock\n");
804                 goto fail;
805         }
806         /* Activate audio codec clock. According to the A10 and A20 user
807          * manuals, Audio_pll can be either 24.576MHz or 22.5792MHz. Most
808          * audio sampling rates require an 24.576MHz input clock with the
809          * exception of 44.1kHz, 22.05kHz, and 11.025kHz. Unfortunately,
810          * both capture and playback use the same clock source so to
811          * safely support independent full duplex operation, we use a fixed
812          * 24.576MHz clock source and don't advertise native support for
813          * the three sampling rates that require a 22.5792MHz input.
814          */
815         error = clk_set_freq(clk_codec, 24576000, CLK_SET_ROUND_DOWN);
816         if (error != 0) {
817                 device_printf(dev, "cannot set codec clock frequency\n");
818                 goto fail;
819         }
820         /* Enable audio codec clock */
821         error = clk_enable(clk_codec);
822         if (error != 0) {
823                 device_printf(dev, "cannot enable codec clock\n");
824                 goto fail;
825         }
826
827         /* Enable DAC */
828         val = CODEC_READ(sc, AC_DAC_DPC);
829         val |= DAC_DPC_EN_DA;
830         CODEC_WRITE(sc, AC_DAC_DPC, val);
831
832 #ifdef notdef
833         error = snd_setup_intr(dev, sc->irq, INTR_MPSAFE, a10codec_intr, sc,
834             &sc->ih);
835         if (error != 0) {
836                 device_printf(dev, "could not setup interrupt handler\n");
837                 goto fail;
838         }
839 #endif
840
841         if (mixer_init(dev, &a10codec_mixer_class, sc)) {
842                 device_printf(dev, "mixer_init failed\n");
843                 goto fail;
844         }
845
846         pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
847
848         if (pcm_register(dev, sc, 1, 1)) {
849                 device_printf(dev, "pcm_register failed\n");
850                 goto fail;
851         }
852
853         pcm_addchan(dev, PCMDIR_PLAY, &a10codec_chan_class, sc);
854         pcm_addchan(dev, PCMDIR_REC, &a10codec_chan_class, sc);
855
856         snprintf(status, SND_STATUSLEN, "at %s", ofw_bus_get_name(dev));
857         pcm_setstatus(dev, status);
858
859         return (0);
860
861 fail:
862         bus_release_resources(dev, a10codec_spec, sc->res);
863         snd_mtxfree(sc->lock);
864         free(sc, M_DEVBUF);
865
866         return (error);
867 }
868
869 static device_method_t a10codec_pcm_methods[] = {
870         /* Device interface */
871         DEVMETHOD(device_probe,         a10codec_probe),
872         DEVMETHOD(device_attach,        a10codec_attach),
873
874         DEVMETHOD_END
875 };
876
877 static driver_t a10codec_pcm_driver = {
878         "pcm",
879         a10codec_pcm_methods,
880         PCM_SOFTC_SIZE,
881 };
882
883 DRIVER_MODULE(a10codec, simplebus, a10codec_pcm_driver, pcm_devclass, 0, 0);
884 MODULE_DEPEND(a10codec, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
885 MODULE_VERSION(a10codec, 1);