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,1442000/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    
	Ref				active;			/* # of dmas in progress */ 
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,1642000/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,4272000/1116/sys/src/9/bitsy/devuda1341.c:411,419
2000/1111    
	IOstate *s = x; 
 
2000/1110    
	/* called with lock */ 
2000/1111    
	return s->active.ref == 0 || s->filling != s->current; 
2000/1116    
	return dmaidle(s->dma) || s->filling != s->current; 
2000/1110    
} 
 
static int 
audioqnotempty(IOstate *s) 
{ 
	/* called with lock */ 
	return s->next != s->filling; 
} 
                 
static int 
2000/1111    
audioidle(void *x) 
2000/1110    
{ 
2000/1111    
	IOstate *s = x; 
2000/1110    
	/* called with lock */ 
2000/1111    
	return s->active.ref == 0; 
2000/1110    
} 
                 
2000/1103    
static void 
audioinit(void) 
{ 
2000/1115/sys/src/9/bitsy/devuda1341.c:436,4852000/1116/sys/src/9/bitsy/devuda1341.c:428,473
2000/1103    
	L3_init(); 
 
2000/1110    
	/* Setup the uarts */ 
2000/1115    
    ppcregs->assignment &= (1<<18);	/* Could be the other way round! */ 
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    
	sspregs->control0 = 0xf<<0 | 0x1<<4 | 0x3<<8; 
2000/1110    
	sspregs->control1 = 0<<3 + 0<<4 + 1<<5; 
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    
	sspregs->control0 |= 1<<7;	/* enable */ 
                 
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); 
	  /* external clock configured for 44100 samples/sec */ 
    gpioregs->set = GPIO_CLK_SET0_o; 
    gpioregs->clear = 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); 
    print("Ser4SSSR=0x%lux\n", sspregs->status); 
2000/1110    
 
2000/1115    
    gpioregs->clear = EGPIO_codec_reset; 
    gpioregs->set = EGPIO_codec_reset; 
                 
2000/1111    
	/* Reset the chip */ 
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */; 
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    
	delay(10); 
2000/1103    
                 
2000/1111    
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */; 
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 ); 
	/* Reset done */ 
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) */ 
	data[0] = 0x00 | /* volume */ 15 & 0x3f;	/* 6 bits, others must be 0 */ 
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,5312000/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    
	/* Reset the chip */ 
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */; 
	L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 ); 
                 
	delay(10); 
                 
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */; 
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 ); 
	/* Reset done */ 
                 
2000/1113    
	if (debug) print("#A: audio enabled\n"); 
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); 
		incref(&b->active); 
2000/1115    
		if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0) { 
			decref(&b->active); 
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,5422000/1116/sys/src/9/bitsy/devuda1341.c:521,527
2000/1110    
} 
 
static void 
2000/1111    
audiointr(void *x, ulong) { 
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,5522000/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    
		decref(&s->active); 
		sendaudio(s); 
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,6012000/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,6722000/1116/sys/src/9/bitsy/devuda1341.c:649,661
2000/1110    
						audio.o.filling = &audio.o.buf[0]; 
					sendaudio(&audio.o); 
				} 
				while(!audioidle(&audio.o)) 
					sleep(&audio.o.vous, audioidle, &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,6852000/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,8632000/1116/sys/src/9/bitsy/devuda1341.c:849,855
2000/1107    
		} 
		while(n > 0) { 
2000/1109    
			/* wait if dma in progress */ 
2000/1115    
			while (a->active.ref && a->filling == a->current) { 
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    
			} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)