]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: qcom: q6asm: add q6asm_get_hw_pointer
authorSrinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Thu, 23 Oct 2025 10:24:31 +0000 (11:24 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 5 Nov 2025 13:28:23 +0000 (13:28 +0000)
Currently q6asm-dai is performing an extra layer of calculation on the hw_ptr,
which is always prone to errors and redundant.

q6asm already has tokens to indentify the pointer pointers which an be
used to get the hw_ptr and this is more accurate then doing the
artificial calculation at upper layers.

Add helper function q6asm_get_hw_pointer() to get this hw_ptr.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Tested-by: Alexey Klimov <alexey.klimov@linaro.org> # RB5, RB3
Link: https://patch.msgid.link/20251023102444.88158-8-srinivas.kandagatla@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/qcom/qdsp6/q6asm.c
sound/soc/qcom/qdsp6/q6asm.h

index 4c3315d4e27da4f1eaa3c66f8370f454c8027b30..1478948f9fe20cf76957dcd6ac4f317e98193349 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/module.h>
+#include <linux/atomic.h>
 #include <linux/soc/qcom/apr.h>
 #include <linux/device.h>
 #include <linux/of_platform.h>
@@ -248,6 +249,7 @@ struct audio_port_data {
        uint32_t num_periods;
        uint32_t dsp_buf;
        uint32_t mem_map_handle;
+       atomic_t hw_ptr;
 };
 
 struct q6asm {
@@ -598,6 +600,14 @@ err:
        return ac;
 }
 
+int q6asm_get_hw_pointer(struct audio_client *ac, unsigned int dir)
+{
+       struct audio_port_data *data = &ac->port[dir];
+
+       return (int)atomic_read(&data->hw_ptr);
+}
+EXPORT_SYMBOL_GPL(q6asm_get_hw_pointer);
+
 static int32_t q6asm_stream_callback(struct apr_device *adev,
                                     struct apr_resp_pkt *data,
                                     int session_id)
@@ -703,6 +713,7 @@ static int32_t q6asm_stream_callback(struct apr_device *adev,
                                goto done;
                        }
                        spin_unlock_irqrestore(&ac->lock, flags);
+                       atomic_set(&port->hw_ptr, token + 1);
                }
                break;
        case ASM_DATA_EVENT_READ_DONE_V2:
@@ -721,6 +732,7 @@ static int32_t q6asm_stream_callback(struct apr_device *adev,
                        }
 
                        phys = port->buf[hdr->token].phys;
+                       atomic_set(&port->hw_ptr, hdr->token + 1);
 
                        if (upper_32_bits(phys) != done->buf_addr_msw ||
                            lower_32_bits(phys) != done->buf_addr_lsw) {
index 519e1b3a3f7c66d5a9c3d3f1c696be05de8f446a..6fafda5bd8498ec33ad046660e2ad14167462af7 100644 (file)
@@ -148,4 +148,5 @@ int q6asm_map_memory_regions(unsigned int dir,
                             phys_addr_t phys,
                             size_t period_sz, unsigned int periods);
 int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac);
+int q6asm_get_hw_pointer(struct audio_client *ac, unsigned int dir);
 #endif /* __Q6_ASM_H__ */