All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleksandr Andrushchenko <andr2000@gmail.com>
To: alsa-devel@alsa-project.org, xen-devel@lists.xen.org,
	linux-kernel@vger.kernel.org
Cc: perex@perex.cz, tiwai@suse.com, andr2000@gmail.com,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Subject: [PATCH 09/11] ALSA: vsnd: Implement ALSA PCM operations
Date: Mon,  7 Aug 2017 10:43:14 +0300	[thread overview]
Message-ID: <1502091796-14413-10-git-send-email-andr2000@gmail.com> (raw)
In-Reply-To: <1502091796-14413-1-git-send-email-andr2000@gmail.com>

From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

Implement ALSA driver operations including:
- start/stop period interrupt emulation
- manage frontend/backend shraed buffers
- manage Xen bus event channel state

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
 sound/drivers/xen-front.c | 175 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 163 insertions(+), 12 deletions(-)

diff --git a/sound/drivers/xen-front.c b/sound/drivers/xen-front.c
index 507c5eb343c8..7275e9cb38c0 100644
--- a/sound/drivers/xen-front.c
+++ b/sound/drivers/xen-front.c
@@ -151,6 +151,11 @@ struct xdrv_info {
 	struct sdev_card_plat_data cfg_plat_data;
 };
 
+static inline void sh_buf_clear(struct sh_buf_info *buf);
+static void sh_buf_free(struct sh_buf_info *buf);
+static int sh_buf_alloc(struct xenbus_device *xb_dev, struct sh_buf_info *buf,
+	unsigned int buffer_size);
+
 static struct sdev_pcm_stream_info *sdrv_stream_get(
 	struct snd_pcm_substream *substream)
 {
@@ -311,71 +316,217 @@ static void sdrv_copy_pcm_hw(struct snd_pcm_hardware *dst,
 
 static int sdrv_alsa_open(struct snd_pcm_substream *substream)
 {
-	return 0;
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct xdrv_info *xdrv_info;
+	unsigned long flags;
+	int ret;
+
+	sdrv_copy_pcm_hw(&runtime->hw, &stream->pcm_hw, &pcm_instance->pcm_hw);
+	runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_DOUBLE |
+		SNDRV_PCM_INFO_BATCH |
+		SNDRV_PCM_INFO_NONINTERLEAVED |
+		SNDRV_PCM_INFO_RESUME |
+		SNDRV_PCM_INFO_PAUSE);
+	runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+
+	ret = sdrv_alsa_timer_create(substream);
+
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	sh_buf_clear(&stream->sh_buf);
+	stream->evt_chnl = &xdrv_info->evt_chnls[stream->unique_id];
+	if (ret < 0)
+		stream->evt_chnl->state = EVTCHNL_STATE_DISCONNECTED;
+	else
+		stream->evt_chnl->state = EVTCHNL_STATE_CONNECTED;
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
+	return ret;
 }
 
 static int sdrv_alsa_close(struct snd_pcm_substream *substream)
 {
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	struct xdrv_info *xdrv_info;
+	unsigned long flags;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+
+	sdrv_alsa_timer_stop(substream);
+
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	stream->evt_chnl->state = EVTCHNL_STATE_DISCONNECTED;
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
 	return 0;
 }
 
 static int sdrv_alsa_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params)
 {
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	struct xdrv_info *xdrv_info;
+	unsigned int buffer_size;
+	int ret;
+
+	buffer_size = params_buffer_bytes(params);
+	sh_buf_clear(&stream->sh_buf);
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+	ret = sh_buf_alloc(xdrv_info->xb_dev,
+		&stream->sh_buf, buffer_size);
+	if (ret < 0)
+		goto fail;
 	return 0;
+
+fail:
+	dev_err(&xdrv_info->xb_dev->dev,
+		"Failed to allocate buffers for stream idx %d\n",
+		stream->unique_id);
+	return ret;
 }
 
 static int sdrv_alsa_hw_free(struct snd_pcm_substream *substream)
 {
+	struct sdev_pcm_instance_info *pcm_instance =
+		snd_pcm_substream_chip(substream);
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	struct xdrv_info *xdrv_info;
+	unsigned long flags;
+
+	xdrv_info = pcm_instance->card_info->xdrv_info;
+	spin_lock_irqsave(&xdrv_info->io_lock, flags);
+	sh_buf_free(&stream->sh_buf);
+	spin_unlock_irqrestore(&xdrv_info->io_lock, flags);
 	return 0;
 }
 
 static int sdrv_alsa_prepare(struct snd_pcm_substream *substream)
 {
-	return 0;
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	int ret = 0;
+
+	if (!stream->is_open)
+		ret = sdrv_alsa_timer_prepare(substream);
+	return ret;
 }
 
 static int sdrv_alsa_trigger(struct snd_pcm_substream *substream, int cmd)
 {
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME:
+		return sdrv_alsa_timer_start(substream);
+
+	case SNDRV_PCM_TRIGGER_STOP:
+		/* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		return sdrv_alsa_timer_stop(substream);
+
+	default:
+		break;
+	}
 	return 0;
 }
 
 static inline snd_pcm_uframes_t sdrv_alsa_pointer(
 	struct snd_pcm_substream *substream)
 {
+	return sdrv_alsa_timer_pointer(substream);
+}
+
+static int sdrv_alsa_playback_do_write(struct snd_pcm_substream *substream,
+	unsigned long pos, unsigned long count)
+{
 	return 0;
 }
 
 static int sdrv_alsa_playback_copy_user(struct snd_pcm_substream *substream,
-		int channel, unsigned long pos, void __user *buf,
-		unsigned long bytes)
+		int channel, unsigned long pos, void __user *src,
+		unsigned long count)
 {
-	return 0;
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+
+	if (unlikely(pos + count > stream->sh_buf.vbuffer_sz))
+		return -EINVAL;
+
+	if (copy_from_user(stream->sh_buf.vbuffer + pos, src, count))
+		return -EFAULT;
+
+	return sdrv_alsa_playback_do_write(substream, pos, count);
 }
 
 static int sdrv_alsa_playback_copy_kernel(struct snd_pcm_substream *substream,
-		int channel, unsigned long pos, void *buf, unsigned long bytes)
+		int channel, unsigned long pos, void *src, unsigned long count)
+{
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+
+	if (unlikely(pos + count > stream->sh_buf.vbuffer_sz))
+		return -EINVAL;
+
+	memcpy(stream->sh_buf.vbuffer + pos, src, count);
+	return sdrv_alsa_playback_do_write(substream, pos, count);
+}
+
+static int sdrv_alsa_playback_do_read(struct snd_pcm_substream *substream,
+	unsigned long pos, unsigned long count)
 {
 	return 0;
 }
 
 static int sdrv_alsa_capture_copy_user(struct snd_pcm_substream *substream,
-		int channel, unsigned long pos, void __user *buf,
-		unsigned long bytes)
+		int channel, unsigned long pos, void __user *dst,
+		unsigned long count)
 {
-	return 0;
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	int ret;
+
+	if (unlikely(pos + count > stream->sh_buf.vbuffer_sz))
+		return -EINVAL;
+
+	ret = sdrv_alsa_playback_do_read(substream, pos, count);
+	if (ret < 0)
+		return ret;
+
+	return copy_to_user(dst, stream->sh_buf.vbuffer + pos, count) ?
+		-EFAULT : 0;
 }
 
 static int sdrv_alsa_capture_copy_kernel(struct snd_pcm_substream *substream,
-		int channel, unsigned long pos, void *buf, unsigned long bytes)
+		int channel, unsigned long pos, void *dst, unsigned long count)
 {
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+	int ret;
+
+	if (unlikely(pos + count > stream->sh_buf.vbuffer_sz))
+		return -EINVAL;
+
+	ret = sdrv_alsa_playback_do_read(substream, pos, count);
+	if (ret < 0)
+		return ret;
+
+	memcpy(dst, stream->sh_buf.vbuffer + pos, count);
 	return 0;
 }
 
 static int sdrv_alsa_playback_fill_silence(struct snd_pcm_substream *substream,
-	int channel, unsigned long pos, unsigned long bytes)
+	int channel, unsigned long pos, unsigned long count)
 {
-	return 0;
+	struct sdev_pcm_stream_info *stream = sdrv_stream_get(substream);
+
+	if (unlikely(pos + count > stream->sh_buf.vbuffer_sz))
+		return -EINVAL;
+
+	memset(stream->sh_buf.vbuffer + pos, 0, count);
+	return sdrv_alsa_playback_do_write(substream, pos, count);
 }
 
 #define MAX_XEN_BUFFER_SIZE	(64 * 1024)
-- 
2.7.4

  parent reply	other threads:[~2017-08-07  7:44 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-07  7:43 [PATCH 00/11] ALSA: vsnd: Add Xen para-virtualized frontend driver Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 01/11] ALSA: vsnd: Implement driver's probe/remove Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 02/11] ALSA: vsnd: Implement Xen bus state handling Oleksandr Andrushchenko
2017-08-07  7:43 ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 03/11] ALSA: vsnd: Read sound driver configuration from Xen store Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 04/11] ALSA: vsnd: Implement Xen event channel handling Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 05/11] ALSA: vsnd: Implement handling of shared buffers Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 06/11] ALSA: vsnd: Introduce ALSA virtual sound driver Oleksandr Andrushchenko
2017-08-07  7:43 ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 07/11] ALSA: vsnd: Initialize virtul sound card Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 08/11] ALSA: vsnd: Add timer for period interrupt emulation Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07 10:27   ` [alsa-devel] " Clemens Ladisch
2017-08-07 10:27   ` Clemens Ladisch
2017-08-07 10:27     ` Clemens Ladisch
2017-08-07 11:30     ` [alsa-devel] " Oleksandr Andrushchenko
2017-08-07 11:30     ` Oleksandr Andrushchenko
2017-08-07 13:11       ` Clemens Ladisch
2017-08-07 13:38         ` Oleksandr Andrushchenko
2017-08-07 13:38         ` Oleksandr Andrushchenko
2017-08-07 13:55           ` Clemens Ladisch
2017-08-07 13:55           ` Clemens Ladisch
2017-08-07 15:14             ` Oleksandr Andrushchenko
2017-08-08  6:09               ` Oleksandr Andrushchenko
2017-08-08  6:09               ` Oleksandr Andrushchenko
2017-08-07 15:14             ` Oleksandr Andrushchenko
2017-08-07 13:11       ` Clemens Ladisch
2017-08-07  7:43 ` [PATCH 09/11] ALSA: vsnd: Implement ALSA PCM operations Oleksandr Andrushchenko
2017-08-07  7:43 ` Oleksandr Andrushchenko [this message]
2017-08-07  7:43 ` [PATCH 10/11] ALSA: vsnd: Implement communication with backend Oleksandr Andrushchenko
2017-08-07  7:43   ` Oleksandr Andrushchenko
2017-08-07  7:43 ` [PATCH 11/11] ALSA: vsnd: Introduce Kconfig option to enable Xen PV sound Oleksandr Andrushchenko
2017-08-07  7:43 ` Oleksandr Andrushchenko
2017-08-07 11:28 ` [PATCH 00/11] ALSA: vsnd: Add Xen para-virtualized frontend driver Takashi Sakamoto
2017-08-07 11:28   ` Takashi Sakamoto
2017-08-07 11:33   ` Oleksandr Andrushchenko
2017-08-07 11:33   ` Oleksandr Andrushchenko
2017-08-07 11:28 ` Takashi Sakamoto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1502091796-14413-10-git-send-email-andr2000@gmail.com \
    --to=andr2000@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.