- 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
This commit is contained in:
parent
9ac658bba2
commit
8e8646698a
|
@ -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>
|
||||
|
@ -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 @@ struct hdafg_softc {
|
|||
} 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 @@ hdafg_commit(struct hdafg_softc *sc)
|
|||
|
||||
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 @@ hdafg_stream_connect_hdmi(struct hdafg_softc *sc, struct hdaudio_assoc *as,
|
|||
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 @@ hdafg_stream_connect(struct hdafg_softc *sc, int mode)
|
|||
{
|
||||
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 @@ hdafg_stream_connect(struct hdafg_softc *sc, int mode)
|
|||
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 @@ hdafg_stream_connect(struct hdafg_softc *sc, int mode)
|
|||
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 @@ hdafg_rate_supported(struct hdafg_softc *sc, u_int frequency)
|
|||
{
|
||||
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 @@ hdafg_rate_supported(struct hdafg_softc *sc, u_int frequency)
|
|||
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 @@ hdafg_configure_encodings(struct hdafg_softc *sc)
|
|||
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 @@ hdafg_attach(device_t parent, device_t self, void *opaque)
|
|||
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 @@ hdafg_attach(device_t parent, device_t self, void *opaque)
|
|||
|
||||
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 @@ hdafg_set_params(void *opaque, int setmode, int usemode,
|
|||
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 @@ hdafg_set_params(void *opaque, int setmode, int usemode,
|
|||
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 @@ hdafg_trigger_output(void *opaque, void *start, void *end, int blksize,
|
|||
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 @@ hdafg_trigger_input(void *opaque, void *start, void *end, int blksize,
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue