From 4b842e4cd3ca7435bdfe908a78c7549ce33db73f Mon Sep 17 00:00:00 2001 From: "shuai.liu" Date: Tue, 10 Feb 2026 14:31:05 +0800 Subject: [PATCH] audiobridge: adapt audiobridge to kernel6.12 [1/1] PD#SWPL-255895 Problem: The dsp and mailbox interfaces and some kernel api in kernel6.12 have changed and need to be re-adapted. Solution: Merge from kernel5.15 and adapt to kernel6.6 API. Verify: A113X2 AV400 Boards. Change-Id: I43973edb0b14e4f13bfac5ea257185cda48fb2b7 Signed-off-by: shuai.liu --- .../boot/dts/amlogic/a5_a113x2_av400_1g.dts | 50 ++++ .../dts/amlogic/a5_a113x2_av400_1g_spk.dts | 50 ++++ .../boot/dts/amlogic/a5_a113x2_av400v2_1g.dts | 50 ++++ .../boot/dts/amlogic/a5_a113x2_av409_2g.dts | 50 ++++ arch/arm64/boot/dts/amlogic/meson-a5.dtsi | 2 +- drivers/audiobridge/Kconfig | 3 +- drivers/audiobridge/Makefile | 2 +- drivers/audiobridge/bridge_arm_pcm.c | 4 +- drivers/audiobridge/bridge_arm_pcm.h | 2 +- drivers/audiobridge/bridge_audio.c | 101 ++++++-- drivers/audiobridge/bridge_common.h | 14 +- drivers/audiobridge/bridge_dsp_card.c | 44 ++-- drivers/audiobridge/bridge_dsp_card.h | 2 +- drivers/audiobridge/bridge_dsp_pcm.c | 240 ++++++++++++------ drivers/audiobridge/bridge_dsp_pcm.h | 4 +- drivers/audiobridge/bridge_pcm_hal.c | 4 +- drivers/audiobridge/bridge_pcm_hal.h | 2 +- drivers/audiobridge/bridge_ringbuffer.h | 26 -- drivers/audiobridge/bridge_uac_pcm.c | 17 +- drivers/audiobridge/bridge_uac_pcm.h | 2 +- drivers/audiobridge/dsp_client_api.c | 94 +++---- drivers/audiobridge/dsp_client_api.h | 41 +-- .../{bridge_ringbuffer.c => ringbuffer.c} | 26 +- drivers/audiobridge/ringbuffer.h | 26 ++ 24 files changed, 613 insertions(+), 243 deletions(-) delete mode 100644 drivers/audiobridge/bridge_ringbuffer.h rename drivers/audiobridge/{bridge_ringbuffer.c => ringbuffer.c} (78%) create mode 100644 drivers/audiobridge/ringbuffer.h diff --git a/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g.dts b/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g.dts index 456415895..1f261ba0b 100644 --- a/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g.dts +++ b/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g.dts @@ -475,6 +475,56 @@ mask = <4>; }; }; + audiobridge { + compatible = "amlogic, audio-bridge"; + status = "disabled"; + mboxes = <&mbox_fifo A5_REE2DSPA_AUDIO_BRIDGE>; + aml-audio-line,link@0 { + auto-running = <1>; + def-volume = <50>; + isolated = <1>; + src { + /* 0-arm,1-dsp,2-uac */ + core = <1>; + /* 0-none,1-tdma,2-tdmb,3-spdif, + * 4-loopback,5-pdmin,6-process + */ + sound-card = <6>; + channels = <4>; + sample-rate = <48000>; + /* 0-s8,1-s16le,7-s32le */ + format = <1>; + create-vir-card = <1>; + }; + dst { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <16000>; + format = <1>; + }; + }; + aml-audio-line,link@1 { + auto-running = <1>; + def-volume = <100>; + isolated = <1>; + src { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + }; + dst { + core = <1>; + sound-card = <2>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + create-vir-card = <1>; + }; + }; + }; }; &audiobus { diff --git a/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g_spk.dts b/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g_spk.dts index 703721c1d..1dba0d61f 100644 --- a/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g_spk.dts +++ b/arch/arm64/boot/dts/amlogic/a5_a113x2_av400_1g_spk.dts @@ -463,6 +463,56 @@ mask = <4>; }; }; + audiobridge { + compatible = "amlogic, audio-bridge"; + status = "disabled"; + mboxes = <&mbox_fifo A5_REE2DSPA_AUDIO_BRIDGE>; + aml-audio-line,link@0 { + auto-running = <1>; + def-volume = <50>; + isolated = <1>; + src { + /* 0-arm,1-dsp,2-uac */ + core = <1>; + /* 0-none,1-tdma,2-tdmb,3-spdif, + * 4-loopback,5-pdmin,6-process + */ + sound-card = <6>; + channels = <4>; + sample-rate = <48000>; + /* 0-s8,1-s16le,7-s32le */ + format = <1>; + create-vir-card = <1>; + }; + dst { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <16000>; + format = <1>; + }; + }; + aml-audio-line,link@1 { + auto-running = <1>; + def-volume = <100>; + isolated = <1>; + src { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + }; + dst { + core = <1>; + sound-card = <2>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + create-vir-card = <1>; + }; + }; + }; }; &audiobus { diff --git a/arch/arm64/boot/dts/amlogic/a5_a113x2_av400v2_1g.dts b/arch/arm64/boot/dts/amlogic/a5_a113x2_av400v2_1g.dts index 384c41b67..958ede299 100644 --- a/arch/arm64/boot/dts/amlogic/a5_a113x2_av400v2_1g.dts +++ b/arch/arm64/boot/dts/amlogic/a5_a113x2_av400v2_1g.dts @@ -475,6 +475,56 @@ mask = <4>; }; }; + audiobridge { + compatible = "amlogic, audio-bridge"; + status = "disabled"; + mboxes = <&mbox_fifo A5_REE2DSPA_AUDIO_BRIDGE>; + aml-audio-line,link@0 { + auto-running = <1>; + def-volume = <50>; + isolated = <1>; + src { + /* 0-arm,1-dsp,2-uac */ + core = <1>; + /* 0-none,1-tdma,2-tdmb,3-spdif, + * 4-loopback,5-pdmin,6-process + */ + sound-card = <6>; + channels = <4>; + sample-rate = <48000>; + /* 0-s8,1-s16le,7-s32le */ + format = <1>; + create-vir-card = <1>; + }; + dst { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <16000>; + format = <1>; + }; + }; + aml-audio-line,link@1 { + auto-running = <1>; + def-volume = <100>; + isolated = <1>; + src { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + }; + dst { + core = <1>; + sound-card = <2>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + create-vir-card = <1>; + }; + }; + }; }; &audiobus { diff --git a/arch/arm64/boot/dts/amlogic/a5_a113x2_av409_2g.dts b/arch/arm64/boot/dts/amlogic/a5_a113x2_av409_2g.dts index f099c1221..8f7cb473d 100644 --- a/arch/arm64/boot/dts/amlogic/a5_a113x2_av409_2g.dts +++ b/arch/arm64/boot/dts/amlogic/a5_a113x2_av409_2g.dts @@ -481,6 +481,56 @@ mask = <4>; }; }; + audiobridge { + compatible = "amlogic, audio-bridge"; + status = "disabled"; + mboxes = <&mbox_fifo A5_REE2DSPA_AUDIO_BRIDGE>; + aml-audio-line,link@0 { + auto-running = <1>; + def-volume = <50>; + isolated = <1>; + src { + /* 0-arm,1-dsp,2-uac */ + core = <1>; + /* 0-none,1-tdma,2-tdmb,3-spdif, + * 4-loopback,5-pdmin,6-process + */ + sound-card = <6>; + channels = <4>; + sample-rate = <48000>; + /* 0-s8,1-s16le,7-s32le */ + format = <1>; + create-vir-card = <1>; + }; + dst { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <16000>; + format = <1>; + }; + }; + aml-audio-line,link@1 { + auto-running = <1>; + def-volume = <100>; + isolated = <1>; + src { + core = <2>; + sound-card = <0>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + }; + dst { + core = <1>; + sound-card = <2>; + channels = <2>; + sample-rate = <48000>; + format = <1>; + create-vir-card = <1>; + }; + }; + }; }; &i2c3 { diff --git a/arch/arm64/boot/dts/amlogic/meson-a5.dtsi b/arch/arm64/boot/dts/amlogic/meson-a5.dtsi index f7b1fcf88..1e7215522 100644 --- a/arch/arm64/boot/dts/amlogic/meson-a5.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-a5.dtsi @@ -390,7 +390,7 @@ hifidsp0: hifidsp0 { compatible = "amlogic, hifidsp0"; status = "okay"; - startup-position = /bits/ 8 ; /*host dsp start mode : DDR*/ + startup-position = /bits/ 8 ; /*host dsp start mode : DDR*/ memory-region = <&dsp_fw_reserved>; reg-names = "base-reg", "health-reg", diff --git a/drivers/audiobridge/Kconfig b/drivers/audiobridge/Kconfig index 8e5c61a7f..4e0c53aa5 100644 --- a/drivers/audiobridge/Kconfig +++ b/drivers/audiobridge/Kconfig @@ -34,11 +34,12 @@ config AMLOGIC_BRIDGE_HID config AMLOGIC_BRIDGE_DSP bool "audio DSP bridge support" - depends on AMLOGIC_AUDIO_BRIDGE && AMLOGIC_HIFI4DSP + depends on AMLOGIC_BREAK_GKI && AMLOGIC_AUDIO_BRIDGE default n help This is the Amlogic. add dsp audio on bridge. kernel bridge dsp driver. support the amlogic dsp bridge. + #endmenu diff --git a/drivers/audiobridge/Makefile b/drivers/audiobridge/Makefile index 71e112c59..f83a2eeea 100644 --- a/drivers/audiobridge/Makefile +++ b/drivers/audiobridge/Makefile @@ -7,7 +7,7 @@ MODULE_NAME = amlogic-audiobridge obj-$(CONFIG_AMLOGIC_AUDIO_BRIDGE) = $(MODULE_NAME).o $(MODULE_NAME)-y += bridge_audio.o \ - bridge_ringbuffer.o \ + ringbuffer.o \ bridge_pcm_hal.o \ bridge_arm_pcm.o diff --git a/drivers/audiobridge/bridge_arm_pcm.c b/drivers/audiobridge/bridge_arm_pcm.c index 325950c60..81a630cd8 100644 --- a/drivers/audiobridge/bridge_arm_pcm.c +++ b/drivers/audiobridge/bridge_arm_pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/audiobridge/bridge_arm_pcm.h b/drivers/audiobridge/bridge_arm_pcm.h index 893db53ea..47ea0247e 100644 --- a/drivers/audiobridge/bridge_arm_pcm.h +++ b/drivers/audiobridge/bridge_arm_pcm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _BRIDGE_ARM_PCM_H diff --git a/drivers/audiobridge/bridge_audio.c b/drivers/audiobridge/bridge_audio.c index 93154df7a..3e582fd3d 100644 --- a/drivers/audiobridge/bridge_audio.c +++ b/drivers/audiobridge/bridge_audio.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -38,13 +38,13 @@ #include #include #include "bridge_common.h" -#include "bridge_ringbuffer.h" +#include "ringbuffer.h" #include "bridge_pcm_hal.h" +#include #define DRIVER_NAME "audio-bridge" #define PREFIX "aml-audio-line," -#define RING_BUFFER_SIZE (1024 * 10) static struct list_head bridge_devs = LIST_HEAD_INIT(bridge_devs); static ssize_t bridge_enable_show(struct kobject *kobj, @@ -108,8 +108,8 @@ static ssize_t bridge_ringbuf_show(struct kobject *kobj, container_of(attr, struct audio_pcm_bridge_t, ringbuf_attr); if (!bridge) return sprintf(buf, "%s err\n", attr->attr.name); - return sprintf(buf, "size:%d, use:%d free:%d\n", bridge_ring_buffer_len(bridge->rb), - bridge_ring_buffer_used_len(bridge->rb), bridge_ring_buffer_free_len(bridge->rb)); + return sprintf(buf, "size:%d, use:%d free:%d\n", ring_buffer_len(bridge->rb), + ring_buffer_used_len(bridge->rb), ring_buffer_free_len(bridge->rb)); } static ssize_t bridge_isolated_show(struct kobject *kobj, @@ -146,6 +146,47 @@ static ssize_t bridge_isolated_store(struct kobject *kobj, return len; } +static int aml_bridge_pcm_format2bytes(enum PCM_FORMAT format) +{ + int format_bytes = 0; + + switch (format) { + case PCM_FORMAT_S8: + format_bytes = 1; + break; + case PCM_FORMAT_S16_LE: + case PCM_FORMAT_S16_BE: + format_bytes = 2; + break; + case PCM_FORMAT_S24_3LE: + case PCM_FORMAT_S24_3BE: + format_bytes = 3; + break; + case PCM_FORMAT_S24_LE: + case PCM_FORMAT_S24_BE: + case PCM_FORMAT_S32_LE: + case PCM_FORMAT_S32_BE: + format_bytes = 4; + break; + default: + format_bytes = 2; + } + + return format_bytes; +} + +static int aml_bridge_calculate_ring_buffer_size(struct audio_pcm_function_t *pcm_function) +{ + int format_bytes = 0; + + if (!pcm_function) + return -1; + + format_bytes = aml_bridge_pcm_format2bytes(pcm_function->format); + + return pcm_function->channels * format_bytes * PERIOD_SIZE_MAX * PERIOD_COUNT; +} + static struct audio_pcm_function_t *aml_bridge_parse_of(struct device *dev, struct device_node *node, char *name) { @@ -177,6 +218,7 @@ static struct audio_pcm_function_t *aml_bridge_parse_of(struct device *dev, if (enable && audio_p->create_virtual_sound_card) audio_p->create_virtual_sound_card(audio_p); audio_p->enable_create_card = enable; + audio_p->ring_buffer_size = aml_bridge_calculate_ring_buffer_size(audio_p); if (!audio_p->set_hw) goto err_parse1; @@ -184,9 +226,9 @@ static struct audio_pcm_function_t *aml_bridge_parse_of(struct device *dev, if (ret < 0) goto err_parse1; - pr_info("%s [core:%d card:%d] channels:%d rate:%d format:%d create-vir-card:%d\n", + pr_info("%s [core:%d card:%d] channels:%d rate:%d format:%d create virtual card:%d rb size:%d\n", name, core, card, audio_p->channels, - audio_p->rate, audio_p->format, enable); + audio_p->rate, audio_p->format, enable, audio_p->ring_buffer_size); return audio_p; err_parse1: if (enable && audio_p->destroy_virtual_sound_card) @@ -301,6 +343,7 @@ static void bridge_control_work(struct work_struct *data) static int aml_bridge_init(struct device *dev, struct device_node *node, int idx) { + static struct mbox_chan *mbox_chan; int ret = 0; u32 value; struct audio_pcm_bridge_t *bridge; @@ -311,27 +354,29 @@ static int aml_bridge_init(struct device *dev, struct device_node *node, int idx goto err_init0; } bridge->id = idx; - bridge->rb = bridge_ring_buffer_init(RING_BUFFER_SIZE); - if (!bridge->rb) { - ret = -ENOMEM; - goto err_init1; - } bridge->audio_cap = aml_bridge_parse_of(dev, node, "src"); if (!bridge->audio_cap) { ret = -ENOMEM; - goto err_init2; + goto err_init1; } bridge->audio_play = aml_bridge_parse_of(dev, node, "dst"); if (!bridge->audio_play) { ret = -ENOMEM; - goto err_init3; + goto err_init2; } if (!bridge->audio_cap->start || !bridge->audio_play->start) { ret = -EINVAL; - goto err_init4; + goto err_init3; } + + bridge->rb = ring_buffer_init(bridge->audio_cap->ring_buffer_size); + if (!bridge->rb) { + ret = -ENOMEM; + goto err_init3; + } + bridge->audio_cap->rb = bridge->rb; bridge->audio_play->rb = bridge->rb; @@ -345,6 +390,18 @@ static int aml_bridge_init(struct device *dev, struct device_node *node, int idx ret = -EINVAL; goto err_init4; } + + if (!mbox_chan) + mbox_chan = aml_mbox_request_channel_byidx(dev, idx); + if (IS_ERR_OR_NULL(mbox_chan)) { + dev_err(dev, "Not find mailbox channel\n"); + ret = -EINVAL; + goto err_init4; + } + + bridge->audio_cap->mbox_chan = mbox_chan; + bridge->audio_play->mbox_chan = mbox_chan; + ret = of_property_read_u32(node, "isolated", &value); if (ret >= 0 && value) bridge->isolated_enable = true; @@ -383,11 +440,11 @@ err_init6: err_init5: aml_bridge_destroy_attribute(bridge); err_init4: - audio_pcm_free(bridge->audio_play); + ring_buffer_release(bridge->rb); err_init3: - audio_pcm_free(bridge->audio_cap); + audio_pcm_free(bridge->audio_play); err_init2: - bridge_ring_buffer_release(bridge->rb); + audio_pcm_free(bridge->audio_cap); err_init1: vfree(bridge); err_init0: @@ -422,7 +479,7 @@ static int aml_bridge_free(void) cur->audio_play = NULL; } if (cur->rb) { - bridge_ring_buffer_release(cur->rb); + ring_buffer_release(cur->rb); cur->rb = NULL; } vfree(cur); @@ -510,10 +567,10 @@ err_probe1: return ret; } -static int audio_bridge_remove(struct platform_device *pdev) +static void audio_bridge_remove(struct platform_device *pdev) { aml_bridge_free(); - return 0; + return; } static const struct of_device_id audio_bridge_of_match[] = { diff --git a/drivers/audiobridge/bridge_common.h b/drivers/audiobridge/bridge_common.h index c7081897c..8f90234ee 100644 --- a/drivers/audiobridge/bridge_common.h +++ b/drivers/audiobridge/bridge_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _BRIDGE_COMMON_H @@ -8,6 +8,7 @@ #include #include +#include enum PCM_CORE { PCM_ARM = 0, @@ -56,8 +57,18 @@ enum PCM_CONTROL { #define VOLUME_MAX 100 #define VOLUME_MIN 0 +/* dsp use smaller period size for low latency but will cause mailbox will + * communicating too frequently so mailbox should use bigger period size + * arm period size = dsp period size * DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE + */ +#define DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE (1) +#define PERIOD_SIZE_MAX (4096) +#define PERIOD_COUNT (4) +#define DSP_PERIOD_SIZE (1024) + struct audio_pcm_function_t { struct ring_buffer *rb; + u32 ring_buffer_size; enum PCM_CORE coreid; enum PCM_CARD cardid; enum PCM_MODE modeid; @@ -82,6 +93,7 @@ struct audio_pcm_function_t { struct kobject *kobj; struct audio_pcm_function_t *opposite; struct audio_pcm_bridge_t *audio_bridge; + struct mbox_chan *mbox_chan; }; struct audio_pcm_bridge_t { diff --git a/drivers/audiobridge/bridge_dsp_card.c b/drivers/audiobridge/bridge_dsp_card.c index 8961ebdf1..86a2a87b9 100644 --- a/drivers/audiobridge/bridge_dsp_card.c +++ b/drivers/audiobridge/bridge_dsp_card.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include @@ -12,25 +12,26 @@ #include #include "bridge_dsp_card.h" -#define BUFF_SIZE_MAX (PAGE_SIZE * 64) -#define SOUND_CARD_ID 2 +/* + * define pcm hardware buffer capability not real size + * support max period bytes size = 8channels * 4bytes * 2048(period size) + * max buffer size = max period size * period count, real size much smaller than this value + */ +#define PRD_SIZE_MAX (PAGE_SIZE * 64) +#define BUFF_SIZE_MAX (PRD_SIZE_MAX * 4) +#define SOUND_CARD_ID (2) + struct aml_aprocess_card *aprocess_card; unsigned int dsp_pcm_num; static struct snd_pcm_hardware aml_aprocess_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 16000, - .rate_max = 16000, - .channels_min = 2, - .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, .buffer_bytes_max = BUFF_SIZE_MAX, - .period_bytes_max = 1024, - .period_bytes_min = 1024, - .periods_min = 4, - .periods_max = 4, - .fifo_size = 0, + .period_bytes_max = PRD_SIZE_MAX, + .periods_min = BUFF_SIZE_MAX / PRD_SIZE_MAX, + .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX, }; void aml_aprocess_set_hw(struct aml_aprocess *p_aprocess, int channels, @@ -41,7 +42,7 @@ void aml_aprocess_set_hw(struct aml_aprocess *p_aprocess, int channels, p_aprocess->g_hw.rate_min = rate; p_aprocess->g_hw.rate_max = rate; p_aprocess->g_hw.channels_min = channels; - p_aprocess->g_hw.channels_min = channels; + p_aprocess->g_hw.channels_max = channels; p_aprocess->g_hw.formats = format; if (format == SNDRV_PCM_FMTBIT_S8) p_aprocess->g_hw.period_bytes_min = channels * period; @@ -51,11 +52,6 @@ void aml_aprocess_set_hw(struct aml_aprocess *p_aprocess, int channels, p_aprocess->g_hw.period_bytes_min = 4 * channels * period; else p_aprocess->g_hw.period_bytes_min = 2 * channels * period; - - p_aprocess->g_hw.period_bytes_max = p_aprocess->g_hw.period_bytes_min; - p_aprocess->g_hw.period_bytes_max = p_aprocess->g_hw.period_bytes_min; - - p_aprocess->g_hw.buffer_bytes_max = 16 * p_aprocess->g_hw.period_bytes_max; } int aml_aprocess_complete(struct aml_aprocess *p_aprocess, char *out, int size) @@ -90,10 +86,6 @@ int aml_aprocess_complete(struct aml_aprocess *p_aprocess, char *out, int size) pending = runtime->dma_bytes - hw_ptr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (!snd_pcm_playback_hw_avail(runtime)) { - snd_pcm_stream_unlock_irqrestore(substream, flags2); - goto fail; - } if (unlikely(pending < size)) { memcpy(out, runtime->dma_area + hw_ptr, pending); memcpy(out + pending, runtime->dma_area, @@ -103,10 +95,6 @@ int aml_aprocess_complete(struct aml_aprocess *p_aprocess, char *out, int size) size); } } else { - if (!snd_pcm_capture_hw_avail(runtime)) { - snd_pcm_stream_unlock_irqrestore(substream, flags2); - goto fail; - } if (unlikely(pending < size)) { memcpy(runtime->dma_area + hw_ptr, out, pending); memcpy(runtime->dma_area, out + pending, @@ -274,7 +262,7 @@ struct aml_aprocess *aml_aprocess_init(struct device *dev, const char *pcm_name, sprintf(card->longname, "%s %i", card_name, card->dev->id); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX); + NULL, 0, BUFF_SIZE_MAX); err = snd_card_register(card); if (err < 0) diff --git a/drivers/audiobridge/bridge_dsp_card.h b/drivers/audiobridge/bridge_dsp_card.h index ba2bda849..e3e7fcb38 100644 --- a/drivers/audiobridge/bridge_dsp_card.h +++ b/drivers/audiobridge/bridge_dsp_card.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _BRIDGE_DSP_CARD_H_ diff --git a/drivers/audiobridge/bridge_dsp_pcm.c b/drivers/audiobridge/bridge_dsp_pcm.c index c27617c1d..2445ff28d 100644 --- a/drivers/audiobridge/bridge_dsp_pcm.c +++ b/drivers/audiobridge/bridge_dsp_pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,7 +35,7 @@ #include #include #include -#include "../hifi4dsp/hifi4dsp_priv.h" +#include "../host/host.h" #include "bridge_common.h" #include @@ -43,22 +43,24 @@ #include #include #include +#include +#include -#include "bridge_ringbuffer.h" +#include "ringbuffer.h" #include "dsp_client_api.h" #include "bridge_pcm_hal.h" #include "bridge_dsp_card.h" -#define COERID SCPI_DSPA +#define SCPI_DSPA 0 +#define COREID SCPI_DSPA +#define MBOX_SYNC 2 -#define DSP_PARAM_CARD 0 -#define PCM_PARAM_PERIOD_SIZE 1024 +#define LOOPBACK_CHANNELS (2) +#define DSP_PARAM_CARD 2 #define GAIN_MAX 0 #define GAIN_MIN -40 -// extern struct hifi4dsp_priv *hifi4dsp_p[HIFI4DSP_MAX_CNT]; - struct dsp_pcm_param { u8 card; u32 device; @@ -72,8 +74,10 @@ struct dsp_pcm_t { void *pcm_handle; struct device *dev; struct task_struct *thread_handle; + struct task_struct *aux_thread_handle; struct dsp_pcm_param pcm_param; struct mutex lock; /* lock to protect dsp bridge data*/ + struct completion complete; struct aml_aprocess *aprocess; u8 speaker_process_flag; u8 run_flag; @@ -137,8 +141,7 @@ static ssize_t bridge_capture_volume_ctr_show(struct kobject *kobj, { struct dsp_pcm_t *dsp_pcm; - if (!hifi4dsp_p[COERID] || - !hifi4dsp_p[COERID]->dsp || !hifi4dsp_p[COERID]->dsp->dspstarted) + if (!host_firmware_ready(COREID)) return 0; if (!cap_pcm || !cap_pcm->private_data) { @@ -154,7 +157,7 @@ static ssize_t bridge_capture_volume_ctr_show(struct kobject *kobj, mutex_lock(&dsp_pcm->lock); if (dsp_pcm->run_flag && dsp_pcm->pcm_handle) pcm_process_client_get_volume_gain(dsp_pcm->pcm_handle, &dsp_pcm->db_gain, - PCM_CAPTURE, cap_pcm->dev, COERID); + PCM_CAPTURE, cap_pcm->mbox_chan, MBOX_SYNC); mutex_unlock(&dsp_pcm->lock); return sprintf(buf, "Volume: %d\nMuteState: %d\n(Volume-Down:%ld, Volume-Up:%ld, Volume-Mute:%ld)\n", @@ -171,8 +174,7 @@ static ssize_t bridge_capture_volume_ctr_store(struct kobject *kobj, if (ret < 0) pr_err("%s err!", __func__); - if (!hifi4dsp_p[COERID] || - !hifi4dsp_p[COERID]->dsp || !hifi4dsp_p[COERID]->dsp->dspstarted) + if (!host_firmware_ready(COREID)) return len; if (!cap_pcm || !cap_pcm->private_data) { @@ -218,7 +220,7 @@ static ssize_t bridge_capture_volume_ctr_store(struct kobject *kobj, mutex_lock(&dsp_pcm->lock); if (dsp_pcm->run_flag && dsp_pcm->pcm_handle) pcm_process_client_set_volume_gain(dsp_pcm->pcm_handle, dsp_pcm->db_gain, - PCM_CAPTURE, cap_pcm->dev, COERID); + PCM_CAPTURE, cap_pcm->mbox_chan, MBOX_SYNC); mutex_unlock(&dsp_pcm->lock); return len; @@ -231,8 +233,7 @@ static ssize_t bridge_playback_process_ctr_show(struct kobject *kobj, { struct dsp_pcm_t *dsp_pcm; - if (!hifi4dsp_p[COERID] || - !hifi4dsp_p[COERID]->dsp || !hifi4dsp_p[COERID]->dsp->dspstarted) + if (!host_firmware_ready(COREID)) return 0; if (!play_pcm || !play_pcm->private_data) { @@ -258,8 +259,7 @@ static ssize_t bridge_playback_process_ctr_store(struct kobject *kobj, if (ret < 0) pr_err("%s err!", __func__); - if (!hifi4dsp_p[COERID] || - !hifi4dsp_p[COERID]->dsp || !hifi4dsp_p[COERID]->dsp->dspstarted) + if (!host_firmware_ready(COREID)) return len; if (!play_pcm || !play_pcm->private_data) { @@ -278,6 +278,62 @@ static ssize_t bridge_playback_process_ctr_store(struct kobject *kobj, static struct kobj_attribute attr_bridge_playback_process_ctr = __ATTR_RW(bridge_playback_process_ctr); +static int thread_capture_complete(void *data) +{ + struct audio_pcm_function_t *info = data; + struct dsp_pcm_t *dsp_pcm = (struct dsp_pcm_t *)info->private_data; + struct rpc_pcm_config pconfig; + u32 read_size = 0, expected_sleep_us = 0, real_sleep_us = 0; + u32 wait_timeout = 0; + char *buf = NULL; + + pconfig.channels = dsp_pcm->pcm_param.channels; + pconfig.rate = dsp_pcm->pcm_param.rate; + pconfig.format = dsp_pcm->pcm_param.format; + pconfig.period_size = DSP_PERIOD_SIZE; + + expected_sleep_us = 1000 * 1000 * pconfig.period_size * + DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE / pconfig.rate; + wait_timeout = expected_sleep_us * 5; + + /* + * Ensure that the ringbuffer consumption + * speed is greater than the production speed + */ + if (pconfig.period_size < 1024) + real_sleep_us = expected_sleep_us - 300; + else + real_sleep_us = expected_sleep_us * 63 / 64; + + read_size = pconfig.period_size * (pconfig.channels - LOOPBACK_CHANNELS) * + pcm_client_format_to_bytes(pconfig.format) * + DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE; + + buf = vmalloc(read_size); + if (!buf) { + vfree(buf); + pr_err("vmalloc failed\n"); + return -1; + } + memset(buf, 0, read_size); + + while (dsp_pcm->run_flag && !kthread_should_stop()) { + if (!wait_for_completion_timeout(&dsp_pcm->complete, + usecs_to_jiffies(wait_timeout))) + continue; + + if (!no_thread_safe_ring_buffer_get(info->rb, buf, read_size)) { + usleep_range(expected_sleep_us / 2, expected_sleep_us); + } else { + aml_aprocess_complete(dsp_pcm->aprocess, buf, read_size); + usleep_range(real_sleep_us - 200, real_sleep_us); + } + } + vfree(buf); + + return 0; +} + static int thread_capture(void *data) { struct audio_pcm_function_t *info = (struct audio_pcm_function_t *)data; @@ -286,52 +342,67 @@ static int thread_capture(void *data) unsigned int size; struct rpc_pcm_config pconfig; struct buf_info buf; + struct device *dev; + u32 read_size = 0, sleep_us = 0; if (!info || !info->private_data) return -EINVAL; dsp_pcm = (struct dsp_pcm_t *)info->private_data; - while (!hifi4dsp_p[COERID] || !hifi4dsp_p[COERID]->dsp || - !hifi4dsp_p[COERID]->dsp->dspstarted) { + while (!host_firmware_ready(COREID)) { if (!dsp_pcm->run_flag || kthread_should_stop()) return -EINVAL; msleep(100); } msleep(100); + dev = host_to_device(COREID); + if (!dev) + return -EINVAL; memset(&buf, 0, sizeof(buf)); pconfig.channels = dsp_pcm->pcm_param.channels; pconfig.rate = dsp_pcm->pcm_param.rate; pconfig.format = dsp_pcm->pcm_param.format; - pconfig.period_size = dsp_pcm->pcm_param.period_size; + pconfig.period_size = DSP_PERIOD_SIZE; + pconfig.period_count = PERIOD_COUNT; + sleep_us = 1000 * 1000 * pconfig.period_size * + DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE / pconfig.rate / 3; + read_size = pconfig.period_size * (pconfig.channels - LOOPBACK_CHANNELS) * + pcm_client_format_to_bytes(pconfig.format) * + DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE; dsp_pcm->pcm_handle = audio_device_open(dsp_pcm->pcm_param.card, dsp_pcm->pcm_param.device, - PCM_IN, &pconfig, info->dev, COERID); + PCM_IN, &pconfig, info->mbox_chan, MBOX_SYNC); if (!dsp_pcm->pcm_handle) { - pr_err("can't open lbpcm device!\n"); + pr_err("can't open libpcm device!\n"); return -ENXIO; } pcm_process_client_set_volume_gain(dsp_pcm->pcm_handle, dsp_pcm->db_gain, - PCM_CAPTURE, info->dev, COERID); + PCM_CAPTURE, info->mbox_chan, MBOX_SYNC); while (dsp_pcm->run_flag && !kthread_should_stop()) { + buf.size = read_size; size = pcm_process_client_dqbuf(dsp_pcm->pcm_handle, &buf, &buf, - PROCESSBUF, info->dev, COERID); + PROCESSBUF, info->mbox_chan, MBOX_SYNC); if (buf.size) { dma_sync_single_for_device - (hifi4dsp_p[COERID]->dsp->dev, + (dev, (phys_addr_t)buf.phyaddr, buf.size, DMA_FROM_DEVICE); - aml_aprocess_complete(dsp_pcm->aprocess, buf.viraddr, buf.size); + if (dsp_pcm->aprocess->status && bridge->isolated_enable) { + no_thread_safe_ring_buffer_put(info->rb, buf.viraddr, buf.size); + complete(&dsp_pcm->complete); + //aml_aprocess_complete(dsp_pcm->aprocess, buf.viraddr, buf.size); + } + if (!bridge->isolated_enable) - bridge_ring_buffer_put(info->rb, buf.viraddr, buf.size); + no_thread_safe_ring_buffer_put(info->rb, buf.viraddr, buf.size); } else { - usleep_range(0, 5000); + usleep_range(sleep_us, sleep_us * 2); } } - - pcm_process_client_close(dsp_pcm->pcm_handle, info->dev, COERID); + pcm_process_client_close(dsp_pcm->pcm_handle, info->mbox_chan, MBOX_SYNC); dsp_pcm->run_flag = 0; return 0; } @@ -341,68 +412,78 @@ static int thread_playback(void *data) struct audio_pcm_function_t *info = (struct audio_pcm_function_t *)data; struct audio_pcm_bridge_t *bridge = info->audio_bridge; struct dsp_pcm_t *dsp_pcm; - u32 size_one_shot; - phys_addr_t shmm_phy = 0; - void *shmm_vir = NULL; struct rpc_pcm_config pconfig; + struct buf_info buf; + struct device *dev; + u32 send_size = 0, sleep_us = 0; if (!info || !info->private_data) return -EINVAL; dsp_pcm = (struct dsp_pcm_t *)info->private_data; - while (!hifi4dsp_p[COERID] || !hifi4dsp_p[COERID]->dsp || - !hifi4dsp_p[COERID]->dsp->dspstarted) { + while (!host_firmware_ready(COREID)) { if (!dsp_pcm->run_flag || kthread_should_stop()) return -EINVAL; msleep(100); } msleep(100); + dev = host_to_device(COREID); + if (!dev) + return -EINVAL; + + memset(&buf, 0, sizeof(buf)); pconfig.channels = dsp_pcm->pcm_param.channels; pconfig.rate = dsp_pcm->pcm_param.rate; pconfig.format = dsp_pcm->pcm_param.format; - pconfig.period_size = dsp_pcm->pcm_param.period_size; + pconfig.period_size = DSP_PERIOD_SIZE; + pconfig.period_count = PERIOD_COUNT; + send_size = pconfig.period_size * pconfig.channels * + pcm_client_format_to_bytes(pconfig.format) * DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE; + buf.size = send_size; + sleep_us = 1000 * 1000 * pconfig.period_size * + DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE / pconfig.rate / 3; pr_info("open playback device!\n"); dsp_pcm->pcm_handle = audio_device_open(dsp_pcm->pcm_param.card, dsp_pcm->pcm_param.device, - PCM_OUT, &pconfig, info->dev, COERID); + PCM_OUT, &pconfig, info->mbox_chan, MBOX_SYNC); if (!dsp_pcm->pcm_handle) { pr_err("can't open playback device!\n"); return -ENXIO; } - pr_info("malloc share mm!\n"); - size_one_shot = pcm_client_frame_to_bytes(dsp_pcm->pcm_handle, pconfig.period_size); - shmm_vir = aml_dsp_mem_allocate(&shmm_phy, size_one_shot, info->dev, COERID); - if (!shmm_vir || !shmm_phy) { - pcm_client_close(dsp_pcm->pcm_handle, info->dev, COERID); - pr_err("can't malloc share memory---size:%d!\n", size_one_shot); - return -ENOMEM; - } - bridge_ring_buffer_go_empty(info->rb); + pr_info("get share mm!\n"); + /* first call qbuf for get ready buffer address */ + pcm_process_client_qbuf(dsp_pcm->pcm_handle, &buf, + RAWBUF, info->mbox_chan, MBOX_SYNC); + + ring_buffer_go_empty(info->rb); pcm_process_client_set_volume_gain(dsp_pcm->pcm_handle, dsp_pcm->db_gain, - PCM_PLAYBACK, dsp_pcm->dev, COERID); + PCM_PLAYBACK, info->mbox_chan, MBOX_SYNC); while (dsp_pcm->run_flag && !kthread_should_stop()) { if (bridge->isolated_enable) { - if (!aml_aprocess_complete(dsp_pcm->aprocess, shmm_vir, size_one_shot)) - memset(shmm_vir, 0, size_one_shot); + if (!dsp_pcm->aprocess->status) { + usleep_range(sleep_us, sleep_us * 2); + continue; + } + if (!aml_aprocess_complete(dsp_pcm->aprocess, buf.viraddr, buf.size)) { + usleep_range(sleep_us, sleep_us * 2); + continue; + } } else { - if (!bridge_ring_buffer_get(info->rb, shmm_vir, size_one_shot)) - memset(shmm_vir, 0, size_one_shot); + if (!no_thread_safe_ring_buffer_get(info->rb, buf.viraddr, buf.size)) + memset(buf.viraddr, 0, buf.size); } dma_sync_single_for_device - (hifi4dsp_p[COERID]->dsp->dev, - (phys_addr_t)shmm_phy, - size_one_shot, + (dev, + (phys_addr_t)buf.phyaddr, + buf.size, DMA_TO_DEVICE); - pcm_process_client_writei_to_speaker(dsp_pcm->pcm_handle, shmm_phy, - pconfig.period_size, !dsp_pcm->speaker_process_flag, - info->dev, COERID); + buf.size = send_size; + pcm_process_client_qbuf(dsp_pcm->pcm_handle, &buf, + RAWBUF, info->mbox_chan, MBOX_SYNC); } - pcm_client_close(dsp_pcm->pcm_handle, info->dev, COERID); - aml_dsp_mem_free(shmm_phy, info->dev, COERID); - shmm_phy = 0; - shmm_vir = NULL; + pcm_process_client_close(dsp_pcm->pcm_handle, info->mbox_chan, MBOX_SYNC); dsp_pcm->run_flag = 0; return 0; } @@ -411,6 +492,7 @@ static int dsp_pcm_start(struct audio_pcm_function_t *audio_pcm) { int rc = 0; struct dsp_pcm_t *dsp_pcm; + struct sched_param param = { .sched_priority = 99 }; if (!audio_pcm || !audio_pcm->private_data) { pr_err("the bridge info is NULL!\n"); @@ -431,10 +513,18 @@ static int dsp_pcm_start(struct audio_pcm_function_t *audio_pcm) } dsp_pcm->run_flag = 1; - if (audio_pcm->modeid == PCM_CAPTURE) + if (audio_pcm->modeid == PCM_CAPTURE) { dsp_pcm->thread_handle = kthread_run(thread_capture, audio_pcm, "dsp_cap"); - else + dsp_pcm->aux_thread_handle = kthread_run(thread_capture_complete, + audio_pcm, "dsp_cap_complete"); + sched_setscheduler(dsp_pcm->thread_handle, SCHED_FIFO, ¶m); + sched_setscheduler(dsp_pcm->aux_thread_handle, SCHED_FIFO, ¶m); + } else { dsp_pcm->thread_handle = kthread_run(thread_playback, audio_pcm, "dsp_play"); + dsp_pcm->aux_thread_handle = NULL; + sched_setscheduler(dsp_pcm->thread_handle, SCHED_FIFO, ¶m); + } + if (IS_ERR(dsp_pcm->thread_handle)) { dsp_pcm->thread_handle = NULL; dsp_pcm->run_flag = 0; @@ -461,6 +551,10 @@ static int dsp_pcm_stop(struct audio_pcm_function_t *audio_pcm) mutex_lock(&dsp_pcm->lock); dsp_pcm->run_flag = 0; + if (dsp_pcm->aux_thread_handle) { + kthread_stop(dsp_pcm->aux_thread_handle); + dsp_pcm->aux_thread_handle = NULL; + } if (dsp_pcm->thread_handle) { kthread_stop(dsp_pcm->thread_handle); dsp_pcm->thread_handle = NULL; @@ -498,12 +592,13 @@ static int dsp_pcm_set_hw(struct audio_pcm_function_t *audio_pcm, u8 channels, u alsa_format = SNDRV_PCM_FMTBIT_S16; break; } + if (audio_pcm->modeid == PCM_CAPTURE) - aml_aprocess_set_hw(dsp_pcm->aprocess, (channels - 2), - alsa_format, 16000, PCM_PARAM_PERIOD_SIZE); + aml_aprocess_set_hw(dsp_pcm->aprocess, (channels - LOOPBACK_CHANNELS), + alsa_format, rate, DSP_PERIOD_SIZE * DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE); else aml_aprocess_set_hw(dsp_pcm->aprocess, channels, - alsa_format, rate, PCM_PARAM_PERIOD_SIZE); + alsa_format, rate, DSP_PERIOD_SIZE * DSP_PERIOD_SIZE_TO_ARM_PERIOD_SIZE); return 0; } @@ -585,14 +680,13 @@ static void dsp_pcm_control(struct audio_pcm_function_t *audio_pcm, int cmd, int dsp_pcm->db_gain = -48; } - if (!hifi4dsp_p[COERID] || - !hifi4dsp_p[COERID]->dsp || !hifi4dsp_p[COERID]->dsp->dspstarted) + if (!host_firmware_ready(COREID)) return; mutex_lock(&dsp_pcm->lock); if (dsp_pcm->run_flag && dsp_pcm->pcm_handle) pcm_process_client_set_volume_gain(dsp_pcm->pcm_handle, dsp_pcm->db_gain, - audio_pcm->modeid, dsp_pcm->dev, COERID); + audio_pcm->modeid, audio_pcm->mbox_chan, MBOX_SYNC); mutex_unlock(&dsp_pcm->lock); } @@ -615,8 +709,7 @@ int dsp_pcm_init(struct audio_pcm_function_t *audio_pcm, return -EINVAL; } dsp_pcm->dev = audio_pcm->dev; - dsp_pcm->pcm_param.card = DSP_PARAM_CARD; - dsp_pcm->pcm_param.period_size = PCM_PARAM_PERIOD_SIZE; + dsp_pcm->pcm_param.card = pcm_card; dsp_pcm->volume = VOLUME_MAX; dsp_pcm->mute = 0; dsp_pcm->db_gain = dsp_pcm->volume * (GAIN_MAX - GAIN_MIN) / @@ -636,6 +729,7 @@ int dsp_pcm_init(struct audio_pcm_function_t *audio_pcm, else play_pcm = audio_pcm; mutex_init(&dsp_pcm->lock); + init_completion(&dsp_pcm->complete); return 0; } diff --git a/drivers/audiobridge/bridge_dsp_pcm.h b/drivers/audiobridge/bridge_dsp_pcm.h index 15c518136..df6d48256 100644 --- a/drivers/audiobridge/bridge_dsp_pcm.h +++ b/drivers/audiobridge/bridge_dsp_pcm.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _BRIDGE_DSP_PCM_H #define _BRIDGE_DSP_PCM_H #include "bridge_common.h" -#include "bridge_ringbuffer.h" +#include "ringbuffer.h" int dsp_pcm_init(struct audio_pcm_function_t *audio_pcm, enum PCM_CARD pcm_card, enum PCM_MODE mode); diff --git a/drivers/audiobridge/bridge_pcm_hal.c b/drivers/audiobridge/bridge_pcm_hal.c index d840d6678..39912ddd2 100644 --- a/drivers/audiobridge/bridge_pcm_hal.c +++ b/drivers/audiobridge/bridge_pcm_hal.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/audiobridge/bridge_pcm_hal.h b/drivers/audiobridge/bridge_pcm_hal.h index aa12f3084..0ab0bb8ba 100644 --- a/drivers/audiobridge/bridge_pcm_hal.h +++ b/drivers/audiobridge/bridge_pcm_hal.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _BRIDGE_PCM_HAL_H diff --git a/drivers/audiobridge/bridge_ringbuffer.h b/drivers/audiobridge/bridge_ringbuffer.h deleted file mode 100644 index 93b52d4ee..000000000 --- a/drivers/audiobridge/bridge_ringbuffer.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ -/* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. - */ - -#ifndef _USER_BRIDGE_RING_BUFFER_H -#define _USER_BRIDGE_RING_BUFFER_H - -struct ring_buffer { - void *buffer; - u32 size; - u32 in; - u32 out; - u8 go_empty; -}; - -struct ring_buffer *bridge_ring_buffer_init(u32 size); -int bridge_ring_buffer_release(struct ring_buffer *ring_buf); -u32 bridge_ring_buffer_len(const struct ring_buffer *ring_buf); -u32 bridge_ring_buffer_used_len(const struct ring_buffer *ring_buf); -u32 bridge_ring_buffer_free_len(const struct ring_buffer *ring_buf); -u32 bridge_ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, u32 size); -u32 bridge_ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, u32 size); -u32 bridge_ring_buffer_go_empty(struct ring_buffer *ring_buf); - -#endif diff --git a/drivers/audiobridge/bridge_uac_pcm.c b/drivers/audiobridge/bridge_uac_pcm.c index 25566322a..dafa8b345 100644 --- a/drivers/audiobridge/bridge_uac_pcm.c +++ b/drivers/audiobridge/bridge_uac_pcm.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ #endif #include "bridge_common.h" -#include "bridge_ringbuffer.h" +#include "ringbuffer.h" #include "bridge_pcm_hal.h" struct uac_pcm_t { @@ -187,7 +187,7 @@ int uac_pcm_start_playback(void) return 0; uac_pcm->uac_status = 1; - return bridge_ring_buffer_go_empty(audio_pcm->rb); + return ring_buffer_go_empty(audio_pcm->rb); } int uac_pcm_stop_playback(void) @@ -202,7 +202,7 @@ int uac_pcm_stop_playback(void) return 0; uac_pcm->uac_status = 0; - return bridge_ring_buffer_go_empty(audio_pcm->rb); + return ring_buffer_go_empty(audio_pcm->rb); } int uac_pcm_write_data(char *buf, unsigned int size) @@ -220,7 +220,7 @@ int uac_pcm_write_data(char *buf, unsigned int size) if (bridge->isolated_enable) return 0; else - return bridge_ring_buffer_put(audio_pcm->rb, buf, size); + return no_thread_safe_ring_buffer_put(audio_pcm->rb, buf, size); } int uac_pcm_read_data(char *buf, unsigned int size) @@ -238,7 +238,7 @@ int uac_pcm_read_data(char *buf, unsigned int size) if (bridge->isolated_enable) return 0; else - return bridge_ring_buffer_get(audio_pcm->rb, buf, size); + return no_thread_safe_ring_buffer_get(audio_pcm->rb, buf, size); } int uac_pcm_ctl_capture(int cmd, int value) @@ -350,9 +350,12 @@ static int uac_pcm_set_hw(struct audio_pcm_function_t *audio_pcm, static int uac_pcm_get_status(struct audio_pcm_function_t *audio_pcm) { struct uac_pcm_t *uac_pcm; + struct audio_pcm_bridge_t *bridge; - if (!audio_pcm || !audio_pcm->private_data) + bridge = audio_pcm->audio_bridge; + if (!audio_pcm || !audio_pcm->private_data || bridge->isolated_enable) return 0; + uac_pcm = audio_pcm->private_data; return uac_pcm->run_flag; diff --git a/drivers/audiobridge/bridge_uac_pcm.h b/drivers/audiobridge/bridge_uac_pcm.h index 25dd5060a..468164d7c 100644 --- a/drivers/audiobridge/bridge_uac_pcm.h +++ b/drivers/audiobridge/bridge_uac_pcm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _BRIDGE_UAC_PCM_H diff --git a/drivers/audiobridge/dsp_client_api.c b/drivers/audiobridge/dsp_client_api.c index 7b529163b..b10a31b83 100644 --- a/drivers/audiobridge/dsp_client_api.c +++ b/drivers/audiobridge/dsp_client_api.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include @@ -9,18 +9,21 @@ #include #include #include "dsp_client_api.h" +#include "bridge_common.h" +#include -int Mbox_invoke(struct device *dev, u32 dspid, int cmd, void *data, u32 len) +int Mbox_invoke(struct mbox_chan *chan, u32 sync, int cmd, void *data, u32 len) { int ret = 0; - ret = mbox_message_send_data_sync(dev, cmd, data, len, dspid); + ret = aml_mbox_transfer_data(chan, cmd, data, len, data, len, sync); if (ret < 0) - dev_err(dev, "Mbox invoke write error: %d\n", ret); + pr_err("Mbox invoke write error: %d\n", ret); + return ret; } -static u32 pcm_client_format_to_bytes(enum DSP_PCM_FORMAT format) +u32 pcm_client_format_to_bytes(enum DSP_PCM_FORMAT format) { switch (format) { case DSP_PCM_FORMAT_S32_LE: @@ -49,7 +52,7 @@ u32 pcm_client_frame_to_bytes(void *hdl, u32 frame) } void *pcm_client_open(u32 card, u32 device, u32 flags, struct rpc_pcm_config *config, - struct device *dev, u32 dspid) + struct mbox_chan *chan, u32 sync) { struct pcm_open_st arg; struct aml_pcm_ctx *p_aml_pcm_ctx = kmalloc(sizeof(*p_aml_pcm_ctx), GFP_KERNEL); @@ -62,7 +65,7 @@ void *pcm_client_open(u32 card, u32 device, u32 flags, struct rpc_pcm_config *co memcpy(&arg.pcm_config, config, sizeof(struct rpc_pcm_config)); arg.out_pcm = 0; - Mbox_invoke(dev, dspid, MBX_TINYALSA_OPEN, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_TINYALSA_OPEN, &arg, sizeof(arg)); if (!arg.out_pcm) { kfree(p_aml_pcm_ctx); return NULL; @@ -72,7 +75,7 @@ void *pcm_client_open(u32 card, u32 device, u32 flags, struct rpc_pcm_config *co return p_aml_pcm_ctx; } -int pcm_client_close(void *hdl, struct device *dev, u32 dspid) +int pcm_client_close(void *hdl, struct mbox_chan *chan, u32 sync) { struct pcm_close_st arg; struct aml_pcm_ctx *p_aml_pcm_ctx = (struct aml_pcm_ctx *)hdl; @@ -81,14 +84,14 @@ int pcm_client_close(void *hdl, struct device *dev, u32 dspid) arg.pcm = p_aml_pcm_ctx->pcm_srv_hdl; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, MBX_TINYALSA_CLOSE, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_TINYALSA_CLOSE, &arg, sizeof(arg)); kfree(p_aml_pcm_ctx); return arg.out_ret; } int pcm_client_writei(void *hdl, const phys_addr_t data, u32 count, - struct device *dev, u32 dspid) + struct mbox_chan *chan, u32 sync) { struct pcm_io_st arg; struct aml_pcm_ctx *p_aml_pcm_ctx = (struct aml_pcm_ctx *)hdl; @@ -99,13 +102,13 @@ int pcm_client_writei(void *hdl, const phys_addr_t data, u32 count, arg.count = count; arg.out_ret = 0; - Mbox_invoke(dev, dspid, MBX_TINYALSA_WRITEI, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_TINYALSA_WRITEI, &arg, sizeof(arg)); return arg.out_ret; } int pcm_process_client_writei_to_speaker(void *hdl, const phys_addr_t data, u32 count, - u32 bypass, struct device *dev, u32 dspid) + u32 bypass, struct mbox_chan *chan, u32 sync) { struct pcm_process_io_st arg; struct aml_pcm_ctx *p_aml_pcm_ctx = (struct aml_pcm_ctx *)hdl; @@ -117,13 +120,13 @@ int pcm_process_client_writei_to_speaker(void *hdl, const phys_addr_t data, u32 arg.out_ret = 0; arg.id = bypass; - Mbox_invoke(dev, dspid, MBX_CMD_APROCESS_WRITE_SPEAKER, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_APROCESS_WRITE_SPEAKER, &arg, sizeof(arg)); return arg.out_ret; } int pcm_client_readi(void *hdl, const phys_addr_t data, u32 count, - struct device *dev, u32 dspid) + struct mbox_chan *chan, u32 sync) { struct pcm_io_st arg; struct aml_pcm_ctx *p_aml_pcm_ctx = (struct aml_pcm_ctx *)hdl; @@ -134,13 +137,13 @@ int pcm_client_readi(void *hdl, const phys_addr_t data, u32 count, arg.count = count; arg.out_ret = 0; - Mbox_invoke(dev, dspid, MBX_TINYALSA_READI, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_TINYALSA_READI, &arg, sizeof(arg)); return arg.out_ret; } void *pcm_process_client_open(u32 card, u32 device, u32 flags, - struct rpc_pcm_config *config, struct device *dev, u32 dspid) + struct rpc_pcm_config *config, struct mbox_chan *chan, u32 sync) { struct pcm_process_open_st arg; struct aml_pro_pcm_ctx *p_aml_pcm_ctx = kmalloc(sizeof(*p_aml_pcm_ctx), GFP_KERNEL); @@ -153,7 +156,7 @@ void *pcm_process_client_open(u32 card, u32 device, u32 flags, memcpy(&arg.pcm_config, config, sizeof(struct rpc_pcm_config)); arg.out_pcm = 0; - Mbox_invoke(dev, dspid, MBX_CMD_APROCESS_OPEN, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_APROCESS_OPEN, &arg, sizeof(arg)); if (!arg.out_pcm) { kfree(p_aml_pcm_ctx); return NULL; @@ -163,7 +166,7 @@ void *pcm_process_client_open(u32 card, u32 device, u32 flags, return p_aml_pcm_ctx; } -int pcm_process_client_close(void *hdl, struct device *dev, u32 dspid) +int pcm_process_client_close(void *hdl, struct mbox_chan *chan, u32 sync) { struct pcm_process_close_st arg; struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; @@ -172,13 +175,13 @@ int pcm_process_client_close(void *hdl, struct device *dev, u32 dspid) arg.pcm = p_aml_pcm_ctx->pcm_srv_hdl; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, MBX_CMD_APROCESS_CLOSE, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_APROCESS_CLOSE, &arg, sizeof(arg)); kfree(p_aml_pcm_ctx); return arg.out_ret; } -int pcm_process_client_start(void *hdl, struct device *dev, u32 dspid) +int pcm_process_client_start(void *hdl, struct mbox_chan *chan, u32 sync) { struct pcm_process_io_st arg; struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; @@ -187,12 +190,12 @@ int pcm_process_client_start(void *hdl, struct device *dev, u32 dspid) arg.pcm = p_aml_pcm_ctx->pcm_srv_hdl; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, MBX_CMD_APROCESS_START, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_APROCESS_START, &arg, sizeof(arg)); return arg.out_ret; } -int pcm_process_client_stop(void *hdl, struct device *dev, u32 dspid) +int pcm_process_client_stop(void *hdl, struct mbox_chan *chan, u32 sync) { struct pcm_process_io_st arg; struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; @@ -201,13 +204,13 @@ int pcm_process_client_stop(void *hdl, struct device *dev, u32 dspid) arg.pcm = p_aml_pcm_ctx->pcm_srv_hdl; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, MBX_CMD_APROCESS_STOP, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_APROCESS_STOP, &arg, sizeof(arg)); return arg.out_ret; } int pcm_process_client_dqbuf(void *hdl, struct buf_info *buf, struct buf_info *release_buf, - u32 type, struct device *dev, u32 dspid) + u32 type, struct mbox_chan *chan, u32 sync) { struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; struct pcm_process_buf_st arg; @@ -220,7 +223,7 @@ int pcm_process_client_dqbuf(void *hdl, struct buf_info *buf, struct buf_info *r arg.pcm = p_aml_pcm_ctx->pcm_srv_hdl; arg.buf_handle = 0; arg.data = 0; - arg.count = 0; + arg.count = buf->size; arg.out_ret = -EINVAL; if (release_buf && release_buf->handle && release_buf->phyaddr && release_buf->viraddr && @@ -230,7 +233,7 @@ int pcm_process_client_dqbuf(void *hdl, struct buf_info *buf, struct buf_info *r else arg.release_buf_handle = 0; - Mbox_invoke(dev, dspid, CMD_APROCESS_DQBUF, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, CMD_APROCESS_DQBUF, &arg, sizeof(arg)); buf->handle = arg.buf_handle; buf->phyaddr = arg.data; @@ -243,13 +246,11 @@ int pcm_process_client_dqbuf(void *hdl, struct buf_info *buf, struct buf_info *r } int pcm_process_client_qbuf(void *hdl, struct buf_info *buf, u32 type, - struct device *dev, u32 dspid) + struct mbox_chan *chan, u32 sync) { struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; struct pcm_process_buf_st arg; - if (!buf->handle) - return 0; if (type == PROCESSBUF) arg.id = 0; else @@ -257,16 +258,23 @@ int pcm_process_client_qbuf(void *hdl, struct buf_info *buf, u32 type, arg.pcm = p_aml_pcm_ctx->pcm_srv_hdl; arg.buf_handle = buf->handle; arg.data = buf->phyaddr; - arg.count = 0; + arg.count = buf->size; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, CMD_APROCESS_QBUF, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, CMD_APROCESS_QBUF, &arg, sizeof(arg)); + + buf->handle = arg.buf_handle; + buf->phyaddr = arg.data; + buf->size = arg.count; + + if (arg.buf_handle) + buf->viraddr = __va((phys_addr_t)buf->phyaddr); return arg.out_ret; } int pcm_process_client_get_volume_gain(void *hdl, int *gain, - int is_out, struct device *dev, u32 dspid) + int is_out, struct mbox_chan *chan, u32 sync) { struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; struct pcm_process_gain_st arg; @@ -276,7 +284,7 @@ int pcm_process_client_get_volume_gain(void *hdl, int *gain, arg.is_out = is_out; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, CMD_APROCESS_GET_GAIN, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, CMD_APROCESS_GET_GAIN, &arg, sizeof(arg)); if (!arg.out_ret) *gain = arg.gain; @@ -284,7 +292,7 @@ int pcm_process_client_get_volume_gain(void *hdl, int *gain, } int pcm_process_client_set_volume_gain(void *hdl, int gain, - int is_out, struct device *dev, u32 dspid) + int is_out, struct mbox_chan *chan, u32 sync) { struct aml_pro_pcm_ctx *p_aml_pcm_ctx = (struct aml_pro_pcm_ctx *)hdl; struct pcm_process_gain_st arg; @@ -294,13 +302,13 @@ int pcm_process_client_set_volume_gain(void *hdl, int gain, arg.is_out = is_out; arg.out_ret = -EINVAL; - Mbox_invoke(dev, dspid, CMD_APROCESS_SET_GAIN, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, CMD_APROCESS_SET_GAIN, &arg, sizeof(arg)); return arg.out_ret; } void *aml_dsp_mem_allocate(phys_addr_t *phy, size_t size, - struct device *dev, u32 dspid) + struct mbox_chan *chan, u32 sync) { struct acodec_shm_alloc_st arg; @@ -308,43 +316,41 @@ void *aml_dsp_mem_allocate(phys_addr_t *phy, size_t size, arg.pid = 0; arg.phy = 0; - Mbox_invoke(dev, dspid, MBX_CMD_SHM_ALLOC, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_SHM_ALLOC, &arg, sizeof(arg)); if (!arg.phy) return NULL; *phy = (phys_addr_t)arg.phy; return __va((phys_addr_t)arg.phy); } -void aml_dsp_mem_free(phys_addr_t phy, struct device *dev, u32 dspid) +void aml_dsp_mem_free(phys_addr_t phy, struct mbox_chan *chan, u32 sync) { struct acodec_shm_free_st arg; arg.phy = (u64)phy; - Mbox_invoke(dev, dspid, MBX_CMD_SHM_FREE, &arg, sizeof(arg)); + Mbox_invoke(chan, sync, MBX_CMD_SHM_FREE, &arg, sizeof(arg)); } void *audio_device_open(u32 card, u32 device, u32 flags, - struct rpc_pcm_config *config, struct device *dev, u32 dspid) + struct rpc_pcm_config *config, struct mbox_chan *chan, u32 sync) { void *phandle = NULL; if (flags & PCM_IN) { - config->period_count = 4; config->start_threshold = 0; config->silence_threshold = 0; config->stop_threshold = 0; - phandle = pcm_process_client_open(card, device, PCM_IN, config, dev, dspid); + phandle = pcm_process_client_open(card, device, PCM_IN, config, chan, sync); if (!phandle) { pr_err("pcm client open fail\n"); return NULL; } } else { - config->period_count = 4; config->start_threshold = 0; config->silence_threshold = 0; config->stop_threshold = 0; - phandle = pcm_client_open(card, device, PCM_OUT, config, dev, dspid); + phandle = pcm_process_client_open(card, device, PCM_OUT, config, chan, sync); if (!phandle) { pr_err("pcm client open fail\n"); return NULL; diff --git a/drivers/audiobridge/dsp_client_api.h b/drivers/audiobridge/dsp_client_api.h index 44bf239b1..d3ccbef12 100644 --- a/drivers/audiobridge/dsp_client_api.h +++ b/drivers/audiobridge/dsp_client_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #ifndef _DSP_CLIENT_API_H @@ -12,6 +12,8 @@ #define MBX_TINYALSA 0x2 #define MBX_PIPELINE 0x3 +/* 0x20 ~ 0x3F reserved for Customer */ + /*sys cmd*/ #define CMD_SHM_ALLOC 0x3 #define CMD_SHM_FREE 0x4 @@ -39,7 +41,7 @@ /*Message composition with module(6bits), function(10bits)*/ #define __MBX_COMPOSE_MSG(mod, func) (((mod) << 10) | ((func) & 0x3FF)) -/*Mssage Composition*/ +/*Mssage composition*/ #define MBX_CMD_SHM_ALLOC __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_SHM_ALLOC) #define MBX_CMD_SHM_FREE __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_SHM_FREE) @@ -172,6 +174,8 @@ enum LOOPBACK_BUF { RAWBUF, }; +struct mbox_chan; + struct rpc_pcm_config { /** The number of channels in a frame */ u32 channels; @@ -317,33 +321,34 @@ struct buf_info { u32 size; }; +u32 pcm_client_format_to_bytes(enum DSP_PCM_FORMAT format); u32 pcm_client_frame_to_bytes(void *hdl, u32 frame); void *pcm_client_open(u32 card, u32 device, u32 flags, - struct rpc_pcm_config *config, struct device *dev, u32 dspid); -int pcm_client_close(void *hdl, struct device *dev, u32 dspid); + struct rpc_pcm_config *config, struct mbox_chan *chan, u32 sync); +int pcm_client_close(void *hdl, struct mbox_chan *chan, u32 sync); int pcm_client_writei(void *hdl, const phys_addr_t data, u32 count, - struct device *dev, u32 dspid); + struct mbox_chan *chan, u32 sync); int pcm_client_readi(void *hdl, const phys_addr_t data, u32 count, - struct device *dev, u32 dspid); + struct mbox_chan *chan, u32 sync); int pcm_process_client_writei_to_speaker(void *hdl, const phys_addr_t data, u32 count, - u32 bypass, struct device *dev, u32 dspid); + u32 bypass, struct mbox_chan *chan, u32 sync); void *pcm_process_client_open(u32 card, u32 device, u32 flags, - struct rpc_pcm_config *config, struct device *dev, u32 dspid); -int pcm_process_client_close(void *hdl, struct device *dev, u32 dspid); -int pcm_process_client_start(void *hdl, struct device *dev, u32 dspid); -int pcm_process_client_stop(void *hdl, struct device *dev, u32 dspid); + struct rpc_pcm_config *config, struct mbox_chan *chan, u32 sync); +int pcm_process_client_close(void *hdl, struct mbox_chan *chan, u32 sync); +int pcm_process_client_start(void *hdl, struct mbox_chan *chan, u32 sync); +int pcm_process_client_stop(void *hdl, struct mbox_chan *chan, u32 sync); int pcm_process_client_dqbuf(void *hdl, struct buf_info *buf, struct buf_info *release_buf, - u32 type, struct device *dev, u32 dspid); + u32 type, struct mbox_chan *chan, u32 sync); int pcm_process_client_qbuf(void *hdl, struct buf_info *buf, u32 type, - struct device *dev, u32 dspid); + struct mbox_chan *chan, u32 sync); int pcm_process_client_get_volume_gain(void *hdl, int *gain, - int is_out, struct device *dev, u32 dspid); + int is_out, struct mbox_chan *chan, u32 sync); int pcm_process_client_set_volume_gain(void *hdl, int gain, - int is_out, struct device *dev, u32 dspid); -void *aml_dsp_mem_allocate(phys_addr_t *phy, size_t size, struct device *dev, u32 dspid); -void aml_dsp_mem_free(phys_addr_t phy, struct device *dev, u32 dspid); + int is_out, struct mbox_chan *chan, u32 sync); +void *aml_dsp_mem_allocate(phys_addr_t *phy, size_t size, struct mbox_chan *chan, u32 sync); +void aml_dsp_mem_free(phys_addr_t phy, struct mbox_chan *chan, u32 sync); void *audio_device_open(u32 card, u32 device, u32 flags, - struct rpc_pcm_config *config, struct device *dev, u32 dspid); + struct rpc_pcm_config *config, struct mbox_chan *chan, u32 sync); #endif /*_DSP_CLIENT_API_H*/ diff --git a/drivers/audiobridge/bridge_ringbuffer.c b/drivers/audiobridge/ringbuffer.c similarity index 78% rename from drivers/audiobridge/bridge_ringbuffer.c rename to drivers/audiobridge/ringbuffer.c index 13079f2a9..e0744080e 100644 --- a/drivers/audiobridge/bridge_ringbuffer.c +++ b/drivers/audiobridge/ringbuffer.c @@ -1,13 +1,13 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* - * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. */ #include #include #include #include -#include "bridge_ringbuffer.h" +#include "ringbuffer.h" static u32 roundup_power_of_2(unsigned int a) { @@ -23,7 +23,7 @@ static u32 roundup_power_of_2(unsigned int a) return (u32)(1 << position); } -struct ring_buffer *bridge_ring_buffer_init(u32 size) +struct ring_buffer *ring_buffer_init(u32 size) { char *buf = NULL; struct ring_buffer *ring_buf = NULL; @@ -53,7 +53,7 @@ struct ring_buffer *bridge_ring_buffer_init(u32 size) return ring_buf; } -int bridge_ring_buffer_release(struct ring_buffer *ring_buf) +int ring_buffer_release(struct ring_buffer *ring_buf) { if (ring_buf) { vfree(ring_buf->buffer); @@ -103,22 +103,22 @@ static u32 __ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, u32 siz return size; } -u32 bridge_ring_buffer_len(const struct ring_buffer *ring_buf) +u32 ring_buffer_len(const struct ring_buffer *ring_buf) { return ring_buf->size; } -u32 bridge_ring_buffer_used_len(const struct ring_buffer *ring_buf) +u32 ring_buffer_used_len(const struct ring_buffer *ring_buf) { return __ring_buffer_len(ring_buf); } -u32 bridge_ring_buffer_free_len(const struct ring_buffer *ring_buf) +u32 ring_buffer_free_len(const struct ring_buffer *ring_buf) { return ring_buf->size - __ring_buffer_len(ring_buf); } -u32 bridge_ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, u32 size) +u32 no_thread_safe_ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, u32 size) { u32 ret; @@ -126,21 +126,25 @@ u32 bridge_ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, u32 size) ring_buf->go_empty = false; ring_buf->out = ring_buf->in; } - if (bridge_ring_buffer_used_len(ring_buf) < size) + if (ring_buffer_used_len(ring_buf) < size) return 0; ret = __ring_buffer_get(ring_buf, buffer, size); return ret; } -u32 bridge_ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, u32 size) +u32 no_thread_safe_ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, u32 size) { u32 ret; + if (ring_buf->go_empty) { + ring_buf->go_empty = false; + ring_buf->in = ring_buf->out; + } ret = __ring_buffer_put(ring_buf, buffer, size); return ret; } -u32 bridge_ring_buffer_go_empty(struct ring_buffer *ring_buf) +u32 ring_buffer_go_empty(struct ring_buffer *ring_buf) { ring_buf->go_empty = true; return 0; diff --git a/drivers/audiobridge/ringbuffer.h b/drivers/audiobridge/ringbuffer.h new file mode 100644 index 000000000..fd57f8de2 --- /dev/null +++ b/drivers/audiobridge/ringbuffer.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2023 Amlogic, Inc. All rights reserved. + */ + +#ifndef _USER_RING_BUFFER_H +#define _USER_RING_BUFFER_H + +struct ring_buffer { + void *buffer; + u32 size; + u32 in; + u32 out; + u8 go_empty; +}; + +struct ring_buffer *ring_buffer_init(u32 size); +int ring_buffer_release(struct ring_buffer *ring_buf); +u32 ring_buffer_len(const struct ring_buffer *ring_buf); +u32 ring_buffer_used_len(const struct ring_buffer *ring_buf); +u32 ring_buffer_free_len(const struct ring_buffer *ring_buf); +u32 no_thread_safe_ring_buffer_get(struct ring_buffer *ring_buf, void *buffer, u32 size); +u32 no_thread_safe_ring_buffer_put(struct ring_buffer *ring_buf, void *buffer, u32 size); +u32 ring_buffer_go_empty(struct ring_buffer *ring_buf); + +#endif