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