Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Jun 2016 19:16:15 GMT
From:      iateaca@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r305548 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
Message-ID:  <201606251916.u5PJGFur007429@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: iateaca
Date: Sat Jun 25 19:16:14 2016
New Revision: 305548
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305548

Log:
  implement the hda_codec_parse_format in order to get the sample rate, bits per sample and no. of channels parameters from the stream format
  implement the hda_codec_audio_output_do_setup function in order to set the stream parameters in the audio player
  call do_setup function when the stream is started just before to wake up the thread
  
  M    bhyve/Makefile
  M    bhyve/hda_codec.c

Modified:
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile	Sat Jun 25 18:28:22 2016	(r305547)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile	Sat Jun 25 19:16:14 2016	(r305548)
@@ -14,6 +14,7 @@
 SRCS=	\
 	atkbdc.c		\
 	acpi.c			\
+	audio.c			\
 	bhyverun.c		\
 	block_if.c		\
 	bootrom.c		\

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c	Sat Jun 25 18:28:22 2016	(r305547)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c	Sat Jun 25 19:16:14 2016	(r305548)
@@ -4,6 +4,7 @@
 #include <unistd.h>
 
 #include "pci_hda.h"
+#include "audio.h"
 
 /*
  * HDA Codec defines
@@ -26,6 +27,23 @@
 
 #define HDA_CODEC_SUPP_STREAM_FORMATS_PCM	(1 << HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
 
+#define HDA_CODEC_FMT_BASE_MASK			(0x01 << 14)
+
+#define HDA_CODEC_FMT_MULT_MASK			(0x07 << 11)
+#define HDA_CODEC_FMT_MULT_2			(0x01 << 11)
+#define HDA_CODEC_FMT_MULT_3			(0x02 << 11)
+#define HDA_CODEC_FMT_MULT_4			(0x03 << 11)
+
+#define HDA_CODEC_FMT_DIV_MASK			0x07
+#define HDA_CODEC_FMT_DIV_SHIFT			8
+
+#define HDA_CODEC_FMT_BITS_MASK			(0x07 << 4)
+#define HDA_CODEC_FMT_BITS_8			(0x00 << 4)
+#define HDA_CODEC_FMT_BITS_16			(0x01 << 4)
+#define HDA_CODEC_FMT_BITS_32			(0x04 << 4)
+
+#define HDA_CODEC_FMT_CHAN_MASK			(0x0f << 0)
+
 #define HDA_CODEC_AUDIO_WCAP_OUTPUT		(0x00 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
 #define HDA_CODEC_AUDIO_WCAP_PIN		(0x04 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
 #define HDA_CODEC_AUDIO_WCAP_CONN_LIST		(1 << HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
@@ -57,6 +75,7 @@
  */
 
 typedef void (*transfer_func_t)(void *arg);
+typedef int (*setup_func_t)(void *arg);
 
 struct hda_audio_ctxt {
 	char name[64];
@@ -65,6 +84,7 @@
 	pthread_mutex_t mtx;
 	pthread_cond_t cond;
 	transfer_func_t do_transfer;
+	setup_func_t do_setup;
 	void *priv;
 };
 
@@ -75,7 +95,7 @@
 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);
+hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname, transfer_func_t do_transfer, setup_func_t do_setup, void *priv);
 static int
 hda_audio_ctxt_start(struct hda_audio_ctxt *actx);
 static int
@@ -96,6 +116,7 @@
 	uint16_t fmt;
 
 	struct hda_audio_ctxt actx;
+	struct audio *aud;
 };
 
 struct hda_codec_softc {
@@ -122,10 +143,14 @@
 static int
 hda_codec_notify(struct hda_codec_inst *hci, uint8_t run, uint8_t stream, uint8_t dir);
 
+static int hda_codec_parse_format(uint16_t fmt, struct audio_params *params);
+
 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);
+static int
+hda_codec_audio_output_do_setup(void *arg);
 
 /*
  * HDA Codec global data
@@ -202,6 +227,7 @@
 hda_codec_init(struct hda_codec_inst *hci, const char *opts)
 {
 	struct hda_codec_softc *sc = NULL;
+	struct hda_codec_stream *st = NULL;
 	int err;
 
 	DPRINTF("cad: 0x%x opts: %s\n", hci->cad, opts);
@@ -219,9 +245,18 @@
 	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);
+	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);
 	assert(!err);
 
+	/* TODO Get the name of the sound device from the config string */
+	st->aud = audio_init("/dev/dsp", 1);
+	if (!st->aud) {
+		DPRINTF("Fail to init the output audio player\n");
+		return -1;
+	}
+
 	hci->priv = sc;
 
 	return 0;
@@ -333,7 +368,7 @@
 	DPRINTF("run: %d, stream: 0x%x, dir: %d\n", run, stream, dir);
 
 	/* TODO search the right stream
-	 * For now, there is only only stream
+	 * For now, there is only one stream
 	 */
 	st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
 
@@ -350,6 +385,50 @@
 	return err;
 }
 
+static int hda_codec_parse_format(uint16_t fmt, struct audio_params *params)
+{
+	uint8_t div = 0;
+
+	/* Compute the Sample Rate */
+	params->rate = (fmt & HDA_CODEC_FMT_BASE_MASK) ? 44100 : 48000;
+
+	switch (fmt & HDA_CODEC_FMT_MULT_MASK) {
+	case HDA_CODEC_FMT_MULT_2:
+		params->rate *= 2;
+		break;
+	case HDA_CODEC_FMT_MULT_3:
+		params->rate *= 3;
+		break;
+	case HDA_CODEC_FMT_MULT_4:
+		params->rate *= 4;
+		break;
+	}
+
+	div = (fmt >> HDA_CODEC_FMT_DIV_SHIFT) & HDA_CODEC_FMT_DIV_MASK;
+	params->rate /= (div + 1);
+
+	/* Compute the Bits per Sample */
+	switch (fmt & HDA_CODEC_FMT_BITS_MASK) {
+	case HDA_CODEC_FMT_BITS_8:
+		params->format = AFMT_U8;
+		break;
+	case HDA_CODEC_FMT_BITS_16:
+		params->format = AFMT_S16_LE;
+		break;
+	case HDA_CODEC_FMT_BITS_32:
+		params->format = AFMT_S32_LE;
+		break;
+	default:
+		DPRINTF("Unknown format bits: 0x%x\n", fmt & HDA_CODEC_FMT_BITS_MASK);
+		return -1;
+	}
+
+	/* Compute the Number of Channels */
+	params->channels = (fmt & HDA_CODEC_FMT_CHAN_MASK) + 1;
+
+	return 0;
+}
+
 static uint32_t
 hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb, uint16_t payload)
 {
@@ -379,14 +458,46 @@
 static void
 hda_codec_audio_output_do_transfer(void *arg)
 {
-	/*
-	 * TODO transfer betweenthe  HDA and sound card
-	 */
-	DPRINTF("\n");
+	struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+	struct hda_codec_stream *st = NULL;
+	struct audio *aud = NULL;
+	int err;
+
+	st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+	aud = st->aud;
+
+	memset(st->buf, 0x31, sizeof(st->buf));
+
+	err = audio_playback(aud, st->buf, sizeof(st->buf));
+	assert(!err);
+
 	usleep(20 * 1000);
+
+	DPRINTF("\n");
 	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, &params);
+	if (err)
+		return -1;
+
+	DPRINTF("rate: %d, channels: %d, format: 0x%x\n", params.rate, params.channels, params.format);
+
+	return audio_set_params(aud, &params);
+}
+
 struct hda_codec_class hda_codec  = {
 	.name		= "hda_codec",
 	.init		= hda_codec_init,
@@ -424,19 +535,21 @@
 }
 
 static int
-hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname, transfer_func_t do_transfer, void *priv)
+hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname, transfer_func_t do_transfer, setup_func_t do_setup, void *priv)
 {
 	int err;
 
 	assert(actx);
 	assert(tname);
 	assert(do_transfer);
+	assert(do_setup);
 	assert(priv);
 
 	memset(actx, 0, sizeof(*actx));
 
 	actx->run = 0;
 	actx->do_transfer = do_transfer;
+	actx->do_setup = do_setup;
 	actx->priv = priv;
 	if (strlen(tname) < sizeof(actx->name))
 		memcpy(actx->name, tname, strlen(tname) + 1);
@@ -461,16 +574,21 @@
 static int
 hda_audio_ctxt_start(struct hda_audio_ctxt *actx)
 {
+	int err = 0;
+
 	/* 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);
+	err = actx->do_setup(actx->priv);
+	if (!err) {
+		actx->run = 1;
+		pthread_cond_signal(&actx->cond);
+	}
 	pthread_mutex_unlock(&actx->mtx);
 
-	return 0;
+	return err;
 }
 
 static int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606251916.u5PJGFur007429>