ASoC: rockchip: Introduce rockchip utils common API

At the monment, we add utils_get/put_performance for
DMC-DVFS-SCENE policy.

Ref: commit cae65d78f0 ("ASoC: rockchip: i2s-tdm: Add support for FIFO-XRUN detection")

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Change-Id: I188e5cfff960aa3679db5c3a8ee847d9c7b685ee
This commit is contained in:
Sugar Zhang
2023-10-15 17:58:05 +08:00
committed by Tao Huang
parent a1a5a0fa34
commit ff0c025724
3 changed files with 170 additions and 0 deletions
+2
View File
@@ -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
+150
View File
@@ -0,0 +1,150 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Rockchip Utils API
*
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
*/
#include <dt-bindings/soc/rockchip-system-status.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <soc/rockchip/rockchip_dmc.h>
#include <soc/rockchip/rockchip-system-status.h>
#include <sound/pcm_params.h>
#include <sound/dmaengine_pcm.h>
#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");
+18
View File
@@ -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 */