[PATCH 07/14] ASoC: q6dsp: q6apm-dai: Add async compress write support

From: Mohammad Rafi Shaik
Date: Wed Feb 01 2023 - 08:52:37 EST


Add async compress write API to send the compressed audio data packet
to ADSP. 

Signed-off-by: Mohammad Rafi Shaik <quic_mohs@xxxxxxxxxxx>
Co-developed-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx>
---
sound/soc/qcom/qdsp6/audioreach.c | 38 +++++++++++++++++++++++++
sound/soc/qcom/qdsp6/audioreach.h | 2 ++
sound/soc/qcom/qdsp6/q6apm-dai.c | 7 +++++
sound/soc/qcom/qdsp6/q6apm.c | 46 +++++++++++++++++++++++++++++++
sound/soc/qcom/qdsp6/q6apm.h | 3 ++
5 files changed, 96 insertions(+)

diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index e84ccbacc0f7..7c45c36e9156 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -240,6 +240,44 @@ void *audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token,
}
EXPORT_SYMBOL_GPL(audioreach_alloc_pkt);

+static void __audioreach_update_pkt(struct gpr_pkt *pkt, int payload_size, uint32_t opcode,
+ uint32_t token, uint32_t src_port, uint32_t dest_port,
+ bool has_cmd_hdr)
+{
+ int pkt_size = GPR_HDR_SIZE + payload_size;
+ void *p;
+
+ if (has_cmd_hdr)
+ pkt_size += APM_CMD_HDR_SIZE;
+
+ p = pkt;
+ pkt->hdr.version = GPR_PKT_VER;
+ pkt->hdr.hdr_size = GPR_PKT_HEADER_WORD_SIZE;
+ pkt->hdr.pkt_size = pkt_size;
+ pkt->hdr.dest_port = dest_port;
+ pkt->hdr.src_port = src_port;
+
+ pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP;
+ pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS;
+ pkt->hdr.token = token;
+ pkt->hdr.opcode = opcode;
+
+ if (has_cmd_hdr) {
+ struct apm_cmd_header *cmd_header;
+
+ p = p + GPR_HDR_SIZE;
+ cmd_header = p;
+ cmd_header->payload_size = payload_size;
+ }
+}
+
+void audioreach_update_pkt(struct gpr_pkt *pkt, int payload_size, uint32_t opcode, uint32_t token,
+ uint32_t src_port, uint32_t dest_port)
+{
+ __audioreach_update_pkt(pkt, payload_size, opcode, token, src_port, dest_port, false);
+}
+EXPORT_SYMBOL_GPL(audioreach_update_pkt);
+
void *audioreach_alloc_apm_pkt(int pkt_size, uint32_t opcode, uint32_t token, uint32_t src_port)
{
return __audioreach_alloc_pkt(pkt_size, opcode, token, src_port, APM_MODULE_INSTANCE_ID,
diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h
index 0faaf75115fd..044994ca4811 100644
--- a/sound/soc/qcom/qdsp6/audioreach.h
+++ b/sound/soc/qcom/qdsp6/audioreach.h
@@ -788,4 +788,6 @@ int audioreach_remove_trailing_silence(struct q6apm *apm, struct audioreach_modu
uint32_t trailing_samples);
int audioreach_compr_set_param(struct q6apm_graph *graph, struct audioreach_module_config *mcfg);
int audioreach_set_real_module_id(struct q6apm *apm, struct audioreach_module *module, uint32_t id);
+void audioreach_update_pkt(struct gpr_pkt *pkt, int payload_size, uint32_t opcode,
+ uint32_t token, uint32_t src_port, uint32_t dest_port);
#endif /* __AUDIOREACH_H__ */
diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
index 8f5d744b3365..e621e31294a1 100644
--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
@@ -38,8 +38,10 @@ enum stream_state {
struct q6apm_dai_rtd {
struct snd_pcm_substream *substream;
struct snd_compr_stream *cstream;
+ struct snd_codec codec;
struct snd_compr_params codec_param;
struct snd_dma_buffer dma_buffer;
+ spinlock_t lock;
phys_addr_t phys;
unsigned int pcm_size;
unsigned int pcm_count;
@@ -51,8 +53,13 @@ struct q6apm_dai_rtd {
uint16_t bits_per_sample;
uint16_t source; /* Encoding source bit mask */
uint16_t session_id;
+ bool next_track;
enum stream_state state;
struct q6apm_graph *graph;
+ uint32_t initial_samples_drop;
+ uint32_t trailing_samples_drop;
+ uint32_t next_track_stream_id;
+ bool notify_on_drain;
};

struct q6apm_dai_data {
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index 811d86bdc092..1a6c7108bae0 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -25,6 +25,8 @@ struct apm_graph_mgmt_cmd {
uint32_t sub_graph_id_list[];
} __packed;

+struct gpr_pkt *pkt;
+
#define APM_GRAPH_MGMT_PSIZE(p, n) ALIGN(struct_size(p, sub_graph_id_list, n), 8)

struct q6apm *g_apm;
@@ -457,6 +459,45 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
}
EXPORT_SYMBOL_GPL(q6apm_write_async);

+int q6apm_write_async_compr(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
+ uint32_t lsw_ts, uint32_t wflags)
+{
+ struct apm_data_cmd_wr_sh_mem_ep_data_buffer_v2 *write_buffer;
+ struct audio_buffer *ab;
+
+ int rc, iid;
+
+ iid = q6apm_graph_get_rx_shmem_module_iid(graph);
+
+ audioreach_update_pkt(pkt, sizeof(*write_buffer), DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2,
+ graph->rx_data.dsp_buf | (len << APM_WRITE_TOKEN_LEN_SHIFT),
+ graph->port->id, iid);
+
+ write_buffer = (void *)pkt + GPR_HDR_SIZE;
+
+ ab = &graph->rx_data.buf[graph->rx_data.dsp_buf];
+
+ write_buffer->buf_addr_lsw = lower_32_bits(ab->phys);
+ write_buffer->buf_addr_msw = upper_32_bits(ab->phys);
+ write_buffer->buf_size = len;
+ write_buffer->timestamp_lsw = lsw_ts;
+ write_buffer->timestamp_msw = msw_ts;
+ write_buffer->mem_map_handle = graph->rx_data.mem_map_handle;
+ write_buffer->flags = wflags;
+
+ graph->rx_data.dsp_buf++;
+
+ if (graph->rx_data.dsp_buf >= graph->rx_data.num_periods)
+ graph->rx_data.dsp_buf = 0;
+
+ rc = gpr_send_port_pkt(graph->port, pkt);
+
+ memset(pkt, 0, sizeof(write_buffer) + GPR_HDR_SIZE);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(q6apm_write_async_compr);
+
int q6apm_read(struct q6apm_graph *graph)
{
struct data_cmd_rd_sh_mem_ep_data_buffer_v2 *read_buffer;
@@ -724,6 +765,11 @@ static int apm_probe(gpr_device_t *gdev)

dev_set_drvdata(dev, apm);

+ pkt = devm_kzalloc(dev, sizeof(struct apm_data_cmd_wr_sh_mem_ep_data_buffer_v2) +
+ GPR_HDR_SIZE, GFP_KERNEL);
+ if (!pkt)
+ return -ENOMEM;
+
mutex_init(&apm->lock);
apm->dev = dev;
apm->gdev = gdev;
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h
index 87d67faf5f1a..630c2bca0f06 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -45,6 +45,7 @@
#define APM_WRITE_TOKEN_LEN_SHIFT 16

#define APM_MAX_SESSIONS 8
+#define APM_LAST_BUFFER_FLAG BIT(30)

struct q6apm {
struct device *dev;
@@ -128,6 +129,8 @@ int q6apm_send_eos_nowait(struct q6apm_graph *graph);
int q6apm_read(struct q6apm_graph *graph);
int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
uint32_t lsw_ts, uint32_t wflags);
+int q6apm_write_async_compr(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
+ uint32_t lsw_ts, uint32_t wflags);

/* Memory Map related */
int q6apm_map_memory_regions(struct q6apm_graph *graph,
--
2.25.1