Hi,
if no one objects, I'll add support for the
"tumbler", as found at
least on my iBook G3/600. I fitted it into the snapper
driver to
minimize duplication, and did some minor cleanup while
there.
Playing and recording work.
Regards,
Aymeric
Index: snapper.c
============================================================
=======
RCS file: /cvsroot/src/sys/arch/macppc/dev/snapper.c,v
retrieving revision 1.20
diff -u -u -r1.20 snapper.c
--- snapper.c 4 Apr 2007 02:14:57 -0000 1.20
+++ snapper.c 16 Sep 2007 13:03:48 -0000
 -61,8
+61,11 
struct snapper_softc {
struct device sc_dev;
int sc_flags;
+#define SNAPPER_IS_TAS3001 0x01
int sc_node;
+ struct audio_encoding_set *sc_encodings;
+
void (*sc_ointr)(void *); /* dma completion intr handler
*/
void *sc_oarg; /* arg for sc_ointr() */
int sc_opages; /* # of output pages */
 -99,7
+102,6 
void snapper_attach(struct device *, struct device *, void
*);
void snapper_defer(struct device *);
int snapper_intr(void *);
-void snapper_close(void *);
int snapper_query_encoding(void *, struct audio_encoding
*);
int snapper_set_params(void *, int, int, audio_params_t *,
audio_params_t *, stream_filter_list_t *,
stream_filter_list_t *);
 -209,8
+211,8 
};
const struct audio_hw_if snapper_hw_if = {
- NULL, /* open */
- snapper_close,
+ NULL,
+ NULL,
NULL,
snapper_query_encoding,
snapper_set_params,
 -473,6
+475,12 
2, AUFMT_STEREO, 3, {32000, 44100, 48000}},
};
+#define TUMBLER_NFORMATS 1
+static const struct audio_format
tumbler_formats[TUMBLER_NFORMATS] = {
+ {NULL, AUMODE_PLAY | AUMODE_RECORD,
AUDIO_ENCODING_SLINEAR_BE, 16, 16,
+ 2, AUFMT_STEREO, 3, {32000, 44100, 48000}},
+};
+
static u_char *amp_mute;
static u_char *headphone_mute;
static u_char *audio_hw_reset;
 -499,12
+507,13 
/* TAS3004 registers */
#define DEQ_MCR1 0x01 /* Main control register 1 (1byte)
*/
-#define DEQ_DRC 0x02 /* Dynamic range compression
(6bytes?) */
+#define DEQ_DRC 0x02 /* Dynamic range compression
(6bytes?)
+ 2 bytes on the TAS 3001 */
#define DEQ_VOLUME 0x04 /* Volume (6bytes) */
#define DEQ_TREBLE 0x05 /* Treble control (1byte) */
#define DEQ_BASS 0x06 /* Bass control (1byte) */
-#define DEQ_MIXER_L 0x07 /* Mixer left gain (9bytes) */
-#define DEQ_MIXER_R 0x08 /* Mixer right gain (9bytes) */
+#define DEQ_MIXER_L 0x07 /* Mixer left gain (9bytes; 3 on
TAS3001) */
+#define DEQ_MIXER_R 0x08 /* Mixer right gain (9bytes; 3 on
TAS3001) */
#define DEQ_LB0 0x0a /* Left biquad 0 (15bytes) */
#define DEQ_LB1 0x0b /* Left biquad 1 (15bytes) */
#define DEQ_LB2 0x0c /* Left biquad 2 (15bytes) */
 -534,6
+543,10 
#define DEQ_MCR1_SM_L 0x00 /* Left justified */
#define DEQ_MCR1_SM_R 0x10 /* Right justified */
#define DEQ_MCR1_SM_I2S 0x20 /* I2S */
+#define DEQ_MCR1_ISM 0x0c /* Input serial port mode */
+#define DEQ_MCR1_ISM_L 0x00 /* Left justified */
+#define DEQ_MCR1_ISM_R 0x04 /* Right justified */
+#define DEQ_MCR1_ISM_I2S 0x08 /* I2S */
#define DEQ_MCR1_W 0x03 /* Serial port word length */
#define DEQ_MCR1_W_16 0x00 /* 16 bit */
#define DEQ_MCR1_W_18 0x01 /* 18 bit */
 -623,6
+636,9 
if (strcmp(compat, "snapper") == 0)
return 1;
+ if (strcmp(compat, "tumbler") == 0)
+ return 1;
+
if (strcmp(compat, "AOAKeylargo") == 0)
return 1;
 -644,10
+660,33 
unsigned long v;
int cirq, oirq, iirq, cirq_type, oirq_type, iirq_type;
int soundbus, intr[6];
+ char compat[32];
sc = (struct snapper_softc *)self;
ca = aux;
+ soundbus = OF_child(ca->ca_node);
+ bzero(compat, sizeof compat);
+ OF_getprop(OF_child(soundbus), "compatible",
compat, sizeof compat);
+
+ sc->sc_flags = 0;
+ if (strcmp(compat, "tumbler") == 0)
+ sc->sc_flags |= SNAPPER_IS_TAS3001;
+
+ if (sc->sc_flags & SNAPPER_IS_TAS3001) {
+ if (auconv_create_encodings(tumbler_formats,
TUMBLER_NFORMATS,
+ &sc->sc_encodings) != 0) {
+ aprint_normal("can't create encodingsn");
+ return;
+ }
+ } else {
+ if (auconv_create_encodings(snapper_formats,
SNAPPER_NFORMATS,
+ &sc->sc_encodings) != 0) {
+ aprint_normal("can't create encodingsn");
+ return;
+ }
+ }
+
v = (((unsigned long) &sc->dbdma_cmdspace[0]) +
0xf) & ~0xf;
sc->sc_odmacmd = (struct dbdma_command *) v;
sc->sc_idmacmd = sc->sc_odmacmd + 20;
 -668,7
+707,6 
sc->sc_odma = (void *)ca->ca_reg[2];
sc->sc_idma = (void *)ca->ca_reg[4];
- soundbus = OF_child(ca->ca_node);
OF_getprop(soundbus, "interrupts", intr, sizeof
intr);
cirq = intr[0];
oirq = intr[2];
 -681,9
+719,9 
intr_establish(oirq, oirq_type, IPL_AUDIO, snapper_intr,
sc);
intr_establish(iirq, iirq_type, IPL_AUDIO, snapper_intr,
sc);
- printf(": irq %d,%d,%dn", cirq, oirq, iirq);
+ aprint_normal(": irq %d,%d,%dn", cirq, oirq,
iirq);
- config_interrupts(self, snapper_defer);
+ config_defer(self, snapper_defer);
}
void
 -694,12
+732,6 
struct deq_softc *deq;
sc = (struct snapper_softc *)dev;
- /*
- for (dv = alldevs.tqh_first; dv;
dv=dv->dv_list.tqe_next)
- if (strncmp(dv->dv_xname, "ki2c", 4) == 0
&&
- strncmp(device_parent(dv)->dv_xname,
"obio", 4) == 0)
- sc->sc_i2c = dv;
- */
for (dv = alldevs.tqh_first; dv;
dv=dv->dv_list.tqe_next)
if (strncmp(dv->dv_xname, "deq", 3) == 0
&&
strncmp(device_parent(dv)->dv_xname,
"ki2c", 4) == 0) {
 -764,69
+796,14 
return 1;
}
-/*
- * Close function is called at splaudio().
- */
-void
-snapper_close(void *h)
-{
- struct snapper_softc *sc;
-
- sc = h;
- snapper_halt_output(sc);
- snapper_halt_input(sc);
-
- sc->sc_ointr = 0;
- sc->sc_iintr = 0;
-}
int
snapper_query_encoding(void *h, struct audio_encoding *ae)
{
- ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
- switch (ae->index) {
- case 0:
- strcpy(ae->name, AudioEslinear);
- ae->encoding = AUDIO_ENCODING_SLINEAR;
- ae->precision = 16;
- ae->flags = 0;
- return 0;
- case 1:
- strcpy(ae->name, AudioEslinear_be);
- ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
- ae->precision = 16;
- ae->flags = 0;
- return 0;
- case 2:
- strcpy(ae->name, AudioEslinear_le);
- ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
- ae->precision = 16;
- return 0;
- case 3:
- strcpy(ae->name, AudioEulinear_be);
- ae->encoding = AUDIO_ENCODING_ULINEAR_BE;
- ae->precision = 16;
- return 0;
- case 4:
- strcpy(ae->name, AudioEulinear_le);
- ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
- ae->precision = 16;
- return 0;
- case 5:
- strcpy(ae->name, AudioEmulaw);
- ae->encoding = AUDIO_ENCODING_ULAW;
- ae->precision = 8;
- return 0;
- case 6:
- strcpy(ae->name, AudioEalaw);
- ae->encoding = AUDIO_ENCODING_ALAW;
- ae->precision = 8;
- return 0;
- default:
- DPRINTF("snapper_query_encoding: invalid encoding
%dn", ae->index);
- return EINVAL;
- }
+ struct snapper_softc *sc = h;
+
+ return auconv_query_encoding(sc->sc_encodings, ae);
}
int
 -836,7
+813,7 
{
struct snapper_softc *sc;
audio_params_t *p;
- stream_filter_list_t *fil;
+ stream_filter_list_t *fil = NULL; /* XXX gcc */
int mode;
sc = h;
 -870,11
+847,22 
}
fil = mode == AUMODE_PLAY ? pfil : rfil;
- if (auconv_set_converter(snapper_formats,
SNAPPER_NFORMATS,
- mode, p, true, fil) < 0) {
- DPRINTF("snapper_set_params: auconv_set_converter
failedn");
- return EINVAL;
+ if (sc->sc_flags & SNAPPER_IS_TAS3001) {
+ if (auconv_set_converter(tumbler_formats,
+ TUMBLER_NFORMATS, mode, p, true, fil) < 0) {
+ DPRINTF("snapper_set_params: "
+ "auconv_set_converter failedn");
+ return EINVAL;
+ }
+ } else { /* TAS 3004 */
+ if (auconv_set_converter(snapper_formats,
+ SNAPPER_NFORMATS, mode, p, true, fil) < 0) {
+ DPRINTF("snapper_set_params: "
+ "auconv_set_converter failedn");
+ return EINVAL;
+ }
}
+
if (sc->sc_swvol)
fil->append(fil, snapper_volume, p);
if (fil->req_size > 0)
 -907,6
+895,7 
sc = h;
dbdma_stop(sc->sc_odma);
dbdma_reset(sc->sc_odma);
+ sc->sc_ointr = NULL;
return 0;
}
 -918,6
+907,7 
sc = h;
dbdma_stop(sc->sc_idma);
dbdma_reset(sc->sc_idma);
+ sc->sc_iintr = NULL;
return 0;
}
 -937,11
+927,12 
SNAPPER_VOL_OUTPUT,
SNAPPER_DIGI1,
SNAPPER_DIGI2,
- SNAPPER_ANALOG,
- SNAPPER_INPUT_SELECT,
SNAPPER_VOL_INPUT,
SNAPPER_TREBLE,
SNAPPER_BASS,
+ /* From this point, unsupported by the TAS 3001 */
+ SNAPPER_ANALOG,
+ SNAPPER_INPUT_SELECT,
SNAPPER_ENUM_LAST
};
 -978,6
+969,9 
return 0;
case SNAPPER_INPUT_SELECT:
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ return ENXIO;
+
/* no change necessary? */
if (mc->un.mask == sc->sc_record_source)
return 0;
 -1014,11
+1008,18 
snapper_write_mixers(sc);
return 0;
case SNAPPER_DIGI2:
- sc->mixer[1]=l;
- sc->mixer[4]=r;
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ sc->mixer[3] = l;
+ else {
+ sc->mixer[1]=l;
+ sc->mixer[4]=r;
+ }
snapper_write_mixers(sc);
return 0;
case SNAPPER_ANALOG:
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ return ENXIO;
+
sc->mixer[2]=l;
sc->mixer[5]=r;
snapper_write_mixers(sc);
 -1050,6
+1051,9 
return 0;
case SNAPPER_INPUT_SELECT:
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ return ENXIO;
+
mc->un.mask = sc->sc_record_source;
return 0;
 -1073,6
+1077,9 
mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
sc->mixer[4];
return 0;
case SNAPPER_ANALOG:
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ return ENXIO;
+
mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
sc->mixer[2];
mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
sc->mixer[5];
return 0;
 -1086,6
+1093,8 
int
snapper_query_devinfo(void *h, mixer_devinfo_t *dip)
{
+ struct snapper_softc *sc = h;
+
switch (dip->index) {
case SNAPPER_OUTPUT_SELECT:
 -1110,6
+1119,9 
return 0;
case SNAPPER_INPUT_SELECT:
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ return ENXIO;
+
dip->mixer_class = SNAPPER_RECORD_CLASS;
strcpy(dip->label.name, AudioNsource);
dip->type = AUDIO_MIXER_SET;
 -1172,16
+1184,21 
strcpy(dip->label.name, AudioNdac);
dip->type = AUDIO_MIXER_VALUE;
dip->prev = dip->next = AUDIO_MIXER_LAST;
- dip->un.v.num_channels = 2;
+ dip->un.v.num_channels =
+ sc->sc_flags & SNAPPER_IS_TAS3001? 1 : 2;
return 0;
case SNAPPER_DIGI2:
dip->mixer_class = SNAPPER_MONITOR_CLASS;
strcpy(dip->label.name, AudioNline);
dip->type = AUDIO_MIXER_VALUE;
dip->prev = dip->next = AUDIO_MIXER_LAST;
- dip->un.v.num_channels = 2;
+ dip->un.v.num_channels =
+ sc->sc_flags & SNAPPER_IS_TAS3001? 1 : 2;
return 0;
case SNAPPER_ANALOG:
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ return ENXIO;
+
dip->mixer_class = SNAPPER_MONITOR_CLASS;
strcpy(dip->label.name, AudioNmicrophone);
dip->type = AUDIO_MIXER_VALUE;
 -1548,6
+1565,9 
return EINVAL;
}
+ if (sc->sc_flags & SNAPPER_IS_TAS3001)
+ mcr1 |= DEQ_MCR1_ISM_I2S;
+
ows = in32rb(sc->sc_reg + I2S_WORDSIZE);
DPRINTF("I2SSetDataWordSizeReg 0x%08x ->
0x%08xn",
ows, wordsize);
 -1675,6
+1695,15 
regblock[0] = reg;
memcpy(®block[1], data, size);
+ if (sc->sc_flags & SNAPPER_IS_TAS3001) {
+ if (reg == DEQ_MIXER_L || reg == DEQ_MIXER_R)
+ size = 3;
+ else if (reg == DEQ_DRC) {
+ size = 2;
+ regblock[1] = 0;
+ regblock[2] = 0;
+ }
+ }
iic_acquire_bus(sc->sc_i2c, 0);
iic_exec(sc->sc_i2c, I2C_OP_WRITE, sc->sc_deqaddr,
regblock, size + 1,
NULL, 0, 0);
|