137 lines
3.9 KiB
C
137 lines
3.9 KiB
C
|
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
|
//
|
||
|
|
// adsp_feature_table.c-- Mediatek ADSP feature control
|
||
|
|
//
|
||
|
|
// Copyright (c) 2018 MediaTek Inc.
|
||
|
|
// Author: Celine Liu <Celine.liu@mediatek.com>
|
||
|
|
|
||
|
|
#include <linux/module.h> /* needed by all modules */
|
||
|
|
#include "adsp_feature_define.h"
|
||
|
|
#include "adsp_dvfs.h"
|
||
|
|
|
||
|
|
#define ADSP_SYSTEM_UNIT(fname) {.name = fname, .freq = 0, .counter = 1}
|
||
|
|
#define ADSP_FEATURE_UNIT(fname) {.name = fname, .freq = 0, .counter = 0}
|
||
|
|
|
||
|
|
DEFINE_MUTEX(adsp_feature_mutex);
|
||
|
|
|
||
|
|
/*adsp feature list*/
|
||
|
|
struct adsp_feature_tb adsp_feature_table[ADSP_NUM_FEATURE_ID] = {
|
||
|
|
[SYSTEM_FEATURE_ID] = ADSP_FEATURE_UNIT("system"),
|
||
|
|
[ADSP_LOGGER_FEATURE_ID] = ADSP_FEATURE_UNIT("logger"),
|
||
|
|
[AURISYS_FEATURE_ID] = ADSP_FEATURE_UNIT("aurisys"),
|
||
|
|
[AUDIO_CONTROLLER_FEATURE_ID] = ADSP_FEATURE_UNIT("audio_controller"),
|
||
|
|
[PRIMARY_FEATURE_ID] = ADSP_FEATURE_UNIT("primary"),
|
||
|
|
[DEEPBUF_FEATURE_ID] = ADSP_FEATURE_UNIT("deepbuf"),
|
||
|
|
[OFFLOAD_FEATURE_ID] = ADSP_FEATURE_UNIT("offload"),
|
||
|
|
[AUDIO_PLAYBACK_FEATURE_ID] = ADSP_FEATURE_UNIT("audplayback"),
|
||
|
|
[A2DP_PLAYBACK_FEATURE_ID] = ADSP_FEATURE_UNIT("a2dp_playback"),
|
||
|
|
[AUDIO_DATAPROVIDER_FEATURE_ID] = ADSP_FEATURE_UNIT("dataprovider"),
|
||
|
|
[SPK_PROTECT_FEATURE_ID] = ADSP_FEATURE_UNIT("spk_protect"),
|
||
|
|
[VOICE_CALL_FEATURE_ID] = ADSP_FEATURE_UNIT("voice_call"),
|
||
|
|
[VOIP_FEATURE_ID] = ADSP_FEATURE_UNIT("voip"),
|
||
|
|
[CAPTURE_UL1_FEATURE_ID] = ADSP_FEATURE_UNIT("capture_ul1"),
|
||
|
|
[CALL_FINAL_FEATURE_ID] = ADSP_FEATURE_UNIT("call_final"),
|
||
|
|
[KTV_FEATURE_ID] = ADSP_FEATURE_UNIT("ktv"),
|
||
|
|
[CAPTURE_RAW_FEATURE_ID] = ADSP_FEATURE_UNIT("capture_raw"),
|
||
|
|
[VOICE_CALL_SUB_FEATURE_ID] = ADSP_FEATURE_UNIT("voice_call_sub"),
|
||
|
|
};
|
||
|
|
|
||
|
|
ssize_t adsp_dump_feature_state(char *buffer, int size)
|
||
|
|
{
|
||
|
|
int n = 0, i = 0;
|
||
|
|
struct adsp_feature_tb *unit;
|
||
|
|
|
||
|
|
n += scnprintf(buffer + n, size - n, "%-20s %-8s %-8s\n",
|
||
|
|
"Feature_name", "Freq", "Counter");
|
||
|
|
for (i = 0; i < ADSP_NUM_FEATURE_ID; i++) {
|
||
|
|
unit = &adsp_feature_table[i];
|
||
|
|
if (!unit->name)
|
||
|
|
continue;
|
||
|
|
n += scnprintf(buffer + n, size - n, "%-20s %-8d %-3d\n",
|
||
|
|
unit->name, unit->freq, unit->counter);
|
||
|
|
}
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
|
||
|
|
int adsp_get_feature_index(char *str)
|
||
|
|
{
|
||
|
|
int i = 0;
|
||
|
|
struct adsp_feature_tb *unit;
|
||
|
|
|
||
|
|
if (!str)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
for (i = 0; i < ADSP_NUM_FEATURE_ID; i++) {
|
||
|
|
unit = &adsp_feature_table[i];
|
||
|
|
if (!unit->name)
|
||
|
|
continue;
|
||
|
|
if (strncmp(unit->name, str, strlen(unit->name)) == 0)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return i == ADSP_NUM_FEATURE_ID ? -EINVAL : i;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool adsp_feature_is_active(void)
|
||
|
|
{
|
||
|
|
uint32_t fid;
|
||
|
|
|
||
|
|
/* not include system feature */
|
||
|
|
for (fid = 0; fid < ADSP_NUM_FEATURE_ID ; fid++) {
|
||
|
|
if (adsp_feature_table[fid].counter > 0)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return fid == ADSP_NUM_FEATURE_ID ? false : true;
|
||
|
|
}
|
||
|
|
|
||
|
|
int adsp_register_feature(enum adsp_feature_id id)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
|
||
|
|
if (id >= ADSP_NUM_FEATURE_ID || id < 0)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
if (!adsp_feature_table[id].name)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
mutex_lock(&adsp_feature_mutex);
|
||
|
|
if (!adsp_feature_is_active()) {
|
||
|
|
pr_debug("[%s]%s, adsp_ready=%x\n", __func__,
|
||
|
|
adsp_feature_table[id].name, is_adsp_ready(ADSP_A_ID));
|
||
|
|
adsp_stop_suspend_timer();
|
||
|
|
ret = adsp_resume();
|
||
|
|
}
|
||
|
|
if (ret == 0)
|
||
|
|
adsp_feature_table[id].counter += 1;
|
||
|
|
mutex_unlock(&adsp_feature_mutex);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
int adsp_deregister_feature(enum adsp_feature_id id)
|
||
|
|
{
|
||
|
|
if (id >= ADSP_NUM_FEATURE_ID || id < 0)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
if (!adsp_feature_table[id].name)
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
mutex_lock(&adsp_feature_mutex);
|
||
|
|
if (adsp_feature_table[id].counter == 0) {
|
||
|
|
pr_err("[%s] error to deregister id=%d\n", __func__, id);
|
||
|
|
mutex_unlock(&adsp_feature_mutex);
|
||
|
|
return -EINVAL;
|
||
|
|
}
|
||
|
|
adsp_feature_table[id].counter -= 1;
|
||
|
|
|
||
|
|
/* no feature registered, delay 1s and then suspend adsp. */
|
||
|
|
if (!adsp_feature_is_active() && (is_adsp_ready(ADSP_A_ID) == 1)) {
|
||
|
|
pr_debug("[%s]%s, adsp_ready=%x\n", __func__,
|
||
|
|
adsp_feature_table[id].name, is_adsp_ready(ADSP_A_ID));
|
||
|
|
adsp_start_suspend_timer();
|
||
|
|
}
|
||
|
|
mutex_unlock(&adsp_feature_mutex);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|