socsvn commit: r305374 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Mon Jun 20 15:07:41 UTC 2016
Author: iateaca
Date: Mon Jun 20 15:07:38 2016
New Revision: 305374
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305374
Log:
= hda_codec.c =
design the struct hda_audio_ctxt data structure: HDA Audio Context data structure
implement the HDA Audio Context (hda_audio_ctxt_thr, hda_audio_ctxt_init, hda_audio_ctxt_start, hda_audio_ctxt_stop)
this context is going to run transfers between the HDA and sound audio card
add ont HDA Audio Context per stream
implement the hda_codec_notify function used by the HDA controller to start / stop the Audio Context in the codec
= pci_hda.c =
implement the hda_notify_codecs function in order to notify the codecs one stream has started / stopped
implement the hda_stream_stop function
M bhyve/hda_codec.c
M bhyve/pci_hda.c
M bhyve/pci_hda.h
Modified:
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Mon Jun 20 09:15:03 2016 (r305373)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Mon Jun 20 15:07:38 2016 (r305374)
@@ -1,4 +1,8 @@
+#include <pthread.h>
+#include <pthread_np.h>
+#include <unistd.h>
+
#include "pci_hda.h"
/*
@@ -43,8 +47,40 @@
#define HDA_CONFIG_DEFAULTCONF_COLOR_BLACK (0x01 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
+#define HDA_CODEC_BUF_SIZE 0x100
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/*
+ * HDA Audio Context data structures
+ */
+
+typedef void (*transfer_func_t)(void *arg);
+
+struct hda_audio_ctxt {
+ char name[64];
+ uint8_t run;
+ pthread_t tid;
+ pthread_mutex_t mtx;
+ pthread_cond_t cond;
+ transfer_func_t do_transfer;
+ void *priv;
+};
+
+/*
+ * HDA Audio Context module function declarations
+ */
+
+static void *
+hda_audio_ctxt_thr(void *arg);
+static int
+hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname, transfer_func_t do_transfer, void *priv);
+static int
+hda_audio_ctxt_start(struct hda_audio_ctxt *actx);
+static int
+hda_audio_ctxt_stop(struct hda_audio_ctxt *actx);
+
/*
* HDA Codec data structures
*/
@@ -54,9 +90,12 @@
typedef uint32_t (*verb_func_t)(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload);
struct hda_codec_stream {
+ uint8_t buf[HDA_CODEC_BUF_SIZE];
uint8_t stream;
uint8_t channel;
uint16_t fmt;
+
+ struct hda_audio_ctxt actx;
};
struct hda_codec_softc {
@@ -80,8 +119,13 @@
hda_codec_reset(struct hda_codec_inst *hci);
static int
hda_codec_command(struct hda_codec_inst *hci, uint32_t cmd_data);
+static int
+hda_codec_notify(struct hda_codec_inst *hci, uint8_t run, uint8_t stream, uint8_t dir);
-uint32_t hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload);
+static uint32_t
+hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload);
+static void
+hda_codec_audio_output_do_transfer(void *arg);
/*
* HDA Codec global data
@@ -158,6 +202,7 @@
hda_codec_init(struct hda_codec_inst *hci, const char *opts)
{
struct hda_codec_softc *sc = NULL;
+ int err;
DPRINTF("cad: 0x%x opts: %s\n", hci->cad, opts);
@@ -174,6 +219,9 @@
sc->verb_handlers = hda_codec_verb_handlers;
DPRINTF("HDA Codec nodes: %d\n", sc->no_nodes);
+ err = hda_audio_ctxt_init(&sc->streams[HDA_CODEC_STREAM_OUTPUT].actx, "hda-audio-output", hda_codec_audio_output_do_transfer, sc);
+ assert(!err);
+
hci->priv = sc;
return 0;
@@ -269,7 +317,41 @@
return hops->response(hci, res, HDA_CODEC_RESPONSE_EX_SOL);
}
-uint32_t hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload)
+static int
+hda_codec_notify(struct hda_codec_inst *hci, uint8_t run, uint8_t stream, uint8_t dir)
+{
+ struct hda_codec_softc *sc = NULL;
+ struct hda_codec_stream *st = NULL;
+ struct hda_audio_ctxt *actx = NULL;
+ int err;
+
+ assert(hci);
+
+ sc = (struct hda_codec_softc *)hci->priv;
+ assert(sc);
+
+ DPRINTF("run: %d, stream: 0x%x, dir: %d\n", run, stream, dir);
+
+ /* TODO search the right stream
+ * For now, there is only only stream
+ */
+ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+
+ if (stream != st->stream)
+ return -1;
+
+ actx = &st->actx;
+
+ if (run)
+ err = hda_audio_ctxt_start(actx);
+ else
+ err = hda_audio_ctxt_stop(actx);
+
+ return err;
+}
+
+static uint32_t
+hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload)
{
struct hda_codec_stream *st = NULL;
uint32_t res = 0;
@@ -294,12 +376,107 @@
return res;
}
+static void
+hda_codec_audio_output_do_transfer(void *arg)
+{
+ /*
+ * TODO transfer betweenthe HDA and sound card
+ */
+ DPRINTF("\n");
+ usleep(20 * 1000);
+ return;
+}
+
struct hda_codec_class hda_codec = {
.name = "hda_codec",
.init = hda_codec_init,
.reset = hda_codec_reset,
.command = hda_codec_command,
+ .notify = hda_codec_notify,
};
HDA_EMUL_SET(hda_codec);
+
+/*
+ * HDA Audio Context module function definitions
+ */
+
+static void *
+hda_audio_ctxt_thr(void *arg)
+{
+ struct hda_audio_ctxt *actx = (struct hda_audio_ctxt *)arg;
+
+ DPRINTF("Start Thread: %s\n", actx->name);
+
+ pthread_mutex_lock(&actx->mtx);
+ while (1) {
+ while (!actx->run)
+ pthread_cond_wait(&actx->cond, &actx->mtx);
+
+ actx->do_transfer(actx->priv);
+ }
+ pthread_mutex_unlock(&actx->mtx);
+
+ pthread_exit(NULL);
+
+ return NULL;
+}
+
+static int
+hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname, transfer_func_t do_transfer, void *priv)
+{
+ int err;
+
+ assert(actx);
+ assert(tname);
+ assert(do_transfer);
+ assert(priv);
+
+ memset(actx, 0, sizeof(*actx));
+
+ actx->run = 0;
+ actx->do_transfer = do_transfer;
+ actx->priv = priv;
+ if (strlen(tname) < sizeof(actx->name))
+ memcpy(actx->name, tname, strlen(tname) + 1);
+ else
+ strcpy(actx->name, "unknown");
+
+ err = pthread_mutex_init(&actx->mtx, NULL);
+ assert(!err);
+
+ err = pthread_cond_init(&actx->cond, NULL);
+ assert(!err);
+
+ err = pthread_create(&actx->tid, NULL, hda_audio_ctxt_thr, actx);
+ assert(!err);
+
+ pthread_set_name_np(actx->tid, tname);
+ assert(!err);
+
+ return 0;
+}
+
+static int
+hda_audio_ctxt_start(struct hda_audio_ctxt *actx)
+{
+ /* The stream is supposed to be stopped */
+ if (actx->run)
+ return -1;
+
+ pthread_mutex_lock(&actx->mtx);
+ actx->run = 1;
+ pthread_cond_signal(&actx->cond);
+ pthread_mutex_unlock(&actx->mtx);
+
+ return 0;
+}
+
+static int
+hda_audio_ctxt_stop(struct hda_audio_ctxt *actx)
+{
+ actx->run = 0;
+ return 0;
+}
+
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Mon Jun 20 09:15:03 2016 (r305373)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Mon Jun 20 15:07:38 2016 (r305374)
@@ -55,6 +55,7 @@
};
struct hda_stream_desc {
+ uint8_t stream;
uint8_t run;
uint8_t dir;
@@ -98,6 +99,8 @@
static int
hda_send_command(struct hda_softc *sc, uint32_t verb);
+static int
+hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream, uint8_t dir);
static void
hda_reset(struct hda_softc *sc);
static void
@@ -106,6 +109,8 @@
hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind);
static int
hda_stream_start(struct hda_softc *sc, uint8_t stream_ind);
+static int
+hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind);
static uint32_t
hda_read(struct hda_softc *sc, uint32_t offset);
static int
@@ -403,6 +408,32 @@
return codec->command(hci, verb);
}
+static int
+hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream, uint8_t dir)
+{
+ struct hda_codec_inst *hci = NULL;
+ struct hda_codec_class *codec = NULL;
+ int err;
+ int i;
+
+ /* Notify each codec */
+ for (i = 0; i < sc->codecs_no; i++) {
+ hci = sc->codecs[i];
+ assert(hci);
+
+ codec = hci->codec;
+ assert(codec);
+
+ if (codec->notify) {
+ err = codec->notify(hci, run, stream, dir);
+ if (!err)
+ break;
+ }
+ }
+
+ return i == sc->codecs_no ? (-1) : 0;
+}
+
static void
hda_reset(struct hda_softc *sc)
{
@@ -485,6 +516,7 @@
uint32_t sdctl = 0;
uint8_t strm = 0;
uint8_t dir = 0;
+ int err;
int i;
assert(!st->run);
@@ -533,8 +565,28 @@
DPRINTF("strm: 0x%x, dir: 0x%x\n", strm, dir);
sc->stream_map[strm] = stream_ind;
+ st->stream = strm;
st->dir = dir;
+ err = hda_notify_codecs(sc, 1, strm, dir);
+ assert(!err);
+
+ return 0;
+}
+
+static int
+hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind)
+{
+ struct hda_stream_desc *st = &sc->streams[stream_ind];
+ uint8_t strm = st->stream;
+ uint8_t dir = st->dir;
+ int err;
+
+ DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x\n", stream_ind, strm, dir);
+
+ err = hda_notify_codecs(sc, 0, strm, dir);
+ assert(!err);
+
return 0;
}
@@ -788,9 +840,14 @@
hda_stream_reset(sc, stream_ind);
}
- if (value & HDAC_SDCTL_RUN) {
- err = hda_stream_start(sc, stream_ind);
- assert(!err);
+ if ((value & HDAC_SDCTL_RUN) != (old & HDAC_SDCTL_RUN)) {
+ if (value & HDAC_SDCTL_RUN) {
+ err = hda_stream_start(sc, stream_ind);
+ assert(!err);
+ } else {
+ err = hda_stream_stop(sc, stream_ind);
+ assert(!err);
+ }
}
return;
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h Mon Jun 20 09:15:03 2016 (r305373)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h Mon Jun 20 15:07:38 2016 (r305374)
@@ -43,6 +43,7 @@
int (*init)(struct hda_codec_inst *hci, const char *opts);
int (*reset)(struct hda_codec_inst *hci);
int (*command)(struct hda_codec_inst *hci, uint32_t cmd_data);
+ int (*notify)(struct hda_codec_inst *hci, uint8_t run, uint8_t stream, uint8_t dir);
};
struct hda_ops {
More information about the svn-soc-all
mailing list