Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/freescale/imx/imx6_ssi.c
39537 views
1
/*-
2
* Copyright (c) 2015 Ruslan Bukin <[email protected]>
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 AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, 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
27
/*
28
* i.MX6 Synchronous Serial Interface (SSI)
29
*
30
* Chapter 61, i.MX 6Dual/6Quad Applications Processor Reference Manual,
31
* Rev. 1, 04/2013
32
*/
33
34
#include <sys/param.h>
35
#include <sys/systm.h>
36
#include <sys/bus.h>
37
#include <sys/kernel.h>
38
#include <sys/module.h>
39
#include <sys/malloc.h>
40
#include <sys/rman.h>
41
#include <sys/timeet.h>
42
#include <sys/timetc.h>
43
44
#include <dev/sound/pcm/sound.h>
45
#include <mixer_if.h>
46
47
#include <dev/ofw/openfirm.h>
48
#include <dev/ofw/ofw_bus.h>
49
#include <dev/ofw/ofw_bus_subr.h>
50
51
#include <machine/bus.h>
52
#include <machine/cpu.h>
53
#include <machine/intr.h>
54
55
#include <arm/freescale/imx/imx6_sdma.h>
56
#include <arm/freescale/imx/imx6_anatopvar.h>
57
#include <arm/freescale/imx/imx_ccmvar.h>
58
59
#define READ4(_sc, _reg) \
60
bus_space_read_4(_sc->bst, _sc->bsh, _reg)
61
#define WRITE4(_sc, _reg, _val) \
62
bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
63
64
#define SSI_NCHANNELS 1
65
#define DMAS_TOTAL 8
66
67
/* i.MX6 SSI registers */
68
69
#define SSI_STX0 0x00 /* Transmit Data Register n */
70
#define SSI_STX1 0x04 /* Transmit Data Register n */
71
#define SSI_SRX0 0x08 /* Receive Data Register n */
72
#define SSI_SRX1 0x0C /* Receive Data Register n */
73
#define SSI_SCR 0x10 /* Control Register */
74
#define SCR_I2S_MODE_S 5 /* I2S Mode Select. */
75
#define SCR_I2S_MODE_M 0x3
76
#define SCR_SYN (1 << 4)
77
#define SCR_NET (1 << 3) /* Network mode */
78
#define SCR_RE (1 << 2) /* Receive Enable. */
79
#define SCR_TE (1 << 1) /* Transmit Enable. */
80
#define SCR_SSIEN (1 << 0) /* SSI Enable */
81
#define SSI_SISR 0x14 /* Interrupt Status Register */
82
#define SSI_SIER 0x18 /* Interrupt Enable Register */
83
#define SIER_RDMAE (1 << 22) /* Receive DMA Enable. */
84
#define SIER_RIE (1 << 21) /* Receive Interrupt Enable. */
85
#define SIER_TDMAE (1 << 20) /* Transmit DMA Enable. */
86
#define SIER_TIE (1 << 19) /* Transmit Interrupt Enable. */
87
#define SIER_TDE0IE (1 << 12) /* Transmit Data Register Empty 0. */
88
#define SIER_TUE0IE (1 << 8) /* Transmitter Underrun Error 0. */
89
#define SIER_TFE0IE (1 << 0) /* Transmit FIFO Empty 0 IE. */
90
#define SSI_STCR 0x1C /* Transmit Configuration Register */
91
#define STCR_TXBIT0 (1 << 9) /* Transmit Bit 0 shift MSB/LSB */
92
#define STCR_TFEN1 (1 << 8) /* Transmit FIFO Enable 1. */
93
#define STCR_TFEN0 (1 << 7) /* Transmit FIFO Enable 0. */
94
#define STCR_TFDIR (1 << 6) /* Transmit Frame Direction. */
95
#define STCR_TXDIR (1 << 5) /* Transmit Clock Direction. */
96
#define STCR_TSHFD (1 << 4) /* Transmit Shift Direction. */
97
#define STCR_TSCKP (1 << 3) /* Transmit Clock Polarity. */
98
#define STCR_TFSI (1 << 2) /* Transmit Frame Sync Invert. */
99
#define STCR_TFSL (1 << 1) /* Transmit Frame Sync Length. */
100
#define STCR_TEFS (1 << 0) /* Transmit Early Frame Sync. */
101
#define SSI_SRCR 0x20 /* Receive Configuration Register */
102
#define SSI_STCCR 0x24 /* Transmit Clock Control Register */
103
#define STCCR_DIV2 (1 << 18) /* Divide By 2. */
104
#define STCCR_PSR (1 << 17) /* Divide clock by 8. */
105
#define WL3_WL0_S 13
106
#define WL3_WL0_M 0xf
107
#define DC4_DC0_S 8
108
#define DC4_DC0_M 0x1f
109
#define PM7_PM0_S 0
110
#define PM7_PM0_M 0xff
111
#define SSI_SRCCR 0x28 /* Receive Clock Control Register */
112
#define SSI_SFCSR 0x2C /* FIFO Control/Status Register */
113
#define SFCSR_RFWM1_S 20 /* Receive FIFO Empty WaterMark 1 */
114
#define SFCSR_RFWM1_M 0xf
115
#define SFCSR_TFWM1_S 16 /* Transmit FIFO Empty WaterMark 1 */
116
#define SFCSR_TFWM1_M 0xf
117
#define SFCSR_RFWM0_S 4 /* Receive FIFO Empty WaterMark 0 */
118
#define SFCSR_RFWM0_M 0xf
119
#define SFCSR_TFWM0_S 0 /* Transmit FIFO Empty WaterMark 0 */
120
#define SFCSR_TFWM0_M 0xf
121
#define SSI_SACNT 0x38 /* AC97 Control Register */
122
#define SSI_SACADD 0x3C /* AC97 Command Address Register */
123
#define SSI_SACDAT 0x40 /* AC97 Command Data Register */
124
#define SSI_SATAG 0x44 /* AC97 Tag Register */
125
#define SSI_STMSK 0x48 /* Transmit Time Slot Mask Register */
126
#define SSI_SRMSK 0x4C /* Receive Time Slot Mask Register */
127
#define SSI_SACCST 0x50 /* AC97 Channel Status Register */
128
#define SSI_SACCEN 0x54 /* AC97 Channel Enable Register */
129
#define SSI_SACCDIS 0x58 /* AC97 Channel Disable Register */
130
131
static MALLOC_DEFINE(M_SSI, "ssi", "ssi audio");
132
133
uint32_t ssi_dma_intr(void *arg, int chn);
134
135
struct ssi_rate {
136
uint32_t speed;
137
uint32_t mfi; /* PLL4 Multiplication Factor Integer */
138
uint32_t mfn; /* PLL4 Multiplication Factor Numerator */
139
uint32_t mfd; /* PLL4 Multiplication Factor Denominator */
140
/* More dividers to configure can be added here */
141
};
142
143
static struct ssi_rate rate_map[] = {
144
{ 192000, 49, 152, 1000 }, /* PLL4 49.152 Mhz */
145
/* TODO: add more frequences */
146
{ 0, 0 },
147
};
148
149
/*
150
* i.MX6 example bit clock formula
151
*
152
* BCLK = 2 channels * 192000 hz * 24 bit = 9216000 hz =
153
* (24000000 * (49 + 152/1000.0) / 4 / 4 / 2 / 2 / 2 / 1 / 1)
154
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
155
* | | | | | | | | | | |
156
* Fref ------/ | | | | | | | | | |
157
* PLL4 div select -/ | | | | | | | | |
158
* PLL4 num --------------/ | | | | | | | |
159
* PLL4 denom -------------------/ | | | | | | |
160
* PLL4 post div ---------------------/ | | | | | |
161
* CCM ssi pre div (CCM_CS1CDR) ----------/ | | | | |
162
* CCM ssi post div (CCM_CS1CDR) -------------/ | | | |
163
* SSI PM7_PM0_S ---------------------------------/ | | |
164
* SSI Fixed divider ---------------------------------/ | |
165
* SSI DIV2 ----------------------------------------------/ |
166
* SSI PSR (prescaler /1 or /8) ------------------------------/
167
*
168
* MCLK (Master clock) depends on DAC, usually BCLK * 4
169
*/
170
171
struct sc_info {
172
struct resource *res[2];
173
bus_space_tag_t bst;
174
bus_space_handle_t bsh;
175
device_t dev;
176
struct mtx *lock;
177
void *ih;
178
int pos;
179
int dma_size;
180
bus_dma_tag_t dma_tag;
181
bus_dmamap_t dma_map;
182
bus_addr_t buf_base_phys;
183
uint32_t *buf_base;
184
struct sdma_conf *conf;
185
struct ssi_rate *sr;
186
struct sdma_softc *sdma_sc;
187
uint32_t sdma_ev_rx;
188
uint32_t sdma_ev_tx;
189
int sdma_channel;
190
};
191
192
/* Channel registers */
193
struct sc_chinfo {
194
struct snd_dbuf *buffer;
195
struct pcm_channel *channel;
196
struct sc_pcminfo *parent;
197
198
/* Channel information */
199
uint32_t dir;
200
uint32_t format;
201
202
/* Flags */
203
uint32_t run;
204
};
205
206
/* PCM device private data */
207
struct sc_pcminfo {
208
device_t dev;
209
uint32_t (*ih)(struct sc_pcminfo *scp);
210
uint32_t chnum;
211
struct sc_chinfo chan[SSI_NCHANNELS];
212
struct sc_info *sc;
213
};
214
215
static struct resource_spec ssi_spec[] = {
216
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
217
{ SYS_RES_IRQ, 0, RF_ACTIVE },
218
{ -1, 0 }
219
};
220
221
static int setup_dma(struct sc_pcminfo *scp);
222
static void setup_ssi(struct sc_info *);
223
static void ssi_configure_clock(struct sc_info *);
224
225
/*
226
* Mixer interface.
227
*/
228
229
static int
230
ssimixer_init(struct snd_mixer *m)
231
{
232
struct sc_pcminfo *scp;
233
struct sc_info *sc;
234
int mask;
235
236
scp = mix_getdevinfo(m);
237
sc = scp->sc;
238
239
if (sc == NULL)
240
return -1;
241
242
mask = SOUND_MASK_PCM;
243
mask |= SOUND_MASK_VOLUME;
244
245
snd_mtxlock(sc->lock);
246
pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL);
247
mix_setdevs(m, mask);
248
snd_mtxunlock(sc->lock);
249
250
return (0);
251
}
252
253
static int
254
ssimixer_set(struct snd_mixer *m, unsigned dev,
255
unsigned left, unsigned right)
256
{
257
struct sc_pcminfo *scp;
258
259
scp = mix_getdevinfo(m);
260
261
/* Here we can configure hardware volume on our DAC */
262
263
#if 1
264
device_printf(scp->dev, "ssimixer_set() %d %d\n",
265
left, right);
266
#endif
267
268
return (0);
269
}
270
271
static kobj_method_t ssimixer_methods[] = {
272
KOBJMETHOD(mixer_init, ssimixer_init),
273
KOBJMETHOD(mixer_set, ssimixer_set),
274
KOBJMETHOD_END
275
};
276
MIXER_DECLARE(ssimixer);
277
278
/*
279
* Channel interface.
280
*/
281
282
static void *
283
ssichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
284
struct pcm_channel *c, int dir)
285
{
286
struct sc_pcminfo *scp;
287
struct sc_chinfo *ch;
288
struct sc_info *sc;
289
290
scp = (struct sc_pcminfo *)devinfo;
291
sc = scp->sc;
292
293
snd_mtxlock(sc->lock);
294
ch = &scp->chan[0];
295
ch->dir = dir;
296
ch->run = 0;
297
ch->buffer = b;
298
ch->channel = c;
299
ch->parent = scp;
300
snd_mtxunlock(sc->lock);
301
302
if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) {
303
device_printf(scp->dev, "Can't setup sndbuf.\n");
304
return NULL;
305
}
306
307
return ch;
308
}
309
310
static int
311
ssichan_free(kobj_t obj, void *data)
312
{
313
struct sc_chinfo *ch = data;
314
struct sc_pcminfo *scp = ch->parent;
315
struct sc_info *sc = scp->sc;
316
317
#if 0
318
device_printf(scp->dev, "ssichan_free()\n");
319
#endif
320
321
snd_mtxlock(sc->lock);
322
/* TODO: free channel buffer */
323
snd_mtxunlock(sc->lock);
324
325
return (0);
326
}
327
328
static int
329
ssichan_setformat(kobj_t obj, void *data, uint32_t format)
330
{
331
struct sc_chinfo *ch = data;
332
333
ch->format = format;
334
335
return (0);
336
}
337
338
static uint32_t
339
ssichan_setspeed(kobj_t obj, void *data, uint32_t speed)
340
{
341
struct sc_pcminfo *scp;
342
struct sc_chinfo *ch;
343
struct ssi_rate *sr;
344
struct sc_info *sc;
345
int threshold;
346
int i;
347
348
ch = data;
349
scp = ch->parent;
350
sc = scp->sc;
351
352
sr = NULL;
353
354
/* First look for equal frequency. */
355
for (i = 0; rate_map[i].speed != 0; i++) {
356
if (rate_map[i].speed == speed)
357
sr = &rate_map[i];
358
}
359
360
/* If no match, just find nearest. */
361
if (sr == NULL) {
362
for (i = 0; rate_map[i].speed != 0; i++) {
363
sr = &rate_map[i];
364
threshold = sr->speed + ((rate_map[i + 1].speed != 0) ?
365
((rate_map[i + 1].speed - sr->speed) >> 1) : 0);
366
if (speed < threshold)
367
break;
368
}
369
}
370
371
sc->sr = sr;
372
373
ssi_configure_clock(sc);
374
375
return (sr->speed);
376
}
377
378
static void
379
ssi_configure_clock(struct sc_info *sc)
380
{
381
struct ssi_rate *sr;
382
383
sr = sc->sr;
384
385
pll4_configure_output(sr->mfi, sr->mfn, sr->mfd);
386
387
/* Configure other dividers here, if any */
388
}
389
390
static uint32_t
391
ssichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
392
{
393
struct sc_chinfo *ch = data;
394
struct sc_pcminfo *scp = ch->parent;
395
struct sc_info *sc = scp->sc;
396
397
sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
398
399
setup_dma(scp);
400
401
return (sndbuf_getblksz(ch->buffer));
402
}
403
404
uint32_t
405
ssi_dma_intr(void *arg, int chn)
406
{
407
struct sc_pcminfo *scp;
408
struct sdma_conf *conf;
409
struct sc_chinfo *ch;
410
struct sc_info *sc;
411
int bufsize;
412
413
scp = arg;
414
ch = &scp->chan[0];
415
sc = scp->sc;
416
conf = sc->conf;
417
418
bufsize = sndbuf_getsize(ch->buffer);
419
420
sc->pos += conf->period;
421
if (sc->pos >= bufsize)
422
sc->pos -= bufsize;
423
424
if (ch->run)
425
chn_intr(ch->channel);
426
427
return (0);
428
}
429
430
static int
431
find_sdma_controller(struct sc_info *sc)
432
{
433
struct sdma_softc *sdma_sc;
434
phandle_t node;
435
device_t sdma_dev;
436
pcell_t dts_value[DMAS_TOTAL];
437
int len;
438
439
if ((node = ofw_bus_get_node(sc->dev)) == -1)
440
return (ENXIO);
441
442
if ((len = OF_getproplen(node, "dmas")) <= 0)
443
return (ENXIO);
444
445
if (len != sizeof(dts_value)) {
446
device_printf(sc->dev,
447
"\"dmas\" property length is invalid: %d (expected %d)",
448
len, sizeof(dts_value));
449
return (ENXIO);
450
}
451
452
OF_getencprop(node, "dmas", dts_value, sizeof(dts_value));
453
454
sc->sdma_ev_rx = dts_value[1];
455
sc->sdma_ev_tx = dts_value[5];
456
457
sdma_sc = NULL;
458
459
sdma_dev = devclass_get_device(devclass_find("sdma"), 0);
460
if (sdma_dev)
461
sdma_sc = device_get_softc(sdma_dev);
462
463
if (sdma_sc == NULL) {
464
device_printf(sc->dev, "No sDMA found. Can't operate\n");
465
return (ENXIO);
466
}
467
468
sc->sdma_sc = sdma_sc;
469
470
return (0);
471
};
472
473
static int
474
setup_dma(struct sc_pcminfo *scp)
475
{
476
struct sdma_conf *conf;
477
struct sc_chinfo *ch;
478
struct sc_info *sc;
479
int fmt;
480
481
ch = &scp->chan[0];
482
sc = scp->sc;
483
conf = sc->conf;
484
485
conf->ih = ssi_dma_intr;
486
conf->ih_user = scp;
487
conf->saddr = sc->buf_base_phys;
488
conf->daddr = rman_get_start(sc->res[0]) + SSI_STX0;
489
conf->event = sc->sdma_ev_tx; /* SDMA TX event */
490
conf->period = sndbuf_getblksz(ch->buffer);
491
conf->num_bd = sndbuf_getblkcnt(ch->buffer);
492
493
/*
494
* Word Length
495
* Can be 32, 24, 16 or 8 for sDMA.
496
*
497
* SSI supports 24 at max.
498
*/
499
500
fmt = sndbuf_getfmt(ch->buffer);
501
502
if (fmt & AFMT_16BIT) {
503
conf->word_length = 16;
504
conf->command = CMD_2BYTES;
505
} else if (fmt & AFMT_24BIT) {
506
conf->word_length = 24;
507
conf->command = CMD_3BYTES;
508
} else {
509
device_printf(sc->dev, "Unknown format\n");
510
return (-1);
511
}
512
513
return (0);
514
}
515
516
static int
517
ssi_start(struct sc_pcminfo *scp)
518
{
519
struct sc_info *sc;
520
int reg;
521
522
sc = scp->sc;
523
524
if (sdma_configure(sc->sdma_channel, sc->conf) != 0) {
525
device_printf(sc->dev, "Can't configure sDMA\n");
526
return (-1);
527
}
528
529
/* Enable DMA interrupt */
530
reg = (SIER_TDMAE);
531
WRITE4(sc, SSI_SIER, reg);
532
533
sdma_start(sc->sdma_channel);
534
535
return (0);
536
}
537
538
static int
539
ssi_stop(struct sc_pcminfo *scp)
540
{
541
struct sc_info *sc;
542
int reg;
543
544
sc = scp->sc;
545
546
reg = READ4(sc, SSI_SIER);
547
reg &= ~(SIER_TDMAE);
548
WRITE4(sc, SSI_SIER, reg);
549
550
sdma_stop(sc->sdma_channel);
551
552
bzero(sc->buf_base, sc->dma_size);
553
554
return (0);
555
}
556
557
static int
558
ssichan_trigger(kobj_t obj, void *data, int go)
559
{
560
struct sc_pcminfo *scp;
561
struct sc_chinfo *ch;
562
struct sc_info *sc;
563
564
ch = data;
565
scp = ch->parent;
566
sc = scp->sc;
567
568
snd_mtxlock(sc->lock);
569
570
switch (go) {
571
case PCMTRIG_START:
572
#if 0
573
device_printf(scp->dev, "trigger start\n");
574
#endif
575
ch->run = 1;
576
577
ssi_start(scp);
578
579
break;
580
581
case PCMTRIG_STOP:
582
case PCMTRIG_ABORT:
583
#if 0
584
device_printf(scp->dev, "trigger stop or abort\n");
585
#endif
586
ch->run = 0;
587
588
ssi_stop(scp);
589
590
break;
591
}
592
593
snd_mtxunlock(sc->lock);
594
595
return (0);
596
}
597
598
static uint32_t
599
ssichan_getptr(kobj_t obj, void *data)
600
{
601
struct sc_pcminfo *scp;
602
struct sc_chinfo *ch;
603
struct sc_info *sc;
604
605
ch = data;
606
scp = ch->parent;
607
sc = scp->sc;
608
609
return (sc->pos);
610
}
611
612
static uint32_t ssi_pfmt[] = {
613
SND_FORMAT(AFMT_S24_LE, 2, 0),
614
0
615
};
616
617
static struct pcmchan_caps ssi_pcaps = {44100, 192000, ssi_pfmt, 0};
618
619
static struct pcmchan_caps *
620
ssichan_getcaps(kobj_t obj, void *data)
621
{
622
623
return (&ssi_pcaps);
624
}
625
626
static kobj_method_t ssichan_methods[] = {
627
KOBJMETHOD(channel_init, ssichan_init),
628
KOBJMETHOD(channel_free, ssichan_free),
629
KOBJMETHOD(channel_setformat, ssichan_setformat),
630
KOBJMETHOD(channel_setspeed, ssichan_setspeed),
631
KOBJMETHOD(channel_setblocksize, ssichan_setblocksize),
632
KOBJMETHOD(channel_trigger, ssichan_trigger),
633
KOBJMETHOD(channel_getptr, ssichan_getptr),
634
KOBJMETHOD(channel_getcaps, ssichan_getcaps),
635
KOBJMETHOD_END
636
};
637
CHANNEL_DECLARE(ssichan);
638
639
static int
640
ssi_probe(device_t dev)
641
{
642
643
if (!ofw_bus_status_okay(dev))
644
return (ENXIO);
645
646
if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ssi"))
647
return (ENXIO);
648
649
device_set_desc(dev, "i.MX6 Synchronous Serial Interface (SSI)");
650
return (BUS_PROBE_DEFAULT);
651
}
652
653
static void
654
ssi_intr(void *arg)
655
{
656
#if 0
657
struct sc_pcminfo *scp;
658
struct sc_info *sc;
659
660
scp = arg;
661
sc = scp->sc;
662
#endif
663
664
/* We don't use SSI interrupt */
665
#if 0
666
device_printf(scp->sc->dev, "SSI Intr 0x%08x\n",
667
READ4(sc, SSI_SISR));
668
#endif
669
}
670
671
static void
672
setup_ssi(struct sc_info *sc)
673
{
674
int reg;
675
676
reg = READ4(sc, SSI_STCCR);
677
reg &= ~(WL3_WL0_M << WL3_WL0_S);
678
reg |= (0xb << WL3_WL0_S); /* 24 bit */
679
reg &= ~(DC4_DC0_M << DC4_DC0_S);
680
reg |= (1 << DC4_DC0_S); /* 2 words per frame */
681
reg &= ~(STCCR_DIV2); /* Divide by 1 */
682
reg &= ~(STCCR_PSR); /* Divide by 1 */
683
reg &= ~(PM7_PM0_M << PM7_PM0_S);
684
reg |= (1 << PM7_PM0_S); /* Divide by 2 */
685
WRITE4(sc, SSI_STCCR, reg);
686
687
reg = READ4(sc, SSI_SFCSR);
688
reg &= ~(SFCSR_TFWM0_M << SFCSR_TFWM0_S);
689
reg |= (8 << SFCSR_TFWM0_S); /* empty slots */
690
WRITE4(sc, SSI_SFCSR, reg);
691
692
reg = READ4(sc, SSI_STCR);
693
reg |= (STCR_TFEN0);
694
reg &= ~(STCR_TFEN1);
695
reg &= ~(STCR_TSHFD); /* MSB */
696
reg |= (STCR_TXBIT0);
697
reg |= (STCR_TXDIR | STCR_TFDIR);
698
reg |= (STCR_TSCKP); /* falling edge */
699
reg |= (STCR_TFSI);
700
reg &= ~(STCR_TFSI); /* active high frame sync */
701
reg &= ~(STCR_TFSL);
702
reg |= STCR_TEFS;
703
WRITE4(sc, SSI_STCR, reg);
704
705
reg = READ4(sc, SSI_SCR);
706
reg &= ~(SCR_I2S_MODE_M << SCR_I2S_MODE_S); /* Not master */
707
reg |= (SCR_SSIEN | SCR_TE);
708
reg |= (SCR_NET);
709
reg |= (SCR_SYN);
710
WRITE4(sc, SSI_SCR, reg);
711
}
712
713
static void
714
ssi_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
715
{
716
bus_addr_t *addr;
717
718
if (err)
719
return;
720
721
addr = (bus_addr_t*)arg;
722
*addr = segs[0].ds_addr;
723
}
724
725
static int
726
ssi_attach(device_t dev)
727
{
728
char status[SND_STATUSLEN];
729
struct sc_pcminfo *scp;
730
struct sc_info *sc;
731
int err;
732
733
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
734
sc->dev = dev;
735
sc->sr = &rate_map[0];
736
sc->pos = 0;
737
sc->conf = malloc(sizeof(struct sdma_conf), M_DEVBUF, M_WAITOK | M_ZERO);
738
739
sc->lock = snd_mtxcreate(device_get_nameunit(dev), "ssi softc");
740
if (sc->lock == NULL) {
741
device_printf(dev, "Can't create mtx\n");
742
return (ENXIO);
743
}
744
745
if (bus_alloc_resources(dev, ssi_spec, sc->res)) {
746
device_printf(dev, "could not allocate resources\n");
747
return (ENXIO);
748
}
749
750
/* Memory interface */
751
sc->bst = rman_get_bustag(sc->res[0]);
752
sc->bsh = rman_get_bushandle(sc->res[0]);
753
754
/* SDMA */
755
if (find_sdma_controller(sc)) {
756
device_printf(dev, "could not find active SDMA\n");
757
return (ENXIO);
758
}
759
760
/* Setup PCM */
761
scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
762
scp->sc = sc;
763
scp->dev = dev;
764
765
/*
766
* Maximum possible DMA buffer.
767
* Will be used partially to match 24 bit word.
768
*/
769
sc->dma_size = 131072;
770
771
/*
772
* Must use dma_size boundary as modulo feature required.
773
* Modulo feature allows setup circular buffer.
774
*/
775
776
err = bus_dma_tag_create(
777
bus_get_dma_tag(sc->dev),
778
4, sc->dma_size, /* alignment, boundary */
779
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
780
BUS_SPACE_MAXADDR, /* highaddr */
781
NULL, NULL, /* filter, filterarg */
782
sc->dma_size, 1, /* maxsize, nsegments */
783
sc->dma_size, 0, /* maxsegsize, flags */
784
NULL, NULL, /* lockfunc, lockarg */
785
&sc->dma_tag);
786
787
err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base,
788
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map);
789
if (err) {
790
device_printf(dev, "cannot allocate framebuffer\n");
791
return (ENXIO);
792
}
793
794
err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base,
795
sc->dma_size, ssi_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT);
796
if (err) {
797
device_printf(dev, "cannot load DMA map\n");
798
return (ENXIO);
799
}
800
801
bzero(sc->buf_base, sc->dma_size);
802
803
/* Setup interrupt handler */
804
err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV,
805
NULL, ssi_intr, scp, &sc->ih);
806
if (err) {
807
device_printf(dev, "Unable to alloc interrupt resource.\n");
808
return (ENXIO);
809
}
810
811
pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
812
813
pcm_init(dev, scp);
814
815
scp->chnum = 0;
816
pcm_addchan(dev, PCMDIR_PLAY, &ssichan_class, scp);
817
scp->chnum++;
818
819
snprintf(status, SND_STATUSLEN, "at simplebus");
820
err = pcm_register(dev, status);
821
if (err) {
822
device_printf(dev, "Can't register pcm.\n");
823
return (ENXIO);
824
}
825
826
mixer_init(dev, &ssimixer_class, scp);
827
setup_ssi(sc);
828
829
imx_ccm_ssi_configure(dev);
830
831
sc->sdma_channel = sdma_alloc();
832
if (sc->sdma_channel < 0) {
833
device_printf(sc->dev, "Can't get sDMA channel\n");
834
return (1);
835
}
836
837
return (0);
838
}
839
840
static device_method_t ssi_pcm_methods[] = {
841
DEVMETHOD(device_probe, ssi_probe),
842
DEVMETHOD(device_attach, ssi_attach),
843
{ 0, 0 }
844
};
845
846
static driver_t ssi_pcm_driver = {
847
"pcm",
848
ssi_pcm_methods,
849
PCM_SOFTC_SIZE,
850
};
851
852
DRIVER_MODULE(ssi, simplebus, ssi_pcm_driver, 0, 0);
853
MODULE_DEPEND(ssi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
854
MODULE_DEPEND(ssi, sdma, 0, 0, 0);
855
MODULE_VERSION(ssi, 1);
856
857