mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
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 <shuai.liu@amlogic.com>
This commit is contained in:
committed by
gerrit autosubmit
parent
42f5a0bbb7
commit
4b842e4cd3
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -390,7 +390,7 @@
|
||||
hifidsp0: hifidsp0 {
|
||||
compatible = "amlogic, hifidsp0";
|
||||
status = "okay";
|
||||
startup-position = /bits/ 8 <PURE_SRAM>; /*host dsp start mode : DDR*/
|
||||
startup-position = /bits/ 8 <PURE_DDR>; /*host dsp start mode : DDR*/
|
||||
memory-region = <&dsp_fw_reserved>;
|
||||
reg-names = "base-reg",
|
||||
"health-reg",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <linux/init.h>
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/amlogic/arm-smccc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.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
|
||||
|
||||
@@ -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 <linux/init.h>
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/amlogic/arm-smccc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.h>
|
||||
@@ -38,13 +38,13 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include "bridge_common.h"
|
||||
#include "bridge_ringbuffer.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "bridge_pcm_hal.h"
|
||||
#include <linux/amlogic/aml_mbox.h>
|
||||
|
||||
#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[] = {
|
||||
|
||||
@@ -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 <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kobject.h>
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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 <linux/module.h>
|
||||
@@ -12,25 +12,26 @@
|
||||
#include <sound/soc.h>
|
||||
#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)
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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 <linux/init.h>
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/amlogic/arm-smccc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.h>
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/amlogic/scpi_protocol.h>
|
||||
#include "../hifi4dsp/hifi4dsp_priv.h"
|
||||
#include "../host/host.h"
|
||||
#include "bridge_common.h"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
@@ -43,22 +43,24 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <uapi/linux/sched/types.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <linux/init.h>
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/amlogic/arm-smccc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.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
|
||||
|
||||
@@ -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
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/amlogic/arm-smccc.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/psci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mutex.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <linux/types.h>
|
||||
@@ -9,18 +9,21 @@
|
||||
#include <linux/amlogic/scpi_protocol.h>
|
||||
#include <linux/dev_printk.h>
|
||||
#include "dsp_client_api.h"
|
||||
#include "bridge_common.h"
|
||||
#include <linux/amlogic/aml_mbox.h>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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 <linux/types.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/log2.h>
|
||||
#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;
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user