Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/hdaudio - Support multi-channel (> 2) output to HDMI...



details:   https://anonhg.NetBSD.org/src/rev/41f22e38b535
branches:  trunk
changeset: 339528:41f22e38b535
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Jul 26 19:06:26 2015 +0000

description:
- Support multi-channel (> 2) output to HDMI sinks.
- Fix a bug in hdafg_set_params that could program converters using the
  wrong audio_params_t if auconv is in use
- Force Tegra124 HDMI codec to a fixed rate 44.1kHz

diffstat:

 sys/dev/hdaudio/hdafg.c |  61 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 45 insertions(+), 16 deletions(-)

diffs (192 lines):

diff -r bdcafb227fa8 -r 41f22e38b535 sys/dev/hdaudio/hdafg.c
--- a/sys/dev/hdaudio/hdafg.c   Sun Jul 26 17:54:46 2015 +0000
+++ b/sys/dev/hdaudio/hdafg.c   Sun Jul 26 19:06:26 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdafg.c,v 1.2 2015/03/28 14:50:20 jmcneill Exp $ */
+/* $NetBSD: hdafg.c,v 1.3 2015/07/26 19:06:26 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <support%precedence.co.uk@localhost>
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdafg.c,v 1.2 2015/03/28 14:50:20 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdafg.c,v 1.3 2015/07/26 19:06:26 jmcneill Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -327,6 +327,8 @@
        } sc_p;
 
        struct hdaudio_audiodev         sc_audiodev;
+
+       uint16_t                        sc_fixed_rate;
 };
 
 static int     hdafg_match(device_t, cfdata_t, void *);
@@ -3041,7 +3043,7 @@
 
 static void
 hdafg_stream_connect_hdmi(struct hdafg_softc *sc, struct hdaudio_assoc *as,
-    struct hdaudio_widget *w, int maxchan)
+    struct hdaudio_widget *w, const audio_params_t *params)
 {
        struct hdmi_audio_infoframe hdmi;
        /* TODO struct displayport_audio_infoframe dp; */
@@ -3069,7 +3071,12 @@
                hdmi.header.packet_type = HDMI_AI_PACKET_TYPE;
                hdmi.header.version = HDMI_AI_VERSION;
                hdmi.header.length = HDMI_AI_LENGTH;
-               hdmi.ct_cc = maxchan - 1;
+               hdmi.ct_cc = params->channels - 1;
+               if (params->channels > 2) {
+                       hdmi.ca = 0x1f;
+               } else {
+                       hdmi.ca = 0x00;
+               }
                hdafg_dd_hdmi_ai_cksum(&hdmi);
        }
        /* update data island with new audio infoframe */
@@ -3092,19 +3099,22 @@
 {
        struct hdaudio_assoc *as = sc->sc_assocs;
        struct hdaudio_widget *w;
+       const audio_params_t *params;
        uint16_t fmt, dfmt;
        int tag, chn, maxchan, c;
        int i, j, k;
 
        KASSERT(mode == AUMODE_PLAY || mode == AUMODE_RECORD);
 
-       if (mode == AUMODE_PLAY)
+       if (mode == AUMODE_PLAY) {
                fmt = hdaudio_stream_param(sc->sc_audiodev.ad_playback,
                    &sc->sc_pparam);
-       else
+               params = &sc->sc_pparam;
+       } else {
                fmt = hdaudio_stream_param(sc->sc_audiodev.ad_capture,
                    &sc->sc_rparam);
-
+               params = &sc->sc_rparam;
+       }
 
        for (i = 0; i < sc->sc_nassocs; i++) {
                if (as[i].as_enable == false)
@@ -3177,6 +3187,8 @@
                                        dfmt |= COP_DIGITAL_CONVCTRL1_NAUDIO;
                                else
                                        dfmt &= ~COP_DIGITAL_CONVCTRL1_NAUDIO;
+                               if (sc->sc_vendor == HDAUDIO_VENDOR_NVIDIA)
+                                       dfmt |= COP_DIGITAL_CONVCTRL1_COPY;
                                hdaudio_command(sc->sc_codec, w->w_nid,
                                    CORB_SET_DIGITAL_CONVERTER_CONTROL_1, dfmt);
                        }
@@ -3203,7 +3215,7 @@
                                continue;
                        if (w->w_pin.cap & (COP_PINCAP_HDMI|COP_PINCAP_DP))
                                hdafg_stream_connect_hdmi(sc, &as[i],
-                                   w, maxchan);
+                                   w, params);
                }
        }
 }
@@ -3237,6 +3249,9 @@
 {
        uint32_t caps = sc->sc_p.pcm_size_rate;
 
+       if (sc->sc_fixed_rate)
+               return frequency == sc->sc_fixed_rate;
+
 #define ISFREQOK(shift)        ((caps & (1 << (shift))) ? true : false)
        switch (frequency) {
        case 8000:
@@ -3251,6 +3266,7 @@
                return ISFREQOK(4);
        case 44100:
                return ISFREQOK(5);
+               return true;
        case 48000:
                return true;    /* Must be supported by all codecs */
        case 88200:
@@ -3433,7 +3449,8 @@
                f.channels = 2;
                f.channel_mask = AUFMT_STEREO;
                f.frequency_type = 0;
-               f.frequency[0] = f.frequency[1] = 48000;
+               f.frequency[0] = f.frequency[1] = sc->sc_fixed_rate ?
+                   sc->sc_fixed_rate : 48000;
                f.mode = AUMODE_PLAY|AUMODE_RECORD;
                hdafg_append_formats(&sc->sc_audiodev, &f);
        }
@@ -3625,6 +3642,16 @@
        hda_print1(sc, ": %s %s%s\n", vendor, product,
            sc->sc_config ? " (custom configuration)" : "");
 
+       switch (sc->sc_vendor) {
+       case HDAUDIO_VENDOR_NVIDIA:
+               switch (sc->sc_product) {
+               case HDAUDIO_PRODUCT_NVIDIA_TEGRA124_HDMI:
+                       sc->sc_fixed_rate = 44100;
+                       break;
+               }
+               break;
+       }
+
        rv = prop_dictionary_get_uint64(args, "function-group", &fgptr);
        if (rv == false || fgptr == 0) {
                hda_error(sc, "missing function-group property\n");
@@ -3715,7 +3742,7 @@
 
        hda_debug(sc, "connecting streams\n");
        defparams.channels = 2;
-       defparams.sample_rate = 48000;
+       defparams.sample_rate = sc->sc_fixed_rate ? sc->sc_fixed_rate : 48000;
        defparams.precision = defparams.validbits = 16;
        defparams.encoding = AUDIO_ENCODING_SLINEAR_LE;
        sc->sc_pparam = sc->sc_rparam = defparams;
@@ -3862,7 +3889,8 @@
                    AUMODE_PLAY, play, TRUE, pfil);
                if (index < 0)
                        return EINVAL;
-               ad->ad_sc->sc_pparam = *play;
+               ad->ad_sc->sc_pparam = pfil->req_size > 0 ?
+                   pfil->filters[0].param : *play;
                hdafg_stream_connect(ad->ad_sc, AUMODE_PLAY);
        }
        if (rec && (setmode & AUMODE_RECORD)) {
@@ -3870,7 +3898,8 @@
                    AUMODE_RECORD, rec, TRUE, rfil);
                if (index < 0)
                        return EINVAL;
-               ad->ad_sc->sc_rparam = *rec;
+               ad->ad_sc->sc_rparam = rfil->req_size > 0 ?
+                   rfil->filters[0].param : *rec;
                hdafg_stream_connect(ad->ad_sc, AUMODE_RECORD);
        }
        return 0;
@@ -4215,9 +4244,9 @@
        ad->ad_playbackintrarg = intrarg;
 
        dmasize = (char *)end - (char *)start;
-       ad->ad_sc->sc_pparam = *param;
        hdafg_stream_connect(ad->ad_sc, AUMODE_PLAY);
-       hdaudio_stream_start(ad->ad_playback, blksize, dmasize, param);
+       hdaudio_stream_start(ad->ad_playback, blksize, dmasize,
+           &ad->ad_sc->sc_pparam);
 
        return 0;
 }
@@ -4238,9 +4267,9 @@
        ad->ad_captureintrarg = intrarg;
 
        dmasize = (char *)end - (char *)start;
-       ad->ad_sc->sc_rparam = *param;
        hdafg_stream_connect(ad->ad_sc, AUMODE_RECORD);
-       hdaudio_stream_start(ad->ad_capture, blksize, dmasize, param);
+       hdaudio_stream_start(ad->ad_capture, blksize, dmasize,
+           &ad->ad_sc->sc_rparam);
 
        return 0;
 }



Home | Main Index | Thread Index | Old Index