You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
381 lines
13 KiB
381 lines
13 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. Technologies Co., Ltd. 2020-2020. All rights reserved.
|
|
* Description: audio hal settings manage source file.
|
|
* Author: yinyingcai
|
|
* Create: 2020-05-11
|
|
* Notes: NA
|
|
* History: 2020-05-11 yinyingcai for CodingStyle
|
|
*/
|
|
#define LOG_TAG "audio_hal_setting"
|
|
#define LOG_NDEBUG 0
|
|
|
|
#include "audio_setting.h"
|
|
#include <log/log.h>
|
|
#include <cutils/properties.h>
|
|
|
|
#include "uapi_version.h"
|
|
#include "uapi_sound.h"
|
|
#include "audio_hw.h"
|
|
#include "securec.h"
|
|
|
|
#define HDMI_MODE_NONE 0 // refere to setting menu order
|
|
#define HDMI_MODE_AUTO 1
|
|
#define HDMI_MODE_LPCM 2
|
|
#define HDMI_MODE_RAW 3
|
|
#define SPDIF_MODE_NONE 0
|
|
#define SPDIF_MODE_LPCM 1
|
|
#define SPDIF_MODE_RAW 2
|
|
#define HBR_MODE_AUTO 0
|
|
#define HBR_MODE_RAW_5_1 1
|
|
#define HBR_MODE_RAW_7_1 2
|
|
#define OUTPUT_FMT_AC3 0
|
|
#define OUTPUT_FMT_TRUEHD 1
|
|
#define String_ENABLE_TRUEHD "1"
|
|
#define String_DISABLE_TRUEHD "0"
|
|
#define PROPERTY_ENABLE_TRUEHD "persist.vendor.audiohal.hp.truehd"
|
|
|
|
#define AUDIO_1POINT_CAPABILITY \
|
|
"AUDIO_CHANNEL_OUT_MONO"
|
|
#define AUDIO_2POINT_CAPABILITY \
|
|
"AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO"
|
|
#define AUDIO_5POINT1_CAPABILITY \
|
|
"AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_5POINT1"
|
|
#define AUDIO_7POINT1_CAPABILITY \
|
|
"AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1"
|
|
|
|
static void set_default_audio_cap(struct audio_setting *setting)
|
|
{
|
|
setting->edidAudioNum = 1; // default only support 1 audio format
|
|
setting->edidAudio[0].enAudFmtCode = (int)AUDIO_FORMAT_PCM_SUB_16_BIT;
|
|
setting->edidAudio[0].u8AudChannel = AUDIO_STEREO_CHANNELS;
|
|
setting->edidAudio[0].u32SupportSampleRateNum = 1; // default only support 1 audio samplerate
|
|
setting->edidAudio[0].enSupportSampleRate[0] = SAMPLE_RATE_48000;
|
|
}
|
|
|
|
static int updateHbr2LbrPolicy(const struct audio_setting *setting)
|
|
{
|
|
#if (UAPI_VERSION_CODE == UAPI_VERSION(1, 0))
|
|
(void) setting;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int initAndOpenHDMI(struct audio_setting *setting)
|
|
{
|
|
#if (UAPI_VERSION_CODE == UAPI_VERSION(1, 0))
|
|
set_default_audio_cap(setting);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void deinit_and_close_hdmi(void)
|
|
{
|
|
ALOGD("deinit_and_close_hdmi over");
|
|
}
|
|
|
|
static int freshHdmiAbility(struct audio_setting *setting, uint32_t HdmiMode)
|
|
{
|
|
int ret = 0;
|
|
setting->hdmiMode = HdmiMode;
|
|
if (HdmiMode == HDMI_MODE_RAW || HdmiMode == HDMI_MODE_AUTO) {
|
|
ret = updateHbr2LbrPolicy(setting);
|
|
if (ret != 0) {
|
|
ALOGE("updateHbr2LbrPolicy ret(0x%x)", ret);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#if (UAPI_VERSION_CODE == UAPI_VERSION(1, 0))
|
|
int setSpdifMode(struct audio_setting *setting, uint32_t SpdifMode)
|
|
{
|
|
int ret;
|
|
uapi_snd snd = UAPI_SND_0;
|
|
uapi_snd_out_port port = UAPI_SND_OUT_PORT_SPDIF0;
|
|
uapi_snd_output_mode mode = UAPI_SND_OUTPUT_MODE_LPCM;
|
|
|
|
if (SpdifMode == SPDIF_MODE_NONE) {
|
|
setting->spdifMode = SPDIF_MODE_NONE;
|
|
ret = uapi_snd_set_soft_mute(snd, port, TRUE);
|
|
ALOGD("SPDIF setting NONE mute port ret(0x%x)", ret);
|
|
return ret;
|
|
}
|
|
|
|
if (SpdifMode == SPDIF_MODE_LPCM) {
|
|
mode = UAPI_SND_OUTPUT_MODE_LPCM;
|
|
} else if (SpdifMode == SPDIF_MODE_RAW) {
|
|
mode = UAPI_SND_OUTPUT_MODE_RAW;
|
|
} else {
|
|
ALOGD("unsupport SPDIF mode");
|
|
}
|
|
ret = uapi_snd_set_output_mode(snd, port, mode);
|
|
ALOGD("Set spdif port mode=%d ret(0x%x)", mode, ret);
|
|
|
|
if (setting->spdifMode == SPDIF_MODE_NONE) {
|
|
ret = uapi_snd_set_soft_mute(snd, port, FALSE);
|
|
ALOGD("SPDIF setting from NONE to other unmute port ret(0x%x)", ret);
|
|
}
|
|
setting->spdifMode = SpdifMode;
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if (UAPI_VERSION_CODE == UAPI_VERSION(1, 0))
|
|
int setHdmiMode(struct audio_setting *setting, uint32_t HdmiMode)
|
|
{
|
|
int ret;
|
|
uapi_snd snd = UAPI_SND_0;
|
|
uapi_snd_out_port port = UAPI_SND_OUT_PORT_HDMITX0;
|
|
uapi_snd_output_mode mode = UAPI_SND_OUTPUT_MODE_LPCM;
|
|
|
|
if (HdmiMode == HDMI_MODE_NONE) {
|
|
ALOGD("HDMI setting NONE mute port");
|
|
ret = uapi_snd_set_soft_mute(snd, port, TRUE);
|
|
setting->hdmiMode = HdmiMode;
|
|
return ret;
|
|
}
|
|
|
|
if (HdmiMode == HDMI_MODE_LPCM) {
|
|
mode = UAPI_SND_OUTPUT_MODE_LPCM;
|
|
} else if (HdmiMode == HDMI_MODE_RAW) {
|
|
mode = UAPI_SND_OUTPUT_MODE_RAW;
|
|
} else if (HdmiMode == HDMI_MODE_AUTO) {
|
|
mode = UAPI_SND_OUTPUT_MODE_AUTO;
|
|
} else {
|
|
ALOGD("unsupport HDMI mode");
|
|
}
|
|
ret = uapi_snd_set_output_mode(snd, port, mode);
|
|
ALOGD("Set hdmi port mode=%d ret(0x%x)", mode, ret);
|
|
|
|
if (setting->hdmiMode == HDMI_MODE_NONE) {
|
|
ret = uapi_snd_set_soft_mute(snd, port, FALSE);
|
|
ALOGD("HDMI setting from NONE to other unmute port ret(0x%x)", ret);
|
|
}
|
|
return freshHdmiAbility(setting, HdmiMode);
|
|
}
|
|
#endif
|
|
|
|
int setHbr2LbrMode(struct audio_setting *setting, uint32_t Hbr2LbrMode)
|
|
{
|
|
setting->Hbr2LbrMode = Hbr2LbrMode;
|
|
return updateHbr2LbrPolicy(setting);
|
|
}
|
|
|
|
static void getHDMIAudioCap(struct audio_setting *setting)
|
|
{
|
|
#if (UAPI_VERSION_CODE == UAPI_VERSION(1, 0))
|
|
set_default_audio_cap(setting);
|
|
#endif
|
|
}
|
|
|
|
static char *get_channels_string(uint32_t channels)
|
|
{
|
|
switch (channels) {
|
|
case AUDIO_MONO_CHANNELS:
|
|
return AUDIO_1POINT_CAPABILITY;
|
|
case AUDIO_STEREO_CHANNELS:
|
|
return AUDIO_2POINT_CAPABILITY;
|
|
case AUDIO_5POINT1_CHANNELS:
|
|
return AUDIO_5POINT1_CAPABILITY;
|
|
case AUDIO_7POINT1_CHANNELS:
|
|
return AUDIO_7POINT1_CAPABILITY;
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static void auto_mode_get_support_formats(struct audio_setting *setting, char* value, uint32_t length)
|
|
{
|
|
int ret = -EINVAL;
|
|
getHDMIAudioCap(setting);
|
|
for (unsigned int i = 0; i < setting->edidAudioNum; i++) {
|
|
switch (setting->edidAudio[i].enAudFmtCode) {
|
|
case AUDIO_FORMAT_PCM_16_BIT:
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_PCM_16_BIT|");
|
|
if (ret != 0) {
|
|
ALOGE("strcat_s AUDIO_FORMAT_PCM_16_BIT INFO failed");
|
|
return;
|
|
}
|
|
break;
|
|
case AUDIO_FORMAT_AC3:
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_AC3|");
|
|
if (ret != 0) {
|
|
ALOGE("strcat_s AUDIO_FORMAT_AC3 INFO failed");
|
|
return;
|
|
}
|
|
break;
|
|
case AUDIO_FORMAT_E_AC3:
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_E_AC3|");
|
|
if (ret != 0) {
|
|
ALOGE("strcat_s AUDIO_FORMAT_E_AC3 INFO failed");
|
|
return;
|
|
}
|
|
break;
|
|
case AUDIO_FORMAT_AAC:
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_AAC|");
|
|
if (ret != 0) {
|
|
ALOGE("strcat_s AUDIO_FORMAT_AAC INFO failed");
|
|
return;
|
|
}
|
|
break;
|
|
case AUDIO_FORMAT_DTS:
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_DTS|");
|
|
if (ret != 0) {
|
|
ALOGE("strcat_s AUDIO_FORMAT_DTS INFO failed");
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
ALOGD("%s: unrepported format", __func__);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int check_valid_format(const struct audio_setting* setting, int targetFormat)
|
|
{
|
|
if (targetFormat == (int)AUDIO_FORMAT_INVALID) {
|
|
return -EINVAL;
|
|
}
|
|
// when hdmimode was HDMI_MODE_LPCM or HDMI_MODE_NONE only report the support channels of pcm
|
|
if ((setting->hdmiMode == HDMI_MODE_LPCM || setting->hdmiMode == HDMI_MODE_NONE) &&
|
|
targetFormat != AUDIO_FORMAT_PCM_16_BIT && setting->spdifMode != SPDIF_MODE_RAW) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void get_support_channels(const struct audio_setting* setting, char* value, int targetFormat, uint32_t length)
|
|
{
|
|
int ret;
|
|
value[0] = '\0';
|
|
|
|
if (check_valid_format(setting, targetFormat) != 0) {
|
|
return;
|
|
}
|
|
|
|
if (setting->hdmiMode == HDMI_MODE_RAW || setting->spdifMode == SPDIF_MODE_RAW) {
|
|
ret = strcat_s(value, length, AUDIO_7POINT1_CAPABILITY);
|
|
if (ret != EOK) {
|
|
ALOGE("strcat_s AUDIO_7POINT1_CAPABILITY ret(0x%x)", ret);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (setting->hdmiMode == HDMI_MODE_LPCM || setting->hdmiMode == HDMI_MODE_NONE) {
|
|
ret = strcat_s(value, length, AUDIO_2POINT_CAPABILITY);
|
|
if (ret != EOK) {
|
|
ALOGE("strcat AUDIO_2POINT_CAPABILITY faild ret(0x%x)", ret);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (setting->hdmiMode != HDMI_MODE_AUTO) {
|
|
ALOGD("%s: unsupported hdmiMode(%d)", __func__, setting->hdmiMode);
|
|
return;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < setting->edidAudioNum; i++) {
|
|
if (setting->edidAudio[i].enAudFmtCode != targetFormat) {
|
|
continue;
|
|
}
|
|
char *channels = get_channels_string (setting->edidAudio[i].u8AudChannel);
|
|
if (channels == NULL) {
|
|
ALOGE("%s: unrepported channel %d", __func__, setting->edidAudio[i].u8AudChannel);
|
|
return;
|
|
}
|
|
ret = strcat_s(value, length, channels);
|
|
if (ret != EOK) {
|
|
ALOGE("strcat_s channel(%d) faild ret(0x%x)", setting->edidAudio[i].u8AudChannel, ret);
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void get_support_formats(struct audio_setting *setting, char* value, uint32_t length)
|
|
{
|
|
int ret;
|
|
value[0] = '\0';
|
|
if (setting->hdmiMode == HDMI_MODE_RAW || setting->spdifMode == SPDIF_MODE_RAW) {
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3");
|
|
if (ret != EOK) {
|
|
ALOGE("strcat_s4 faild ret(0x%x)", ret);
|
|
return;
|
|
}
|
|
} else if (setting->hdmiMode == HDMI_MODE_AUTO) {
|
|
auto_mode_get_support_formats(setting, value, length);
|
|
} else if (setting->hdmiMode == HDMI_MODE_LPCM || setting->hdmiMode == HDMI_MODE_NONE) {
|
|
ret = strcat_s(value, length, "AUDIO_FORMAT_PCM_16_BIT");
|
|
if (ret != EOK) {
|
|
ALOGE("strcat_s6 faild ret(0x%x)", ret);
|
|
return;
|
|
}
|
|
} else {
|
|
ALOGD("%s: unsupported hdmiMode(%d)", __func__, setting->hdmiMode);
|
|
}
|
|
}
|
|
|
|
static int get_rates_string(int samplerate, char *value, uint32_t length)
|
|
{
|
|
switch (samplerate) {
|
|
case SAMPLE_RATE_8000:
|
|
return strcat_s(value, length, "8000|");
|
|
case SAMPLE_RATE_11025:
|
|
return strcat_s(value, length, "11025|");
|
|
case SAMPLE_RATE_12000:
|
|
return strcat_s(value, length, "12000|");
|
|
case SAMPLE_RATE_16000:
|
|
return strcat_s(value, length, "16000|");
|
|
case SAMPLE_RATE_22050:
|
|
return strcat_s(value, length, "22050|");
|
|
case SAMPLE_RATE_24000:
|
|
return strcat_s(value, length, "24000|");
|
|
case SAMPLE_RATE_32000:
|
|
return strcat_s(value, length, "32000|");
|
|
case SAMPLE_RATE_44100:
|
|
return strcat_s(value, length, "44100|");
|
|
case SAMPLE_RATE_48000:
|
|
return strcat_s(value, length, "48000|");
|
|
default:
|
|
ALOGD("%s: unrepported sample rate", __func__);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void get_support_rates(const struct audio_setting* setting, char* value, int targetFormat, uint32_t length)
|
|
{
|
|
int ret;
|
|
value[0] = '\0';
|
|
|
|
if (check_valid_format(setting, targetFormat) != 0) {
|
|
return;
|
|
}
|
|
|
|
if (setting->hdmiMode != HDMI_MODE_AUTO) {
|
|
// 22050,16000,11025,8000 samplerate check by VTS
|
|
ret = strcat_s(value, length, "48000|44100|32000|22050|24000|16000|11025|8000");
|
|
if (ret != EOK) {
|
|
ALOGE("strcat_s rate all faild ret(0x%x)", ret);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < setting->edidAudioNum; i++) {
|
|
if (setting->edidAudio[i].enAudFmtCode != targetFormat) {
|
|
continue;
|
|
}
|
|
for (unsigned int j = 0; j < setting->edidAudio[i].u32SupportSampleRateNum; j++) {
|
|
ret = get_rates_string((int)(setting->edidAudio[i].enSupportSampleRate[j]), value, length);
|
|
if (ret != 0) {
|
|
ALOGE("strcat_s rate %d failed(0x%x)", setting->edidAudio[i].enSupportSampleRate[j], ret);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|