Index: uspace/drv/audio/hdaudio/codec.c
===================================================================
--- uspace/drv/audio/hdaudio/codec.c	(revision 93c3163d85dbf285fc087252626c487aef284ce4)
+++ uspace/drv/audio/hdaudio/codec.c	(revision 99cb9bfebb014147307d479faf5f7fc243842ddc)
@@ -259,31 +259,4 @@
 	    codec->out_aw, rates, formats);
 
-	/* XXX Choose appropriate parameters */
-	uint32_t fmt;
-	/* 48 kHz, 16-bits, 1 channel */
-	fmt = fmt_bits_16 << fmt_bits_l;
-
-	/* Create stream */
-	ddf_msg(LVL_NOTE, "Create stream");
-	hda_stream_t *stream;
-	stream = hda_stream_create(hda, sdir_output, fmt);
-	if (stream == NULL)
-		goto error;
-
-	/* Configure converter */
-
-	ddf_msg(LVL_NOTE, "Configure converter format");
-	rc = hda_set_converter_fmt(codec, codec->out_aw, fmt);
-	if (rc != EOK)
-		goto error;
-
-	ddf_msg(LVL_NOTE, "Configure converter stream, channel");
-	rc = hda_set_converter_ctl(codec, codec->out_aw, stream->sid, 0);
-	if (rc != EOK)
-		goto error;
-
-	ddf_msg(LVL_NOTE, "Start stream");
-	hda_stream_start(stream);
-
 	ddf_msg(LVL_NOTE, "Codec OK");
 	return codec;
@@ -299,4 +272,30 @@
 }
 
+int hda_out_converter_setup(hda_codec_t *codec, uint8_t sid)
+{
+	int rc;
+
+	/* XXX Choose appropriate parameters */
+	uint32_t fmt;
+	/* 48 kHz, 16-bits, 1 channel */
+	fmt = fmt_bits_16 << fmt_bits_l;
+
+	/* Configure converter */
+
+	ddf_msg(LVL_NOTE, "Configure converter format");
+	rc = hda_set_converter_fmt(codec, codec->out_aw, fmt);
+	if (rc != EOK)
+		goto error;
+
+	ddf_msg(LVL_NOTE, "Configure converter stream, channel");
+	rc = hda_set_converter_ctl(codec, codec->out_aw, sid, 0);
+	if (rc != EOK)
+		goto error;
+
+	return EOK;
+error:
+	return rc;
+}
+
 /** @}
  */
Index: uspace/drv/audio/hdaudio/codec.h
===================================================================
--- uspace/drv/audio/hdaudio/codec.h	(revision 93c3163d85dbf285fc087252626c487aef284ce4)
+++ uspace/drv/audio/hdaudio/codec.h	(revision 99cb9bfebb014147307d479faf5f7fc243842ddc)
@@ -46,4 +46,5 @@
 extern hda_codec_t *hda_codec_init(hda_t *, uint8_t);
 extern void hda_codec_fini(hda_codec_t *);
+extern int hda_out_converter_setup(hda_codec_t *, uint8_t);
 
 #endif
Index: uspace/drv/audio/hdaudio/hdaudio.c
===================================================================
--- uspace/drv/audio/hdaudio/hdaudio.c	(revision 93c3163d85dbf285fc087252626c487aef284ce4)
+++ uspace/drv/audio/hdaudio/hdaudio.c	(revision 99cb9bfebb014147307d479faf5f7fc243842ddc)
@@ -353,4 +353,5 @@
 
 	if (0) ddf_msg(LVL_NOTE, "## interrupt ##");
+//	ddf_msg(LVL_NOTE, "interrupt arg4=0x%x", (int)IPC_GET_ARG4(*icall));
 	hda_ctl_interrupt(hda->ctl);
 }
Index: uspace/drv/audio/hdaudio/hdaudio.h
===================================================================
--- uspace/drv/audio/hdaudio/hdaudio.h	(revision 93c3163d85dbf285fc087252626c487aef284ce4)
+++ uspace/drv/audio/hdaudio/hdaudio.h	(revision 99cb9bfebb014147307d479faf5f7fc243842ddc)
@@ -50,4 +50,5 @@
 	hda_regs_t *regs;
 	struct hda_ctl *ctl;
+	struct hda_stream *pcm_stream;
 } hda_t;
 
Index: uspace/drv/audio/hdaudio/pcm_iface.c
===================================================================
--- uspace/drv/audio/hdaudio/pcm_iface.c	(revision 93c3163d85dbf285fc087252626c487aef284ce4)
+++ uspace/drv/audio/hdaudio/pcm_iface.c	(revision 99cb9bfebb014147307d479faf5f7fc243842ddc)
@@ -40,4 +40,10 @@
 #include <stdbool.h>
 
+#include "codec.h"
+#include "hdactl.h"
+#include "hdaudio.h"
+#include "spec/fmt.h"
+#include "stream.h"
+
 static int hda_get_info_str(ddf_fun_t *, const char **);
 static unsigned hda_query_cap(ddf_fun_t *, audio_cap_t);
@@ -74,14 +80,40 @@
 };
 
+enum {
+	max_buffer_size = 65536 /* XXX this is completely arbitrary */
+};
+
+static hda_t *fun_to_hda(ddf_fun_t *fun)
+{
+	return (hda_t *)ddf_dev_data_get(ddf_fun_get_dev(fun));
+}
+
 static int hda_get_info_str(ddf_fun_t *fun, const char **name)
 {
 	ddf_msg(LVL_NOTE, "hda_get_info_str()");
-	return ENOTSUP;
+	if (name)
+		*name = "High Definition Audio";
+	return EOK;
 }
 
 static unsigned hda_query_cap(ddf_fun_t *fun, audio_cap_t cap)
 {
-	ddf_msg(LVL_NOTE, "hda_query_cap()");
-	return ENOTSUP;
+	ddf_msg(LVL_NOTE, "hda_query_cap(%d)", cap);
+	switch (cap) {
+	case AUDIO_CAP_PLAYBACK:
+	case AUDIO_CAP_INTERRUPT:
+		return 1;
+	case AUDIO_CAP_BUFFER_POS:
+	case AUDIO_CAP_CAPTURE:
+		return 0;
+	case AUDIO_CAP_MAX_BUFFER:
+		return max_buffer_size;
+	case AUDIO_CAP_INTERRUPT_MIN_FRAMES:
+		return 128;
+	case AUDIO_CAP_INTERRUPT_MAX_FRAMES:
+		return 16384;
+	default:
+		return ENOTSUP;
+	}
 }
 
@@ -89,12 +121,53 @@
     unsigned *rate, pcm_sample_format_t *format)
 {
-	ddf_msg(LVL_NOTE, "hda_test_format()");
-	return ENOTSUP;
+	int rc = EOK;
+
+	ddf_msg(LVL_NOTE, "hda_test_format(%u, %u, %d)\n",
+	    *channels, *rate, *format);
+
+	if (*channels != 1) {
+		*channels = 1;
+		rc = ELIMIT;
+	}
+
+	if (*format != PCM_SAMPLE_SINT16_LE) {
+		*format = PCM_SAMPLE_SINT16_LE;
+		rc = ELIMIT;
+	}
+
+	if (*rate != 48000) {
+		*rate = 48000;
+		rc = ELIMIT;
+	}
+
+	return rc;
 }
 
 static int hda_get_buffer(ddf_fun_t *fun, void **buffer, size_t *size)
 {
-	ddf_msg(LVL_NOTE, "hda_get_buffer()");
-	return ENOTSUP;
+	hda_t *hda = fun_to_hda(fun);
+
+	ddf_msg(LVL_NOTE, "hda_get_buffer(): hda=%p", hda);
+	if (hda->pcm_stream != NULL)
+		return EBUSY;
+
+	/* XXX Choose appropriate parameters */
+	uint32_t fmt;
+	/* 48 kHz, 16-bits, 1 channel */
+	fmt = fmt_bits_16 << fmt_bits_l;
+
+	ddf_msg(LVL_NOTE, "hda_get_buffer() - create stream");
+	hda->pcm_stream = hda_stream_create(hda, sdir_output, fmt);
+	if (hda->pcm_stream == NULL)
+		return EIO;
+
+	ddf_msg(LVL_NOTE, "hda_get_buffer() - fill info");
+	/* XXX This is only one buffer */
+	*buffer = hda->pcm_stream->buf[0];
+	*size = hda->pcm_stream->bufsize;
+
+	ddf_msg(LVL_NOTE, "hda_get_buffer() retturing EOK, buffer=%p, size=%zu",
+	    *buffer, *size);
+	return EOK;
 }
 
@@ -119,6 +192,13 @@
 static int hda_release_buffer(ddf_fun_t *fun)
 {
+	hda_t *hda = fun_to_hda(fun);
+
 	ddf_msg(LVL_NOTE, "hda_release_buffer()");
-	return ENOTSUP;
+	if (hda->pcm_stream == NULL)
+		return EINVAL;
+
+	hda_stream_destroy(hda->pcm_stream);
+	hda->pcm_stream = NULL;
+	return EOK;
 }
 
@@ -126,6 +206,15 @@
     unsigned channels, unsigned rate, pcm_sample_format_t format)
 {
+	hda_t *hda = fun_to_hda(fun);
+	int rc;
+
 	ddf_msg(LVL_NOTE, "hda_start_playback()");
-	return ENOTSUP;
+
+	rc = hda_out_converter_setup(hda->ctl->codec, hda->pcm_stream->sid);
+	if (rc != EOK)
+		return rc;
+
+	hda_stream_start(hda->pcm_stream);
+	return EOK;
 }
 
Index: uspace/drv/audio/hdaudio/stream.c
===================================================================
--- uspace/drv/audio/hdaudio/stream.c	(revision 93c3163d85dbf285fc087252626c487aef284ce4)
+++ uspace/drv/audio/hdaudio/stream.c	(revision 99cb9bfebb014147307d479faf5f7fc243842ddc)
@@ -102,5 +102,5 @@
 		for (j = 0; j < stream->bufsize / 2; j++) {
 			int16_t *bp = stream->buf[i];
-			bp[j] = (k > 128) ? -10000 : 10000;
+			bp[j] = (k > 128) ? -100 : 100;
 			++k;
 			if (k >= 256)
