socsvn commit: r305548 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sat Jun 25 19:16:16 UTC 2016
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, ¶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,
@@ -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
More information about the svn-soc-all
mailing list