]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bitsy/devuda1341.c
merge
[plan9front.git] / sys / src / 9 / bitsy / devuda1341.c
1 /*
2  *      SAC/UDA 1341 Audio driver for the Bitsy
3  *
4  *      The Philips UDA 1341 sound chip is accessed through the Serial Audio
5  *      Controller (SAC) of the StrongARM SA-1110.  This is much more a SAC
6  *      controller than a UDA controller, but we have a devsac.c already.
7  *
8  *      The code morphs Nicolas Pitre's <nico@cam.org> Linux controller
9  *      and Ken's Soundblaster controller.
10  *
11  *      The interface should be identical to that of devaudio.c
12  */
13 #include        "u.h"
14 #include        "../port/lib.h"
15 #include        "mem.h"
16 #include        "dat.h"
17 #include        "fns.h"
18 #include        "../port/error.h"
19 #include        "io.h"
20 #include        "sa1110dma.h"
21
22 static int debug = 0;
23
24 /*
25  * GPIO based L3 bus support.
26  *
27  * This provides control of Philips L3 type devices. 
28  * GPIO lines are used for clock, data and mode pins.
29  *
30  * Note: The L3 pins are shared with I2C devices. This should not present
31  * any problems as long as an I2C start sequence is not generated. This is
32  * defined as a 1->0 transition on the data lines when the clock is high.
33  * It is critical this code only allow data transitions when the clock
34  * is low. This is always legal in L3.
35  *
36  * The IIC interface requires the clock and data pin to be LOW when idle. We
37  * must make sure we leave them in this state.
38  *
39  * It appears the read data is generated on the falling edge of the clock
40  * and should be held stable during the clock high time.
41  */
42
43 /* 
44  * L3 setup and hold times (expressed in µs)
45  */
46 enum {
47         L3_AcquireTime =                1,
48         L3_ReleaseTime =                1,
49         L3_DataSetupTime =      (190+999)/1000, /* 190 ns */
50         L3_DataHoldTime =               ( 30+999)/1000,
51         L3_ModeSetupTime =      (190+999)/1000,
52         L3_ModeHoldTime =       (190+999)/1000,
53         L3_ClockHighTime =      (100+999)/1000,
54         L3_ClockLowTime =               (100+999)/1000,
55         L3_HaltTime =                   (190+999)/1000,
56 };
57
58 /* UDA 1341 Registers */
59 enum {
60         /* Status0 register */
61         UdaStatusDC             = 0,    /* 1 bit */
62         UdaStatusIF             = 1,    /* 3 bits */
63         UdaStatusSC             = 4,    /* 2 bits */
64         UdaStatusRST            = 6,    /* 1 bit */
65 };
66
67 enum {
68         /* Status1 register */
69         UdaStatusPC     = 0,    /* 2 bits */
70         UdaStatusDS     = 2,    /* 1 bit */
71         UdaStatusPDA    = 3,    /* 1 bit */
72         UdaStatusPAD    = 4,    /* 1 bit */
73         UdaStatusIGS    = 5,    /* 1 bit */
74         UdaStatusOGS    = 6,    /* 1 bit */
75 };
76
77 /*
78  * UDA1341 L3 address and command types
79  */
80
81 enum {
82         UDA1341_DATA0 = 0,
83         UDA1341_DATA1,
84         UDA1341_STATUS,
85         UDA1341_L3Addr = 0x14,
86 };
87
88 typedef struct  AQueue  AQueue;
89 typedef struct  Buf     Buf;
90 typedef struct  IOstate IOstate;
91
92 enum
93 {
94         Qdir            = 0,
95         Qaudio,
96         Qvolume,
97         Qstatus,
98         Qstats,
99
100         Fmono           = 1,
101         Fin                     = 2,
102         Fout                    = 4,
103
104         Aclosed         = 0,
105         Aread,
106         Awrite,
107
108         Vaudio          = 0,
109         Vmic,
110         Vtreb,
111         Vbass,
112         Vspeed,
113         Vbufsize,
114         Vfilter,
115         Vinvert,
116         Nvol,
117
118         Bufsize         = 4* 1024,      /* 46 ms each */
119         Nbuf                    = 10,                   /* 1.5 seconds total */
120
121         Speed           = 44100,
122         Ncmd            = 50,                   /* max volume command words */
123 };
124
125 enum {
126         Flushbuf = 0xe0000000,
127 };
128
129 /* System Clock -- according to the manual, it seems that when the UDA is
130     configured in non MSB/I2S mode, it uses a divisor of 256 to the 12.288MHz
131     clock.  The other rates are only supported in MSB mode, which should be 
132     implemented at some point */
133 enum {
134         SC512FS = 0 << 2,
135         SC384FS = 1 << 2,
136         SC256FS = 2 << 2,
137         CLOCKMASK = 3 << 2,
138 };
139
140 /* Format */
141 enum {
142         LSB16 = 1 << 1,
143         LSB18 = 2 << 1,
144         LSB20 = 3 << 1,
145         MSB =   4 << 1,
146         MSB16 = 5 << 1,
147         MSB18 = 6 << 1,
148         MSB20 = 7 << 1,
149 };
150
151 Dirtab
152 audiodir[] =
153 {
154         ".",                    {Qdir, 0, QTDIR},       0,      DMDIR|0555,
155         "audio",                {Qaudio},                       0,      0666,
156         "volume",               {Qvolume},              0,      0666,
157         "audiostatus",  {Qstatus},                      0,      0444,
158         "audiostats",   {Qstats},                       0,      0444,
159 };
160
161 struct  Buf
162 {
163         uchar*  virt;
164         ulong   phys;
165         uint    nbytes;
166 };
167
168 struct  IOstate
169 {
170         QLock;
171         Lock                    ilock;
172         Rendez          vous;
173         Chan            *chan;          /* chan of open */
174         int                     dma;                    /* dma chan, alloc on open, free on close */
175         int                     bufinit;                /* boolean, if buffers allocated */
176         Buf                     buf[Nbuf];              /* buffers and queues */
177         volatile Buf    *current;               /* next dma to finish */
178         volatile Buf    *next;          /* next candidate for dma */
179         volatile Buf    *filling;               /* buffer being filled */
180 /* to have defines just like linux — there's a real operating system */
181 #define emptying filling
182 };
183
184 static  struct
185 {
186         QLock;
187         int             amode;                  /* Aclosed/Aread/Awrite for /audio */
188         int             intr;                   /* boolean an interrupt has happened */
189         int             rivol[Nvol];    /* right/left input/output volumes */
190         int             livol[Nvol];
191         int             rovol[Nvol];
192         int             lovol[Nvol];
193         ulong   totcount;               /* how many bytes processed since open */
194         vlong   tottime;                /* time at which totcount bytes were processed */
195         IOstate i;
196         IOstate o;
197 } audio;
198
199 int     zerodma;        /* dma buffer used for sending zero */
200
201 typedef struct Iostats Iostats;
202 struct Iostats {
203         ulong   totaldma;
204         ulong   idledma;
205         ulong   faildma;
206         ulong   samedma;
207         ulong   empties;
208 };
209
210 static struct
211 {
212         ulong   bytes;
213         Iostats rx, tx;
214 } iostats;
215
216 static void setaudio(int in, int out, int left, int right, int value);
217 static void setspeed(int in, int out, int left, int right, int value);
218 static void setbufsize(int in, int out, int left, int right, int value);
219
220 static  struct
221 {
222         char*   name;
223         int             flag;
224         int             ilval;          /* initial  values */
225         int             irval;
226         void            (*setval)(int, int, int, int, int);
227 } volumes[] =
228 {
229 [Vaudio]        {"audio",               Fout|Fmono,             80,             80,     setaudio },
230 [Vmic]  {"mic",         Fin|Fmono,                0,              0,    nil },
231 [Vtreb] {"treb",                Fout|Fmono,             50,             50,     nil },
232 [Vbass] {"bass",                Fout|Fmono,             50,             50,     nil },
233 [Vspeed]        {"speed",               Fin|Fout|Fmono, Speed,  Speed,  setspeed },
234 [Vbufsize]      {"bufsize",     Fin|Fout|Fmono, Bufsize,        Bufsize,        setbufsize },
235 [Vfilter]       {"filter",              Fout|Fmono,               0,              0,    nil },
236 [Vinvert]       {"invert",              Fin|Fout|Fmono,   0,              0,    nil },
237 [Nvol]  {0}
238 };
239
240 static void     setreg(char *name, int val, int n);
241
242 /*
243  * Grab control of the IIC/L3 shared pins
244  */
245 static void
246 L3_acquirepins(void)
247 {
248         gpioregs->set = (GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
249         gpioregs->direction |=  (GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
250         microdelay(L3_AcquireTime);
251 }
252
253 /*
254  * Release control of the IIC/L3 shared pins
255  */
256 static void
257 L3_releasepins(void)
258 {
259         gpioregs->direction &= ~(GPIO_L3_MODE_o | GPIO_L3_SCLK_o | GPIO_L3_SDA_io);
260         microdelay(L3_ReleaseTime);
261 }
262
263 /*
264  * Initialize the interface
265  */
266 static void 
267 L3_init(void)
268 {
269         gpioregs->altfunc &= ~(GPIO_L3_SDA_io | GPIO_L3_SCLK_o | GPIO_L3_MODE_o);
270         L3_releasepins();
271 }
272
273 /*
274  * Get a bit. The clock is high on entry and on exit. Data is read after
275  * the clock low time has expired.
276  */
277 static int
278 L3_getbit(void)
279 {
280         int data;
281
282         gpioregs->clear = GPIO_L3_SCLK_o;
283         microdelay(L3_ClockLowTime);
284
285         data = (gpioregs->level & GPIO_L3_SDA_io) ? 1 : 0;
286
287         gpioregs->set = GPIO_L3_SCLK_o;
288         microdelay(L3_ClockHighTime);
289
290         return data;
291 }
292
293 /*
294  * Send a bit. The clock is high on entry and on exit. Data is sent only
295  * when the clock is low (I2C compatibility).
296  */
297 static void
298 L3_sendbit(int bit)
299 {
300         gpioregs->clear = GPIO_L3_SCLK_o;
301
302         if (bit & 1)
303                 gpioregs->set = GPIO_L3_SDA_io;
304         else
305                 gpioregs->clear = GPIO_L3_SDA_io;
306
307         /* Assumes L3_DataSetupTime < L3_ClockLowTime */
308         microdelay(L3_ClockLowTime);
309
310         gpioregs->set = GPIO_L3_SCLK_o;
311         microdelay(L3_ClockHighTime);
312 }
313
314 /*
315  * Send a byte. The mode line is set or pulsed based on the mode sequence
316  * count. The mode line is high on entry and exit. The mod line is pulsed
317  * before the second data byte and before ech byte thereafter.
318  */
319 static void
320 L3_sendbyte(char data, int mode)
321 {
322         int i;
323
324         switch(mode) {
325         case 0: /* Address mode */
326                 gpioregs->clear = GPIO_L3_MODE_o;
327                 break;
328         case 1: /* First data byte */
329                 break;
330         default: /* Subsequent bytes */
331                 gpioregs->clear = GPIO_L3_MODE_o;
332                 microdelay(L3_HaltTime);
333                 gpioregs->set = GPIO_L3_MODE_o;
334                 break;
335         }
336
337         microdelay(L3_ModeSetupTime);
338
339         for (i = 0; i < 8; i++)
340                 L3_sendbit(data >> i);
341
342         if (mode == 0)  /* Address mode */
343                 gpioregs->set = GPIO_L3_MODE_o;
344
345         microdelay(L3_ModeHoldTime);
346 }
347
348 /*
349  * Get a byte. The mode line is set or pulsed based on the mode sequence
350  * count. The mode line is high on entry and exit. The mod line is pulsed
351  * before the second data byte and before each byte thereafter. This
352  * function is never valid with mode == 0 (address cycle) as the address
353  * is always sent on the bus, not read.
354  */
355 static char
356 L3_getbyte(int mode)
357 {
358         char data = 0;
359         int i;
360
361         switch(mode) {
362         case 0: /* Address mode - never valid */
363                 break;
364         case 1: /* First data byte */
365                 break;
366         default: /* Subsequent bytes */
367                 gpioregs->clear = GPIO_L3_MODE_o;
368                 microdelay(L3_HaltTime);
369                 gpioregs->set = GPIO_L3_MODE_o;
370                 break;
371         }
372
373         microdelay(L3_ModeSetupTime);
374
375         for (i = 0; i < 8; i++)
376                 data |= (L3_getbit() << i);
377
378         microdelay(L3_ModeHoldTime);
379
380         return data;
381 }
382
383 /*
384  * Write data to a device on the L3 bus. The address is passed as well as
385  * the data and length. The length written is returned. The register space
386  * is encoded in the address (low two bits are set and device address is
387  * in the upper 6 bits).
388  */
389 static int
390 L3_write(uchar addr, uchar *data, int len)
391 {
392         int mode = 0;
393         int bytes = len;
394
395         L3_acquirepins();
396         L3_sendbyte(addr, mode++);
397         while(len--)
398                 L3_sendbyte(*data++, mode++);
399         L3_releasepins();
400         return bytes;
401 }
402
403 /*
404  * Read data from a device on the L3 bus. The address is passed as well as
405  * the data and length. The length read is returned. The register space
406  * is encoded in the address (low two bits are set and device address is
407  * in the upper 6 bits).
408
409  * Commented out, not used
410 static int
411 L3_read(uchar addr, uchar *data, int len)
412 {
413         int mode = 0;
414         int bytes = len;
415
416         L3_acquirepins();
417         L3_sendbyte(addr, mode++);
418         gpioregs->direction &= ~(GPIO_L3_SDA_io);
419         while(len--)
420                 *data++ = L3_getbyte(mode++);
421         L3_releasepins();
422         return bytes;
423 }
424  */
425
426 void
427 audiomute(int on)
428 {
429         egpiobits(EGPIO_audio_mute, on);
430 }
431
432 static  char    Emode[]         = "illegal open mode";
433 static  char    Evolume[]       = "illegal volume specifier";
434
435 static void
436 bufinit(IOstate *b)
437 {
438         int i;
439
440         if (debug) print("bufinit\n");
441         for (i = 0; i < Nbuf; i++) {
442                 b->buf[i].virt = xalloc(Bufsize);
443                 b->buf[i].phys = PADDR(b->buf[i].virt);
444                 memset(b->buf[i].virt, 0xAA, Bufsize);
445         }
446         b->bufinit = 1;
447 };
448
449 static void
450 setempty(IOstate *b)
451 {
452         int i;
453
454         if (debug) print("setempty\n");
455         for (i = 0; i < Nbuf; i++) {
456                 b->buf[i].nbytes = 0;
457         }
458         b->filling = b->buf;
459         b->current = b->buf;
460         b->next = b->buf;
461 }
462
463 static int
464 audioqnotempty(void *x)
465 {
466         IOstate *s = x;
467
468         return dmaidle(s->dma) || s->emptying != s->current;
469 }
470
471 static int
472 audioqnotfull(void *x)
473 {
474         IOstate *s = x;
475
476         return dmaidle(s->dma) || s->filling != s->current;
477 }
478
479 SSPregs *sspregs;
480 MCPregs *mcpregs;
481
482 static void
483 audioinit(void)
484 {
485         /* Turn MCP operations off */
486         mcpregs = mapspecial(MCPREGS, sizeof(MCPregs));
487         mcpregs->status &= ~(1<<16);
488
489         sspregs = mapspecial(SSPREGS, sizeof(SSPregs));
490
491 }
492
493 uchar   status0[1]              = {0x02};
494 uchar   status1[1]              = {0x80};
495 uchar   data00[1]               = {0x00};               /* volume control, bits 0 – 5 */
496 uchar   data01[1]               = {0x40};
497 uchar   data02[1]               = {0x80};
498 uchar   data0e0[2]      = {0xc0, 0xe0};
499 uchar   data0e1[2]      = {0xc1, 0xe0};
500 uchar   data0e2[2]      = {0xc2, 0xf2};
501 /* there is no data0e3 */
502 uchar   data0e4[2]      = {0xc4, 0xe0};
503 uchar   data0e5[2]      = {0xc5, 0xe0};
504 uchar   data0e6[2]      = {0xc6, 0xe3};
505
506 static void
507 enable(void)
508 {
509         uchar   data[1];
510
511         L3_init();
512
513         /* Setup the uarts */
514         ppcregs->assignment &= ~(1<<18);
515
516         sspregs->control0 = 0;
517         sspregs->control0 = 0x031f; /* 16 bits, TI frames, serial clock rate 3 */
518         sspregs->control1 = 0x0020; /* ext clock */
519         sspregs->control0 = 0x039f;     /* enable */
520
521         /* Enable the audio power */
522         audioicpower(1);
523         egpiobits(EGPIO_codec_reset, 1);
524
525         setspeed(0, 0, 0, 0, volumes[Vspeed].ilval);
526
527         data[0] = status0[0] | 1 << UdaStatusRST;
528         L3_write(UDA1341_L3Addr | UDA1341_STATUS, data, 1 );
529         gpioregs->clear = EGPIO_codec_reset;
530         gpioregs->set = EGPIO_codec_reset;
531         /* write uda 1341 status[0] */
532         data[0] = status0[0];
533         L3_write(UDA1341_L3Addr | UDA1341_STATUS, data, 1);
534
535         if (debug)
536                 print("enable:  status0 = 0x%2.2ux\n", data[0]);
537
538         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
539         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
540         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e2, 2);
541         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e6, 2 );
542
543         if (debug) {
544                 print("enable:  status0 = 0x%2.2ux\n", data[0]);
545                 print("enable:  status1 = 0x%2.2ux\n", status1[0]);
546                 print("enable:  data02  = 0x%2.2ux\n", data02[0]);
547                 print("enable:  data0e2 = 0x%4.4ux\n", data0e2[0] | data0e2[1]<<8);
548                 print("enable:  data0e4 = 0x%4.4ux\n", data0e4[0] | data0e4[1]<<8);
549                 print("enable:  data0e6 = 0x%4.4ux\n", data0e6[0] | data0e6[1]<<8);
550                 print("enable:  sspregs->control0 = 0x%lux\n", sspregs->control0);
551                 print("enable:  sspregs->control1 = 0x%lux\n", sspregs->control1);
552         }
553 }
554
555 static  void
556 resetlevel(void)
557 {
558         int i;
559
560         for(i=0; volumes[i].name; i++) {
561                 audio.lovol[i] = volumes[i].ilval;
562                 audio.rovol[i] = volumes[i].irval;
563                 audio.livol[i] = volumes[i].ilval;
564                 audio.rivol[i] = volumes[i].irval;
565         }
566 }
567
568 static void
569 mxvolume(void) {
570         int *left, *right;
571
572         setspeed(0, 0, 0, 0, volumes[Vspeed].ilval);
573         if (!dmaidle(audio.i.dma) || !dmaidle(audio.o.dma))
574                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, status0, 1);
575
576         if(audio.amode & Aread){
577                 left = audio.livol;
578                 right = audio.rivol;
579                 if (left[Vmic]+right[Vmic] == 0) {
580                         /* Turn on automatic gain control (AGC) */
581                         data0e4[1] |= 0x10;
582                         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
583                 } else {
584                         int v;
585                         /* Turn on manual gain control */
586                         v = ((left[Vmic]+right[Vmic])*0x7f/200)&0x7f;
587                         data0e4[1] &= ~0x13;
588                         data0e5[1] &= ~0x1f;
589                         data0e4[1] |= v & 0x3;
590                         data0e5[0] |= (v & 0x7c)<<6;
591                         data0e5[1] |= (v & 0x7c)>>2;
592                         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e4, 2 );
593                         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data0e5, 2 );
594                 }
595                 if (left[Vinvert]+right[Vinvert] == 0)
596                         status1[0] &= ~0x04;
597                 else
598                         status1[0] |= 0x04;
599                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
600                 if (debug) {
601                         print("mxvolume:        status1 = 0x%2.2ux\n", status1[0]);
602                         print("mxvolume:        data0e4 = 0x%4.4ux\n", data0e4[0]|data0e4[0]<<8);
603                         print("mxvolume:        data0e5 = 0x%4.4ux\n", data0e5[0]|data0e5[0]<<8);
604                 }
605         }
606         if(audio.amode & Awrite){
607                 left = audio.lovol;
608                 right = audio.rovol;
609                 data00[0] &= ~0x3f;
610                 data00[0] |= ((200-left[Vaudio]-right[Vaudio])*0x3f/200)&0x3f;
611                 if (left[Vtreb]+right[Vtreb] <= 100
612                  && left[Vbass]+right[Vbass] <= 100)
613                         /* settings neutral */
614                         data02[0] &= ~0x03;
615                 else {
616                         data02[0] |= 0x03;
617                         data01[0] &= ~0x3f;
618                         data01[0] |= ((left[Vtreb]+right[Vtreb]-100)*0x3/100)&0x03;
619                         data01[0] |= (((left[Vbass]+right[Vbass]-100)*0xf/100)&0xf)<<2;
620                 }
621                 if (left[Vfilter]+right[Vfilter] == 0)
622                         data02[0] &= ~0x10;
623                 else
624                         data02[0]|= 0x10;
625                 if (left[Vinvert]+right[Vinvert] == 0)
626                         status1[0] &= ~0x10;
627                 else
628                         status1[0] |= 0x10;
629                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
630                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
631                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, data01, 1);
632                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, data02, 1);
633                 if (debug) {
634                         print("mxvolume:        status1 = 0x%2.2ux\n", status1[0]);
635                         print("mxvolume:        data00  = 0x%2.2ux\n", data00[0]);
636                         print("mxvolume:        data01  = 0x%2.2ux\n", data01[0]);
637                         print("mxvolume:        data02  = 0x%2.2ux\n", data02[0]);
638                 }
639         }
640 }
641
642 static void
643 setreg(char *name, int val, int n)
644 {
645         uchar x[2];
646         int i;
647
648         x[0] = val;
649         x[1] = val>>8;
650
651         if(strcmp(name, "pause") == 0){
652                 for(i = 0; i < n; i++)
653                         microdelay(val);
654                 return;
655         }
656
657         switch(n){
658         case 1:
659         case 2:
660                 break;
661         default:
662                 error("setreg");
663         }
664
665         if(strcmp(name, "status") == 0){
666                 L3_write(UDA1341_L3Addr | UDA1341_STATUS, x, n);
667         } else if(strcmp(name, "data0") == 0){
668                 L3_write(UDA1341_L3Addr | UDA1341_DATA0, x, n);
669         } else if(strcmp(name, "data1") == 0){
670                 L3_write(UDA1341_L3Addr | UDA1341_DATA1, x, n);
671         } else
672                 error("setreg");
673 }
674
675 static void
676 outenable(void) {
677         /* turn on DAC, set output gain switch */
678         audioamppower(1);
679         audiomute(0);
680         status1[0] |= 0x41;
681         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
682         /* set volume */
683         data00[0] |= 0xf;
684         L3_write(UDA1341_L3Addr | UDA1341_DATA0, data00, 1);
685         if (debug) {
686                 print("outenable:       status1 = 0x%2.2ux\n", status1[0]);
687                 print("outenable:       data00  = 0x%2.2ux\n", data00[0]);
688         }
689 }
690
691 static void
692 outdisable(void) {
693         dmastop(audio.o.dma);
694         /* turn off DAC, clear output gain switch */
695         audiomute(1);
696         status1[0] &= ~0x41;
697         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
698         if (debug) {
699                 print("outdisable:      status1 = 0x%2.2ux\n", status1[0]);
700         }
701         audioamppower(0);
702 }
703
704 static void
705 inenable(void) {
706         /* turn on ADC, set input gain switch */
707         status1[0] |= 0x22;
708         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
709         if (debug) {
710                 print("inenable:        status1 = 0x%2.2ux\n", status1[0]);
711         }
712 }
713
714 static void
715 indisable(void) {
716         dmastop(audio.i.dma);
717         /* turn off ADC, clear input gain switch */
718         status1[0] &= ~0x22;
719         L3_write(UDA1341_L3Addr | UDA1341_STATUS, status1, 1);
720         if (debug) {
721                 print("indisable:       status1 = 0x%2.2ux\n", status1[0]);
722         }
723 }
724
725 static void
726 sendaudio(IOstate *s) {
727         /* interrupt routine calls this too */
728         int n;
729
730         if (debug > 1) print("#A: sendaudio\n");
731         ilock(&s->ilock);
732         if ((audio.amode &  Aread) && s->next == s->filling && dmaidle(s->dma)) {
733                 // send an empty buffer to provide an input clock
734                 zerodma |= dmastart(s->dma, Flushbuf, volumes[Vbufsize].ilval) & 0xff;
735                 if (zerodma == 0)
736                         if (debug) print("emptyfail\n");
737                 iostats.tx.empties++;
738                 iunlock(&s->ilock);
739                 return;
740         }
741         while (s->next != s->filling) {
742                 s->next->nbytes &= ~0x3;        /* must be a multiple of 4 */
743                 if(s->next->nbytes) {
744                         if ((n = dmastart(s->dma, s->next->phys, s->next->nbytes)) == 0) {
745                                 iostats.tx.faildma++;
746                                 break;
747                         }
748                         iostats.tx.totaldma++;
749                         switch (n >> 8) {
750                         case 1:
751                                 iostats.tx.idledma++;
752                                 break;
753                         case 3:
754                                 iostats.tx.faildma++;
755                                 break;
756                         }
757                         if (debug) {
758                                 if (debug > 1)
759                                         print("dmastart @%p\n", s->next);
760                                 else
761                                         iprint("+");
762                         }
763                         s->next->nbytes = 0;
764                 }
765                 s->next++;
766                 if (s->next == &s->buf[Nbuf])
767                         s->next = &s->buf[0];
768         }
769         iunlock(&s->ilock);
770 }
771
772 static void
773 recvaudio(IOstate *s) {
774         /* interrupt routine calls this too */
775         int n;
776
777         if (debug > 1) print("#A: recvaudio\n");
778         ilock(&s->ilock);
779         while (s->next != s->emptying) {
780                 assert(s->next->nbytes == 0);
781                 if ((n = dmastart(s->dma, s->next->phys, volumes[Vbufsize].ilval)) == 0) {
782                         iostats.rx.faildma++;
783                         break;
784                 }
785                 iostats.rx.totaldma++;
786                 switch (n >> 8) {
787                 case 1:
788                         iostats.rx.idledma++;
789                         break;
790                 case 3:
791                         iostats.rx.faildma++;
792                         break;
793                 }
794                 if (debug) {
795                         if (debug > 1)
796                                 print("dmastart @%p\n", s->next);
797                         else
798                                 iprint("+");
799                 }
800                 s->next++;
801                 if (s->next == &s->buf[Nbuf])
802                         s->next = &s->buf[0];
803         }
804         iunlock(&s->ilock);
805 }
806
807 void
808 audiopower(int flag) {
809         IOstate *s;
810
811         if (debug) {
812                 iprint("audiopower %d\n", flag);
813         }
814         if (flag) {
815                 /* power on only when necessary */
816                 if (audio.amode) {
817                         audioamppower(1);
818                         audioicpower(1);
819                         egpiobits(EGPIO_codec_reset, 1);
820                         enable();
821                         if (audio.amode & Aread) {
822                                 inenable();
823                                 s = &audio.i;
824                                 dmareset(s->dma, 1, 0, 4, 2, SSPRecvDMA, Port4SSP);
825                                 recvaudio(s);
826                         }
827                         if (audio.amode & Awrite) {
828                                 outenable();
829                                 s = &audio.o;
830                                 dmareset(s->dma, 0, 0, 4, 2, SSPXmitDMA, Port4SSP);
831                                 sendaudio(s);
832                         }
833                         mxvolume();
834                 }
835         } else {
836                 /* power off */
837                 if (audio.amode & Aread)
838                         indisable();
839                 if (audio.amode & Awrite)
840                         outdisable();
841                 egpiobits(EGPIO_codec_reset, 0);
842                 audioamppower(0);
843                 audioicpower(0);
844         }
845 }
846
847 static void
848 audiointr(void *x, ulong ndma) {
849         IOstate *s = x;
850
851         if (debug) {
852                 if (debug > 1)
853                         iprint("#A: audio interrupt @%p\n", s->current);
854                 else
855                         iprint("-");
856         }
857         if (s == &audio.i || (ndma & ~zerodma)) {
858                 /* A dma, not of a zero buffer completed, update current
859                  * Only interrupt routine touches s->current
860                  */
861                 s->current->nbytes = (s == &audio.i)? volumes[Vbufsize].ilval: 0;
862                 s->current++;
863                 if (s->current == &s->buf[Nbuf])
864                         s->current = &s->buf[0];
865         }
866         if (ndma) {
867                 if (s == &audio.o) {
868                         zerodma &= ~ndma;
869                         sendaudio(s);
870                 } else if (s == &audio.i)
871                         recvaudio(s);
872         }
873         wakeup(&s->vous);
874 }
875
876 static Chan*
877 audioattach(char *param)
878 {
879         return devattach('A', param);
880 }
881
882 static Walkqid*
883 audiowalk(Chan *c, Chan *nc, char **name, int nname)
884 {
885         return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen);
886 }
887
888 static int
889 audiostat(Chan *c, uchar *db, int n)
890 {
891         return devstat(c, db, n, audiodir, nelem(audiodir), devgen);
892 }
893
894 static Chan*
895 audioopen(Chan *c, int mode)
896 {
897         IOstate *s;
898         int omode = mode;
899
900         switch((ulong)c->qid.path) {
901         default:
902                 error(Eperm);
903                 break;
904
905         case Qstatus:
906         case Qstats:
907                 if((omode&7) != OREAD)
908                         error(Eperm);
909         case Qvolume:
910         case Qdir:
911                 break;
912
913         case Qaudio:
914                 omode = (omode & 0x7) + 1;
915                 if (omode & ~(Aread | Awrite))
916                         error(Ebadarg);
917                 qlock(&audio);
918                 if(audio.amode & omode){
919                         qunlock(&audio);
920                         error(Einuse);
921                 }
922                 enable();
923                 memset(&iostats, 0, sizeof(iostats));
924                 if (omode & Aread) {
925                         inenable();
926                         s = &audio.i;
927                         if(s->bufinit == 0)
928                                 bufinit(s);
929                         setempty(s);
930                         s->emptying = &s->buf[Nbuf-1];
931                         s->chan = c;
932                         s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s);
933                         audio.amode |= Aread;
934                 }
935                 if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) {
936                         s = &audio.o;
937                         if(s->bufinit == 0)
938                                 bufinit(s);
939                         setempty(s);
940                         s->chan = c;
941                         s->dma = dmaalloc(0, 0, 4, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)s);
942                 }       
943                 if (omode & Awrite) {
944                         audio.amode |= Awrite;
945                         outenable();
946                 }
947                 mxvolume();
948                 if (audio.amode & Aread)
949                         sendaudio(&audio.o);
950                 qunlock(&audio);
951                         
952                 if (debug) print("open done\n");
953                 break;
954         }
955         c = devopen(c, mode, audiodir, nelem(audiodir), devgen);
956         c->mode = openmode(mode);
957         c->flag |= COPEN;
958         c->offset = 0;
959
960         return c;
961 }
962
963 static void
964 audioclose(Chan *c)
965 {
966         IOstate *s;
967
968         switch((ulong)c->qid.path) {
969         default:
970                 error(Eperm);
971                 break;
972
973         case Qdir:
974         case Qvolume:
975         case Qstatus:
976         case Qstats:
977                 break;
978
979         case Qaudio:
980                 if (debug > 1) print("#A: close\n");
981                 if(c->flag & COPEN) {
982                         qlock(&audio);
983                         if (audio.i.chan == c) {
984                                 /* closing the read end */
985                                 audio.amode &= ~Aread;
986                                 s = &audio.i;
987                                 qlock(s);
988                                 indisable();
989                                 setempty(s);
990                                 dmafree(s->dma);
991                                 qunlock(s);
992                                 if ((audio.amode & Awrite) == 0) {
993                                         s = &audio.o;
994                                         qlock(s);
995                                         while(waserror())
996                                                 ;
997                                         dmawait(s->dma);
998                                         poperror();
999                                         outdisable();
1000                                         setempty(s);
1001                                         dmafree(s->dma);
1002                                         qunlock(s);
1003                                 }
1004                         }
1005                         if (audio.o.chan == c) {
1006                                 /* closing the write end */
1007                                 audio.amode &= ~Awrite;
1008                                 s = &audio.o;
1009                                 qlock(s);
1010                                 if (s->filling->nbytes) {
1011                                         /* send remaining partial buffer */
1012                                         s->filling++;
1013                                         if (s->filling == &s->buf[Nbuf])
1014                                                 s->filling = &s->buf[0];
1015                                         sendaudio(s);
1016                                 }
1017                                 while(waserror())
1018                                         ;
1019                                 dmawait(s->dma);
1020                                 poperror();
1021                                 outdisable();
1022                                 setempty(s);
1023                                 if ((audio.amode & Aread) == 0)
1024                                         dmafree(s->dma);
1025                                 qunlock(s);
1026                         }
1027                         if (audio.amode == 0) {
1028                                 /* turn audio off */
1029                                 egpiobits(EGPIO_codec_reset, 0);
1030                                 audioicpower(0);
1031                         }
1032                         qunlock(&audio);
1033                 }
1034                 break;
1035         }
1036 }
1037
1038 static long
1039 audioread(Chan *c, void *v, long n, vlong off)
1040 {
1041         int liv, riv, lov, rov;
1042         long m, n0;
1043         char buf[300];
1044         int j;
1045         ulong offset = off;
1046         char *p;
1047         IOstate *s;
1048
1049         n0 = n;
1050         p = v;
1051         switch((ulong)c->qid.path) {
1052         default:
1053                 error(Eperm);
1054                 break;
1055
1056         case Qdir:
1057                 return devdirread(c, p, n, audiodir, nelem(audiodir), devgen);
1058
1059         case Qaudio:
1060                 if (debug > 1) print("#A: read %ld\n", n);
1061                 if((audio.amode & Aread) == 0)
1062                         error(Emode);
1063                 s = &audio.i;
1064                 qlock(s);
1065                 if(waserror()){
1066                         qunlock(s);
1067                         nexterror();
1068                 }
1069                 while(n > 0) {
1070                         if(s->emptying->nbytes == 0) {
1071                                 if (debug > 1) print("#A: emptied @%p\n", s->emptying);
1072                                 recvaudio(s);
1073                                 s->emptying++;
1074                                 if (s->emptying == &s->buf[Nbuf])
1075                                         s->emptying = s->buf;
1076                         }
1077                         /* wait if dma in progress */
1078                         while (!dmaidle(s->dma) && s->emptying == s->current) {
1079                                 if (debug > 1) print("#A: sleep\n");
1080                                 sleep(&s->vous, audioqnotempty, s);
1081                         }
1082
1083                         m = (s->emptying->nbytes > n)? n: s->emptying->nbytes;
1084                         memmove(p, s->emptying->virt + volumes[Vbufsize].ilval - 
1085                                           s->emptying->nbytes, m);
1086
1087                         s->emptying->nbytes -= m;
1088                         n -= m;
1089                         p += m;
1090                 }
1091                 poperror();
1092                 qunlock(s);
1093                 break;
1094
1095         case Qstatus:
1096                 buf[0] = 0;
1097                 snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n",
1098                         audio.totcount, audio.tottime);
1099                 return readstr(offset, p, n, buf);
1100
1101         case Qstats:
1102                 buf[0] = 0;
1103                 snprint(buf, sizeof(buf), 
1104                             "bytes %lud\nRX dmas %lud, while idle %lud, while busy %lud, "
1105                             "out-of-order %lud, empty dmas %lud\n"
1106                             "TX dmas %lud, while idle %lud, while busy %lud, "
1107                             "out-of-order %lud, empty dmas %lud\n",
1108                             iostats.bytes, iostats.rx.totaldma, iostats.rx.idledma, 
1109                             iostats.rx.faildma, iostats.rx.samedma, iostats.rx.empties,
1110                             iostats.tx.totaldma, iostats.tx.idledma, 
1111                             iostats.tx.faildma, iostats.tx.samedma, iostats.tx.empties);
1112
1113                 return readstr(offset, p, n, buf);
1114
1115         case Qvolume:
1116                 j = 0;
1117                 buf[0] = 0;
1118                 for(m=0; volumes[m].name; m++){
1119                         if (m == Vaudio) {
1120                                 liv = audio.livol[m];
1121                                 riv = audio.rivol[m];
1122                                 lov = audio.lovol[m];
1123                                 rov = audio.rovol[m];
1124                         }
1125                         else {
1126                                 lov = liv = volumes[m].ilval;
1127                                 rov = riv = volumes[m].irval;
1128                         }
1129         
1130                         j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
1131                         if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
1132                                 if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
1133                                         j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
1134                                 else{
1135                                         if(volumes[m].flag & Fin)
1136                                                 j += snprint(buf+j, sizeof(buf)-j,
1137                                                         " in %d", liv);
1138                                         if(volumes[m].flag & Fout)
1139                                                 j += snprint(buf+j, sizeof(buf)-j,
1140                                                         " out %d", lov);
1141                                 }
1142                         }else{
1143                                 if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
1144                                     liv==lov && riv==rov)
1145                                         j += snprint(buf+j, sizeof(buf)-j,
1146                                                 " left %d right %d",
1147                                                 liv, riv);
1148                                 else{
1149                                         if(volumes[m].flag & Fin)
1150                                                 j += snprint(buf+j, sizeof(buf)-j,
1151                                                         " in left %d right %d",
1152                                                         liv, riv);
1153                                         if(volumes[m].flag & Fout)
1154                                                 j += snprint(buf+j, sizeof(buf)-j,
1155                                                         " out left %d right %d",
1156                                                         lov, rov);
1157                                 }
1158                         }
1159                         j += snprint(buf+j, sizeof(buf)-j, "\n");
1160                 }
1161                 return readstr(offset, p, n, buf);
1162         }
1163         return n0-n;
1164 }
1165
1166 static void
1167 setaudio(int in, int out, int left, int right, int value)
1168 {
1169         if (value < 0 || value > 100) 
1170                 error(Evolume);
1171         if(left && out)
1172                 audio.lovol[Vaudio] = value;
1173         if(left && in)
1174                 audio.livol[Vaudio] = value;
1175         if(right && out)
1176                 audio.rovol[Vaudio] = value;
1177         if(right && in)
1178                 audio.rivol[Vaudio] = value;
1179 }
1180
1181 static void 
1182 setspeed(int, int, int, int, int speed)
1183 {
1184         uchar   clock;
1185
1186         /* external clock configured for 44100 samples/sec */
1187         switch (speed) {
1188         case 32000:
1189                 /* 00 */
1190                 gpioregs->clear = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
1191                 clock = SC384FS;        /* Only works in MSB mode! */
1192                 break;
1193         case 48000:
1194                 /* 00 */
1195                 gpioregs->clear = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
1196                 clock = SC256FS;
1197                 break;
1198         default:
1199                 speed = 44100;
1200         case 44100:
1201                 /* 01 */
1202                 gpioregs->set = GPIO_CLK_SET0_o;
1203                 gpioregs->clear = GPIO_CLK_SET1_o;
1204                 clock = SC256FS;
1205                 break;
1206         case 8000:
1207                 /* 10 */
1208                 gpioregs->set = GPIO_CLK_SET1_o;
1209                 gpioregs->clear = GPIO_CLK_SET0_o;
1210                 clock = SC512FS;        /* Only works in MSB mode! */
1211                 break;
1212         case 16000:
1213                 /* 10 */
1214                 gpioregs->set = GPIO_CLK_SET1_o;
1215                 gpioregs->clear = GPIO_CLK_SET0_o;
1216                 clock = SC256FS;
1217                 break;
1218         case 11025:
1219                 /* 11 */
1220                 gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
1221                 clock = SC512FS;        /* Only works in MSB mode! */
1222                 break;
1223         case 22050:
1224                 /* 11 */
1225                 gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o;
1226                 clock = SC256FS;
1227                 break;
1228         }
1229
1230         /* Wait for the UDA1341 to wake up */
1231         delay(100);
1232
1233         /* Reset the chip */
1234         status0[0] &= ~CLOCKMASK;
1235
1236         status0[0] |=clock;
1237         volumes[Vspeed].ilval = speed;
1238 }
1239
1240 static void
1241 setbufsize(int, int, int, int, int value)
1242 {
1243         if ((value % 8) != 0 || value < 8 || value >= Bufsize)
1244                 error(Ebadarg);
1245         volumes[Vbufsize].ilval = value;
1246 }
1247
1248 static long
1249 audiowrite(Chan *c, void *vp, long n, vlong)
1250 {
1251         long m, n0;
1252         int i, v, left, right, in, out;
1253         char *p;
1254         IOstate *a;
1255         Cmdbuf *cb;
1256
1257         p = vp;
1258         n0 = n;
1259         switch((ulong)c->qid.path) {
1260         default:
1261                 error(Eperm);
1262                 break;
1263
1264         case Qvolume:
1265                 v = Vaudio;
1266                 left = 1;
1267                 right = 1;
1268                 in = 1;
1269                 out = 1;
1270                 cb = parsecmd(p, n);
1271                 if(waserror()){
1272                         free(cb);
1273                         nexterror();
1274                 }
1275
1276                 for(i = 0; i < cb->nf; i++){
1277                         /*
1278                          * a number is volume
1279                          */
1280                         if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') {
1281                                 m = strtoul(cb->f[i], 0, 10);
1282                                 if (volumes[v].setval)
1283                                         volumes[v].setval(in, out, left, right, m);
1284                                 goto cont0;
1285                         }
1286
1287                         for(m=0; volumes[m].name; m++) {
1288                                 if(strcmp(cb->f[i], volumes[m].name) == 0) {
1289                                         v = m;
1290                                         in = 1;
1291                                         out = 1;
1292                                         left = 1;
1293                                         right = 1;
1294                                         goto cont0;
1295                                 }
1296                         }
1297
1298                         if(strcmp(cb->f[i], "reset") == 0) {
1299                                 resetlevel();
1300                                 goto cont0;
1301                         }
1302                         if(strcmp(cb->f[i], "debug") == 0) {
1303                                 debug = debug?0:1;
1304                                 goto cont0;
1305                         }
1306                         if(strcmp(cb->f[i], "in") == 0) {
1307                                 in = 1;
1308                                 out = 0;
1309                                 goto cont0;
1310                         }
1311                         if(strcmp(cb->f[i], "out") == 0) {
1312                                 in = 0;
1313                                 out = 1;
1314                                 goto cont0;
1315                         }
1316                         if(strcmp(cb->f[i], "left") == 0) {
1317                                 left = 1;
1318                                 right = 0;
1319                                 goto cont0;
1320                         }
1321                         if(strcmp(cb->f[i], "right") == 0) {
1322                                 left = 0;
1323                                 right = 1;
1324                                 goto cont0;
1325                         }
1326                         if(strcmp(cb->f[i], "reg") == 0) {
1327                                 if(cb->nf < 3)
1328                                         error(Evolume);
1329                                 setreg(cb->f[1], atoi(cb->f[2]), cb->nf == 4 ? atoi(cb->f[3]):1);
1330                                 return n0;
1331                         }
1332                         error(Evolume);
1333                         break;
1334                 cont0:;
1335                 }
1336                 mxvolume();
1337                 poperror();
1338                 free(cb);
1339                 break;
1340
1341         case Qaudio:
1342                 if (debug > 1) print("#A: write %ld\n", n);
1343                 if((audio.amode & Awrite) == 0)
1344                         error(Emode);
1345                 a = &audio.o;
1346                 qlock(a);
1347                 if(waserror()){
1348                         qunlock(a);
1349                         nexterror();
1350                 }
1351                 while(n > 0) {
1352                         /* wait if dma in progress */
1353                         while (!dmaidle(a->dma) && !zerodma && a->filling == a->current) {
1354                                 if (debug > 1) print("#A: sleep\n");
1355                                 sleep(&a->vous, audioqnotfull, a);
1356                         }
1357                         m = volumes[Vbufsize].ilval - a->filling->nbytes;
1358                         if(m > n)
1359                                 m = n;
1360                         memmove(a->filling->virt + a->filling->nbytes, p, m);
1361
1362                         a->filling->nbytes += m;
1363                         n -= m;
1364                         p += m;
1365                         if(a->filling->nbytes >= volumes[Vbufsize].ilval) {
1366                                 if (debug > 1) print("#A: filled @%p\n", a->filling);
1367                                 a->filling++;
1368                                 if (a->filling == &a->buf[Nbuf])
1369                                         a->filling = a->buf;
1370                                 sendaudio(a);
1371                         }
1372                 }
1373                 poperror();
1374                 qunlock(a);
1375                 break;
1376         }
1377         return n0 - n;
1378 }
1379
1380 Dev uda1341devtab = {
1381         'A',
1382         "audio",
1383
1384         devreset,
1385         audioinit,
1386         devshutdown,
1387         audioattach,
1388         audiowalk,
1389         audiostat,
1390         audioopen,
1391         devcreate,
1392         audioclose,
1393         audioread,
1394         devbread,
1395         audiowrite,
1396         devbwrite,
1397         devremove,
1398         devwstat,
1399         audiopower,
1400 };