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

> The TAS3004 has two analog inputs, one is connected to the internal
> microphone, one to the line in if you have one ( my iBook doesn't so
> that input is silent ). The CD drive doesn't have an analog connection
> to the audio chip, even MacOS rips CDs for playback.

Ah... so the record sources can be cleaned up somewhat, as in the
patch below.  Now the microphone is selected as the default source.
I still need to figure out how to get better sound, though...

Magnus

--- snapper.c	12 Dec 2005 10:43:47 +0100	1.7
+++ snapper.c	19 Dec 2005 17:36:22 +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;
@@ -674,10 +690,15 @@
 		if (mc->un.mask == sc->sc_record_source)
 			return 0;
 		switch (mc->un.mask) {
-		case 1 << 0: /* CD */
-		case 1 << 1: /* microphone */
-		case 1 << 2: /* line in */
-			/* XXX TO BE DONE */
+		case 1 << 0: /* 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;
+		case 1 << 1: /* line in */
+			/* Select both channels of A input */
+			data = 0;
+			tas3004_write(sc, DEQ_ACR, &data);
 			break;
 		default: /* invalid argument */
 			return EINVAL;
@@ -796,13 +817,11 @@
 		strcpy(dip->label.name, AudioNsource);
 		dip->type = AUDIO_MIXER_SET;
 		dip->prev = dip->next = AUDIO_MIXER_LAST;
-		dip->un.s.num_mem = 3;
-		strcpy(dip->un.s.member[0].label.name, AudioNcd);
+		dip->un.s.num_mem = 2;
+		strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
 		dip->un.s.member[0].mask = 1 << 0;
-		strcpy(dip->un.s.member[1].label.name, AudioNmicrophone);
+		strcpy(dip->un.s.member[1].label.name, AudioNline);
 		dip->un.s.member[1].mask = 1 << 1;
-		strcpy(dip->un.s.member[2].label.name, AudioNline);
-		dip->un.s.member[2].mask = 1 << 2;
 		return 0;
 
 	case SNAPPER_VOL_INPUT:
@@ -956,9 +975,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
@@ -1164,7 +1227,7 @@
 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
 	{ 0, 0, 0 },						/* LLB_GAIN */
 	{ 0, 0, 0 },						/* RLB_GAIN */
-	{ 0xc0 },							/* ACR - right channel of input B is the microphone */
+	{ DEQ_ACR_ADM | DEQ_ACR_LRB | DEQ_ACR_INP_B },		/* ACR - right channel of input B is the microphone */
 	{ 2 }							/* MCR2 - AllPass mode since we don't use the equalizer anyway */
 };
 
@@ -1219,8 +1282,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 +1478,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)
@@ -1476,6 +1539,11 @@
 	
 	sc->sc_bass = 128;
 	sc->sc_treble = 128;
+
+	/* Record source defaults to microphone.  This reflects the
+	 * default value for the ACR (see tas3004_initdata).
+	 */
+	sc->sc_record_source = 1 << 0;
 	
 	/* We mute the analog input for now */
 	sc->mixer[0] = 80;