socsvn commit: r306995 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sat Jul 30 20:37:04 UTC 2016
Author: iateaca
Date: Sat Jul 30 20:37:01 2016
New Revision: 306995
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=306995
Log:
implement audio_record - records samples from the sound device using blocking operations
add suport for input stream in hda_codec (implement hda_codec_audio_input_nid, hda_codec_audio_input_do_transfer, hda_codec_audio_input_do_setup)
if hda_transfer is called with stream=0 return error(it means the stream has been stopped)
M bhyve/audio.c
M bhyve/audio.h
M bhyve/hda_codec.c
M bhyve/pci_hda.c
Modified:
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c Sat Jul 30 19:03:32 2016 (r306994)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c Sat Jul 30 20:37:01 2016 (r306995)
@@ -161,3 +161,36 @@
return 0;
}
+/*
+ * audio_record - records samples from the sound device using blocking operations
+ * @aud - the audio player used to capture the samples
+ * @buf - the buffer to receive the samples
+ * @count - the number of bytes to capture in buffer
+ * Returns -1 on error and 0 on success
+ */
+int audio_record(struct audio *aud, void *buf, size_t count)
+{
+ int audio_fd = -1;
+ ssize_t len = 0, total = 0;
+
+ assert(aud);
+ assert(!aud->dir);
+ assert(buf);
+
+ audio_fd = aud->fd;
+ assert(audio_fd != -1);
+
+ total = 0;
+ while (total < count) {
+ len = read(audio_fd, buf + total, count - total);
+ if (len == -1) {
+ DPRINTF("Fail to write to fd: %d, errno: %d\n", audio_fd, errno);
+ return -1;
+ }
+
+ total += len;
+ }
+
+ return 0;
+}
+
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h Sat Jul 30 19:03:32 2016 (r306994)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h Sat Jul 30 20:37:01 2016 (r306995)
@@ -46,4 +46,13 @@
*/
int audio_playback(struct audio *aud, const void *buf, size_t count);
+/*
+ * audio_record - records samples from the sound device using blocking operations
+ * @aud - the audio player used to capture the samples
+ * @buf - the buffer to receive the samples
+ * @count - the number of bytes to capture in buffer
+ * Returns -1 on error and 0 on success
+ */
+int audio_record(struct audio *aud, void *buf, size_t count);
+
#endif /* _AUDIO_EMUL_H_ */
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Sat Jul 30 19:03:32 2016 (r306994)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Sat Jul 30 20:37:01 2016 (r306995)
@@ -171,6 +171,15 @@
hda_codec_audio_output_do_transfer(void *arg);
static int
hda_codec_audio_output_do_setup(void *arg);
+static uint32_t
+hda_codec_audio_input_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload);
+static void
+hda_codec_audio_input_do_transfer(void *arg);
+static int
+hda_codec_audio_input_do_setup(void *arg);
+
+static uint32_t
+hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb, uint16_t payload);
/*
* HDA Codec global data
@@ -267,6 +276,7 @@
static const verb_func_t hda_codec_verb_handlers[HDA_CODEC_NODES_COUNT] = {
[HDA_CODEC_AUDIO_OUTPUT_NID] = hda_codec_audio_output_nid,
+ [HDA_CODEC_AUDIO_INPUT_NID] = hda_codec_audio_input_nid,
};
/*
@@ -295,6 +305,9 @@
sc->verb_handlers = hda_codec_verb_handlers;
DPRINTF("HDA Codec nodes: %d\n", sc->no_nodes);
+ /*
+ * Initialize the Audio Output stream
+ */
st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
err = hda_audio_ctxt_init(&st->actx, "hda-audio-output", hda_codec_audio_output_do_transfer, hda_codec_audio_output_do_setup, sc);
@@ -307,6 +320,21 @@
return -1;
}
+ /*
+ * Initialize the Audio Input stream
+ */
+ st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+
+ err = hda_audio_ctxt_init(&st->actx, "hda-audio-input", hda_codec_audio_input_do_transfer, hda_codec_audio_input_do_setup, sc);
+ assert(!err);
+
+ /* TODO Get the name of the sound device from the config string */
+ st->aud = audio_init("/dev/dsp", 0);
+ if (!st->aud) {
+ DPRINTF("Fail to init the input audio player\n");
+ return -1;
+ }
+
sc->hci = hci;
hci->priv = sc;
@@ -319,6 +347,7 @@
struct hda_ops *hops = NULL;
struct hda_codec_softc *sc = NULL;
struct hda_codec_stream *st = NULL;
+ int i;
assert(hci);
@@ -328,11 +357,13 @@
sc = (struct hda_codec_softc *)hci->priv;
assert(sc);
- st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
- st->left_gain = HDA_CODEC_AMP_NUMSTEPS;
- st->right_gain = HDA_CODEC_AMP_NUMSTEPS;
- st->left_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
- st->right_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
+ for (i = 0; i < HDA_CODEC_STREAMS_COUNT; i++) {
+ st = &sc->streams[i];
+ st->left_gain = HDA_CODEC_AMP_NUMSTEPS;
+ st->right_gain = HDA_CODEC_AMP_NUMSTEPS;
+ st->left_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
+ st->right_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
+ }
DPRINTF("cad: 0x%x\n", hci->cad);
@@ -420,28 +451,28 @@
struct hda_codec_softc *sc = NULL;
struct hda_codec_stream *st = NULL;
struct hda_audio_ctxt *actx = NULL;
+ int i;
int err;
assert(hci);
+ assert(stream);
sc = (struct hda_codec_softc *)hci->priv;
assert(sc);
- /* TODO search the right stream
- * For now, there is only one stream
- */
- st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ for (i = 0; i < HDA_CODEC_STREAMS_COUNT; i++) {
+ st = &sc->streams[i];
+ if (st->stream == stream)
+ break;
+ }
DPRINTF("run: %d, stream: 0x%x, st->stream: 0x%x dir: %d\n", run, stream, st->stream, dir);
- if (!st->stream) {
- DPRINTF("Stream not set\n");
+ if (stream != st->stream) {
+ DPRINTF("Stream not found\n");
return 0;
}
- if (stream != st->stream)
- return -1;
-
actx = &st->actx;
if (run)
@@ -504,15 +535,132 @@
static uint32_t
hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload)
{
+ struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ int res;
+
+ res = hda_codec_audio_inout_nid(st, verb, payload);
+
+ return res;
+}
+
+static void
+hda_codec_audio_output_do_transfer(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_inst *hci = NULL;
+ struct hda_ops *hops = NULL;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ int err;
+
+ hci = sc->hci;
+ assert(hci);
+
+ hops = hci->hops;
+ assert(hops);
+
+ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ aud = st->aud;
+
+ err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf));
+ if (err)
+ return;
+
+ err = audio_playback(aud, st->buf, sizeof(st->buf));
+ assert(!err);
+
+ return;
+}
+
+static int
+hda_codec_audio_output_do_setup(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ struct audio_params params;
+ int err;
+
+ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ aud = st->aud;
+
+ err = hda_codec_parse_format(st->fmt, ¶ms);
+ if (err)
+ return -1;
+
+ DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
+
+ return audio_set_params(aud, ¶ms);
+}
+
+static uint32_t
+hda_codec_audio_input_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload)
+{
+ struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+ int res;
+
+ res = hda_codec_audio_inout_nid(st, verb, payload);
+
+ return res;
+}
+
+static void
+hda_codec_audio_input_do_transfer(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_inst *hci = NULL;
+ struct hda_ops *hops = NULL;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ int err;
+
+ hci = sc->hci;
+ assert(hci);
+
+ hops = hci->hops;
+ assert(hops);
+
+ st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+ aud = st->aud;
+
+ err = audio_record(aud, st->buf, sizeof(st->buf));
+ assert(!err);
+
+ hops->transfer(hci, st->stream, 0, st->buf, sizeof(st->buf));
+
+ return;
+}
+
+static int
+hda_codec_audio_input_do_setup(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ struct audio_params params;
+ int err;
+
+ st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+ aud = st->aud;
+
+ err = hda_codec_parse_format(st->fmt, ¶ms);
+ if (err)
+ return -1;
+
+ DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
+
+ return audio_set_params(aud, ¶ms);
+}
+
+static uint32_t
+hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb, uint16_t payload)
+{
uint32_t res = 0;
uint8_t mute = 0;
uint8_t gain = 0;
DPRINTF("verb: 0x%x, payload, 0x%x\n", verb, payload);
- st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
-
switch (verb) {
case HDA_CMD_VERB_GET_CONV_FMT:
res = st->fmt;
@@ -521,7 +669,6 @@
st->fmt = payload;
break;
case HDA_CMD_VERB_GET_AMP_GAIN_MUTE:
- assert(payload & HDA_CMD_GET_AMP_GAIN_MUTE_OUTPUT);
if (payload & HDA_CMD_GET_AMP_GAIN_MUTE_LEFT) {
res = st->left_gain | st->left_mute;
DPRINTF("GET_AMP_GAIN_MUTE_LEFT: 0x%x\n", res);
@@ -531,8 +678,6 @@
}
break;
case HDA_CMD_VERB_SET_AMP_GAIN_MUTE:
- assert(payload & HDA_CMD_SET_AMP_GAIN_MUTE_OUTPUT);
-
mute = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
gain = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK;
@@ -566,56 +711,6 @@
return res;
}
-static void
-hda_codec_audio_output_do_transfer(void *arg)
-{
- struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
- struct hda_codec_inst *hci = NULL;
- struct hda_ops *hops = NULL;
- struct hda_codec_stream *st = NULL;
- struct audio *aud = NULL;
- int err;
-
- hci = sc->hci;
- assert(hci);
-
- hops = hci->hops;
- assert(hops);
-
- st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
- aud = st->aud;
-
- err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf));
- if (err)
- return;
-
- err = audio_playback(aud, st->buf, sizeof(st->buf));
- assert(!err);
-
- return;
-}
-
-static int
-hda_codec_audio_output_do_setup(void *arg)
-{
- struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
- struct hda_codec_stream *st = NULL;
- struct audio *aud = NULL;
- struct audio_params params;
- int err;
-
- st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
- aud = st->aud;
-
- err = hda_codec_parse_format(st->fmt, ¶ms);
- if (err)
- return -1;
-
- DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
-
- return audio_set_params(aud, ¶ms);
-}
-
struct hda_codec_class hda_codec = {
.name = "hda_codec",
.init = hda_codec_init,
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sat Jul 30 19:03:32 2016 (r306994)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sat Jul 30 20:37:01 2016 (r306995)
@@ -1112,6 +1112,11 @@
assert(buf);
assert(!(count % HDA_DMA_ACCESS_LEN));
+ if (!stream) {
+ DPRINTF("Invalid stream\n");
+ return -1;
+ }
+
sc = hci->hda;
assert(stream < HDA_STREAM_TAGS_CNT);
More information about the svn-soc-all
mailing list