Add async compress write API to send the compressed audio data packet to ADSP.
Signed-off-by: Mohammad Rafi Shaik quic_mohs@quicinc.com Co-developed-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- 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,