From ff0c025724c9a3ea8557892f00e5907f5d59b281 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 15 Oct 2023 17:58:05 +0800 Subject: [PATCH] ASoC: rockchip: Introduce rockchip utils common API At the monment, we add utils_get/put_performance for DMC-DVFS-SCENE policy. Ref: commit cae65d78f0f4 ("ASoC: rockchip: i2s-tdm: Add support for FIFO-XRUN detection") Signed-off-by: Sugar Zhang Change-Id: I188e5cfff960aa3679db5c3a8ee847d9c7b685ee --- sound/soc/rockchip/Makefile | 2 + sound/soc/rockchip/rockchip_utils.c | 150 ++++++++++++++++++++++++++++ sound/soc/rockchip/rockchip_utils.h | 18 ++++ 3 files changed, 170 insertions(+) create mode 100644 sound/soc/rockchip/rockchip_utils.c create mode 100644 sound/soc/rockchip/rockchip_utils.h diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index b12252cba2bf..ca8dfb54841c 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # ROCKCHIP Platform Support +snd-soc-rockchip-objs := rockchip_utils.o snd-soc-rockchip-dlp-objs := rockchip_dlp.o snd-soc-rockchip-dlp-pcm-objs := rockchip_dlp_pcm.o snd-soc-rockchip-i2s-objs := rockchip_i2s.o @@ -17,6 +18,7 @@ snd-soc-rockchip-vad-$(CONFIG_ARM64) += vad_preprocess_arm64.o snd-soc-rockchip-vad-$(CONFIG_ARM) += vad_preprocess_arm.o endif +obj-$(CONFIG_SND_SOC_ROCKCHIP) += snd-soc-rockchip.o obj-$(CONFIG_SND_SOC_ROCKCHIP_DLP) += snd-soc-rockchip-dlp.o obj-$(CONFIG_SND_SOC_ROCKCHIP_DLP_PCM) += snd-soc-rockchip-dlp-pcm.o obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o diff --git a/sound/soc/rockchip/rockchip_utils.c b/sound/soc/rockchip/rockchip_utils.c new file mode 100644 index 000000000000..c8cbd71537d1 --- /dev/null +++ b/sound/soc/rockchip/rockchip_utils.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Rockchip Utils API + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DMC_STALL_TIME_US_DEFAULT 100 +#define TIME_MARGIN_US 20 + +static DEFINE_MUTEX(list_mutex); +static LIST_HEAD(substream_ref_list); + +struct substream_ref { + struct list_head node; + struct snd_pcm_substream *substream; +}; + +static int substream_ref_new(struct snd_pcm_substream *substream) +{ + struct substream_ref *ref = NULL; + bool found = false; + int ret = 0; + + mutex_lock(&list_mutex); + list_for_each_entry(ref, &substream_ref_list, node) { + if (ref->substream == substream) { + found = true; + break; + } + } + + if (found) { + ret = -EEXIST; + goto _err_unlock; + } + + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) { + ret = -ENOMEM; + goto _err_unlock; + } + + ref->substream = substream; + + list_add(&ref->node, &substream_ref_list); + +_err_unlock: + mutex_unlock(&list_mutex); + + return ret; +} + +static bool substream_ref_found(struct snd_pcm_substream *substream) +{ + struct substream_ref *ref = NULL, *_ref = NULL; + bool found = false; + + mutex_lock(&list_mutex); + list_for_each_entry_safe(ref, _ref, &substream_ref_list, node) { + if (ref->substream == substream) { + list_del(&ref->node); + found = true; + break; + } + } + mutex_unlock(&list_mutex); + + if (found) + kfree(ref); + + return found; +} + +static bool fifo_bigger_than_stall(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai, + int fifo_word) +{ + unsigned int rate = params_rate(params); + unsigned int channels = params_channels(params); + int width = params_physical_width(params); + int fifo_time, stall_time, data_word; + + dev_dbg(dai->dev, "stream[%d]: %px, rate: %u, channels: %u, width: %d\n", + substream->stream, substream, rate, channels, width); + + stall_time = rockchip_dmcfreq_get_stall_time_ns() / 1000; + if (!stall_time) + stall_time = DMC_STALL_TIME_US_DEFAULT; + + stall_time += TIME_MARGIN_US; + + data_word = rate * channels * width / 32; + + if (!fifo_word || !data_word) + return true; + + fifo_time = 1000000 * fifo_word / data_word; + + dev_dbg(dai->dev, "data: %d, fifo: %d, fifo time: %d us, stall time: %d us\n", + data_word, fifo_word, fifo_time, stall_time); + + return (fifo_time > stall_time); +} + +void rockchip_utils_get_performance(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai, + int fifo_word) +{ + might_sleep(); + + if (fifo_bigger_than_stall(substream, params, dai, fifo_word)) + return; + + if (substream_ref_new(substream)) + return; + + dev_dbg(dai->dev, "%s: stream[%d]: %px\n", + __func__, substream->stream, substream); + + rockchip_set_system_status(SYS_STATUS_PERFORMANCE); +} +EXPORT_SYMBOL_GPL(rockchip_utils_get_performance); + +void rockchip_utils_put_performance(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + might_sleep(); + + if (!substream_ref_found(substream)) + return; + + dev_dbg(dai->dev, "%s: stream[%d]: %px\n", + __func__, substream->stream, substream); + + rockchip_clear_system_status(SYS_STATUS_PERFORMANCE); +} +EXPORT_SYMBOL_GPL(rockchip_utils_put_performance); + +MODULE_LICENSE("GPL"); diff --git a/sound/soc/rockchip/rockchip_utils.h b/sound/soc/rockchip/rockchip_utils.h new file mode 100644 index 000000000000..24280b2fd156 --- /dev/null +++ b/sound/soc/rockchip/rockchip_utils.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Rockchip Utils API + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + */ + +#ifndef _ROCKCHIP_UTILS_H +#define _ROCKCHIP_UTILS_H + +void rockchip_utils_get_performance(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai, + int fifo_word); +void rockchip_utils_put_performance(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); + +#endif /* _ROCKCHIP_UTILS_H */