socsvn commit: r305562 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve

iateaca at FreeBSD.org iateaca at FreeBSD.org
Sun Jun 26 17:01:24 UTC 2016


Author: iateaca
Date: Sun Jun 26 17:01:21 2016
New Revision: 305562
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305562

Log:
  implement the hda_transfer function in order to transfer the samples between the guest system memory and the sound device
  TODO this function is called from the codec context and must be synchronized with the hda context using a mutex
  
  M    bhyve/audio.c
  M    bhyve/audio.h
  M    bhyve/hda_codec.c
  M    bhyve/pci_hda.c
  M    bhyve/pci_hda.h

Modified:
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h
  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/audio.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c	Sun Jun 26 16:38:42 2016	(r305561)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.c	Sun Jun 26 17:01:21 2016	(r305562)
@@ -135,7 +135,7 @@
  * @buf - the buffer containing the samples
  * @count - the number of bytes in buffer
  */
-ssize_t audio_playback(struct audio *aud, const void *buf, size_t count)
+int audio_playback(struct audio *aud, const void *buf, size_t count)
 {
 	int audio_fd = -1;
 	ssize_t len = 0, total = 0;

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h	Sun Jun 26 16:38:42 2016	(r305561)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/audio.h	Sun Jun 26 17:01:21 2016	(r305562)
@@ -25,6 +25,7 @@
  * audio_init - initialize an instance of audio player
  * @dev_name - the backend sound device used to play / capture
  * @dir - dir = 1 for write mode, dir = 0 for read mode
+ * Returns NULL on error and the address of the audio player instance
  */
 struct audio *audio_init(const char *dev_name, uint8_t dir);
 
@@ -32,6 +33,7 @@
  * audio_set_params - reset the sound device and set the audio params
  * @aud - the audio player to be configured
  * @params - the audio parameters to be set
+ * Returns -1 on error and 0 on success
  */
 int audio_set_params(struct audio *aud, struct audio_params *params);
 
@@ -40,7 +42,8 @@
  * @aud - the audio player used to play the samples
  * @buf - the buffer containing the samples
  * @count - the number of bytes in buffer
+ * Returns -1 on error and 0 on success
  */
-ssize_t audio_playback(struct audio *aud, const void *buf, size_t count);
+int audio_playback(struct audio *aud, const void *buf, size_t count);
 
 #endif  /* _AUDIO_EMUL_H_ */

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c	Sun Jun 26 16:38:42 2016	(r305561)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c	Sun Jun 26 17:01:21 2016	(r305562)
@@ -121,6 +121,7 @@
 };
 
 struct hda_codec_softc {
+	struct hda_codec_inst *hci;
 	uint32_t subsystem_id;
 	uint32_t no_nodes;
 	const uint32_t (*get_parameters)[HDA_CODEC_PARAMS_COUNT];
@@ -258,6 +259,7 @@
 		return -1;
 	}
 
+	sc->hci = hci;
 	hci->priv = sc;
 
 	return 0;
@@ -462,21 +464,28 @@
 hda_codec_audio_output_do_transfer(void *arg)
 {
 	struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+	struct hda_codec_inst *hci = NULL;
+	struct hda_ops *hops = NULL;
 	struct hda_codec_stream *st = NULL;
 	struct audio *aud = NULL;
 	int err;
 
+	hci = sc->hci;
+	assert(hci);
+
+	hops = hci->hops;
+	assert(hops);
+
 	st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
 	aud = st->aud;
 
-	memset(st->buf, 0x31, sizeof(st->buf));
+	err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf));
+	if (err)
+		return;
 
 	err = audio_playback(aud, st->buf, sizeof(st->buf));
 	assert(!err);
 
-	usleep(20 * 1000);
-
-	DPRINTF("\n");
 	return;
 }
 

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sun Jun 26 16:38:42 2016	(r305561)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sun Jun 26 17:01:21 2016	(r305562)
@@ -22,6 +22,7 @@
 #define HDA_STREAM_REGS_BASE	0x80
 #define HDA_STREAM_REGS_LEN	0x20
 
+#define HDA_DMA_ACCESS_LEN	(sizeof(uint32_t))
 #define HDA_BDL_MAX_LEN		0x0100
 
 /*
@@ -59,6 +60,11 @@
 	uint8_t run;
 	uint8_t dir;
 
+	/* bp is the no. of bytes transferred in the current bdle */
+	uint32_t bp;
+	/* be is the no. of bdles transferred in the bdl */
+	uint32_t be;
+
 	struct hda_bdle_desc bdl[HDA_BDL_MAX_LEN];
 	uint32_t bdl_cnt;
 };
@@ -156,6 +162,9 @@
 hda_signal_state_change(struct hda_codec_inst *hci);
 static int
 hda_response(struct hda_codec_inst *hci, uint32_t response, uint8_t unsol);
+static int
+hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir, void *buf, size_t count);
+
 
 /*
  * PCI HDA function declarations
@@ -218,6 +227,7 @@
 static struct hda_ops hops = {
 	.signal		= hda_signal_state_change,
 	.response	= hda_response,
+	.transfer	= hda_transfer,
 };
 
 struct pci_devemu pci_de_hda = {
@@ -542,6 +552,8 @@
 	bdle = (struct hda_bdle *)bdl_vaddr;
 	for (i = 0; i < bdl_cnt; i++, bdle++) {
 		bdle_sz = bdle->len;
+		assert(!(bdle_sz % HDA_DMA_ACCESS_LEN));
+
 		bdle_addrl = bdle->addrl;
 		bdle_addrh = bdle->addrh;
 
@@ -567,6 +579,11 @@
 	sc->stream_map[strm] = stream_ind;
 	st->stream = strm;
 	st->dir = dir;
+	st->bp = 0;
+	st->be = 0;
+	hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, 0);
+
+	st->run = 1;
 
 	err = hda_notify_codecs(sc, 1, strm, dir);
 	assert(!err);
@@ -584,6 +601,8 @@
 
 	DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x\n", stream_ind, strm, dir);
 
+	st->run = 0;
+
 	err = hda_notify_codecs(sc, 0, strm, dir);
 	assert(!err);
 
@@ -925,6 +944,84 @@
 	return 0;
 }
 
+static int
+hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir, void *buf, size_t count)
+{
+	struct hda_softc *sc = NULL;
+	struct hda_stream_desc *st = NULL;
+	struct hda_bdle_desc *bdl = NULL;
+	struct hda_bdle_desc *bdle_desc = NULL;
+	uint8_t stream_ind = 0;
+	uint32_t lpib = 0;
+	uint32_t off = 0;
+	size_t left = 0;
+	uint8_t irq = 0;
+
+	assert(hci);
+	assert(hci->hda);
+	assert(buf);
+	assert(!(count % HDA_DMA_ACCESS_LEN));
+
+	sc = hci->hda;
+
+	assert(stream < HDA_STREAM_TAGS_CNT);
+	stream_ind = sc->stream_map[stream];
+
+	st = &sc->streams[stream_ind];
+	if (!st->run) {
+		DPRINTF("Stream 0x%x stopped\n", stream);
+		return -1;
+	}
+
+	assert(st->stream == stream);
+	assert(st->dir == dir);
+
+	off = hda_get_offset_stream(stream_ind);
+
+	lpib = hda_get_reg_by_offset(sc, off + HDAC_SDLPIB);
+
+	bdl = st->bdl;
+
+	assert(st->be < st->bdl_cnt);
+	assert(st->bp < bdl[st->be].len);
+
+	left = count;
+	while (left) {
+		bdle_desc = &bdl[st->be];
+
+		if (dir)
+			*(uint32_t *)buf = hda_dma_ld_dword(bdle_desc->addr + st->bp);
+		else
+			hda_dma_st_dword(bdle_desc->addr + st->bp, *(uint32_t *)buf);
+
+		buf += HDA_DMA_ACCESS_LEN;
+		st->bp += HDA_DMA_ACCESS_LEN;
+		lpib += HDA_DMA_ACCESS_LEN;
+		left -= HDA_DMA_ACCESS_LEN;
+
+		if (st->bp == bdle_desc->len) {
+			st->bp = 0;
+			if (bdle_desc->ioc)
+				irq = 1;
+			st->be++;
+			if (st->be == st->bdl_cnt) {
+				st->be = 0;
+				lpib = 0;
+			}
+			bdle_desc = &bdl[st->be];
+		}
+	}
+
+	hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, lpib);
+
+	if (irq) {
+		hda_set_field_by_offset(sc, off + HDAC_SDSTS, HDAC_SDSTS_BCIS, HDAC_SDSTS_BCIS);
+		hda_update_intr(sc);
+	}
+
+	return 0;
+}
+
 /*
  * PCI HDA function definitions
  */

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h	Sun Jun 26 16:38:42 2016	(r305561)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h	Sun Jun 26 17:01:21 2016	(r305562)
@@ -49,6 +49,7 @@
 struct hda_ops {
 	int (*signal)(struct hda_codec_inst *hci);
 	int (*response)(struct hda_codec_inst *hci, uint32_t response, uint8_t unsol);
+	int (*transfer)(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir, void *buf, size_t count);
 };
 
 #define HDA_EMUL_SET(x)		DATA_SET(hda_codec_class_set, x);


More information about the svn-soc-all mailing list