]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ASoC: q6apm: add q6apm_get_hw_pointer helper
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Fri, 14 Mar 2025 17:47:57 +0000 (17:47 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Apr 2025 08:45:26 +0000 (10:45 +0200)
commit 0badb5432fd525a00db5630c459b635e9d47f445 upstream.

Implement an helper function in q6apm to be able to read the current
hardware pointer for both read and write buffers.

This should help q6apm-dai to get the hardware pointer consistently
without it doing manual calculation, which could go wrong in some race
conditions.

Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support")
Cc: stable@vger.kernel.org
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Tested-by: Johan Hovold <johan+linaro@kernel.org>
Link: https://patch.msgid.link/20250314174800.10142-3-srinivas.kandagatla@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
sound/soc/qcom/qdsp6/q6apm.c
sound/soc/qcom/qdsp6/q6apm.h

index 2a2a5bd98110bc70c2a164efb22df4147979d295..ca57413cb7847a4322f7b5b598d9c025534925cf 100644 (file)
@@ -494,6 +494,19 @@ int q6apm_read(struct q6apm_graph *graph)
 }
 EXPORT_SYMBOL_GPL(q6apm_read);
 
+int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir)
+{
+       struct audioreach_graph_data *data;
+
+       if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+               data = &graph->rx_data;
+       else
+               data = &graph->tx_data;
+
+       return (int)atomic_read(&data->hw_ptr);
+}
+EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer);
+
 static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
 {
        struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
@@ -520,7 +533,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
                done = data->payload;
                phys = graph->rx_data.buf[token].phys;
                mutex_unlock(&graph->lock);
-
+               /* token numbering starts at 0 */
+               atomic_set(&graph->rx_data.hw_ptr, token + 1);
                if (lower_32_bits(phys) == done->buf_addr_lsw &&
                    upper_32_bits(phys) == done->buf_addr_msw) {
                        graph->result.opcode = hdr->opcode;
@@ -553,6 +567,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
                rd_done = data->payload;
                phys = graph->tx_data.buf[hdr->token].phys;
                mutex_unlock(&graph->lock);
+               /* token numbering starts at 0 */
+               atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1);
 
                if (upper_32_bits(phys) == rd_done->buf_addr_msw &&
                    lower_32_bits(phys) == rd_done->buf_addr_lsw) {
index f486bd639b9f0d277b6b28937f65d3b8c5436f18..74fa4fed881bf96fb2f128c10993db2cd55ec2c4 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef __Q6APM_H__
 #define __Q6APM_H__
 #include <linux/types.h>
+#include <linux/atomic.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
 #include <linux/kernel.h>
@@ -78,6 +79,7 @@ struct audioreach_graph_data {
        uint32_t num_periods;
        uint32_t dsp_buf;
        uint32_t mem_map_handle;
+       atomic_t hw_ptr;
 };
 
 struct audioreach_graph {
@@ -151,4 +153,5 @@ int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph,
 int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
 int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
 int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id);
+int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir);
 #endif /* __APM_GRAPH_ */