Date: Mon, 20 Jun 2016 15:07:39 GMT From: iateaca@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r305374 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve Message-ID: <201606201507.u5KF7dGx077565@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606201507.u5KF7dGx077565>