Skip site navigation (1)Skip section navigation (2)
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>