hal: add support for multi-copps for multiple BEs
Add support for multi-copps for multiple BEs with independent
calibration data. This allows for more accurate calibration of device
copps.
Change-Id: I2628cf16564a6cd596e7f2663063a7cd64749bdc
CRs-Fixed: 1110415
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 7a4a0ed..446e205 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -763,18 +763,23 @@
}
}
-int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
- struct audio_usecase *usecase)
+static int send_app_type_cfg_for_device(struct audio_device *adev,
+ struct audio_usecase *usecase,
+ int split_snd_device)
{
char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
size_t app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {0};
int len = 0, rc;
struct mixer_ctl *ctl;
- int pcm_device_id, acdb_dev_id = 0, snd_device = usecase->out_snd_device;
+ int pcm_device_id = 0, acdb_dev_id, app_type;
+ int snd_device = split_snd_device, snd_device_be_idx = -1;
int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
char value[PROPERTY_VALUE_MAX] = {0};
- ALOGV("%s", __func__);
+ ALOGV("%s: usecase->out_snd_device %s, usecase->in_snd_device %s, split_snd_device %s",
+ __func__, platform_get_snd_device_name(usecase->out_snd_device),
+ platform_get_snd_device_name(usecase->in_snd_device),
+ platform_get_snd_device_name(split_snd_device));
if (usecase->type != PCM_PLAYBACK && usecase->type != PCM_CAPTURE) {
ALOGE("%s: not a playback/capture path, no need to cfg app type", __func__);
@@ -791,18 +796,16 @@
goto exit_send_app_type_cfg;
}
if (usecase->type == PCM_PLAYBACK) {
- snd_device = usecase->out_snd_device;
pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
"Audio Stream %d App Type Cfg", pcm_device_id);
- acdb_dev_id = platform_get_snd_device_acdb_id(usecase->out_snd_device);
} else if (usecase->type == PCM_CAPTURE) {
- snd_device = usecase->in_snd_device;
pcm_device_id = platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
"Audio Stream Capture %d App Type Cfg", pcm_device_id);
- acdb_dev_id = platform_get_snd_device_acdb_id(usecase->in_snd_device);
}
+
+ acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
if (acdb_dev_id <= 0) {
ALOGE("%s: Couldn't get the acdb dev id", __func__);
rc = -EINVAL;
@@ -819,6 +822,13 @@
snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
platform_get_spkr_prot_snd_device(snd_device) : snd_device;
+ snd_device_be_idx = platform_get_snd_device_backend_index(snd_device);
+ if (snd_device_be_idx < 0) {
+ ALOGE("%s: Couldn't get the backend index for snd device %s ret=%d",
+ __func__, platform_get_snd_device_name(snd_device),
+ snd_device_be_idx);
+ }
+
if ((usecase->type == PCM_PLAYBACK) && (usecase->stream.out != NULL)) {
if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
@@ -860,7 +870,8 @@
}
sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
- app_type_cfg[len++] = usecase->stream.out->app_type_cfg.app_type;
+ app_type = usecase->stream.out->app_type_cfg.app_type;
+ app_type_cfg[len++] = app_type;
app_type_cfg[len++] = acdb_dev_id;
if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
(usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
@@ -869,24 +880,31 @@
} else {
app_type_cfg[len++] = sample_rate;
}
+ if (snd_device_be_idx > 0)
+ app_type_cfg[len++] = snd_device_be_idx;
- ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, usecase->stream.out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
+ ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d, snd_device_be_idx %d",
+ __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
} else if ((usecase->type == PCM_CAPTURE) && (usecase->stream.in != NULL)) {
- app_type_cfg[len++] = usecase->stream.in->app_type_cfg.app_type;
+ app_type = usecase->stream.in->app_type_cfg.app_type;
+ app_type_cfg[len++] = app_type;
app_type_cfg[len++] = acdb_dev_id;
- app_type_cfg[len++] = usecase->stream.in->app_type_cfg.sample_rate;
- ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, usecase->stream.in->app_type_cfg.app_type, acdb_dev_id,
- usecase->stream.in->app_type_cfg.sample_rate);
+ sample_rate = usecase->stream.in->app_type_cfg.sample_rate;
+ app_type_cfg[len++] = sample_rate;
+ if (snd_device_be_idx > 0)
+ app_type_cfg[len++] = snd_device_be_idx;
+ ALOGI("%s CAPTURE app_type %d, acdb_dev_id %d, sample_rate %d, snd_device_be_idx %d",
+ __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
} else {
- app_type_cfg[len++] = platform_get_default_app_type_v2(adev->platform, usecase->type);
+ app_type = platform_get_default_app_type_v2(adev->platform, usecase->type);
+ app_type_cfg[len++] = app_type;
app_type_cfg[len++] = acdb_dev_id;
app_type_cfg[len++] = sample_rate;
- ALOGI("%s default app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, platform_get_default_app_type_v2(adev->platform, usecase->type),
- acdb_dev_id, sample_rate);
+ if (snd_device_be_idx > 0)
+ app_type_cfg[len++] = snd_device_be_idx;
+ ALOGI("%s default app_type %d, acdb_dev_id %d, sample_rate %d, snd_device_be_idx %d",
+ __func__, app_type, acdb_dev_id, sample_rate, snd_device_be_idx);
}
mixer_ctl_set_array(ctl, app_type_cfg, len);
@@ -895,6 +913,51 @@
return rc;
}
+int audio_extn_utils_send_app_type_cfg(struct audio_device *adev,
+ struct audio_usecase *usecase)
+{
+ int i, num_devices = 0;
+ snd_device_t new_snd_devices[SND_DEVICE_OUT_END] = {0};
+ int rc = 0;
+
+ switch (usecase->type) {
+ case PCM_PLAYBACK:
+ ALOGD("%s: usecase->out_snd_device %s",
+ __func__, platform_get_snd_device_name(usecase->out_snd_device));
+ /* check for out combo device */
+ if (platform_split_snd_device(adev->platform,
+ usecase->out_snd_device,
+ &num_devices, new_snd_devices)) {
+ new_snd_devices[0] = usecase->out_snd_device;
+ num_devices = 1;
+ }
+ break;
+ case PCM_CAPTURE:
+ ALOGD("%s: usecase->in_snd_device %s",
+ __func__, platform_get_snd_device_name(usecase->in_snd_device));
+ /* check for in combo device */
+ if (platform_split_snd_device(adev->platform,
+ usecase->in_snd_device,
+ &num_devices, new_snd_devices)) {
+ new_snd_devices[0] = usecase->in_snd_device;
+ num_devices = 1;
+ }
+ break;
+ default:
+ ALOGI("%s: not a playback/capture path, no need to cfg app type", __func__);
+ rc = 0;
+ break;
+ }
+
+ for (i = 0; i < num_devices; i++) {
+ rc = send_app_type_cfg_for_device(adev, usecase, new_snd_devices[i]);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
int read_line_from_file(const char *path, char *buf, size_t count)
{
char * fgets_ret;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 0870bde..e76398d 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -216,6 +216,7 @@
typedef int (*acdb_init_t)(const char *, char *, int);
typedef int (*acdb_init_v3_t)(const char *, char *, struct listnode *);
typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
+typedef void (*acdb_send_audio_cal_v3_t)(int, int, int, int, int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
typedef int (*acdb_get_default_app_type_t)(void);
@@ -247,6 +248,9 @@
char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
};
+static int max_be_dai_names = 0;
+static const struct be_dai_name_struct *be_dai_name_table;
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -276,6 +280,7 @@
acdb_init_v3_t acdb_init_v3;
acdb_deallocate_t acdb_deallocate;
acdb_send_audio_cal_t acdb_send_audio_cal;
+ acdb_send_audio_cal_v3_t acdb_send_audio_cal_v3;
acdb_set_audio_cal_t acdb_set_audio_cal;
acdb_get_audio_cal_t acdb_get_audio_cal;
acdb_send_voice_cal_t acdb_send_voice_cal;
@@ -1398,17 +1403,129 @@
backend_tag_table[SND_DEVICE_OUT_BT_A2DP] = strdup("bt-a2dp");
backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp");
+ hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_REVERSE] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_VBAT] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_LINE] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_HEADPHONES] = strdup("SLIMBUS_6_RX");
hw_interface_table[SND_DEVICE_OUT_HEADPHONES_DSD] = strdup("SLIMBUS_2_RX");
hw_interface_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("SLIMBUS_5_RX");
- hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI_RX");
- hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI_RX");
- hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT_RX");
- hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_LINE] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_VBAT] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_HEADPHONES] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_LINE] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI");
+ hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT");
+ hw_interface_table[SND_DEVICE_OUT_BT_SCO] = strdup("SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_BT_A2DP] = strdup("SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("SLIMBUS_0_RX-and-SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("RT_PROXY_DAI_001_RX");
+ hw_interface_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("RT_PROXY_DAI_001_RX");
hw_interface_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_USB_HEADPHONES] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = strdup("SLIMBUS_0_RX-and-USB_AUDIO_RX");
- hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
- hw_interface_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("PROXY_PORT_RX");
+ hw_interface_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("SLIMBUS_8_TX");
+ hw_interface_table[SND_DEVICE_OUT_ANC_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_ANC_FB_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_ANC_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_ANC_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_PROTECTED] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_PROTECTED_VBAT] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_WSA] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_WSA] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_WSA] = strdup("SLIMBUS_0_RX");
+#ifdef RECORD_PLAY_CONCURRENCY
+ hw_interface_table[SND_DEVICE_OUT_VOIP_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOIP_SPEAKER] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOIP_HEADPHONES] = strdup("SLIMBUS_6_RX");
+#endif
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HEADSET_MIC_FLUENCE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HDMI_MIC] = strdup("HDMI");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_CAMCORDER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_QMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_MIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_DMIC_STEREO] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_RX] = strdup("RT_PROXY_DAI_002_TX");
+ hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("SLIMBUS_8_TX");
+ hw_interface_table[SND_DEVICE_IN_AANC_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_QUAD_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_STEREO_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK_MONO_1] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK_MONO_2] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_FLUENCE_DMIC_AANC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_QMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_THREE_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_TMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_TMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_STEREO_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_THREE_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
/*remove ALAC & APE from DSP decoder list based on software decoder availability*/
@@ -1790,6 +1907,101 @@
}
}
+/*
+ * Retrieves the be_dai_name_table from kernel to enable a mapping
+ * between sound device hw interfaces and backend IDs. This allows HAL to
+ * specify the backend a specific calibration is needed for.
+ */
+static int init_be_dai_name_table(struct audio_device *adev)
+{
+ const char *mixer_ctl_name = "Backend DAI Name Table";
+ struct mixer_ctl *ctl;
+ int i, j, ret, size;
+ bool valid_hw_interface;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer name %s\n",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ mixer_ctl_update(ctl);
+
+ size = mixer_ctl_get_num_values(ctl);
+ if (size <= 0){
+ ALOGE("%s: Failed to get %s size %d\n",
+ __func__, mixer_ctl_name, size);
+ ret = -EFAULT;
+ goto done;
+ }
+
+ be_dai_name_table =
+ (const struct be_dai_name_struct *)calloc(1, size);
+ if (be_dai_name_table == NULL) {
+ ALOGE("%s: Failed to allocate memory for %s\n",
+ __func__, mixer_ctl_name);
+ ret = -ENOMEM;
+ goto freeMem;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)be_dai_name_table, size);
+ if (ret) {
+ ALOGE("%s: Failed to get %s, ret %d\n",
+ __func__, mixer_ctl_name, ret);
+ ret = -EFAULT;
+ goto freeMem;
+ }
+
+ if (be_dai_name_table != NULL) {
+ max_be_dai_names = size / sizeof(struct be_dai_name_struct);
+ ALOGV("%s: Successfully got %s, number of be dais is %d\n",
+ __func__, mixer_ctl_name, max_be_dai_names);
+ ret = 0;
+ } else {
+ ALOGE("%s: Failed to get %s\n", __func__, mixer_ctl_name);
+ ret = -EFAULT;
+ goto freeMem;
+ }
+
+ /*
+ * Validate all sound devices have a valid backend set to catch
+ * errors for uncommon sound devices
+ */
+ for (i = 0; i < SND_DEVICE_MAX; i++) {
+ valid_hw_interface = false;
+
+ if (hw_interface_table[i] == NULL) {
+ ALOGW("%s: sound device %s has no hw interface set\n",
+ __func__, platform_get_snd_device_name(i));
+ continue;
+ }
+
+ for (j = 0; j < max_be_dai_names; j++) {
+ if (strcmp(hw_interface_table[i], be_dai_name_table[j].be_name)
+ == 0) {
+ valid_hw_interface = true;
+ break;
+ }
+ }
+ if (!valid_hw_interface)
+ ALOGD("%s: sound device %s does not have a valid hw interface set (disregard for combo devices) %s\n",
+ __func__, platform_get_snd_device_name(i), hw_interface_table[i]);
+ }
+
+ goto done;
+
+freeMem:
+ if (be_dai_name_table) {
+ free((void *)be_dai_name_table);
+ be_dai_name_table = NULL;
+ }
+
+done:
+ return ret;
+}
+
void *platform_init(struct audio_device *adev)
{
char value[PROPERTY_VALUE_MAX];
@@ -1884,6 +2096,8 @@
my_data->hw_dep_fd = -1;
my_data->mono_speaker = SPKR_1;
+ be_dai_name_table = NULL;
+
property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro"))) {
my_data->fluence_type = FLUENCE_QUAD_MIC | FLUENCE_DUAL_MIC;
@@ -1983,7 +2197,13 @@
my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
"acdb_loader_send_audio_cal_v2");
if (!my_data->acdb_send_audio_cal)
- ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
+ ALOGE("%s: Could not find the symbol acdb_send_audio_cal_v2 from %s",
+ __func__, LIB_ACDB_LOADER);
+
+ my_data->acdb_send_audio_cal_v3 = (acdb_send_audio_cal_v3_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_send_audio_cal_v3");
+ if (!my_data->acdb_send_audio_cal_v3)
+ ALOGE("%s: Could not find the symbol acdb_send_audio_cal_v3 from %s",
__func__, LIB_ACDB_LOADER);
my_data->acdb_set_audio_cal = (acdb_set_audio_cal_t)dlsym(my_data->acdb_handle,
@@ -2087,6 +2307,12 @@
}
}
+ /*
+ * Get the be_dai_name_table from kernel which provides a mapping
+ * between a backend string name and a backend ID
+ */
+ init_be_dai_name_table(adev);
+
/* obtain source mic type from max mic count*/
get_source_mic_type(my_data);
ALOGD("%s: Fluence_Type(%d) max_mic_count(%d) mic_type(0x%x) fluence_in_voice_call(%d)"
@@ -2257,6 +2483,11 @@
my_data->edid_info = NULL;
}
+ if (be_dai_name_table) {
+ free((void *)be_dai_name_table);
+ be_dai_name_table = NULL;
+ }
+
if (my_data->hw_dep_fd >= 0) {
close(my_data->hw_dep_fd);
my_data->hw_dep_fd = -1;
@@ -2847,7 +3078,7 @@
struct platform_data *my_data = (struct platform_data *)platform;
int acdb_dev_id, acdb_dev_type;
int snd_device = SND_DEVICE_OUT_SPEAKER;
- int new_snd_device[SND_DEVICE_OUT_END];
+ int new_snd_device[SND_DEVICE_OUT_END] = {0};
int i, num_devices = 1;
if (usecase->type == PCM_PLAYBACK)
@@ -2877,14 +3108,18 @@
__func__, new_snd_device[i]);
return -EINVAL;
}
- if (my_data->acdb_send_audio_cal) {
- ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
- __func__, new_snd_device[i], acdb_dev_id);
- if (new_snd_device[i] >= SND_DEVICE_OUT_BEGIN &&
- new_snd_device[i] < SND_DEVICE_OUT_END)
- acdb_dev_type = ACDB_DEV_TYPE_OUT;
- else
- acdb_dev_type = ACDB_DEV_TYPE_IN;
+ ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
+ __func__, new_snd_device[i], acdb_dev_id);
+ if (new_snd_device[i] >= SND_DEVICE_OUT_BEGIN &&
+ new_snd_device[i] < SND_DEVICE_OUT_END)
+ acdb_dev_type = ACDB_DEV_TYPE_OUT;
+ else
+ acdb_dev_type = ACDB_DEV_TYPE_IN;
+
+ if (my_data->acdb_send_audio_cal_v3) {
+ my_data->acdb_send_audio_cal_v3(acdb_dev_id, acdb_dev_type, app_type,
+ sample_rate, i);
+ } else if (my_data->acdb_send_audio_cal) {
my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
sample_rate);
}
@@ -5163,7 +5398,7 @@
struct audio_usecase *usecase, snd_device_t snd_device)
{
int backend_idx = DEFAULT_CODEC_BACKEND;
- int new_snd_devices[SND_DEVICE_OUT_END];
+ int new_snd_devices[SND_DEVICE_OUT_END] = {0};
int i, num_devices = 1;
struct audio_backend_cfg backend_cfg;
bool ret = false;
@@ -5342,6 +5577,51 @@
return ret;
}
+int platform_get_snd_device_backend_index(snd_device_t device)
+{
+ int i, be_dai_id;
+ const char * hw_interface_name = NULL;
+
+ ALOGV("%s: enter with device %s\n",
+ __func__, platform_get_snd_device_name(device));
+
+ if ((device <= SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d", __func__, device);
+ be_dai_id = -EINVAL;
+ goto done;
+ }
+
+ /* Get string value of necessary backend for device */
+ hw_interface_name = hw_interface_table[device];
+ if (hw_interface_name == NULL) {
+ ALOGE("%s: no hw_interface set for device %s\n",
+ __func__, platform_get_snd_device_name(device));
+ be_dai_id = -EINVAL;
+ goto done;
+ }
+
+ /* Check if be dai name table was retrieved successfully */
+ if (be_dai_name_table == NULL) {
+ ALOGE("%s: BE DAI Name Table is not present\n", __func__);
+ be_dai_id = -EFAULT;
+ goto done;
+ }
+
+ /* Get backend ID for device specified */
+ for (i = 0; i < max_be_dai_names; i++) {
+ if (strcmp(hw_interface_name, be_dai_name_table[i].be_name) == 0) {
+ be_dai_id = be_dai_name_table[i].be_id;
+ goto done;
+ }
+ }
+ ALOGE("%s: no interface matching name %s\n", __func__, hw_interface_name);
+ be_dai_id = -EINVAL;
+ goto done;
+
+done:
+ return be_dai_id;
+}
+
int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
{
int ret = 0;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 0835329..c2ffd4a 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1104,6 +1104,11 @@
return -ENOSYS;
}
+int platform_get_snd_device_backend_index(snd_device_t device)
+{
+ return -ENOSYS;
+}
+
bool platform_sound_trigger_device_needs_event(snd_device_t snd_device __unused)
{
return false;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 06fb1fb..501a347 100755
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -192,6 +192,7 @@
typedef int (*acdb_init_t)(const char *, char *, int);
typedef int (*acdb_init_v3_t)(const char *, char *, struct listnode *);
typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
+typedef void (*acdb_send_audio_cal_v3_t)(int, int, int, int, int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
typedef int (*acdb_get_default_app_type_t)(void);
@@ -223,6 +224,9 @@
char name[ACDB_METAINFO_KEY_MODULE_NAME_LEN];
};
+static int max_be_dai_names = 0;
+static const struct be_dai_name_struct *be_dai_name_table;
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -251,6 +255,7 @@
acdb_init_v3_t acdb_init_v3;
acdb_deallocate_t acdb_deallocate;
acdb_send_audio_cal_t acdb_send_audio_cal;
+ acdb_send_audio_cal_v3_t acdb_send_audio_cal_v3;
acdb_set_audio_cal_t acdb_set_audio_cal;
acdb_get_audio_cal_t acdb_get_audio_cal;
acdb_send_voice_cal_t acdb_send_voice_cal;
@@ -1218,17 +1223,126 @@
backend_tag_table[SND_DEVICE_OUT_BT_A2DP] = strdup("bt-a2dp");
backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("speaker-and-bt-a2dp");
+ hw_interface_table[SND_DEVICE_OUT_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_REVERSE] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_VBAT] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_LINE] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_HEADPHONES] = strdup("SLIMBUS_6_RX");
hw_interface_table[SND_DEVICE_OUT_HEADPHONES_DSD] = strdup("SLIMBUS_2_RX");
hw_interface_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("SLIMBUS_5_RX");
- hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI_RX");
- hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI_RX");
- hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT_RX");
- hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_LINE] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_VBAT] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_HEADPHONES] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_LINE] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_HDMI] = strdup("HDMI");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("SLIMBUS_0_RX-and-HDMI");
+ hw_interface_table[SND_DEVICE_OUT_DISPLAY_PORT] = strdup("DISPLAY_PORT");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_DISPLAY_PORT] = strdup("SLIMBUS_0_RX-and-DISPLAY_PORT");
+ hw_interface_table[SND_DEVICE_OUT_BT_SCO] = strdup("SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_BT_A2DP] = strdup("SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP] = strdup("SLIMBUS_0_RX-and-SLIMBUS_7_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_FULL_HEADPHONES] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("RT_PROXY_DAI_001_RX");
+ hw_interface_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("RT_PROXY_DAI_001_RX");
hw_interface_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_USB_HEADPHONES] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = strdup("SLIMBUS_0_RX-and-USB_AUDIO_RX");
- hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
- hw_interface_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("PROXY_PORT_RX");
+ hw_interface_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("SLIMBUS_8_TX");
+ hw_interface_table[SND_DEVICE_OUT_ANC_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_ANC_FB_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_ANC_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_ANC_FB_HEADSET] = strdup("SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_ANC_HEADSET] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_AND_ANC_FB_HEADSET] = strdup("SLIMBUS_0_RX-and-SLIMBUS_6_RX");
+ hw_interface_table[SND_DEVICE_OUT_ANC_HANDSET] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_PROTECTED] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_PROTECTED_VBAT] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_OUT_SPEAKER_WSA] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_WSA] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_2_WSA] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_EXTERNAL] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_DMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HEADSET_MIC_FLUENCE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HDMI_MIC] = strdup("HDMI");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("SLIMBUS_7_TX");
+ hw_interface_table[SND_DEVICE_IN_CAMCORDER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_QMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_FULL_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_VCO_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_HCO_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_MIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_DMIC_STEREO] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_RX] = strdup("RT_PROXY_DAI_002_TX");
+ hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("SLIMBUS_8_TX");
+ hw_interface_table[SND_DEVICE_IN_AANC_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_QUAD_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_STEREO_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK_MONO_1] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK_MONO_2] = strdup("SLIMBUS_4_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_FLUENCE_DMIC_AANC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_QMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_QMIC_FLUENCE] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_THREE_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_TMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_REC_TMIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_STEREO_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_THREE_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
@@ -1497,6 +1611,101 @@
}
}
+/*
+ * Retrieves the be_dai_name_table from kernel to enable a mapping
+ * between sound device hw interfaces and backend IDs. This allows HAL to
+ * specify the backend a specific calibration is needed for.
+ */
+static int init_be_dai_name_table(struct audio_device *adev)
+{
+ const char *mixer_ctl_name = "Backend DAI Name Table";
+ struct mixer_ctl *ctl;
+ int i, j, ret, size;
+ bool valid_hw_interface;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer name %s\n",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ mixer_ctl_update(ctl);
+
+ size = mixer_ctl_get_num_values(ctl);
+ if (size <= 0){
+ ALOGE("%s: Failed to get %s size %d\n",
+ __func__, mixer_ctl_name, size);
+ ret = -EFAULT;
+ goto done;
+ }
+
+ be_dai_name_table =
+ (const struct be_dai_name_struct *)calloc(1, size);
+ if (be_dai_name_table == NULL) {
+ ALOGE("%s: Failed to allocate memory for %s\n",
+ __func__, mixer_ctl_name);
+ ret = -ENOMEM;
+ goto freeMem;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)be_dai_name_table, size);
+ if (ret) {
+ ALOGE("%s: Failed to get %s, ret %d\n",
+ __func__, mixer_ctl_name, ret);
+ ret = -EFAULT;
+ goto freeMem;
+ }
+
+ if (be_dai_name_table != NULL) {
+ max_be_dai_names = size / sizeof(struct be_dai_name_struct);
+ ALOGV("%s: Successfully got %s, number of be dais is %d\n",
+ __func__, mixer_ctl_name, max_be_dai_names);
+ ret = 0;
+ } else {
+ ALOGE("%s: Failed to get %s\n", __func__, mixer_ctl_name);
+ ret = -EFAULT;
+ goto freeMem;
+ }
+
+ /*
+ * Validate all sound devices have a valid backend set to catch
+ * errors for uncommon sound devices
+ */
+ for (i = 0; i < SND_DEVICE_MAX; i++) {
+ valid_hw_interface = false;
+
+ if (hw_interface_table[i] == NULL) {
+ ALOGW("%s: sound device %s has no hw interface set\n",
+ __func__, platform_get_snd_device_name(i));
+ continue;
+ }
+
+ for (j = 0; j < max_be_dai_names; j++) {
+ if (strcmp(hw_interface_table[i], be_dai_name_table[j].be_name)
+ == 0) {
+ valid_hw_interface = true;
+ break;
+ }
+ }
+ if (!valid_hw_interface)
+ ALOGD("%s: sound device %s does not have a valid hw interface set (disregard for combo devices) %s\n",
+ __func__, platform_get_snd_device_name(i), hw_interface_table[i]);
+ }
+
+ goto done;
+
+freeMem:
+ if (be_dai_name_table) {
+ free((void *)be_dai_name_table);
+ be_dai_name_table = NULL;
+ }
+
+done:
+ return ret;
+}
+
void *platform_init(struct audio_device *adev)
{
char platform[PROPERTY_VALUE_MAX];
@@ -1649,6 +1858,8 @@
my_data->hw_dep_fd = -1;
my_data->mono_speaker = SPKR_1;
+ be_dai_name_table = NULL;
+
property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro"))) {
my_data->fluence_type = FLUENCE_QUAD_MIC | FLUENCE_DUAL_MIC;
@@ -1716,7 +1927,13 @@
my_data->acdb_send_audio_cal = (acdb_send_audio_cal_t)dlsym(my_data->acdb_handle,
"acdb_loader_send_audio_cal_v2");
if (!my_data->acdb_send_audio_cal)
- ALOGE("%s: Could not find the symbol acdb_send_audio_cal from %s",
+ ALOGE("%s: Could not find the symbol acdb_send_audio_cal_v2 from %s",
+ __func__, LIB_ACDB_LOADER);
+
+ my_data->acdb_send_audio_cal_v3 = (acdb_send_audio_cal_v3_t)dlsym(my_data->acdb_handle,
+ "acdb_loader_send_audio_cal_v3");
+ if (!my_data->acdb_send_audio_cal_v3)
+ ALOGE("%s: Could not find the symbol acdb_send_audio_cal_v3 from %s",
__func__, LIB_ACDB_LOADER);
my_data->acdb_set_audio_cal = (acdb_set_audio_cal_t)dlsym(my_data->acdb_handle,
@@ -1805,6 +2022,12 @@
acdb_init_fail:
+ /*
+ * Get the be_dai_name_table from kernel which provides a mapping
+ * between a backend string name and a backend ID
+ */
+ init_be_dai_name_table(adev);
+
if (audio_extn_can_use_ras()) {
if (property_get_bool("persist.speaker.prot.enable", false)) {
platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED,
@@ -1961,6 +2184,11 @@
my_data->edid_info = NULL;
}
+ if (be_dai_name_table) {
+ free((void *)be_dai_name_table);
+ be_dai_name_table = NULL;
+ }
+
if (my_data->hw_dep_fd >= 0) {
close(my_data->hw_dep_fd);
my_data->hw_dep_fd = -1;
@@ -2531,7 +2759,7 @@
struct platform_data *my_data = (struct platform_data *)platform;
int acdb_dev_id, acdb_dev_type;
int snd_device = SND_DEVICE_OUT_SPEAKER;
- int new_snd_device[SND_DEVICE_OUT_END];
+ int new_snd_device[SND_DEVICE_OUT_END] = {0};
int i, num_devices = 1;
if (usecase->type == PCM_PLAYBACK)
@@ -2561,14 +2789,18 @@
__func__, new_snd_device[i]);
return -EINVAL;
}
- if (my_data->acdb_send_audio_cal) {
- ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
- __func__, new_snd_device[i], acdb_dev_id);
- if (new_snd_device[i] >= SND_DEVICE_OUT_BEGIN &&
- new_snd_device[i] < SND_DEVICE_OUT_END)
- acdb_dev_type = ACDB_DEV_TYPE_OUT;
- else
- acdb_dev_type = ACDB_DEV_TYPE_IN;
+ ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
+ __func__, new_snd_device[i], acdb_dev_id);
+ if (new_snd_device[i] >= SND_DEVICE_OUT_BEGIN &&
+ new_snd_device[i] < SND_DEVICE_OUT_END)
+ acdb_dev_type = ACDB_DEV_TYPE_OUT;
+ else
+ acdb_dev_type = ACDB_DEV_TYPE_IN;
+
+ if (my_data->acdb_send_audio_cal_v3) {
+ my_data->acdb_send_audio_cal_v3(acdb_dev_id, acdb_dev_type,
+ app_type, sample_rate, i);
+ } else if (my_data->acdb_send_audio_cal) {
my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
sample_rate);
}
@@ -5042,7 +5274,7 @@
struct audio_usecase *usecase, snd_device_t snd_device)
{
int backend_idx = DEFAULT_CODEC_BACKEND;
- int new_snd_devices[SND_DEVICE_OUT_END];
+ int new_snd_devices[SND_DEVICE_OUT_END] = {0};
int i, num_devices = 1;
bool ret = false;
struct platform_data *my_data = (struct platform_data *)adev->platform;
@@ -5219,6 +5451,50 @@
return ret;
}
+int platform_get_snd_device_backend_index(snd_device_t device)
+{
+ int i, be_dai_id;
+ const char * hw_interface_name = NULL;
+
+ ALOGV("%s: enter with device %d\n", __func__, device);
+
+ if ((device <= SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d",
+ __func__, device);
+ be_dai_id = -EINVAL;
+ goto done;
+ }
+
+ /* Get string value of necessary backend for device */
+ hw_interface_name = hw_interface_table[device];
+ if (hw_interface_name == NULL) {
+ ALOGE("%s: no hw_interface set for device %d\n", __func__, device);
+ be_dai_id = -EINVAL;
+ goto done;
+ }
+
+ /* Check if be dai name table was retrieved successfully */
+ if (be_dai_name_table == NULL) {
+ ALOGE("%s: BE DAI Name Table is not present\n", __func__);
+ be_dai_id = -EFAULT;
+ goto done;
+ }
+
+ /* Get backend ID for device specified */
+ for (i = 0; i < max_be_dai_names; i++) {
+ if (strcmp(hw_interface_name, be_dai_name_table[i].be_name) == 0) {
+ be_dai_id = be_dai_name_table[i].be_id;
+ goto done;
+ }
+ }
+ ALOGE("%s: no interface matching name %s\n", __func__, hw_interface_name);
+ be_dai_id = -EINVAL;
+ goto done;
+
+done:
+ return be_dai_id;
+}
+
int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
{
int ret = 0;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 82bef97..269aedc 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -52,6 +52,12 @@
int na_mode;
} native_audio_prop;
+#define BE_DAI_NAME_MAX_LENGTH 24
+struct be_dai_name_struct {
+ unsigned int be_id;
+ char be_name[BE_DAI_NAME_MAX_LENGTH];
+};
+
enum card_status_t;
void *platform_init(struct audio_device *adev);
@@ -133,6 +139,7 @@
int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend,
const char * hw_interface);
+int platform_get_snd_device_backend_index(snd_device_t device);
/* From platform_info.c */
int platform_info_init(const char *filename, void *);