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,252001/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    
static int debug = 2; 
2001/0502    
static int debug = 0; 
2000/1113    
 
2000/1103    
/* 
 * GPIO based L3 bus support. 
2001/0501/sys/src/9/bitsy/devuda1341.c:139,1532001/0502/sys/src/9/bitsy/devuda1341.c:139,153
2000/1103    
{ 
	QLock; 
2000/1115    
	Lock			ilock; 
2000/1110    
	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 */ 
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 */ 
	volatile Buf	*next;			/* next candidate for dma */ 
2001/0502    
	volatile Buf	*next;		/* next candidate for dma */ 
2000/1110    
	volatile Buf	*filling;		/* buffer being filled */ 
2000/1118    
/* just be be cute (and to have defines like linux, a real operating system) */ 
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,1712001/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,1782001/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,1962001/0502/sys/src/9/bitsy/devuda1341.c:187,200
2000/1103    
	int	irval; 
} volumes[] = 
{ 
2000/1207    
[Vaudio]	{"audio",	Fout|Fmono,	 80,	 80}, 
[Vmic]		{"mic",		Fin|Fmono,	  0,	  0}, 
[Vtreb]		{"treb",	Fout|Fmono,	 50,	 50}, 
[Vbass]		{"bass",	Fout|Fmono, 	 50,	 50}, 
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}, 
[Vfilter]	{"filter",	Fout|Fmono,	  0,	  0}, 
[Vinvert]	{"invert",	Fin|Fout|Fmono,	  0,	  0}, 
[Nvol]		{0} 
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,4042001/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,6862001/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,6942001/0502/sys/src/9/bitsy/devuda1341.c:708,714
2000/1115    
			break; 
		} 
2000/1116    
		iostats.totaldma++; 
2000/1117    
		switch (n) { 
2001/0502    
		switch (n >> 8) { 
2000/1117    
		case 1: 
			iostats.idledma++; 
			break; 
2001/0501/sys/src/9/bitsy/devuda1341.c:724,7302001/0502/sys/src/9/bitsy/devuda1341.c:744,750
2000/1118    
			break; 
		} 
		iostats.totaldma++; 
		switch (n) { 
2001/0502    
		switch (n >> 8) { 
2000/1118    
		case 1: 
			iostats.idledma++; 
			break; 
2001/0501/sys/src/9/bitsy/devuda1341.c:791,8042001/0502/sys/src/9/bitsy/devuda1341.c:811,830
2000/1122    
		else 
			iprint("-"); 
	} 
2000/1121    
	/* Only interrupt routine touches s->current */ 
	s->current++; 
	if (s->current == &s->buf[Nbuf]) 
		s->current = &s->buf[0]; 
	if (ndma > 0) { 
		if (s == &audio.o) 
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    
		else if (s == &audio.i) 
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,8802001/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    
		if (omode & Awrite) { 
2000/1117    
			outenable(); 
2001/0502    
		if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) { 
2000/1117    
			s = &audio.o; 
2000/1109    
			audio.amode |= Awrite; 
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,9132001/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); 
			if(waserror()){ 
				qunlock(&audio); 
				nexterror(); 
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,9232001/0502/sys/src/9/bitsy/devuda1341.c:963,968
2000/1118    
				audio.amode &= ~Awrite; 
2000/1117    
				s = &audio.o; 
				qlock(s); 
				if(waserror()){ 
					qunlock(s); 
					nexterror(); 
				} 
				if (s->filling->nbytes) { 
					/* send remaining partial buffer */ 
					s->filling++; 
2001/0501/sys/src/9/bitsy/devuda1341.c:925,9582001/0502/sys/src/9/bitsy/devuda1341.c:970,991
2000/1117    
						s->filling = &s->buf[0]; 
					sendaudio(s); 
2000/1110    
				} 
2000/1117    
				dmawait(s->dma); 
2001/0502    
				while(waserror()) { 
					dmawait(s->dma); 
					if (dmaidle(s->dma)) 
						break; 
				} 
2000/1117    
				outdisable(); 
				setempty(s); 
				dmafree(s->dma); 
2001/0502    
				if ((audio.amode & Aread) == 0) 
					dmafree(s->dma); 
2000/1117    
				qunlock(s); 
				poperror(); 
2000/1110    
			} 
			if (audio.i.chan == c) { 
				/* closing the read end */ 
				audio.amode &= ~Aread; 
2000/1118    
				s = &audio.i; 
				qlock(s); 
				if(waserror()){ 
					qunlock(s); 
					nexterror(); 
				} 
2000/1117    
				indisable(); 
2000/1118    
				setempty(s); 
				dmafree(s->dma); 
				qunlock(s); 
				poperror(); 
2000/1110    
			} 
			if (audio.amode == 0) { 
				/* turn audio off */ 
2000/1122    
				egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0); 
2000/1110    
			} 
2000/1107    
			qunlock(&audio); 
2000/1117    
			poperror(); 
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,10182001/0502/sys/src/9/bitsy/devuda1341.c:1042,1050
2000/1118    
				sleep(&s->vous, audioqnotempty, s); 
			} 
 
			m = Bufsize - s->emptying->nbytes; 
			if(m > n) 
				m = n; 
			memmove(p, s->emptying->virt + s->emptying->nbytes, m); 
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; 


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