Subject: Re: snapper microphone support
To: None <port-macppc@netbsd.org>
From: Magnus Henoch <mange@freemail.hu>
List: port-macppc
Date: 12/19/2005 16:08:35
Michael <macallan18@earthlink.net> writes:

> Not really difficult, someone probably did it already - did you have a
> look at arch/macppc/dev/snapper.c ? 

I started to hack it, and came to a good start.  With the patch below, 
the commands:

mixerctl -w record.source=mic
mixerctl -w monitor.Analog=100
audiorecord -d /dev/audio0 foo.wav

give a recording from the internal microphone.  The sound is faint,
and there is some noise, but it's something at least.  The manual
mentions many features I don't understand; maybe some of them would
give better sound.

Comments on the code are very welcome.  I haven't yet figured out how
to enable recording from CD or line-in, or how to set the input
volume.

Magnus


--- snapper.c	12 Dec 2005 10:43:47 +0100	1.7
+++ snapper.c	19 Dec 2005 15:24:38 +0100	
@@ -68,6 +68,7 @@
 
 	void (*sc_iintr)(void *);	/* dma completion intr handler */
 	void *sc_iarg;			/* arg for sc_iintr() */
+	int sc_ipages;			/* # of input pages */
 
 	u_int sc_record_source;		/* recording source mask */
 	u_int sc_output_mask;		/* output source mask */
@@ -398,7 +399,7 @@
 
 	/* intr_establish(cirq, cirq_type, IPL_AUDIO, snapper_intr, sc); */
 	intr_establish(oirq, oirq_type, IPL_AUDIO, snapper_intr, sc);
-	/* intr_establish(iirq, iirq_type, IPL_AUDIO, snapper_intr, sc); */
+	intr_establish(iirq, iirq_type, IPL_AUDIO, snapper_intr, sc);
 
 	printf(": irq %d,%d,%d\n", cirq, oirq, iirq);
 
@@ -463,6 +464,20 @@
 		cmd++;
 	}
 
+	cmd = sc->sc_idmacmd;
+	count = sc->sc_ipages;
+	while (count-- > 0) {
+		if ((dbdma_ld16(&cmd->d_command) & 0x30) == 0x30) {
+			status = dbdma_ld16(&cmd->d_status);
+			cmd->d_status = 0;
+			if (status)	/* status == 0x8400 */
+				if (sc->sc_iintr)
+					(*sc->sc_iintr)(sc->sc_iarg);
+		}
+		cmd++;
+	}
+	    
+
 	return 1;
 }
 
@@ -643,6 +658,7 @@
 {
 	struct snapper_softc *sc;
 	int l, r;
+	u_char data;
 
 	DPRINTF("snapper_set_port dev = %d, type = %d\n", mc->dev, mc->type);
 	sc = h;
@@ -675,10 +691,14 @@
 			return 0;
 		switch (mc->un.mask) {
 		case 1 << 0: /* CD */
-		case 1 << 1: /* microphone */
 		case 1 << 2: /* line in */
 			/* XXX TO BE DONE */
 			break;
+		case 1 << 1: /* microphone */
+			/* Select right channel of B input */
+			data = DEQ_ACR_ADM | DEQ_ACR_LRB | DEQ_ACR_INP_B;
+			tas3004_write(sc, DEQ_ACR, &data);
+			break;
 		default: /* invalid argument */
 			return EINVAL;
 		}
@@ -956,9 +976,53 @@
 		      void (*intr)(void *), void *arg,
 		      const audio_params_t *param)
 {
+	struct snapper_softc *sc;
+	struct dbdma_command *cmd;
+	vaddr_t va;
+	int i, len, intmode;
+
+	DPRINTF("trigger_input %p %p 0x%x\n", start, end, bsize);
+	sc = h;
+	cmd = sc->sc_idmacmd;
+	sc->sc_iintr = intr;
+	sc->sc_iarg = arg;
+	sc->sc_ipages = ((char *)end - (char *)start) / NBPG;
+
+#ifdef DIAGNOSTIC
+	if (sc->sc_ipages > 16)
+		panic("snapper_trigger_input");
+#endif
+
+	va = (vaddr_t)start;
+	len = 0;
+	for (i = sc->sc_ipages; i > 0; i--) {
+		len += NBPG;
+		if (len < bsize)
+			intmode = 0;
+		else {
+			len = 0;
+			intmode = DBDMA_INT_ALWAYS;
+		}
 
+		DBDMA_BUILD(cmd, DBDMA_CMD_IN_MORE, 0, NBPG, vtophys(va),
+		    intmode, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
+		cmd++;
+		va += NBPG;
+	}
+
+	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0,
+	    0/*vtophys((vaddr_t)sc->sc_odmacmd)*/, 0, DBDMA_WAIT_NEVER,
+	    DBDMA_BRANCH_ALWAYS);
+
+	dbdma_st32(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_idmacmd));
+
+	dbdma_start(sc->sc_idma, sc->sc_idmacmd);
+
+	return 0;
+	/*
 	printf("snapper_trigger_input called\n");
 	return 1;
+	*/
 }
 
 void
@@ -1219,8 +1283,8 @@
 	size = tas3004_regsize[reg];
 	KASSERT(size > 0);
 
-#ifdef DEBUG_SNAPPER
-	printf("reg: %x, %d %d\n",reg,size,((char*)data)[0]);
+#ifdef SNAPPER_DEBUG
+	printf("reg: %x, %d %d\n",reg,size,((const char*)data)[0]);
 #endif
 #if 0
 	ki2c_setmode(sc->sc_i2c, 8); /* std+sub mode */
@@ -1415,7 +1479,7 @@
 		OF_getprop(gpio, "name", name, sizeof name);
 		OF_getprop(gpio, "audio-gpio", audio_gpio, sizeof audio_gpio);
 		OF_getprop(gpio, "AAPL,address", &addr, sizeof addr);
-		/* printf("0x%x %s %s\n", gpio, name, audio_gpio); */
+		DPRINTF(" 0x%x %s %s\n", gpio, name, audio_gpio);
 
 		/* gpio5 */
 		if (strcmp(audio_gpio, "headphone-mute") == 0)