File Index
Files and directories
Sign in
FILE

stream-ipc.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/sof/stream-ipc.c C
  1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2//
  3// This file is provided under a dual BSD/GPLv2 license.  When using or
  4// redistributing this file, you may do so under either license.
  5//
  6// Copyright(c) 2019 Intel Corporation
  7//
  8// Authors: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
  9
 10/* Generic SOF IPC code */
 11
 12#include <linux/device.h>
 13#include <linux/export.h>
 14#include <linux/module.h>
 15#include <linux/types.h>
 16
 17#include <sound/pcm.h>
 18#include <sound/sof/stream.h>
 19
 20#include "ops.h"
 21#include "sof-priv.h"
 22#include "sof-audio.h"
 23
 24struct sof_stream {
 25	size_t posn_offset;
 26};
 27
 28/* Mailbox-based Generic IPC implementation */
 29int sof_ipc_msg_data(struct snd_sof_dev *sdev,
 30		     struct snd_sof_pcm_stream *sps,
 31		     void *p, size_t sz)
 32{
 33	if (!sps || !sdev->stream_box.size) {
 34		snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
 35	} else {
 36		size_t posn_offset;
 37
 38		if (sps->substream) {
 39			struct sof_stream *stream = sps->substream->runtime->private_data;
 40
 41			/* The stream might already be closed */
 42			if (!stream)
 43				return -ESTRPIPE;
 44
 45			posn_offset = stream->posn_offset;
 46		} else if (sps->cstream) {
 47
 48			struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
 49
 50			if (!sstream)
 51				return -ESTRPIPE;
 52
 53			posn_offset = sstream->posn_offset;
 54
 55		} else {
 56			dev_err(sdev->dev, "%s: No stream opened\n", __func__);
 57			return -EINVAL;
 58		}
 59
 60		snd_sof_dsp_mailbox_read(sdev, posn_offset, p, sz);
 61	}
 62
 63	return 0;
 64}
 65EXPORT_SYMBOL(sof_ipc_msg_data);
 66
 67int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
 68			       struct snd_sof_pcm_stream *sps,
 69			       size_t posn_offset)
 70{
 71	/* check if offset is overflow or it is not aligned */
 72	if (posn_offset > sdev->stream_box.size ||
 73	    posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
 74		return -EINVAL;
 75
 76	posn_offset += sdev->stream_box.offset;
 77
 78	if (sps->substream) {
 79		struct sof_stream *stream = sps->substream->runtime->private_data;
 80
 81		stream->posn_offset = posn_offset;
 82		dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
 83			sps->substream->stream, posn_offset);
 84	} else if (sps->cstream) {
 85		struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
 86
 87		sstream->posn_offset = posn_offset;
 88		dev_dbg(sdev->dev, "compr: stream dir %d, posn mailbox offset is %zu",
 89			sps->cstream->direction, posn_offset);
 90	} else {
 91		dev_err(sdev->dev, "No stream opened");
 92		return -EINVAL;
 93	}
 94
 95	return 0;
 96}
 97EXPORT_SYMBOL(sof_set_stream_data_offset);
 98
 99int sof_stream_pcm_open(struct snd_sof_dev *sdev,
100			struct snd_pcm_substream *substream)
101{
102	struct sof_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
103
104	if (!stream)
105		return -ENOMEM;
106
107	/* binding pcm substream to hda stream */
108	substream->runtime->private_data = stream;
109
110	/* align to DMA minimum transfer size */
111	snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
112
113	/* avoid circular buffer wrap in middle of period */
114	snd_pcm_hw_constraint_integer(substream->runtime,
115				      SNDRV_PCM_HW_PARAM_PERIODS);
116
117	return 0;
118}
119EXPORT_SYMBOL(sof_stream_pcm_open);
120
121int sof_stream_pcm_close(struct snd_sof_dev *sdev,
122			 struct snd_pcm_substream *substream)
123{
124	struct sof_stream *stream = substream->runtime->private_data;
125
126	substream->runtime->private_data = NULL;
127	kfree(stream);
128
129	return 0;
130}
131EXPORT_SYMBOL(sof_stream_pcm_close);
~/ Read-only file preview.