All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] ASoC: qdsp6: add compress offload support
@ 2018-09-26 10:23 ` Srinivas Kandagatla
  0 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: linux-kernel, vkoul, bgoswami, rohitkr, lgirdwood, tiwai,
	devicetree, mark.rutland, Srinivas Kandagatla

This patchset adds support to very basic MP3 playback compress offload
support via QDSP ASM module.

Tested this patchset on DB410c with APQ8016 and DB820c with APQ8096 using
tinycompress library.

Adding other codec support should be trivial w.r.t qdsp6 side, however
there are other dependencies like compress UAPI header changes and
FastRPC which are being worked in parallel. Once ready will post them!

thanks,
srini

Changes since v1 (https://patchwork.kernel.org/cover/10585805/)
- added support to snd_compr_set_runtime_buffer()
- make use of generic copy function
- few trivial cleanups suggested by Vinod Koul

Srinivas Kandagatla (5):
  ALSA: soc-compress: add support to snd_compr_set_runtime_buffer()
  ALSA: compress: make use of runtime buffer for copy
  ASoC: q6asm-dai: dt-bindings: Add support to compress dais
  ASoC: qdsp6: q6asm: add support to MP3 format
  ASoC: qdsp6: q6asm-dai: Add support to compress offload

 .../devicetree/bindings/sound/qcom,q6asm.txt  |  27 ++
 include/sound/compress_driver.h               |  19 +
 sound/core/compress_offload.c                 |  18 +-
 sound/soc/qcom/Kconfig                        |   1 +
 sound/soc/qcom/qdsp6/q6asm-dai.c              | 377 +++++++++++++++++-
 sound/soc/qcom/qdsp6/q6asm.c                  |   5 +
 6 files changed, 443 insertions(+), 4 deletions(-)

-- 
2.19.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 0/5] ASoC: qdsp6: add compress offload support
@ 2018-09-26 10:23 ` Srinivas Kandagatla
  0 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: mark.rutland, devicetree, bgoswami, lgirdwood, tiwai,
	linux-kernel, vkoul, rohitkr, Srinivas Kandagatla

This patchset adds support to very basic MP3 playback compress offload
support via QDSP ASM module.

Tested this patchset on DB410c with APQ8016 and DB820c with APQ8096 using
tinycompress library.

Adding other codec support should be trivial w.r.t qdsp6 side, however
there are other dependencies like compress UAPI header changes and
FastRPC which are being worked in parallel. Once ready will post them!

thanks,
srini

Changes since v1 (https://patchwork.kernel.org/cover/10585805/)
- added support to snd_compr_set_runtime_buffer()
- make use of generic copy function
- few trivial cleanups suggested by Vinod Koul

Srinivas Kandagatla (5):
  ALSA: soc-compress: add support to snd_compr_set_runtime_buffer()
  ALSA: compress: make use of runtime buffer for copy
  ASoC: q6asm-dai: dt-bindings: Add support to compress dais
  ASoC: qdsp6: q6asm: add support to MP3 format
  ASoC: qdsp6: q6asm-dai: Add support to compress offload

 .../devicetree/bindings/sound/qcom,q6asm.txt  |  27 ++
 include/sound/compress_driver.h               |  19 +
 sound/core/compress_offload.c                 |  18 +-
 sound/soc/qcom/Kconfig                        |   1 +
 sound/soc/qcom/qdsp6/q6asm-dai.c              | 377 +++++++++++++++++-
 sound/soc/qcom/qdsp6/q6asm.c                  |   5 +
 6 files changed, 443 insertions(+), 4 deletions(-)

-- 
2.19.0

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/5] ALSA: soc-compress: add support to snd_compr_set_runtime_buffer()
  2018-09-26 10:23 ` Srinivas Kandagatla
  (?)
@ 2018-09-26 10:23 ` Srinivas Kandagatla
  2018-10-05  0:31   ` Vinod
  -1 siblings, 1 reply; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: linux-kernel, vkoul, bgoswami, rohitkr, lgirdwood, tiwai,
	devicetree, mark.rutland, Srinivas Kandagatla

This patch adds support to set runtime dma buffer on compressed stream.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 include/sound/compress_driver.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index ea8c93bbb0e0..0cdc3999ecfa 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -23,6 +23,7 @@ struct snd_compr_ops;
  * struct snd_compr_runtime: runtime stream description
  * @state: stream state
  * @ops: pointer to DSP callbacks
+ * @dma_buffer_p: runtime dma buffer pointer
  * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
  *	DSP doesn't implement copy
  * @buffer_size: size of the above buffer
@@ -37,6 +38,7 @@ struct snd_compr_ops;
 struct snd_compr_runtime {
 	snd_pcm_state_t state;
 	struct snd_compr_ops *ops;
+	struct snd_dma_buffer *dma_buffer_p;
 	void *buffer;
 	u64 buffer_size;
 	u32 fragment_size;
@@ -175,6 +177,23 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
 	wake_up(&stream->runtime->sleep);
 }
 
+/**
+ * snd_compr_set_runtime_buffer - Set the Compress runtime buffer
+ * @substream: compress substream to set
+ * @bufp: the buffer information, NULL to clear
+ *
+ * Copy the buffer information to runtime buffer when @bufp is non-NULL.
+ * Otherwise it clears the current buffer information.
+ */
+static inline void snd_compr_set_runtime_buffer(
+					struct snd_compr_stream *substream,
+					struct snd_dma_buffer *bufp)
+{
+	struct snd_compr_runtime *runtime = substream->runtime;
+
+	runtime->dma_buffer_p = bufp;
+}
+
 int snd_compr_stop_error(struct snd_compr_stream *stream,
 			 snd_pcm_state_t state);
 
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/5] ALSA: compress: make use of runtime buffer for copy
  2018-09-26 10:23 ` Srinivas Kandagatla
@ 2018-09-26 10:23   ` Srinivas Kandagatla
  -1 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: linux-kernel, vkoul, bgoswami, rohitkr, lgirdwood, tiwai,
	devicetree, mark.rutland, Srinivas Kandagatla

Default copy function uses kmalloc to allocate buffers, lets check
if the runtime buffers are setup before making this allocations.
This can be useful if the buffers are dma buffers.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 sound/core/compress_offload.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 26b5e245b074..a5b09e75e787 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -171,7 +171,8 @@ static int snd_compr_free(struct inode *inode, struct file *f)
 	}
 
 	data->stream.ops->free(&data->stream);
-	kfree(data->stream.runtime->buffer);
+	if (!data->stream.runtime->dma_buffer_p)
+		kfree(data->stream.runtime->buffer);
 	kfree(data->stream.runtime);
 	kfree(data);
 	return 0;
@@ -505,7 +506,7 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
 		struct snd_compr_params *params)
 {
 	unsigned int buffer_size;
-	void *buffer;
+	void *buffer = NULL;
 
 	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
 	if (stream->ops->copy) {
@@ -514,7 +515,18 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
 		 * the data from core
 		 */
 	} else {
-		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (stream->runtime->dma_buffer_p) {
+
+			if (buffer_size > stream->runtime->dma_buffer_p->bytes)
+				dev_err(&stream->device->dev,
+						"Not enough DMA buffer");
+			else
+				buffer = stream->runtime->dma_buffer_p->area;
+
+		} else {
+			buffer = kmalloc(buffer_size, GFP_KERNEL);
+		}
+
 		if (!buffer)
 			return -ENOMEM;
 	}
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/5] ALSA: compress: make use of runtime buffer for copy
@ 2018-09-26 10:23   ` Srinivas Kandagatla
  0 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: mark.rutland, devicetree, bgoswami, lgirdwood, tiwai,
	linux-kernel, vkoul, rohitkr, Srinivas Kandagatla

Default copy function uses kmalloc to allocate buffers, lets check
if the runtime buffers are setup before making this allocations.
This can be useful if the buffers are dma buffers.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 sound/core/compress_offload.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 26b5e245b074..a5b09e75e787 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -171,7 +171,8 @@ static int snd_compr_free(struct inode *inode, struct file *f)
 	}
 
 	data->stream.ops->free(&data->stream);
-	kfree(data->stream.runtime->buffer);
+	if (!data->stream.runtime->dma_buffer_p)
+		kfree(data->stream.runtime->buffer);
 	kfree(data->stream.runtime);
 	kfree(data);
 	return 0;
@@ -505,7 +506,7 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
 		struct snd_compr_params *params)
 {
 	unsigned int buffer_size;
-	void *buffer;
+	void *buffer = NULL;
 
 	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
 	if (stream->ops->copy) {
@@ -514,7 +515,18 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
 		 * the data from core
 		 */
 	} else {
-		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (stream->runtime->dma_buffer_p) {
+
+			if (buffer_size > stream->runtime->dma_buffer_p->bytes)
+				dev_err(&stream->device->dev,
+						"Not enough DMA buffer");
+			else
+				buffer = stream->runtime->dma_buffer_p->area;
+
+		} else {
+			buffer = kmalloc(buffer_size, GFP_KERNEL);
+		}
+
 		if (!buffer)
 			return -ENOMEM;
 	}
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 3/5] ASoC: q6asm-dai: dt-bindings: Add support to compress dais
  2018-09-26 10:23 ` Srinivas Kandagatla
                   ` (2 preceding siblings ...)
  (?)
@ 2018-09-26 10:23 ` Srinivas Kandagatla
  -1 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: linux-kernel, vkoul, bgoswami, rohitkr, lgirdwood, tiwai,
	devicetree, mark.rutland, Srinivas Kandagatla

This patch adds board specific bindings required for dais, In particular
for compressed dais and dai direction.

Board specific setup involves setting up some of dais as compressed dais
and also specify direction of any dai. Some of the dais might only
support capture/playback depending on the board level wiring.

These two new dt properties will allow such flexibilty at board level dts.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Reviewed-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/sound/qcom,q6asm.txt  | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt
index f9c7bd8c1bc0..9f5378c51686 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6asm.txt
+++ b/Documentation/devicetree/bindings/sound/qcom,q6asm.txt
@@ -27,6 +27,28 @@ used by the apr service device.
 	Value type: <u32>
 	Definition: Must be 1
 
+== ASM DAI is subnode of "dais" and represent a dai, it includes board specific
+configuration of each dai. Must contain the following properties.
+
+- reg
+	Usage: required
+	Value type: <u32>
+	Definition: Must be dai id
+
+- direction:
+	Usage: Required for Compress offload dais
+	Value type: <u32>
+	Definition: Specifies the direction of the dai stream
+			0 for both tx and rx
+			1 for only tx (Capture/Encode)
+			2 for only rx (Playback/Decode)
+
+- is-compress-dai:
+	Usage: Required for Compress offload dais
+	Value type: <boolean>
+	Definition: present for Compress offload dais
+
+
 = EXAMPLE
 
 q6asm@7 {
@@ -35,5 +57,10 @@ q6asm@7 {
 	q6asmdai: dais {
 		compatible = "qcom,q6asm-dais";
 		#sound-dai-cells = <1>;
+		mm@0 {
+			reg = <0>;
+			direction = <2>;
+			is-compress-dai;
+		};
 	};
 };
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 4/5] ASoC: qdsp6: q6asm: add support to MP3 format
  2018-09-26 10:23 ` Srinivas Kandagatla
                   ` (3 preceding siblings ...)
  (?)
@ 2018-09-26 10:23 ` Srinivas Kandagatla
  -1 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: linux-kernel, vkoul, bgoswami, rohitkr, lgirdwood, tiwai,
	devicetree, mark.rutland, Srinivas Kandagatla

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 sound/soc/qcom/qdsp6/q6asm.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c
index 2b2c7233bb5f..e98aee1baadd 100644
--- a/sound/soc/qcom/qdsp6/q6asm.c
+++ b/sound/soc/qcom/qdsp6/q6asm.c
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <uapi/sound/asound.h>
+#include <uapi/sound/compress_params.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
@@ -37,6 +38,7 @@
 #define ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2	0x00010DA3
 #define ASM_SESSION_CMD_RUN_V2			0x00010DAA
 #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2	0x00010DA5
+#define ASM_MEDIA_FMT_MP3			0x00010BE9
 #define ASM_DATA_CMD_WRITE_V2			0x00010DAB
 #define ASM_DATA_CMD_READ_V2			0x00010DAC
 #define ASM_SESSION_CMD_SUSPEND			0x00010DEC
@@ -869,6 +871,9 @@ int q6asm_open_write(struct audio_client *ac, uint32_t format,
 	open->postprocopo_id = ASM_NULL_POPP_TOPOLOGY;
 
 	switch (format) {
+	case SND_AUDIOCODEC_MP3:
+		open->dec_fmt_id = ASM_MEDIA_FMT_MP3;
+		break;
 	case FORMAT_LINEAR_PCM:
 		open->dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
 		break;
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 5/5] ASoC: qdsp6: q6asm-dai: Add support to compress offload
  2018-09-26 10:23 ` Srinivas Kandagatla
                   ` (4 preceding siblings ...)
  (?)
@ 2018-09-26 10:23 ` Srinivas Kandagatla
  2018-10-05  0:39   ` Vinod
  -1 siblings, 1 reply; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-09-26 10:23 UTC (permalink / raw)
  To: broonie, alsa-devel, robh+dt
  Cc: linux-kernel, vkoul, bgoswami, rohitkr, lgirdwood, tiwai,
	devicetree, mark.rutland, Srinivas Kandagatla

This patch adds MP3 playback support in q6asm dais, adding other codec
support should be pretty trivial.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 sound/soc/qcom/Kconfig           |   1 +
 sound/soc/qcom/qdsp6/q6asm-dai.c | 377 ++++++++++++++++++++++++++++++-
 2 files changed, 377 insertions(+), 1 deletion(-)

diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index 2a4c912d1e48..ebf991bb546c 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -66,6 +66,7 @@ config SND_SOC_QDSP6_ASM
 	tristate
 
 config SND_SOC_QDSP6_ASM_DAI
+	select SND_SOC_COMPRESS
 	tristate
 
 config SND_SOC_QDSP6
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 9db9a2944ef2..57b8abcbebcd 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -11,6 +11,8 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/pcm.h>
+#include <linux/spinlock.h>
+#include <sound/compress_driver.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/of_device.h>
@@ -31,6 +33,16 @@
 #define CAPTURE_MIN_PERIOD_SIZE     320
 #define SID_MASK_DEFAULT	0xF
 
+/* Default values used if user space does not set */
+#define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
+#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
+#define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
+#define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
+#define Q6ASM_DAI_TX_RX	0
+#define Q6ASM_DAI_TX	1
+#define Q6ASM_DAI_RX	2
+
+
 enum stream_state {
 	Q6ASM_STREAM_IDLE = 0,
 	Q6ASM_STREAM_STOPPED,
@@ -39,11 +51,22 @@ enum stream_state {
 
 struct q6asm_dai_rtd {
 	struct snd_pcm_substream *substream;
+	struct snd_compr_stream *cstream;
+	struct snd_compr_params codec_param;
+	struct snd_dma_buffer dma_buffer;
+
 	phys_addr_t phys;
+	spinlock_t lock;
+
 	unsigned int pcm_size;
 	unsigned int pcm_count;
 	unsigned int pcm_irq_pos;       /* IRQ position */
 	unsigned int periods;
+
+	unsigned int bytes_sent;
+	unsigned int bytes_received;
+	unsigned int copied_total;
+
 	uint16_t bits_per_sample;
 	uint16_t source; /* Encoding source bit mask */
 	struct audio_client *audio_client;
@@ -139,6 +162,21 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
 	.mask = 0,
 };
 
+static const struct snd_compr_codec_caps q6asm_compr_caps = {
+	.num_descriptors = 1,
+	.descriptor[0].max_ch = 2,
+	.descriptor[0].sample_rates = {	8000, 11025, 12000, 16000, 22050,
+					24000, 32000, 44100, 48000, 88200,
+					96000, 176400, 192000 },
+	.descriptor[0].num_sample_rates = 13,
+	.descriptor[0].bit_rate[0] = 320,
+	.descriptor[0].bit_rate[1] = 128,
+	.descriptor[0].num_bitrates = 2,
+	.descriptor[0].profiles = 0,
+	.descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
+	.descriptor[0].formats = 0,
+};
+
 static void event_handler(uint32_t opcode, uint32_t token,
 			  uint32_t *payload, void *priv)
 {
@@ -461,6 +499,306 @@ static struct snd_pcm_ops q6asm_dai_ops = {
 	.mmap		= q6asm_dai_mmap,
 };
 
+static void compress_event_handler(uint32_t opcode, uint32_t token,
+				   uint32_t *payload, void *priv)
+{
+	struct q6asm_dai_rtd *prtd = priv;
+	struct snd_compr_stream *substream = prtd->cstream;
+	unsigned long flags;
+	uint64_t avail;
+
+	switch (opcode) {
+	case ASM_CLIENT_EVENT_CMD_RUN_DONE:
+		spin_lock_irqsave(&prtd->lock, flags);
+		if (!prtd->bytes_sent) {
+			q6asm_write_async(prtd->audio_client, prtd->pcm_count,
+					  0, 0, NO_TIMESTAMP);
+			prtd->bytes_sent += prtd->pcm_count;
+		}
+
+		spin_unlock_irqrestore(&prtd->lock, flags);
+		break;
+
+	case ASM_CLIENT_EVENT_CMD_EOS_DONE:
+		prtd->state = Q6ASM_STREAM_STOPPED;
+		break;
+
+	case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
+		spin_lock_irqsave(&prtd->lock, flags);
+
+		prtd->copied_total += prtd->pcm_count;
+		snd_compr_fragment_elapsed(substream);
+
+		if (prtd->state != Q6ASM_STREAM_RUNNING) {
+			spin_unlock_irqrestore(&prtd->lock, flags);
+			break;
+		}
+
+		avail = prtd->bytes_received - prtd->bytes_sent;
+
+		if (avail >= prtd->pcm_count) {
+			q6asm_write_async(prtd->audio_client,
+					   prtd->pcm_count, 0, 0, NO_TIMESTAMP);
+			prtd->bytes_sent += prtd->pcm_count;
+		}
+
+		spin_unlock_irqrestore(&prtd->lock, flags);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
+{
+	struct snd_soc_pcm_runtime *rtd = stream->private_data;
+	struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct q6asm_dai_data *pdata;
+	struct device *dev = c->dev;
+	struct q6asm_dai_rtd *prtd;
+	int stream_id, size, ret;
+
+	stream_id = cpu_dai->driver->id;
+	pdata = snd_soc_component_get_drvdata(c);
+	if (!pdata) {
+		dev_err(dev, "Drv data not found ..\n");
+		return -EINVAL;
+	}
+
+	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+	if (!prtd)
+		return -ENOMEM;
+
+	prtd->cstream = stream;
+	prtd->audio_client = q6asm_audio_client_alloc(dev,
+					(q6asm_cb)compress_event_handler,
+					prtd, stream_id, LEGACY_PCM_MODE);
+	if (!prtd->audio_client) {
+		dev_err(dev, "Could not allocate memory\n");
+		kfree(prtd);
+		return -ENOMEM;
+	}
+
+	size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
+			COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
+	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
+				  &prtd->dma_buffer);
+	if (ret) {
+		dev_err(dev, "Cannot allocate buffer(s)\n");
+		return ret;
+	}
+
+	if (pdata->sid < 0)
+		prtd->phys = prtd->dma_buffer.addr;
+	else
+		prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
+
+	snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
+	spin_lock_init(&prtd->lock);
+	runtime->private_data = prtd;
+
+	return 0;
+}
+
+static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
+{
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct q6asm_dai_rtd *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = stream->private_data;
+
+	if (prtd->audio_client) {
+		if (prtd->state)
+			q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+
+		snd_dma_free_pages(&prtd->dma_buffer);
+		q6asm_unmap_memory_regions(stream->direction,
+					   prtd->audio_client);
+		q6asm_audio_client_free(prtd->audio_client);
+		prtd->audio_client = NULL;
+	}
+	q6routing_stream_close(rtd->dai_link->id, stream->direction);
+	kfree(prtd);
+
+	return 0;
+}
+
+static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream,
+				      struct snd_compr_params *params)
+{
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct q6asm_dai_rtd *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = stream->private_data;
+	struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+	int dir = stream->direction;
+	struct q6asm_dai_data *pdata;
+	struct device *dev = c->dev;
+	int ret;
+
+	memcpy(&prtd->codec_param, params, sizeof(*params));
+
+	pdata = snd_soc_component_get_drvdata(c);
+	if (!pdata)
+		return -EINVAL;
+
+	if (!prtd || !prtd->audio_client) {
+		dev_err(dev, "private data null or audio client freed\n");
+		return -EINVAL;
+	}
+
+	prtd->periods = runtime->fragments;
+	prtd->pcm_count = runtime->fragment_size;
+	prtd->pcm_size = runtime->fragments * runtime->fragment_size;
+	prtd->bits_per_sample = 16;
+	if (dir == SND_COMPRESS_PLAYBACK) {
+		ret = q6asm_open_write(prtd->audio_client, params->codec.id,
+					prtd->bits_per_sample);
+
+		if (ret < 0) {
+			dev_err(dev, "q6asm_open_write failed\n");
+			q6asm_audio_client_free(prtd->audio_client);
+			prtd->audio_client = NULL;
+			return ret;
+		}
+	}
+
+	prtd->session_id = q6asm_get_session_id(prtd->audio_client);
+	ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
+			      prtd->session_id, dir);
+	if (ret) {
+		dev_err(dev, "Stream reg failed ret:%d\n", ret);
+		return ret;
+	}
+
+	ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
+				       (prtd->pcm_size / prtd->periods),
+				       prtd->periods);
+
+	if (ret < 0) {
+		dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
+		return -ENOMEM;
+	}
+
+	prtd->state = Q6ASM_STREAM_RUNNING;
+
+	return 0;
+}
+
+static int q6asm_dai_compr_trigger(struct snd_compr_stream *stream, int cmd)
+{
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct q6asm_dai_rtd *prtd = runtime->private_data;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		prtd->state = Q6ASM_STREAM_STOPPED;
+		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int q6asm_dai_compr_pointer(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct q6asm_dai_rtd *prtd = runtime->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&prtd->lock, flags);
+
+	tstamp->copied_total = prtd->copied_total;
+	tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
+
+	spin_unlock_irqrestore(&prtd->lock, flags);
+
+	return 0;
+}
+
+static int q6asm_dai_compr_ack(struct snd_compr_stream *stream,
+				size_t count)
+{
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct q6asm_dai_rtd *prtd = runtime->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&prtd->lock, flags);
+	prtd->bytes_received += count;
+	spin_unlock_irqrestore(&prtd->lock, flags);
+
+	return count;
+}
+
+static int q6asm_dai_compr_mmap(struct snd_compr_stream *stream,
+		struct vm_area_struct *vma)
+{
+	struct snd_compr_runtime *runtime = stream->runtime;
+	struct q6asm_dai_rtd *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = stream->private_data;
+	struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
+	struct device *dev = c->dev;
+
+	return dma_mmap_coherent(dev, vma,
+			prtd->dma_buffer.area, prtd->dma_buffer.addr,
+			prtd->dma_buffer.bytes);
+}
+
+static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream,
+				    struct snd_compr_caps *caps)
+{
+	caps->direction = SND_COMPRESS_PLAYBACK;
+	caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
+	caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
+	caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
+	caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
+	caps->num_codecs = 1;
+	caps->codecs[0] = SND_AUDIOCODEC_MP3;
+
+	return 0;
+}
+
+static int q6asm_dai_compr_get_codec_caps(struct snd_compr_stream *stream,
+					  struct snd_compr_codec_caps *codec)
+{
+	switch (codec->codec) {
+	case SND_AUDIOCODEC_MP3:
+		*codec = q6asm_compr_caps;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct snd_compr_ops q6asm_dai_compr_ops = {
+	.open		= q6asm_dai_compr_open,
+	.free		= q6asm_dai_compr_free,
+	.set_params	= q6asm_dai_compr_set_params,
+	.pointer	= q6asm_dai_compr_pointer,
+	.trigger	= q6asm_dai_compr_trigger,
+	.get_caps	= q6asm_dai_compr_get_caps,
+	.get_codec_caps	= q6asm_dai_compr_get_codec_caps,
+	.mmap		= q6asm_dai_compr_mmap,
+	.ack		= q6asm_dai_compr_ack,
+};
+
 static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_pcm_substream *psubstream, *csubstream;
@@ -548,7 +886,7 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = {
 	.ops		= &q6asm_dai_ops,
 	.pcm_new	= q6asm_dai_pcm_new,
 	.pcm_free	= q6asm_dai_pcm_free,
-
+	.compr_ops	= &q6asm_dai_compr_ops,
 };
 
 static struct snd_soc_dai_driver q6asm_fe_dais[] = {
@@ -562,6 +900,41 @@ static struct snd_soc_dai_driver q6asm_fe_dais[] = {
 	Q6ASM_FEDAI_DRIVER(8),
 };
 
+static int of_q6asm_parse_dai_data(struct device *dev,
+				    struct q6asm_dai_data *pdata)
+{
+	static struct snd_soc_dai_driver *dai_drv;
+	struct snd_soc_pcm_stream empty_stream;
+	struct device_node *node;
+	int ret, id, dir;
+
+	memset(&empty_stream, 0, sizeof(empty_stream));
+
+	for_each_child_of_node(dev->of_node, node) {
+		ret = of_property_read_u32(node, "reg", &id);
+		if (ret || id > MAX_SESSIONS || id < 0) {
+			dev_err(dev, "valid dai id not found:%d\n", ret);
+			continue;
+		}
+
+		dai_drv = &q6asm_fe_dais[id];
+
+		ret = of_property_read_u32(node, "direction", &dir);
+		if (ret)
+			continue;
+
+		if (dir == Q6ASM_DAI_RX)
+			dai_drv->capture = empty_stream;
+		else if (dir == Q6ASM_DAI_TX)
+			dai_drv->playback = empty_stream;
+
+		if (of_property_read_bool(node, "is-compress-dai"))
+			dai_drv->compress_new = snd_soc_new_compress;
+	}
+
+	return 0;
+}
+
 static int q6asm_dai_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -582,6 +955,8 @@ static int q6asm_dai_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, pdata);
 
+	of_q6asm_parse_dai_data(dev, pdata);
+
 	return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
 					q6asm_fe_dais,
 					ARRAY_SIZE(q6asm_fe_dais));
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 1/5] ALSA: soc-compress: add support to snd_compr_set_runtime_buffer()
  2018-09-26 10:23 ` [PATCH v2 1/5] ALSA: soc-compress: add support to snd_compr_set_runtime_buffer() Srinivas Kandagatla
@ 2018-10-05  0:31   ` Vinod
  2018-10-05  8:16     ` Srinivas Kandagatla
  0 siblings, 1 reply; 12+ messages in thread
From: Vinod @ 2018-10-05  0:31 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: broonie, alsa-devel, robh+dt, linux-kernel, bgoswami, rohitkr,
	lgirdwood, tiwai, devicetree, mark.rutland

On 26-09-18, 11:23, Srinivas Kandagatla wrote:
> This patch adds support to set runtime dma buffer on compressed stream.

The change is fine as is, but I feel we need to document the motivation
in the changelog. The core changes need a bit more explanation on why we
should add this..

> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
>  include/sound/compress_driver.h | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
> index ea8c93bbb0e0..0cdc3999ecfa 100644
> --- a/include/sound/compress_driver.h
> +++ b/include/sound/compress_driver.h
> @@ -23,6 +23,7 @@ struct snd_compr_ops;
>   * struct snd_compr_runtime: runtime stream description
>   * @state: stream state
>   * @ops: pointer to DSP callbacks
> + * @dma_buffer_p: runtime dma buffer pointer
>   * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
>   *	DSP doesn't implement copy
>   * @buffer_size: size of the above buffer
> @@ -37,6 +38,7 @@ struct snd_compr_ops;
>  struct snd_compr_runtime {
>  	snd_pcm_state_t state;
>  	struct snd_compr_ops *ops;
> +	struct snd_dma_buffer *dma_buffer_p;
>  	void *buffer;
>  	u64 buffer_size;
>  	u32 fragment_size;
> @@ -175,6 +177,23 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
>  	wake_up(&stream->runtime->sleep);
>  }
>  
> +/**
> + * snd_compr_set_runtime_buffer - Set the Compress runtime buffer
> + * @substream: compress substream to set
> + * @bufp: the buffer information, NULL to clear
> + *
> + * Copy the buffer information to runtime buffer when @bufp is non-NULL.
> + * Otherwise it clears the current buffer information.
> + */
> +static inline void snd_compr_set_runtime_buffer(
> +					struct snd_compr_stream *substream,
> +					struct snd_dma_buffer *bufp)
> +{
> +	struct snd_compr_runtime *runtime = substream->runtime;
> +
> +	runtime->dma_buffer_p = bufp;
> +}
> +
>  int snd_compr_stop_error(struct snd_compr_stream *stream,
>  			 snd_pcm_state_t state);
>  
> -- 
> 2.19.0

-- 
~Vinod

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 5/5] ASoC: qdsp6: q6asm-dai: Add support to compress offload
  2018-09-26 10:23 ` [PATCH v2 5/5] ASoC: qdsp6: q6asm-dai: Add support to compress offload Srinivas Kandagatla
@ 2018-10-05  0:39   ` Vinod
  2018-10-05  8:15     ` Srinivas Kandagatla
  0 siblings, 1 reply; 12+ messages in thread
From: Vinod @ 2018-10-05  0:39 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: broonie, alsa-devel, robh+dt, linux-kernel, bgoswami, rohitkr,
	lgirdwood, tiwai, devicetree, mark.rutland

On 26-09-18, 11:23, Srinivas Kandagatla wrote:
> This patch adds MP3 playback support in q6asm dais, adding other codec
> support should be pretty trivial.
> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
>  sound/soc/qcom/Kconfig           |   1 +
>  sound/soc/qcom/qdsp6/q6asm-dai.c | 377 ++++++++++++++++++++++++++++++-
>  2 files changed, 377 insertions(+), 1 deletion(-)
> 
> diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
> index 2a4c912d1e48..ebf991bb546c 100644
> --- a/sound/soc/qcom/Kconfig
> +++ b/sound/soc/qcom/Kconfig
> @@ -66,6 +66,7 @@ config SND_SOC_QDSP6_ASM
>  	tristate
>  
>  config SND_SOC_QDSP6_ASM_DAI
> +	select SND_SOC_COMPRESS
>  	tristate
>  
>  config SND_SOC_QDSP6
> diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
> index 9db9a2944ef2..57b8abcbebcd 100644
> --- a/sound/soc/qcom/qdsp6/q6asm-dai.c
> +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
> @@ -11,6 +11,8 @@
>  #include <sound/soc.h>
>  #include <sound/soc-dapm.h>
>  #include <sound/pcm.h>
> +#include <linux/spinlock.h>
> +#include <sound/compress_driver.h>
>  #include <asm/dma.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/of_device.h>
> @@ -31,6 +33,16 @@
>  #define CAPTURE_MIN_PERIOD_SIZE     320
>  #define SID_MASK_DEFAULT	0xF
>  
> +/* Default values used if user space does not set */
> +#define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
> +#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
> +#define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
> +#define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
> +#define Q6ASM_DAI_TX_RX	0
> +#define Q6ASM_DAI_TX	1
> +#define Q6ASM_DAI_RX	2
> +
> +

Unnecessary double space

>  enum stream_state {
>  	Q6ASM_STREAM_IDLE = 0,
>  	Q6ASM_STREAM_STOPPED,
> @@ -39,11 +51,22 @@ enum stream_state {
>  
>  struct q6asm_dai_rtd {
>  	struct snd_pcm_substream *substream;
> +	struct snd_compr_stream *cstream;
> +	struct snd_compr_params codec_param;
> +	struct snd_dma_buffer dma_buffer;
> +
>  	phys_addr_t phys;
> +	spinlock_t lock;

why would we need a lock for compress case?

-- 
~Vinod

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 5/5] ASoC: qdsp6: q6asm-dai: Add support to compress offload
  2018-10-05  0:39   ` Vinod
@ 2018-10-05  8:15     ` Srinivas Kandagatla
  0 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-10-05  8:15 UTC (permalink / raw)
  To: Vinod
  Cc: broonie, alsa-devel, robh+dt, linux-kernel, bgoswami, rohitkr,
	lgirdwood, tiwai, devicetree, mark.rutland

Thanks Vinod for the Review!

On 05/10/18 01:39, Vinod wrote:
> On 26-09-18, 11:23, Srinivas Kandagatla wrote:
>> This patch adds MP3 playback support in q6asm dais, adding other codec
>> support should be pretty trivial.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
>> ---
>>   sound/soc/qcom/Kconfig           |   1 +
>>   sound/soc/qcom/qdsp6/q6asm-dai.c | 377 ++++++++++++++++++++++++++++++-
>>   2 files changed, 377 insertions(+), 1 deletion(-)
>>
...
>> +#define Q6ASM_DAI_RX	2
>> +
>> +
> 
> Unnecessary double space
> 

I did notice this just after I sent the patch!
>>   enum stream_state {
>>   	Q6ASM_STREAM_IDLE = 0,
>>   	Q6ASM_STREAM_STOPPED,
>> @@ -39,11 +51,22 @@ enum stream_state {
>>   
>>   struct q6asm_dai_rtd {
>>   	struct snd_pcm_substream *substream;
>> +	struct snd_compr_stream *cstream;
>> +	struct snd_compr_params codec_param;
>> +	struct snd_dma_buffer dma_buffer;
>> +
>>   	phys_addr_t phys;
>> +	spinlock_t lock;
> 
> why would we need a lock for compress case?
bytes_received counter is updated as part of Ack and referenced in the 
irq context in the event_handler callback from dsp, this lock is to 
protect it !

--srini
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 1/5] ALSA: soc-compress: add support to snd_compr_set_runtime_buffer()
  2018-10-05  0:31   ` Vinod
@ 2018-10-05  8:16     ` Srinivas Kandagatla
  0 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2018-10-05  8:16 UTC (permalink / raw)
  To: Vinod
  Cc: broonie, alsa-devel, robh+dt, linux-kernel, bgoswami, rohitkr,
	lgirdwood, tiwai, devicetree, mark.rutland

Thanks for review!

On 05/10/18 01:31, Vinod wrote:
> On 26-09-18, 11:23, Srinivas Kandagatla wrote:
>> This patch adds support to set runtime dma buffer on compressed stream.
> The change is fine as is, but I feel we need to document the motivation
> in the changelog. The core changes need a bit more explanation on why we
> should add this..

Sure, I will add more information into the change log in next version.

--srini

> 
>> Signed-off-by: Srinivas Kandagatla<srinivas.kandagatla@linaro.org>
>> ---
>>   include/sound/compress_driver.h | 19 +++++++++++++++++++
>>   1 file changed, 19 insertions(+)
>>
>> diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
>> index ea8c93bbb0e0..0cdc3999ecfa 100644
>> --- a/include/sound/compress_driver.h
>> +++ b/include/sound/compress_driver.h
>> @@ -23,6 +23,7 @@ struct snd_compr_ops;
>>    * struct snd_compr_runtime: runtime stream description
>>    * @state: stream state
>>    * @ops: pointer to DSP callbacks

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-10-05  8:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-26 10:23 [PATCH v2 0/5] ASoC: qdsp6: add compress offload support Srinivas Kandagatla
2018-09-26 10:23 ` Srinivas Kandagatla
2018-09-26 10:23 ` [PATCH v2 1/5] ALSA: soc-compress: add support to snd_compr_set_runtime_buffer() Srinivas Kandagatla
2018-10-05  0:31   ` Vinod
2018-10-05  8:16     ` Srinivas Kandagatla
2018-09-26 10:23 ` [PATCH v2 2/5] ALSA: compress: make use of runtime buffer for copy Srinivas Kandagatla
2018-09-26 10:23   ` Srinivas Kandagatla
2018-09-26 10:23 ` [PATCH v2 3/5] ASoC: q6asm-dai: dt-bindings: Add support to compress dais Srinivas Kandagatla
2018-09-26 10:23 ` [PATCH v2 4/5] ASoC: qdsp6: q6asm: add support to MP3 format Srinivas Kandagatla
2018-09-26 10:23 ` [PATCH v2 5/5] ASoC: qdsp6: q6asm-dai: Add support to compress offload Srinivas Kandagatla
2018-10-05  0:39   ` Vinod
2018-10-05  8:15     ` Srinivas Kandagatla

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.