| plan 9 kernel history: overview | file list | diff list |
2000/1116/bitsy/devuda1341.c (diff list | history)
| 2000/1115/sys/src/9/bitsy/devuda1341.c:138,144 – 2000/1116/sys/src/9/bitsy/devuda1341.c:138,143 (short | long | prev | next) | ||
| 2000/1110 | int dma; /* dma chan, alloc on open, free on close */ int bufinit; /* boolean, if buffers allocated */ Buf buf[Nbuf]; /* buffers and queues */ | |
| 2000/1111 |
| |
| 2000/1110 | volatile Buf *current; /* next dma to finish */ volatile Buf *next; /* next candidate for dma */ volatile Buf *filling; /* buffer being filled */ | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:159,164 – 2000/1116/sys/src/9/bitsy/devuda1341.c:158,171 | ||
| 2000/1109 | IOstate o; | |
| 2000/1103 | } audio; | |
| 2000/1116 | static struct { ulong bytes; ulong totaldma; ulong idledma; ulong faildma; } iostats; | |
| 2000/1103 | static struct { char* name; | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:404,427 – 2000/1116/sys/src/9/bitsy/devuda1341.c:411,419 | ||
| 2000/1111 | IOstate *s = x; | |
| 2000/1110 | /* called with lock */ | |
| 2000/1111 |
| |
| 2000/1116 | return dmaidle(s->dma) || s->filling != s->current; | |
| 2000/1110 | } | |
| 2000/1111 |
| |
| 2000/1110 |
| |
| 2000/1111 |
| |
| 2000/1110 |
| |
| 2000/1111 |
| |
| 2000/1110 |
| |
| 2000/1103 | static void audioinit(void) { | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:436,485 – 2000/1116/sys/src/9/bitsy/devuda1341.c:428,473 | ||
| 2000/1103 | L3_init(); | |
| 2000/1110 | /* Setup the uarts */ | |
| 2000/1115 |
| |
| 2000/1116 | ppcregs->assignment &= ~(1<<18); | |
| 2000/1103 | ||
| 2000/1111 | gpioregs->altfunc &= ~(GPIO_SSP_TXD_o | GPIO_SSP_RXD_i | GPIO_SSP_SCLK_o | GPIO_SSP_SFRM_o); gpioregs->altfunc |= (GPIO_SSP_CLK_i); gpioregs->direction &= ~(GPIO_SSP_CLK_i); | |
| 2000/1103 | ||
| 2000/1115 |
| |
| 2000/1110 |
| |
| 2000/1116 | sspregs->control0 = 0; sspregs->control0 = 0x031f; /* 16 bits, TI frames, serial clock rate 3 */ sspregs->control1 = 0x0020; /* ext clock */ sspregs->control0 = 0x039f; /* enable */ | |
| 2000/1110 | ||
| 2000/1115 |
| |
| 2000/1110 | /* Enable the audio power */ | |
| 2000/1111 | audiopower(1); amplifierpower(1); audiomute(0); | |
| 2000/1110 | ||
| 2000/1116 | /* external clock configured for 44100 samples/sec */ | |
| 2000/1111 | gpioregs->direction |= (GPIO_CLK_SET0_o|GPIO_CLK_SET1_o); | |
| 2000/1110 | ||
| 2000/1116 | /* This is purportedly the wrong way round: 0 should be set, 1 cleared */ gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o; // gpioregs->clear = GPIO_CLK_SET1_o; | |
| 2000/1110 | /* Wait for the UDA1341 to wake up */ | |
| 2000/1111 | delay(100); | |
| 2000/1110 | ||
| 2000/1115 |
| |
| 2000/1111 | /* Reset the chip */ | |
| 2000/1116 | data[0] = 2<<UdaStatusSC | 1<<UdaStatusIF | 1<<UdaStatusRST; | |
| 2000/1111 | L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 ); | |
| 2000/1116 | gpioregs->set = EGPIO_codec_reset; gpioregs->clear = EGPIO_codec_reset; /* write uda 1341 status[0] */ data[0] &= ~(1<<UdaStatusRST); /* clear reset */ L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 ); | |
| 2000/1110 | ||
| 2000/1115 |
| |
| 2000/1103 | ||
| 2000/1111 |
| |
| 2000/1103 | ||
| 2000/1111 | /* write uda 1341 status[1] */ data[0] = 0x80 | 0x3<<UdaStatusPC | 1<<UdaStatusIGS | 1<<UdaStatusOGS; L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1); /* write uda 1341 data0[0] (volume) */ | |
| 2000/1116 | data[0] = 15 & 0x3f; /* 6 bits, others must be 0 */ | |
| 2000/1111 | L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 1); /* write uda 1341 data0[2] (mode switch) */ | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:501,531 – 2000/1116/sys/src/9/bitsy/devuda1341.c:489,516 | ||
| 2000/1111 | data[1] = 0xe0 | 0<<2 | 3; /* agc time constant and output level */ L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 2 ); | |
| 2000/1115 |
| |
| 2000/1113 |
| |
| 2000/1116 | if (debug) { print("#A: audio enabled\n"); print("\tsspregs->control0 = 0x%lux\n", sspregs->control0); print("\tsspregs->control1 = 0x%lux\n", sspregs->control1); } | |
| 2000/1103 | } | |
| 2000/1107 | static void | |
| 2000/1111 | sendaudio(IOstate *b) { | |
| 2000/1115 | /* interrupt routine calls this too */ | |
| 2000/1116 | int n; | |
| 2000/1115 | if (debug > 1) print("#A: sendaudio\n"); ilock(&b->ilock); | |
| 2000/1110 | while (b->next != b->filling) { assert(b->next->nbytes); | |
| 2000/1115 |
| |
| 2000/1116 | if ((n = dmastart(b->dma, b->next->virt, b->next->nbytes)) == 0) { iostats.faildma++; | |
| 2000/1115 | break; } | |
| 2000/1116 | iostats.totaldma++; if (n == 1) iostats.idledma++; | |
| 2000/1115 | if (debug > 1) print("#A: dmastart @%p\n", b->next); b->next->nbytes = 0; | |
| 2000/1110 | b->next++; | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:536,542 – 2000/1116/sys/src/9/bitsy/devuda1341.c:521,527 | ||
| 2000/1110 | } static void | |
| 2000/1111 |
| |
| 2000/1116 | audiointr(void *x, ulong ndma) { | |
| 2000/1110 | IOstate *s = x; if (s == &audio.o) { | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:545,552 – 2000/1116/sys/src/9/bitsy/devuda1341.c:530,537 | ||
| 2000/1110 | s->current++; | |
| 2000/1111 | if (s->current == &s->buf[Nbuf]) s->current = &s->buf[0]; | |
| 2000/1115 |
| |
| 2000/1116 | if (ndma > 0) sendaudio(s); | |
| 2000/1109 | } | |
| 2000/1111 | wakeup(&s->vous); | |
| 2000/1109 | } | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:596,601 – 2000/1116/sys/src/9/bitsy/devuda1341.c:581,587 | ||
| 2000/1107 | error(Einuse); } | |
| 2000/1111 | audioenable(); | |
| 2000/1116 | memset(&iostats, 0, sizeof(iostats)); | |
| 2000/1109 | if (omode & Aread) { | |
| 2000/1108 | /* read */ | |
| 2000/1109 | audio.amode |= Aread; | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:663,672 – 2000/1116/sys/src/9/bitsy/devuda1341.c:649,661 | ||
| 2000/1110 | audio.o.filling = &audio.o.buf[0]; sendaudio(&audio.o); } | |
| 2000/1116 | delay(2000); // dmawait(audio.o.dma); if (!dmaidle(audio.o.dma)) print("dma still busy\n"); | |
| 2000/1111 | amplifierpower(0); | |
| 2000/1110 | setempty(&audio.o); | |
| 2000/1116 | dmafree(audio.o.dma); | |
| 2000/1110 | } if (audio.i.chan == c) { /* closing the read end */ | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:680,685 – 2000/1116/sys/src/9/bitsy/devuda1341.c:669,677 | ||
| 2000/1107 | poperror(); | |
| 2000/1110 | qunlock(&audio.o); | |
| 2000/1107 | qunlock(&audio); | |
| 2000/1116 | print("total dmas: %lud\n", iostats.totaldma); print("dmas while idle: %lud\n", iostats.idledma); print("dmas while busy: %lud\n", iostats.faildma); | |
| 2000/1107 | } break; } | |
| 2000/1115/sys/src/9/bitsy/devuda1341.c:857,863 – 2000/1116/sys/src/9/bitsy/devuda1341.c:849,855 | ||
| 2000/1107 | } while(n > 0) { | |
| 2000/1109 | /* wait if dma in progress */ | |
| 2000/1115 |
| |
| 2000/1116 | while (!dmaidle(a->dma) && a->filling == a->current) { | |
| 2000/1115 | if (debug > 1) print("#A: sleep\n"); | |
| 2000/1110 | sleep(&a->vous, audioqnotfull, a); | |
| 2000/1115 | } | |