Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/macppc/dev various minor fixes and updates:



details:   https://anonhg.NetBSD.org/src/rev/111ed7b50b2e
branches:  trunk
changeset: 459671:111ed7b50b2e
user:      macallan <macallan%NetBSD.org@localhost>
date:      Fri Sep 20 21:24:34 2019 +0000

description:
various minor fixes and updates:
- add (very) basic ONYX support. Treat as 16bit codec with software volume
  control. Makes basic audio work on PCIe G5
- correctly detect TAS3001 without 'compatible' property, now this works on
  Quicksilver
- mute line input on TAS3001 - it's unconnected on Quicksilver and causes noise
- make more of an effort to match codecs to i2sbus instances, needed on G5 and
  some other models with software 'modems'

diffstat:

 sys/arch/macppc/dev/snapper.c |  204 +++++++++++++++++++++++++++++++----------
 1 files changed, 155 insertions(+), 49 deletions(-)

diffs (truncated from 348 to 300 lines):

diff -r 110a5c41250c -r 111ed7b50b2e sys/arch/macppc/dev/snapper.c
--- a/sys/arch/macppc/dev/snapper.c     Fri Sep 20 17:25:11 2019 +0000
+++ b/sys/arch/macppc/dev/snapper.c     Fri Sep 20 21:24:34 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: snapper.c,v 1.52 2019/06/08 08:02:37 isaki Exp $       */
+/*     $NetBSD: snapper.c,v 1.53 2019/09/20 21:24:34 macallan Exp $    */
 /*     Id: snapper.c,v 1.11 2002/10/31 17:42:13 tsubai Exp     */
 /*     Id: i2s.c,v 1.12 2005/01/15 14:32:35 tsubai Exp         */
 
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: snapper.c,v 1.52 2019/06/08 08:02:37 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: snapper.c,v 1.53 2019/09/20 21:24:34 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/audioio.h>
@@ -55,7 +55,7 @@
 
 #include <macppc/dev/deqvar.h>
 #include <macppc/dev/obiovar.h>
-
+//#define SNAPPER_DEBUG
 #ifdef SNAPPER_DEBUG
 # define DPRINTF printf
 #else
@@ -66,9 +66,12 @@
 
 struct snapper_softc {
        device_t sc_dev;
-       int sc_mode;              // 0 for TAS3004
+       int sc_mode;
+#define SNAPPER_IS_TAS3004     0 // codec is TAS3004
 #define SNAPPER_IS_TAS3001     1 // codec is TAS3001
-#define SNAPPER_SWVOL          2 // software codec
+#define SNAPPER_IS_PCM3052     2 // codec is PCM3052
+#define SNAPPER_IS_CS8416      3 // codec is CS8416
+#define SNAPPER_SWVOL          4 // software codec
        
        int sc_node;
 
@@ -475,6 +478,21 @@
 };
 #define TUMBLER_NFORMATS       __arraycount(tumbler_formats)
 
+/* OF hands us the codec in 16bit mode, run with it for now */
+static const struct audio_format onyx_formats[] = {
+       {
+               .mode           = AUMODE_PLAY | AUMODE_RECORD,
+               .encoding       = AUDIO_ENCODING_SLINEAR_BE,
+               .validbits      = 16,
+               .precision      = 16,
+               .channels       = 2,
+               .channel_mask   = AUFMT_STEREO,
+               .frequency_type = 3,
+               .frequency      = { 44100, 48000, 96000 },
+       },
+};
+#define ONYX_NFORMATS  __arraycount(onyx_formats)
+
 static bus_size_t amp_mute;
 static bus_size_t headphone_mute;
 static bus_size_t audio_hw_reset;
@@ -492,6 +510,16 @@
 /* I2S_INT register definitions */
 #define I2S_INT_CLKSTOPPEND 0x01000000  /* clock-stop interrupt pending */
 
+/* I2S_WORDSIZE register definitions */
+#define INPUT_STEREO            (2 << 24)
+#define INPUT_MONO              (1 << 24)
+#define INPUT_16BIT             (0 << 16)
+#define INPUT_24BIT             (3 << 16)
+#define OUTPUT_STEREO           (2 << 8)
+#define OUTPUT_MONO             (1 << 8)
+#define OUTPUT_16BIT            (0 << 0)
+#define OUTPUT_24BIT            (3 << 0)
+
 /* FCR(0x3c) bits */
 #define KEYLARGO_FCR1   0x3c
 #define  I2S0CLKEN      0x1000
@@ -639,6 +667,9 @@
        if (strcmp(compat, "AOAK2") == 0)
                return 1;
                
+       if (strcmp(compat, "AOAbase") == 0)
+               return 1;
+
        if (OF_getprop(soundchip, "platform-tas-codec-ref",
            &soundcodec, sizeof soundcodec) == sizeof soundcodec)
                return 1;
@@ -664,6 +695,8 @@
        memset(compat, 0, sizeof compat);
        OF_getprop(OF_child(soundbus), "compatible", compat, sizeof compat);
 
+       sc->sc_mode = SNAPPER_IS_TAS3004;
+
        if (strcmp(compat, "tumbler") == 0)
                sc->sc_mode = SNAPPER_IS_TAS3001;
        sc->sc_swvol_l = 255;
@@ -718,8 +751,8 @@
        oirq = intr[2];
        iirq = intr[4];
        /* cirq_type = intr[1] ? IST_LEVEL : IST_EDGE; */
-       oirq_type = intr[3] ? IST_LEVEL : IST_EDGE;
-       iirq_type = intr[5] ? IST_LEVEL : IST_EDGE;
+       oirq_type = (intr[3] & 1) ? IST_LEVEL : IST_EDGE;
+       iirq_type = (intr[5] & 1) ? IST_LEVEL : IST_EDGE;
 
        /* intr_establish(cirq, cirq_type, IPL_AUDIO, snapper_intr, sc); */
        intr_establish(oirq, oirq_type, IPL_AUDIO, snapper_intr, sc);
@@ -743,25 +776,79 @@
        device_t dv;
        deviter_t di;
        struct deq_softc *deq;
+       char prop[64], next[64], codec[64], *cref;
+       int codec_node, soundbus, sound, ok, deqnode = 0;
        
        sc = device_private(dev);
+
+       /* look for platform-*-codec-ref node */
+
+       /*
+        * XXX
+        * there can be more than one i2sbus, the one we want just so happens
+        * to be the first we see
+        */
+       soundbus = OF_child(sc->sc_node);
+       sound = OF_child(soundbus);
+       ok = OF_nextprop(sound, NULL, next);
+       codec_node = 0;
+       while (ok && (codec_node == 0)) {
+               DPRINTF("prop %d %s\n", ok, next);
+               strncpy(prop, next, 64);
+               if ((cref = strstr(next, "-codec-ref")) != NULL) {
+                       OF_getprop(sound, next, &codec_node, 4);
+                       if (codec_node != 0) {
+                               OF_getprop(codec_node, "compatible", codec, 64);
+                               DPRINTF("%08x %s\n", codec_node, codec);
+                       }
+               }       
+               ok = OF_nextprop(sound, prop, next);
+       }       
+
        for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
             dv != NULL;
             dv = deviter_next(&di)) {
                if (device_is_a(dv, "deq")) {
                        deq = device_private(dv);
+                       if (codec_node != 0) {
+                               if (codec_node != deq->sc_node)
+                                       continue;
+                       }
                        sc->sc_i2c = deq->sc_i2c;
                        sc->sc_deqaddr = deq->sc_address;
+                       deqnode = deq->sc_node;
                }
        }
        deviter_release(&di);
 
+       DPRINTF("deqnode: %08x\n", deqnode);
+
        /* If we don't find a codec, it's not the end of the world;
         * we can control the volume in software in this case.
         */
-       if (sc->sc_i2c == NULL)
+       if (sc->sc_i2c == NULL) {
                sc->sc_mode = SNAPPER_SWVOL;
+       } else if (deqnode != 0) {
+               int ret;
+               codec[0] = 0;
+               ret = OF_getprop(deqnode, "compatible", codec, 64);
 
+               DPRINTF("codec <%s> %d\n", codec, ret);
+
+               if (codec[0] == 0) {
+                       if (sc->sc_deqaddr == 0x34) {
+                               sc->sc_mode = SNAPPER_IS_TAS3001;
+                       } else
+                               sc->sc_mode = SNAPPER_IS_TAS3004;
+               } else if (strcmp(codec, "tas3004") == 0) {
+                       sc->sc_mode = SNAPPER_IS_TAS3004;
+               } else if (strcmp(codec, "pcm3052") == 0) {
+                       sc->sc_mode = SNAPPER_IS_PCM3052;
+               } else if (strcmp(codec, "cs8416") == 0) {
+                       sc->sc_mode = SNAPPER_IS_CS8416;
+               }
+       }
+       DPRINTF("mode %d\n", sc->sc_mode);
        switch (sc->sc_mode) {
        case SNAPPER_SWVOL:
                aprint_verbose("%s: software codec\n", device_xname(dev));
@@ -769,9 +856,15 @@
        case SNAPPER_IS_TAS3001:
                aprint_verbose("%s: codec: TAS3001\n", device_xname(dev));
                break;
-       case 0:
+       case SNAPPER_IS_TAS3004:
                aprint_verbose("%s: codec: TAS3004\n", device_xname(dev));
                break;
+       case SNAPPER_IS_PCM3052:
+               aprint_verbose("%s: codec: PCM3052 / ONYX\n", device_xname(dev));
+               break;
+       default:
+               aprint_error_dev(sc->sc_dev, "unsupported codec\n");
+               sc->sc_mode = SNAPPER_SWVOL;
        }
 
        snapper_init(sc, sc->sc_node);
@@ -826,13 +919,19 @@
 {
        struct snapper_softc *sc = h;
 
-       if (sc->sc_mode == SNAPPER_IS_TAS3001) {
-               return audio_query_format(tumbler_formats, TUMBLER_NFORMATS,
-                   afp);
-       } else {
-               return audio_query_format(snapper_formats, SNAPPER_NFORMATS,
-                   afp);
+       switch (sc->sc_mode) {
+               case SNAPPER_IS_TAS3001:
+                       return audio_query_format(tumbler_formats,
+                           TUMBLER_NFORMATS, afp);
+               case SNAPPER_SWVOL:
+               case SNAPPER_IS_TAS3004:
+                       return audio_query_format(snapper_formats,
+                           SNAPPER_NFORMATS, afp);
+               case SNAPPER_IS_PCM3052:
+                       return audio_query_format(onyx_formats,
+                           ONYX_NFORMATS, afp);
        }
+       return -1;
 }
 
 static int
@@ -870,8 +969,8 @@
                        const audio_params_t *param)
 {
 
-       if (size < NBPG)
-               size = NBPG;
+       if (size < (3 * NBPG))
+               size = (3 * NBPG);
        return size & ~PGOFSET;
 }
 
@@ -1476,7 +1575,7 @@
 {
        uint8_t regs[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
        int i;
-
+if (sc->sc_mode > 1) return;
        /* Left channel of SDIN1 */
        ADJUST(i, sc->mixer[0]);
        regs[0] = snapper_mixer_gain[i][0];
@@ -1619,11 +1718,13 @@
        DPRINTF("precision: %d\n", sc->sc_bitspersample);
        switch(sc->sc_bitspersample) {
                case 16:
-                       wordsize = 0x02000200;
+                       wordsize = INPUT_STEREO | INPUT_16BIT |
+                                  OUTPUT_STEREO | OUTPUT_16BIT;
                        mcr1 = DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_16;
                        break;
                case 24:
-                       wordsize = 0x03000300;
+                       wordsize = INPUT_STEREO | INPUT_24BIT |
+                                  OUTPUT_STEREO | OUTPUT_24BIT;
                        mcr1 = DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_24;
                        break;
                default:
@@ -1895,34 +1996,36 @@
        delay(10000);
 
 noreset:
-       DEQ_WRITE(sc, DEQ_LB0, tas3004_initdata.LB0);
-       DEQ_WRITE(sc, DEQ_LB1, tas3004_initdata.LB1);
-       DEQ_WRITE(sc, DEQ_LB2, tas3004_initdata.LB2);
-       DEQ_WRITE(sc, DEQ_LB3, tas3004_initdata.LB3);
-       DEQ_WRITE(sc, DEQ_LB4, tas3004_initdata.LB4);
-       DEQ_WRITE(sc, DEQ_LB5, tas3004_initdata.LB5);
-       DEQ_WRITE(sc, DEQ_LB6, tas3004_initdata.LB6);
-       DEQ_WRITE(sc, DEQ_RB0, tas3004_initdata.RB0);
-       DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1);
-       DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1);
-       DEQ_WRITE(sc, DEQ_RB2, tas3004_initdata.RB2);
-       DEQ_WRITE(sc, DEQ_RB3, tas3004_initdata.RB3);
-       DEQ_WRITE(sc, DEQ_RB4, tas3004_initdata.RB4);
-       DEQ_WRITE(sc, DEQ_RB5, tas3004_initdata.RB5);
-       DEQ_WRITE(sc, DEQ_MCR1, tas3004_initdata.MCR1);
-       DEQ_WRITE(sc, DEQ_MCR2, tas3004_initdata.MCR2);
-       DEQ_WRITE(sc, DEQ_DRC, tas3004_initdata.DRC);
-       DEQ_WRITE(sc, DEQ_VOLUME, tas3004_initdata.VOLUME);
-       DEQ_WRITE(sc, DEQ_TREBLE, tas3004_initdata.TREBLE);
-       DEQ_WRITE(sc, DEQ_BASS, tas3004_initdata.BASS);
-       DEQ_WRITE(sc, DEQ_MIXER_L, tas3004_initdata.MIXER_L);
-       DEQ_WRITE(sc, DEQ_MIXER_R, tas3004_initdata.MIXER_R);
-       DEQ_WRITE(sc, DEQ_LLB, tas3004_initdata.LLB);
-       DEQ_WRITE(sc, DEQ_RLB, tas3004_initdata.RLB);
-       DEQ_WRITE(sc, DEQ_LLB_GAIN, tas3004_initdata.LLB_GAIN);



Home | Main Index | Thread Index | Old Index