hal: add support for I2S based external modem
There are specific xml files used for I2S based external modem.
Add check to load the correct xml file.
For I2S based external modem, voice sample rate can be 8k or
16k based on vocoder type. Call csd client api to get the
correct sample rate to configure voice call.
Change-Id: Ie9799336620f49a890355be74fe1830eb348cabe
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index 128e4af..59bdb56 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -125,7 +125,9 @@
static void update_hardware_info_8084(struct hardware_info *hw_info, const char *snd_card_name)
{
- if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card")) {
+ if (!strcmp(snd_card_name, "apq8084-taiko-mtp-snd-card") ||
+ !strncmp(snd_card_name, "apq8084-taiko-i2s-mtp-snd-card",
+ sizeof("apq8084-taiko-i2s-mtp-snd-card"))) {
strlcpy(hw_info->type, "mtp", sizeof(hw_info->type));
strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name));
hw_info->snd_devices = NULL;
@@ -137,6 +139,13 @@
hw_info->snd_devices = (snd_device_t *)taiko_apq8084_CDP_variant_devices;
hw_info->num_snd_devices = ARRAY_SIZE(taiko_apq8084_CDP_variant_devices);
strlcpy(hw_info->dev_extn, "-cdp", sizeof(hw_info->dev_extn));
+ } else if (!strncmp(snd_card_name, "apq8084-taiko-i2s-cdp-snd-card",
+ sizeof("apq8084-taiko-i2s-cdp-snd-card"))) {
+ strlcpy(hw_info->type, " cdp", sizeof(hw_info->type));
+ strlcpy(hw_info->name, "apq8084", sizeof(hw_info->name));
+ hw_info->snd_devices = NULL;
+ hw_info->num_snd_devices = 0;
+ strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
} else if (!strcmp(snd_card_name, "apq8084-taiko-liquid-snd-card")) {
strlcpy(hw_info->type , " liquid", sizeof(hw_info->type));
strlcpy(hw_info->name, "apq8084", sizeof(hw_info->type));
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 4161d87..b88d86f 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -36,6 +36,11 @@
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
+#define MIXER_XML_PATH_I2S "/system/etc/mixer_paths_i2s.xml"
+
+#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
+#define PLATFORM_INFO_XML_PATH_I2S "/system/etc/audio_platform_info_i2s.xml"
+
#define LIB_ACDB_LOADER "libacdbloader.so"
#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
@@ -109,6 +114,7 @@
int fluence_type;
int btsco_sample_rate;
bool slowtalk;
+ bool is_i2s_ext_modem;
/* Audio calibration related functions */
void *acdb_handle;
int voice_feature_set;
@@ -410,7 +416,7 @@
return 0;
}
-static struct csd_data *open_csd_client()
+static struct csd_data *open_csd_client(bool i2s_ext_modem)
{
struct csd_data *csd = calloc(1, sizeof(struct csd_data));
@@ -512,6 +518,16 @@
__func__, dlerror());
goto error;
}
+
+ csd->get_sample_rate = (get_sample_rate_t)dlsym(csd->csd_client,
+ "csd_client_get_sample_rate");
+ if (csd->get_sample_rate == NULL) {
+ ALOGE("%s: dlsym error %s for csd_client_get_sample_rate",
+ __func__, dlerror());
+
+ goto error;
+ }
+
csd->init = (init_t)dlsym(csd->csd_client, "csd_client_init");
if (csd->init == NULL) {
@@ -519,7 +535,7 @@
__func__, dlerror());
goto error;
} else {
- csd->init();
+ csd->init(i2s_ext_modem);
}
}
return csd;
@@ -557,7 +573,23 @@
ALOGD("%s: num_modems %d\n", __func__, mdm_detect_info.num_modems);
if (mdm_detect_info.num_modems > 0)
- plat_data->csd = open_csd_client();
+ plat_data->csd = open_csd_client(plat_data->is_i2s_ext_modem);
+}
+
+static bool platform_is_i2s_ext_modem(const char *snd_card_name,
+ struct platform_data *plat_data)
+{
+ plat_data->is_i2s_ext_modem = false;
+
+ if (!strncmp(snd_card_name, "apq8084-taiko-i2s-mtp-snd-card",
+ sizeof("apq8084-taiko-i2s-mtp-snd-card")) ||
+ !strncmp(snd_card_name, "apq8084-taiko-i2s-cdp-snd-card",
+ sizeof("apq8084-taiko-i2s-cdp-snd-card"))) {
+ plat_data->is_i2s_ext_modem = true;
+ }
+ ALOGV("%s, is_i2s_ext_modem:%d",__func__, plat_data->is_i2s_ext_modem);
+
+ return plat_data->is_i2s_ext_modem;
}
void *platform_init(struct audio_device *adev)
@@ -593,10 +625,16 @@
if (!my_data->hw_info) {
ALOGE("%s: Failed to init hardware info", __func__);
} else {
- if (audio_extn_read_xml(adev, snd_card_num, MIXER_XML_PATH,
- MIXER_XML_PATH_AUXPCM) == -ENOSYS)
+ if (platform_is_i2s_ext_modem(snd_card_name, my_data)) {
+ ALOGD("%s: Call MIXER_XML_PATH_I2S", __func__);
+
+ adev->audio_route = audio_route_init(snd_card_num,
+ MIXER_XML_PATH_I2S);
+ } else if (audio_extn_read_xml(adev, snd_card_num, MIXER_XML_PATH,
+ MIXER_XML_PATH_AUXPCM) == -ENOSYS) {
adev->audio_route = audio_route_init(snd_card_num,
MIXER_XML_PATH);
+ }
if (!adev->audio_route) {
ALOGE("%s: Failed to init audio route controls, aborting.",
__func__);
@@ -695,7 +733,10 @@
}
/* Initialize ACDB ID's */
- platform_info_init();
+ if (my_data->is_i2s_ext_modem)
+ platform_info_init(PLATFORM_INFO_XML_PATH_I2S);
+ else
+ platform_info_init(PLATFORM_INFO_XML_PATH);
/* load csd client */
platform_csd_init(my_data);
@@ -971,6 +1012,20 @@
return ret;
}
+int platform_get_sample_rate(void *platform, uint32_t *rate)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ int ret = 0;
+
+ if ((my_data->csd != NULL) && my_data->is_i2s_ext_modem) {
+ ret = my_data->csd->get_sample_rate(rate);
+ if (ret < 0) {
+ ALOGE("%s: csd_get_sample_rate error %d\n", __func__, ret);
+ }
+ }
+ return ret;
+}
+
int platform_set_voice_volume(void *platform, int volume)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index e80d3f1..e2ec822 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -221,7 +221,7 @@
#define LIB_CSD_CLIENT "libcsd-client.so"
/* CSD-CLIENT related functions */
-typedef int (*init_t)();
+typedef int (*init_t)(bool);
typedef int (*deinit_t)();
typedef int (*disable_device_t)();
typedef int (*enable_device_config_t)(int, int);
@@ -235,6 +235,7 @@
typedef int (*stop_playback_t)(uint32_t);
typedef int (*start_record_t)(uint32_t, int);
typedef int (*stop_record_t)(uint32_t);
+typedef int (*get_sample_rate_t)(uint32_t *);
/* CSD Client structure */
struct csd_data {
void *csd_client;
@@ -252,6 +253,7 @@
stop_playback_t stop_playback;
start_record_t start_record;
stop_record_t stop_record;
+ get_sample_rate_t get_sample_rate;
};
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 81291a2..2ec6b50 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -44,6 +44,7 @@
int platform_stop_voice_call(void *platform, uint32_t vsid);
int platform_set_voice_volume(void *platform, int volume);
int platform_set_mic_mute(void *platform, bool state);
+int platform_get_sample_rate(void *platform, uint32_t *rate);
snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_device);
int platform_set_hdmi_channels(void *platform, int channel_count);
@@ -63,7 +64,7 @@
bool platform_listen_update_status(snd_device_t snd_device);
/* From platform_info_parser.c */
-int platform_info_init(void);
+int platform_info_init(const char *filename);
struct audio_offload_info_t;
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 8f56107..85a05eb 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -38,7 +38,6 @@
#include "platform_api.h"
#include <platform.h>
-#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
#define BUF_SIZE 1024
static void process_device(const XML_Char **attr)
@@ -52,20 +51,20 @@
index = platform_get_snd_device_index((char *)attr[1]);
if (index < 0) {
- ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
- __func__, attr[1], PLATFORM_INFO_XML_PATH);
+ ALOGE("%s: Device %s in platform info xml not found, no ACDB ID set!",
+ __func__, attr[1]);
goto done;
}
if (strcmp(attr[2], "acdb_id") != 0) {
- ALOGE("%s: Device %s in %s has no acdb_id, no ACDB ID set!",
- __func__, attr[1], PLATFORM_INFO_XML_PATH);
+ ALOGE("%s: Device %s in platform info xml has no acdb_id, no ACDB ID set!",
+ __func__, attr[1]);
goto done;
}
if(platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
- ALOGE("%s: Device %s in %s, ACDB ID %d was not set!",
- __func__, attr[1], PLATFORM_INFO_XML_PATH, atoi((char *)attr[3]));
+ ALOGE("%s: Device %s in platform info xml ACDB ID %d was not set!",
+ __func__, attr[1], atoi((char *)attr[3]));
goto done;
}
@@ -91,7 +90,7 @@
}
-int platform_info_init(void)
+int platform_info_init(const char *filename)
{
XML_Parser parser;
FILE *file;
@@ -99,10 +98,10 @@
int bytes_read;
void *buf;
- file = fopen(PLATFORM_INFO_XML_PATH, "r");
+ file = fopen(filename, "r");
if (!file) {
ALOGD("%s: Failed to open %s, using defaults.",
- __func__, PLATFORM_INFO_XML_PATH);
+ __func__, filename);
ret = -ENODEV;
goto done;
}
@@ -134,7 +133,7 @@
if (XML_ParseBuffer(parser, bytes_read,
bytes_read == 0) == XML_STATUS_ERROR) {
ALOGE("%s: XML_ParseBuffer failed, for %s",
- __func__, PLATFORM_INFO_XML_PATH);
+ __func__, filename);
ret = -EINVAL;
goto err_free_parser;
}
diff --git a/hal/voice.c b/hal/voice.c
index 28d44db..1c3ab38 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -106,6 +106,7 @@
int i, ret = 0;
struct audio_usecase *uc_info;
int pcm_dev_rx_id, pcm_dev_tx_id;
+ uint32_t sample_rate = 8000;
struct voice_session *session = NULL;
struct pcm_config voice_config = pcm_config_voice_call;
@@ -133,6 +134,13 @@
ret = -EIO;
goto error_start_voice;
}
+ ret = platform_get_sample_rate(adev->platform, &sample_rate);
+ if (ret < 0) {
+ ALOGE("platform_get_sample_rate error %d\n", ret);
+ } else {
+ voice_config.rate = sample_rate;
+ }
+ ALOGD("voice_config.rate %d\n", voice_config.rate);
ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
__func__, adev->snd_card, pcm_dev_rx_id);