| plan 9 kernel history: overview | file list | diff list |
2001/0502/bitsy/devuda1341.c (diff list | history)
| 2001/0501/sys/src/9/bitsy/devuda1341.c:19,25 – 2001/0502/sys/src/9/bitsy/devuda1341.c:19,25 (short | long | prev | next) | ||
| 2000/1103 | #include "io.h" | |
| 2000/1110 | #include "sa1110dma.h" | |
| 2000/1103 | ||
| 2001/0501 |
| |
| 2001/0502 | static int debug = 0; | |
| 2000/1113 | ||
| 2000/1103 | /* * GPIO based L3 bus support. | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:139,153 – 2001/0502/sys/src/9/bitsy/devuda1341.c:139,153 | ||
| 2000/1103 | { QLock; | |
| 2000/1115 | Lock ilock; | |
| 2000/1110 |
| |
| 2001/0502 | Rendez vous; Chan *chan; /* chan of open */ int dma; /* dma chan, alloc on open, free on close */ int bufinit; /* boolean, if buffers allocated */ Buf buf[Nbuf]; /* buffers and queues */ | |
| 2000/1110 | volatile Buf *current; /* next dma to finish */ | |
| 2001/0502 | volatile Buf *next; /* next candidate for dma */ | |
| 2000/1110 | volatile Buf *filling; /* buffer being filled */ | |
| 2000/1118 |
| |
| 2001/0502 | /* to have defines just like linux — there's a real operating system */ | |
| 2000/1118 | #define emptying filling | |
| 2000/1109 | }; | |
| 2000/1103 | ||
| 2001/0501/sys/src/9/bitsy/devuda1341.c:166,171 – 2001/0502/sys/src/9/bitsy/devuda1341.c:166,174 | ||
| 2000/1109 | IOstate o; | |
| 2000/1103 | } audio; | |
| 2001/0502 | Buf zeroes; int zerodma; /* dma buffer used for sending zero */ | |
| 2000/1116 | static struct { ulong bytes; | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:173,178 – 2001/0502/sys/src/9/bitsy/devuda1341.c:176,182 | ||
| 2000/1116 | ulong idledma; ulong faildma; | |
| 2000/1117 | ulong samedma; | |
| 2001/0502 | ulong empties; | |
| 2000/1116 | } iostats; | |
| 2000/1103 | static struct | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:183,196 – 2001/0502/sys/src/9/bitsy/devuda1341.c:187,200 | ||
| 2000/1103 | int irval; } volumes[] = { | |
| 2000/1207 |
| |
| 2001/0502 | [Vaudio] {"audio", Fout|Fmono, 80, 80}, [Vmic] {"mic", Fin|Fmono, 0, 0}, [Vtreb] {"treb", Fout|Fmono, 50, 50}, [Vbass] {"bass", Fout|Fmono, 50, 50}, | |
| 2000/1207 | [Vspeed] {"speed", Fin|Fout|Fmono, Speed, Speed}, | |
| 2001/0502 | [Vfilter] {"filter", Fout|Fmono, 0, 0}, [Vinvert] {"invert", Fin|Fout|Fmono, 0, 0}, [Nvol] {0} | |
| 2000/1103 | }; | |
| 2001/0421 | static void setreg(char *name, int val, int n); | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:397,404 – 2001/0502/sys/src/9/bitsy/devuda1341.c:401,415 | ||
| 2000/1118 | for (i = 0; i < Nbuf; i++) { | |
| 2000/1109 | b->buf[i].virt = xalloc(Bufsize); | |
| 2000/1118 | b->buf[i].phys = PADDR(b->buf[i].virt); | |
| 2001/0502 | memset(b->buf[i].virt, 0xAA, Bufsize); | |
| 2000/1118 | } | |
| 2000/1109 | b->bufinit = 1; | |
| 2001/0502 | if (b == &audio.o) { zeroes.virt = xalloc(Bufsize); zeroes.phys = PADDR(b->buf[i].virt); memset(zeroes.virt, 0, Bufsize); } | |
| 2000/1109 | }; | |
| 2000/1103 | ||
| 2000/1109 | static void | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:681,686 – 2001/0502/sys/src/9/bitsy/devuda1341.c:692,706 | ||
| 2000/1116 | ||
| 2000/1115 | if (debug > 1) print("#A: sendaudio\n"); | |
| 2000/1117 | ilock(&s->ilock); | |
| 2001/0502 | if ((audio.amode & Aread) && s->next == s->filling && dmaidle(s->dma)) { // send an empty buffer to provide an input clock zerodma |= dmastart(s->dma, zeroes.phys, Bufsize) & 0xff; if (zerodma == 0) if (debug) print("emptyfail\n"); iostats.empties++; iunlock(&s->ilock); return; } | |
| 2000/1117 | while (s->next != s->filling) { assert(s->next->nbytes); | |
| 2000/1118 | if ((n = dmastart(s->dma, s->next->phys, s->next->nbytes)) == 0) { | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:688,694 – 2001/0502/sys/src/9/bitsy/devuda1341.c:708,714 | ||
| 2000/1115 | break; } | |
| 2000/1116 | iostats.totaldma++; | |
| 2000/1117 |
| |
| 2001/0502 | switch (n >> 8) { | |
| 2000/1117 | case 1: iostats.idledma++; break; | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:724,730 – 2001/0502/sys/src/9/bitsy/devuda1341.c:744,750 | ||
| 2000/1118 | break; } iostats.totaldma++; | |
| 2001/0502 | switch (n >> 8) { | |
| 2000/1118 | case 1: iostats.idledma++; break; | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:791,804 – 2001/0502/sys/src/9/bitsy/devuda1341.c:811,830 | ||
| 2000/1122 | else iprint("-"); } | |
| 2000/1121 |
| |
| 2001/0502 | if (s == &audio.i || (ndma & ~zerodma)) { /* A dma, not of a zero buffer completed, update current * Only interrupt routine touches s->current */ s->current->nbytes = (s == &audio.i)? Bufsize: 0; s->current++; if (s->current == &s->buf[Nbuf]) s->current = &s->buf[0]; } if (ndma) { if (s == &audio.o) { zerodma &= ~ndma; | |
| 2000/1116 | sendaudio(s); | |
| 2000/1121 |
| |
| 2001/0502 | } else if (s == &audio.i) | |
| 2000/1118 | recvaudio(s); | |
| 2000/1109 | } | |
| 2000/1111 | wakeup(&s->vous); | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:862,880 – 2001/0502/sys/src/9/bitsy/devuda1341.c:888,910 | ||
| 2000/1122 | s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s); | |
| 2000/1125 | audio.amode |= Aread; | |
| 2000/1108 | } | |
| 2000/1121 |
| |
| 2000/1117 |
| |
| 2001/0502 | if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) { | |
| 2000/1117 | s = &audio.o; | |
| 2000/1109 |
| |
| 2000/1117 | if(s->bufinit == 0) bufinit(s); setempty(s); s->chan = c; s->dma = dmaalloc(0, 0, 4, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)s); | |
| 2001/0502 | } if (omode & Awrite) { | |
| 2000/1125 | audio.amode |= Awrite; | |
| 2001/0502 | outenable(); | |
| 2000/1107 | } | |
| 2000/1117 | mxvolume(); | |
| 2000/1115 | qunlock(&audio); | |
| 2001/0502 | if (audio.amode == Aread) sendaudio(&audio.o); | |
| 2000/1122 | if (debug) print("open done\n"); | |
| 2000/1107 | break; } | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:905,913 – 2001/0502/sys/src/9/bitsy/devuda1341.c:935,962 | ||
| 2000/1115 | if (debug > 1) print("#A: close\n"); | |
| 2000/1107 | if(c->flag & COPEN) { qlock(&audio); | |
| 2001/0502 | if (audio.i.chan == c) { /* closing the read end */ audio.amode &= ~Aread; s = &audio.i; qlock(s); indisable(); setempty(s); dmafree(s->dma); qunlock(s); if ((audio.amode & Awrite) == 0) { s = &audio.o; qlock(s); while(waserror()) { dmawait(s->dma); if (dmaidle(s->dma)) break; } outdisable(); setempty(s); dmafree(s->dma); qunlock(s); } | |
| 2000/1107 | } | |
| 2000/1110 | if (audio.o.chan == c) { | |
| 2000/1118 | /* closing the write end */ | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:914,923 – 2001/0502/sys/src/9/bitsy/devuda1341.c:963,968 | ||
| 2000/1118 | audio.amode &= ~Awrite; | |
| 2000/1117 | s = &audio.o; qlock(s); | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:925,958 – 2001/0502/sys/src/9/bitsy/devuda1341.c:970,991 | ||
| 2000/1117 | s->filling = &s->buf[0]; sendaudio(s); | |
| 2000/1110 | } | |
| 2000/1117 |
| |
| 2001/0502 | while(waserror()) { dmawait(s->dma); if (dmaidle(s->dma)) break; } | |
| 2000/1117 | outdisable(); setempty(s); | |
| 2001/0502 | if ((audio.amode & Aread) == 0) dmafree(s->dma); | |
| 2000/1117 | qunlock(s); | |
| 2000/1110 | } | |
| 2000/1118 |
| |
| 2000/1117 |
| |
| 2000/1118 |
| |
| 2000/1110 |
| |
| 2000/1122 | egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0); | |
| 2000/1110 | } | |
| 2000/1107 | qunlock(&audio); | |
| 2000/1117 |
| |
| 2000/1130 | if (debug) { print("total dmas: %lud\n", iostats.totaldma); print("dmas while idle: %lud\n", iostats.idledma); | |
| 2001/0501/sys/src/9/bitsy/devuda1341.c:1009,1018 – 2001/0502/sys/src/9/bitsy/devuda1341.c:1042,1050 | ||
| 2000/1118 | sleep(&s->vous, audioqnotempty, s); } | |
| 2001/0502 | m = (s->emptying->nbytes > n)? n: s->emptying->nbytes; memmove(p, s->emptying->virt + Bufsize - s->emptying->nbytes, m); | |
| 2000/1118 | s->emptying->nbytes -= m; n -= m; | |