Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci/hdaudio Add support for formats other than 16bit...
details: https://anonhg.NetBSD.org/src/rev/b93358124911
branches: trunk
changeset: 747262:b93358124911
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Sep 07 16:21:08 2009 +0000
description:
Add support for formats other than 16bit/48kHz.
diffstat:
sys/dev/pci/hdaudio/hdaudio.c | 87 +++++++++++++-
sys/dev/pci/hdaudio/hdaudio_afg.c | 219 +++++++++++++++++++++++++++++--------
sys/dev/pci/hdaudio/hdaudiovar.h | 3 +-
3 files changed, 248 insertions(+), 61 deletions(-)
diffs (truncated from 497 to 300 lines):
diff -r b3ea102b47df -r b93358124911 sys/dev/pci/hdaudio/hdaudio.c
--- a/sys/dev/pci/hdaudio/hdaudio.c Mon Sep 07 15:12:03 2009 +0000
+++ b/sys/dev/pci/hdaudio/hdaudio.c Mon Sep 07 16:21:08 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio.c,v 1.2 2009/09/06 17:33:53 sborrill Exp $ */
+/* $NetBSD: hdaudio.c,v 1.3 2009/09/07 16:21:08 jmcneill Exp $ */
/*
* Copyright (c) 2009 Precedence Technologies Ltd <support%precedence.co.uk@localhost>
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.2 2009/09/06 17:33:53 sborrill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio.c,v 1.3 2009/09/07 16:21:08 jmcneill Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -948,6 +948,77 @@
mutex_exit(&sc->sc_stream_mtx);
}
+/*
+ * Convert most of audio_params_t to stream fmt descriptor; noticably missing
+ * is the # channels bits, as this is encoded differently in codec and
+ * stream descriptors.
+ *
+ * TODO: validate that the stream and selected codecs can handle the fmt
+ */
+uint16_t
+hdaudio_stream_param(struct hdaudio_stream *st, const audio_params_t *param)
+{
+ uint16_t fmt = 0;
+
+ switch (param->sample_rate) {
+ case 8000:
+ fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) |
+ HDAUDIO_FMT_DIV(6);
+ break;
+ case 11025:
+ fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1) |
+ HDAUDIO_FMT_DIV(4);
+ break;
+ case 16000:
+ fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) |
+ HDAUDIO_FMT_DIV(3);
+ break;
+ case 22050:
+ fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1) |
+ HDAUDIO_FMT_DIV(2);
+ break;
+ case 32000:
+ fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(2) |
+ HDAUDIO_FMT_DIV(3);
+ break;
+ case 44100:
+ fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(1);
+ break;
+ case 48000:
+ fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1);
+ break;
+ case 88200:
+ fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(2);
+ break;
+ case 96000:
+ fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(2);
+ break;
+ case 176400:
+ fmt |= HDAUDIO_FMT_BASE_44 | HDAUDIO_FMT_MULT(4);
+ break;
+ case 192000:
+ fmt |= HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(4);
+ break;
+ default:
+ return 0;
+ }
+
+ if (param->precision == 16 && param->validbits == 8)
+ fmt |= HDAUDIO_FMT_BITS_8_16;
+ else if (param->precision == 16 && param->validbits == 16)
+ fmt |= HDAUDIO_FMT_BITS_16_16;
+ else if (param->precision == 32 && param->validbits == 20)
+ fmt |= HDAUDIO_FMT_BITS_20_32;
+ else if (param->precision == 32 && param->validbits == 24)
+ fmt |= HDAUDIO_FMT_BITS_24_32;
+ else if (param->precision == 32 && param->validbits == 32)
+ fmt |= HDAUDIO_FMT_BITS_32_32;
+ else
+ return 0;
+
+ return fmt;
+}
+
void
hdaudio_stream_reset(struct hdaudio_stream *st)
{
@@ -996,6 +1067,7 @@
struct hdaudio_bdl_entry *bdl;
uint64_t dmaaddr;
uint32_t intctl;
+ uint16_t fmt;
uint8_t ctl0, ctl2;
int cnt, snum = st->st_shift;
@@ -1050,15 +1122,10 @@
/*
* Program stream format
- *
- * XXX 48kHz, 16-bit, stereo for now
*/
- hda_write2(sc, HDAUDIO_SD_FMT(snum),
- HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) |
- HDAUDIO_FMT_DIV(1) | HDAUDIO_FMT_BITS_16_16 |
- HDAUDIO_FMT_CHAN(params->channels));
-
- /* XXX program codecs for stream number */
+ fmt = hdaudio_stream_param(st, params) |
+ HDAUDIO_FMT_CHAN(params->channels);
+ hda_write2(sc, HDAUDIO_SD_FMT(snum), fmt);
/*
* Switch on interrupts for this stream
diff -r b3ea102b47df -r b93358124911 sys/dev/pci/hdaudio/hdaudio_afg.c
--- a/sys/dev/pci/hdaudio/hdaudio_afg.c Mon Sep 07 15:12:03 2009 +0000
+++ b/sys/dev/pci/hdaudio/hdaudio_afg.c Mon Sep 07 16:21:08 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_afg.c,v 1.5 2009/09/07 11:59:53 jmcneill Exp $ */
+/* $NetBSD: hdaudio_afg.c,v 1.6 2009/09/07 16:21:08 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: hdaudio_afg.c,v 1.5 2009/09/07 11:59:53 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.6 2009/09/07 16:21:08 jmcneill Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -151,7 +151,7 @@
"Other"
};
-#define HDAUDIO_MAXFORMATS 10
+#define HDAUDIO_MAXFORMATS 24
#define HDAUDIO_MAXCONNECTIONS 32
#define HDAUDIO_MAXPINS 16
#define HDAUDIO_PARSE_MAXDEPTH 10
@@ -285,7 +285,7 @@
struct hdaudio_mixer *sc_mixers;
int sc_pchan, sc_rchan;
- int sc_curpchan, sc_currchan;
+ audio_params_t sc_pparam, sc_rparam;
struct callout sc_jack_callout;
@@ -378,12 +378,12 @@
hdaudio_afg_append_formats(struct hdaudio_audiodev *ad,
const struct audio_format *format)
{
- struct hdaudio_afg_softc *sc = ad->ad_sc;
- if (ad->ad_nformats >= HDAUDIO_MAXFORMATS) {
- hda_error(sc, "too many formats\n");
- return EINVAL;
+ if (ad->ad_nformats + 1 >= HDAUDIO_MAXFORMATS) {
+ hda_print1(ad->ad_sc, "[ENOMEM] ");
+ return ENOMEM;
}
ad->ad_formats[ad->ad_nformats++] = *format;
+
return 0;
}
@@ -2609,32 +2609,37 @@
int tag, chn, maxchan, c;
int i, j;
- fmt = HDAUDIO_FMT_BASE_48 | HDAUDIO_FMT_MULT(1) |
- HDAUDIO_FMT_DIV(1) | HDAUDIO_FMT_BITS_16_16;
+ KASSERT(mode == AUMODE_PLAY || mode == AUMODE_RECORD);
+
dfmt = COP_DIGITAL_CONVCTRL1_DIGEN; /* TODO: AC3 */
+ if (mode == AUMODE_PLAY)
+ fmt = hdaudio_stream_param(sc->sc_audiodev.ad_playback,
+ &sc->sc_pparam);
+ else
+ fmt = hdaudio_stream_param(sc->sc_audiodev.ad_capture,
+ &sc->sc_rparam);
+
for (i = 0; i < sc->sc_nassocs; i++) {
if (as[i].as_enable == false)
continue;
- if ((mode & (AUMODE_PLAY|AUMODE_RECORD)) == AUMODE_PLAY &&
- as[i].as_dir != HDAUDIO_PINDIR_OUT)
+ if (mode == AUMODE_PLAY && as[i].as_dir != HDAUDIO_PINDIR_OUT)
continue;
- if ((mode & (AUMODE_PLAY|AUMODE_RECORD)) == AUMODE_RECORD &&
- as[i].as_dir != HDAUDIO_PINDIR_IN)
+ if (mode == AUMODE_RECORD && as[i].as_dir != HDAUDIO_PINDIR_IN)
continue;
fmt &= ~HDAUDIO_FMT_CHAN_MASK;
if (as[i].as_dir == HDAUDIO_PINDIR_OUT &&
sc->sc_audiodev.ad_playback != NULL) {
tag = hdaudio_stream_tag(sc->sc_audiodev.ad_playback);
- fmt |= HDAUDIO_FMT_CHAN(sc->sc_curpchan);
- maxchan = sc->sc_curpchan;
+ fmt |= HDAUDIO_FMT_CHAN(sc->sc_pparam.channels);
+ maxchan = sc->sc_pparam.channels;
} else if (as[i].as_dir == HDAUDIO_PINDIR_IN &&
sc->sc_audiodev.ad_capture != NULL) {
tag = hdaudio_stream_tag(sc->sc_audiodev.ad_capture);
- fmt |= HDAUDIO_FMT_CHAN(sc->sc_currchan);
- maxchan = sc->sc_currchan;
+ fmt |= HDAUDIO_FMT_CHAN(sc->sc_rparam.channels);
+ maxchan = sc->sc_rparam.channels;
} else {
tag = 0;
if (as[i].as_dir == HDAUDIO_PINDIR_OUT) {
@@ -2732,40 +2737,85 @@
return nchans;
}
-static void
-hdaudio_afg_configure_encodings(struct hdaudio_afg_softc *sc)
+static bool
+hdaudio_afg_rate_supported(struct hdaudio_afg_softc *sc, u_int frequency)
{
- struct hdaudio_assoc *as = sc->sc_assocs;
+ uint32_t caps = sc->sc_p.pcm_size_rate;
+
+#define ISFREQOK(shift) ((caps & (1 << (shift))) ? true : false)
+ switch (frequency) {
+ case 8000:
+ return ISFREQOK(0);
+ case 11025:
+ return ISFREQOK(1);
+ case 16000:
+ return ISFREQOK(2);
+ case 22050:
+ return ISFREQOK(3);
+ case 32000:
+ return ISFREQOK(4);
+ case 44100:
+ return ISFREQOK(5);
+ case 48000:
+ return true; /* Must be supported by all codecs */
+ case 88200:
+ return ISFREQOK(7);
+ case 96000:
+ return ISFREQOK(8);
+ case 176400:
+ return ISFREQOK(9);
+ case 192000:
+ return ISFREQOK(10);
+ case 384000:
+ return ISFREQOK(11);
+ default:
+ return false;
+ }
+#undef ISFREQOK
+}
+
+static bool
+hdaudio_afg_bits_supported(struct hdaudio_afg_softc *sc, u_int bits)
+{
+ uint32_t caps = sc->sc_p.pcm_size_rate;
+#define ISBITSOK(shift) ((caps & (1 << (shift))) ? true : false)
+ switch (bits) {
+ case 8:
+ return ISBITSOK(16);
+ case 16:
+ return ISBITSOK(17);
+ case 20:
+ return ISBITSOK(18);
+ case 24:
+ return ISBITSOK(19);
+ case 32:
+ return ISBITSOK(20);
+ default:
+ return false;
+ }
+#undef ISBITSOK
+}
+
+static bool
+hdaudio_afg_probe_encoding(struct hdaudio_afg_softc *sc,
+ u_int minrate, u_int maxrate, u_int validbits, u_int precision)
+{
struct audio_format f;
- int nchan, i;
-
- sc->sc_pchan = sc->sc_rchan = 0;
-
- for (nchan = 0, i = 0; i < sc->sc_nassocs; i++) {
Home |
Main Index |
Thread Index |
Old Index