hal: update combo device handling
If the wired headset/headphone/line devices are handled by
a different backend than speaker/earpiece devices, the combo
devices such as speaker+headphones can be split into individual
devices and enabled/disabled independently.
CRs-fixed: 989410
Change-Id: I379b56940eaf384d3cd1d9fe392b7fec65df023b
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 44ff952..739d463 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -1342,7 +1342,8 @@
property_get("ro.board.platform", platform, "");
if (!strncmp("apq8084", platform, sizeof("apq8084"))) {
platform_set_snd_device_backend(SND_DEVICE_OUT_VOICE_SPEAKER,
- "speaker-protected");
+ "speaker-protected",
+ "SLIMBUS_0_RX");
}
}
}
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 8f49b8d..9f82869 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -618,8 +618,10 @@
app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
app_type_cfg[len++] = acdb_dev_id;
app_type_cfg[len++] = sample_rate;
- ALOGI("%s PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, platform_get_default_app_type(adev->platform), acdb_dev_id, sample_rate);
+ ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, __LINE__,
+ platform_get_default_app_type(adev->platform),
+ acdb_dev_id, sample_rate);
} else if (usecase->type == PCM_PLAYBACK) {
if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
@@ -630,9 +632,6 @@
usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
}
- if (!audio_extn_is_hifi_audio_enabled())
- usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
-
sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
property_get("audio.playback.mch.downsample",value,"");
@@ -652,8 +651,10 @@
else
app_type_cfg[len++] = sample_rate;
- 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:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, __LINE__,
+ platform_get_default_app_type(adev->platform),
+ acdb_dev_id, sample_rate);
} else if (usecase->type == PCM_CAPTURE) {
app_type_cfg[len++] = platform_get_default_app_type_v2(adev->platform, usecase->type);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index d7a3169..2489471 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -485,6 +485,8 @@
int enable_snd_device(struct audio_device *adev,
snd_device_t snd_device)
{
+ int i, num_devices = 0;
+ snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
char device_name[DEVICE_NAME_MAX_SIZE] = {0};
if (snd_device < SND_DEVICE_MIN ||
@@ -529,6 +531,11 @@
audio_extn_dev_arbi_release(snd_device);
return -EINVAL;
}
+ } else if (platform_can_split_snd_device(adev->platform, snd_device,
+ &num_devices, new_snd_devices)) {
+ for (i = 0; i < num_devices; i++) {
+ enable_snd_device(adev, new_snd_devices[i]);
+ }
} else {
ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
/* due to the possibility of calibration overwrite between listen
@@ -564,6 +571,8 @@
int disable_snd_device(struct audio_device *adev,
snd_device_t snd_device)
{
+ int i, num_devices = 0;
+ snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
char device_name[DEVICE_NAME_MAX_SIZE] = {0};
if (snd_device < SND_DEVICE_MIN ||
@@ -597,6 +606,11 @@
if (platform_can_enable_spkr_prot_on_device(snd_device) &&
audio_extn_spkr_prot_is_enabled()) {
audio_extn_spkr_prot_stop_processing(snd_device);
+ } else if (platform_can_split_snd_device(adev->platform, snd_device,
+ &num_devices, new_snd_devices)) {
+ for (i = 0; i < num_devices; i++) {
+ disable_snd_device(adev, new_snd_devices[i]);
+ }
} else {
audio_route_reset_and_update_path(adev->audio_route, device_name);
}
@@ -623,15 +637,13 @@
}
static void check_usecases_codec_backend(struct audio_device *adev,
- struct audio_usecase *uc_info,
- snd_device_t snd_device)
+ struct audio_usecase *uc_info,
+ snd_device_t snd_device)
{
struct listnode *node;
struct audio_usecase *usecase;
bool switch_device[AUDIO_USECASE_MAX];
int i, num_uc_to_switch = 0;
- int backend_idx = DEFAULT_CODEC_BACKEND;
- int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
/*
* This function is to make sure that all the usecases that are active on
@@ -655,7 +667,6 @@
ALOGD("%s:becf: force routing %d", __func__, force_routing);
- backend_idx = platform_get_backend_index(snd_device);
/* Disable all the usecases on the shared backend other than the
* specified usecase.
*/
@@ -665,26 +676,23 @@
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- if (usecase == uc_info)
- continue;
- usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
-
- ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
- "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
- __func__, i, backend_idx, usecase_backend_idx,
+ ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
+ "backends match %d",__func__, i,
platform_get_snd_device_name(snd_device),
- platform_get_snd_device_name(usecase->out_snd_device));
+ platform_get_snd_device_name(usecase->out_snd_device),
+ platform_check_backends_match(snd_device, usecase->out_snd_device));
if (usecase->type != PCM_CAPTURE &&
- (usecase->out_snd_device != snd_device || force_routing) &&
- usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
- usecase_backend_idx == backend_idx) {
- ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
- __func__, use_case_table[usecase->id],
- platform_get_snd_device_name(usecase->out_snd_device));
- disable_audio_route(adev, usecase);
- switch_device[usecase->id] = true;
- num_uc_to_switch++;
+ usecase != uc_info &&
+ (usecase->out_snd_device != snd_device || force_routing) &&
+ usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
+ platform_check_backends_match(snd_device, usecase->out_snd_device)) {
+ ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
+ __func__, use_case_table[usecase->id],
+ platform_get_snd_device_name(usecase->out_snd_device));
+ disable_audio_route(adev, usecase);
+ switch_device[usecase->id] = true;
+ num_uc_to_switch++;
}
}
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 923135e..e078ba4 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -659,7 +659,8 @@
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)},
};
-static char * backend_table[SND_DEVICE_MAX] = {0};
+static char * backend_tag_table[SND_DEVICE_MAX] = {0};
+static char * hw_interface_table[SND_DEVICE_MAX] = {0};
static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
@@ -1274,33 +1275,37 @@
const char *MEDIA_MIMETYPE_AUDIO_APE = "audio/x-ape";
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
- backend_table[dev] = NULL;
+ backend_tag_table[dev] = NULL;
+ hw_interface_table[dev] = NULL;
}
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
- // TBD - do these go to the platform-info.xml file.
- // will help in avoiding strdups here
- backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
- backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
- backend_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("bt-sco");
- backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("bt-sco-wb");
- backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
- backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
- backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
- backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
- backend_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
- backend_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
- backend_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
- backend_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
- backend_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
+ // To overwrite these go to the audio_platform_info.xml file.
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("bt-sco");
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("bt-sco-wb");
+ backend_tag_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
+ backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
+ backend_tag_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
+ backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
+ backend_tag_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
+ backend_tag_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
+ backend_tag_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
+ backend_tag_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
+ backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
strdup("speaker-and-usb-headphones");
- backend_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
- backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
- backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
- backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
- backend_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("vbat-voice-speaker");
+ backend_tag_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
+ backend_tag_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
+ backend_tag_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
+ backend_tag_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
+ backend_tag_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("vbat-voice-speaker");
+
+ 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_VOICE_TX] = strdup("AFE_PCM_RX");
/*remove ALAC & APE from DSP decoder list based on software decoder availability*/
for (count = 0; count < (int32_t) (sizeof(dsp_only_decoders_mime)/sizeof(dsp_only_decoders_mime[0]));
@@ -1930,6 +1935,11 @@
strdup("SLIM_5_RX Format");
my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].samplerate_mixer_ctl =
strdup("SLIM_5_RX SampleRate");
+
+ my_data->current_backend_cfg[HEADPHONE_BACKEND].bitwidth_mixer_ctl =
+ strdup("SLIM_6_RX Format");
+ my_data->current_backend_cfg[HEADPHONE_BACKEND].samplerate_mixer_ctl =
+ strdup("SLIM_6_RX SampleRate");
} else {
my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
strdup("MI2S_RX Format");
@@ -1980,9 +1990,9 @@
int32_t dev;
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
- if (backend_table[dev]) {
- free(backend_table[dev]);
- backend_table[dev]= NULL;
+ if (backend_tag_table[dev]) {
+ free(backend_tag_table[dev]);
+ backend_tag_table[dev]= NULL;
}
}
@@ -2059,7 +2069,7 @@
return;
}
- const char * suffix = backend_table[snd_device];
+ const char * suffix = backend_tag_table[snd_device];
if (suffix != NULL) {
strlcat(mixer_path, " ", MIXER_PATH_MAX_LENGTH);
@@ -2067,6 +2077,40 @@
}
}
+bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_device2)
+{
+ bool result = true;
+
+ ALOGV("%s: snd_device1 = %s, snd_device2 = %s", __func__,
+ platform_get_snd_device_name(snd_device1),
+ platform_get_snd_device_name(snd_device2));
+
+ if ((snd_device1 < SND_DEVICE_MIN) || (snd_device1 >= SND_DEVICE_OUT_END)) {
+ ALOGE("%s: Invalid snd_device = %s", __func__,
+ platform_get_snd_device_name(snd_device1));
+ return false;
+ }
+ if ((snd_device2 < SND_DEVICE_MIN) || (snd_device2 >= SND_DEVICE_OUT_END)) {
+ ALOGE("%s: Invalid snd_device = %s", __func__,
+ platform_get_snd_device_name(snd_device2));
+ return false;
+ }
+ const char * be_itf1 = hw_interface_table[snd_device1];
+ const char * be_itf2 = hw_interface_table[snd_device2];
+
+ if (NULL != be_itf1 && NULL != be_itf2) {
+ if (0 != strcmp(be_itf1, be_itf2))
+ result = false;
+ } else if (NULL == be_itf1 && NULL != be_itf2) {
+ result = false;
+ } else if (NULL != be_itf1 && NULL == be_itf2) {
+ result = false;
+ }
+
+ ALOGV("%s: be_itf1 = %s, be_itf2 = %s, match %d", __func__, be_itf1, be_itf2, result);
+ return result;
+}
+
int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
{
int device_id = -1;
@@ -2198,6 +2242,8 @@
goto done;
}
+ ALOGV("%s: acdb_device_table[%s]: old = %d new = %d", __func__,
+ platform_get_snd_device_name(snd_device), acdb_device_table[snd_device], acdb_id);
acdb_device_table[snd_device] = acdb_id;
done:
return ret;
@@ -2390,21 +2436,27 @@
}
-int platform_get_backend_index(snd_device_t snd_device)
+static int platform_get_backend_index(snd_device_t snd_device)
{
int32_t port = DEFAULT_CODEC_BACKEND;
if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
- if (backend_table[snd_device] != NULL &&
- !strcmp(backend_table[snd_device], "headphones-44.1"))
- port = HEADPHONE_44_1_BACKEND;
- else
- port = DEFAULT_CODEC_BACKEND;
+ if (backend_tag_table[snd_device] != NULL) {
+ if (strncmp(backend_tag_table[snd_device], "headphones-44.1",
+ sizeof("headphones-44.1")) == 0)
+ port = HEADPHONE_44_1_BACKEND;
+ else if (strncmp(backend_tag_table[snd_device], "headphones",
+ sizeof("headphones")) == 0)
+ port = HEADPHONE_BACKEND;
+ else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
+ port = HDMI_RX_BACKEND;
+ }
} else {
ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
}
- ALOGV("%s:napb: backend port - %d", __func__, port);
+ ALOGV("%s:napb: backend port - %d device - %d ", __func__, port,
+ snd_device);
return port;
}
@@ -2415,6 +2467,8 @@
int acdb_dev_id, acdb_dev_type;
struct audio_device *adev = my_data->adev;
int snd_device = SND_DEVICE_OUT_SPEAKER;
+ int new_snd_device[SND_DEVICE_OUT_END];
+ int i, num_devices = 1;
if (usecase->type == PCM_PLAYBACK)
snd_device = usecase->out_snd_device;
@@ -2425,26 +2479,34 @@
snd_device = usecase->in_snd_device;
acdb_dev_id = acdb_device_table[platform_get_spkr_prot_snd_device(snd_device)];
- // Do not use Rx path default app type for TX path
- if ((usecase->type == PCM_CAPTURE) && (app_type == DEFAULT_APP_TYPE_RX_PATH)) {
- ALOGD("Resetting app type for Tx path to default");
- app_type = DEFAULT_APP_TYPE_TX_PATH;
+ if(!platform_can_split_snd_device(platform, snd_device, &num_devices, new_snd_device)) {
+ new_snd_device[0] = snd_device;
}
- if (acdb_dev_id < 0) {
- ALOGE("%s: Could not find acdb id for device(%d)",
- __func__, snd_device);
- return -EINVAL;
- }
- if (my_data->acdb_send_audio_cal) {
- ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
- __func__, snd_device, acdb_dev_id);
- if (snd_device >= SND_DEVICE_OUT_BEGIN &&
- snd_device < SND_DEVICE_OUT_END)
- acdb_dev_type = ACDB_DEV_TYPE_OUT;
- else
- acdb_dev_type = ACDB_DEV_TYPE_IN;
- my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
- sample_rate);
+
+ for (i = 0; i < num_devices; i++) {
+ acdb_dev_id = acdb_device_table[platform_get_spkr_prot_snd_device(new_snd_device[i])];
+
+ // Do not use Rx path default app type for TX path
+ if ((usecase->type == PCM_CAPTURE) && (app_type == DEFAULT_APP_TYPE_RX_PATH)) {
+ ALOGD("Resetting app type for Tx path to default");
+ app_type = DEFAULT_APP_TYPE_TX_PATH;
+ }
+ if (acdb_dev_id < 0) {
+ ALOGE("%s: Could not find acdb id for device(%d)",
+ __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;
+ my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
+ sample_rate);
+ }
}
return 0;
}
@@ -2705,6 +2767,57 @@
return ret;
}
+bool platform_can_split_snd_device(void *platform,
+ snd_device_t snd_device,
+ int *num_devices,
+ snd_device_t *new_snd_devices)
+{
+ bool status = false;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if (NULL == num_devices || NULL == new_snd_devices) {
+ ALOGE("%s: NULL pointer ..", __func__);
+ return false;
+ }
+
+ /*
+ * If wired headset/headphones/line devices share the same backend
+ * with speaker/earpiece this routine returns false.
+ */
+ if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_HEADPHONES)) {
+ *num_devices = 2;
+
+ if (my_data->is_vbat_speaker)
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_WSA;
+ else
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+
+ new_snd_devices[1] = SND_DEVICE_OUT_HEADPHONES;
+ status = true;
+ } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_HDMI)) {
+ *num_devices = 2;
+
+ if (my_data->is_vbat_speaker)
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER_WSA;
+ else
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+
+ new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
+ status = true;
+ }
+
+ ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
+ snd_device, *num_devices, *new_snd_devices);
+
+ return status;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -4112,7 +4225,7 @@
/*
* configures afe with bit width and Sample Rate
*/
-int platform_set_codec_backend_cfg(struct audio_device* adev,
+static int platform_set_codec_backend_cfg(struct audio_device* adev,
snd_device_t snd_device,
unsigned int bit_width, unsigned int sample_rate)
{
@@ -4219,7 +4332,7 @@
* goes through all the current usecases and picks the highest
* bitwidth & samplerate
*/
-bool platform_check_codec_backend_cfg(struct audio_device* adev,
+static bool platform_check_codec_backend_cfg(struct audio_device* adev,
struct audio_usecase* usecase,
snd_device_t snd_device,
unsigned int* new_bit_width,
@@ -4232,7 +4345,6 @@
unsigned int bit_width;
unsigned int sample_rate;
int backend_idx = DEFAULT_CODEC_BACKEND;
- int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
int na_mode = platform_get_native_support();
@@ -4242,8 +4354,7 @@
sample_rate = *new_sample_rate;
ALOGI("%s:becf: afe: Codec selected backend: %d current bit width: %d and sample rate: %d",
- __func__,
- backend_idx, bit_width, sample_rate);
+ __func__, backend_idx, bit_width, sample_rate);
// For voice calls use default configuration i.e. 16b/48K, only applicable to
// default backend
@@ -4270,8 +4381,6 @@
uc = node_to_item(node, struct audio_usecase, list);
struct stream_out *out = (struct stream_out*) uc->stream.out;
if (uc->type == PCM_PLAYBACK && out && usecase != uc) {
- usecase_backend_idx =
- platform_get_backend_index(uc->out_snd_device);
ALOGD("%s:napb: (%d) - (%s)id (%d) sr %d bw "
"(%d) device %s", __func__, i++, use_case_table[uc->id],
@@ -4279,7 +4388,7 @@
out->bit_width,
platform_get_snd_device_name(uc->out_snd_device));
- if (usecase_backend_idx == backend_idx) {
+ if (platform_check_backends_match(snd_device, uc->out_snd_device)) {
if (bit_width < out->bit_width)
bit_width = out->bit_width;
if (sample_rate < out->sample_rate)
@@ -4319,10 +4428,12 @@
* hifi playback not supported on spkr devices, limit the Sample Rate
* to 48 khz.
*/
- if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (SND_DEVICE_OUT_SPEAKER == snd_device ||
+ SND_DEVICE_OUT_SPEAKER_WSA == snd_device ||
+ SND_DEVICE_OUT_SPEAKER_VBAT == snd_device) {
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- ALOGD("%s:becf: afe: playback on speakers Configure afe to \
- default Sample Rate(48k)", __func__);
+ ALOGD("%s:becf: afe: playback on speaker device Configure afe to "
+ "default Sample Rate(48k)", __func__);
}
/*
@@ -4339,8 +4450,8 @@
* reset the sample rate to default value(48K), if hifi audio is not supported
*/
if (!my_data->hifi_audio) {
- ALOGD("%s:becf: afe: only 48KHZ sample rate is supported \
- Configure afe to default Sample Rate(48k)", __func__);
+ ALOGD("%s:becf: afe: only 48KHZ sample rate is supported "
+ "Configure afe to default Sample Rate(48k)", __func__);
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
}
@@ -4384,6 +4495,9 @@
unsigned int new_sample_rate;
int backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
+ int new_snd_devices[SND_DEVICE_OUT_END];
+ int i, num_devices = 1;
+ bool ret = false;
backend_idx = platform_get_backend_index(snd_device);
@@ -4394,17 +4508,27 @@
", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
new_sample_rate, backend_idx, usecase->id,
platform_get_snd_device_name(snd_device));
- if (platform_check_codec_backend_cfg(adev, usecase, snd_device,
- &new_bit_width, &new_sample_rate)) {
- platform_set_codec_backend_cfg(adev, snd_device,
- new_bit_width, new_sample_rate);
- return true;
+
+ if (!platform_can_split_snd_device(adev->platform, snd_device,
+ &num_devices, new_snd_devices))
+ new_snd_devices[0] = snd_device;
+
+ for (i = 0; i < num_devices; i++) {
+ ALOGI("%s: becf: new_snd_devices[%d] is %s", __func__, i,
+ platform_get_snd_device_name(new_snd_devices[i]));
+ if (platform_check_codec_backend_cfg(adev, usecase, new_snd_devices[i],
+ &new_bit_width, &new_sample_rate)) {
+ platform_set_codec_backend_cfg(adev, new_snd_devices[i],
+ new_bit_width, new_sample_rate);
+ ret = true;
+ }
}
- return false;
+ return ret;
}
-int platform_set_snd_device_backend(snd_device_t device, const char *backend)
+int platform_set_snd_device_backend(snd_device_t device, const char *backend_tag,
+ const char * hw_interface)
{
int ret = 0;
@@ -4415,10 +4539,22 @@
goto done;
}
- if (backend_table[device]) {
- free(backend_table[device]);
+ ALOGD("%s: backend_tag_table[%s]: old = %s new = %s", __func__,
+ platform_get_snd_device_name(device),
+ backend_tag_table[device] != NULL ? backend_tag_table[device]: "null",
+ backend_tag);
+ if (backend_tag_table[device]) {
+ free(backend_tag_table[device]);
}
- backend_table[device] = strdup(backend);
+ backend_tag_table[device] = strdup(backend_tag);
+
+ if (hw_interface != NULL) {
+ if (hw_interface_table[device])
+ free(hw_interface_table[device]);
+
+ ALOGD("%s: hw_interface_table[%d] = %s", __func__, device, hw_interface);
+ hw_interface_table[device] = strdup(hw_interface);
+ }
done:
return ret;
}
@@ -4436,6 +4572,7 @@
ALOGE("%s: invalid usecase type", __func__);
ret = -EINVAL;
}
+ ALOGV("%s: pcm_device_table[%d][%d] = %d", __func__, usecase, type, pcm_id);
pcm_device_table[usecase][type] = pcm_id;
done:
return ret;
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index da16feb..23435ea 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -191,7 +191,12 @@
#define HEADPHONE_44_1_BACKEND_PORT 5
enum {
DEFAULT_CODEC_BACKEND,
+ SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
HEADPHONE_44_1_BACKEND,
+ SLIMBUS_5_RX = HEADPHONE_44_1_BACKEND,
+ HEADPHONE_BACKEND,
+ SLIMBUS_6_RX = HEADPHONE_BACKEND,
+ HDMI_RX_BACKEND,
MAX_CODEC_BACKENDS
};
#define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index e32a73d..48470b9 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1080,8 +1080,9 @@
return -ENOSYS;
}
-int platform_set_snd_device_backend(snd_device_t snd_device __unused,
- const char * backend __unused)
+int platform_set_snd_device_backend(snd_device_t device __unused,
+ const char *backend __unused,
+ const char *hw_interface __unused)
{
return -ENOSYS;
}
@@ -1210,4 +1211,16 @@
int platform_spkr_prot_is_wsa_analog_mode(void *adev __unused)
{
return 0;
+bool platform_can_split_snd_device(void *platform __unused,
+ snd_device_t in_snd_device __unused,
+ int *num_devices __unused,
+ snd_device_t *out_snd_devices __unused)
+{
+ return false;
+}
+
+bool platform_check_backends_match(snd_device_t snd_device1 __unused,
+ snd_device_t snd_device2 __unused)
+{
+ return true;
}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index c8edd3e..03f6e25 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -636,7 +636,8 @@
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS)},
};
-static char * backend_table[SND_DEVICE_MAX] = {0};
+static char * backend_tag_table[SND_DEVICE_MAX] = {0};
+static char * hw_interface_table[SND_DEVICE_MAX] = {0};
static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
@@ -1035,35 +1036,39 @@
const char *MEDIA_MIMETYPE_AUDIO_APE = "audio/x-ape";
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
- backend_table[dev] = NULL;
+ backend_tag_table[dev] = NULL;
+ hw_interface_table[dev] = NULL;
}
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
backend_bit_width_table[dev] = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
- // TBD - do these go to the platform-info.xml file.
- // will help in avoiding strdups here
- backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
- backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
- backend_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("bt-sco");
- backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("bt-sco-wb");
- backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
- backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
- backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
- backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
- backend_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
- backend_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
-
- backend_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
- backend_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
- backend_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
+ // To overwrite these go to the audio_platform_info.xml file.
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_NREC] = strdup("bt-sco");
+ backend_tag_table[SND_DEVICE_IN_BT_SCO_MIC_WB_NREC] = strdup("bt-sco-wb");
+ backend_tag_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
+ backend_tag_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
+ backend_tag_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
+ backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
+ backend_tag_table[SND_DEVICE_OUT_VOICE_TX] = strdup("afe-proxy");
+ backend_tag_table[SND_DEVICE_IN_VOICE_RX] = strdup("afe-proxy");
+ backend_tag_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
+ backend_tag_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
+ backend_tag_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
strdup("speaker-and-usb-headphones");
- backend_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
- backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
- backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
- backend_table[SND_DEVICE_OUT_HEADPHONES] = strdup("headphones");
- backend_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
- backend_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("voice-speaker-vbat");
+ backend_tag_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
+ backend_tag_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
+ backend_tag_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
+ backend_tag_table[SND_DEVICE_OUT_HEADPHONES] = strdup("headphones");
+ backend_tag_table[SND_DEVICE_OUT_HEADPHONES_44_1] = strdup("headphones-44.1");
+ backend_tag_table[SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = strdup("voice-speaker-vbat");
+
+ 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_VOICE_TX] = strdup("AFE_PCM_RX");
/*remove ALAC & APE from DSP decoder list based on software decoder availability*/
@@ -1644,6 +1649,11 @@
}
}
+ my_data->current_backend_cfg[HEADPHONE_BACKEND].bitwidth_mixer_ctl =
+ strdup("SLIM_6_RX Format");
+ my_data->current_backend_cfg[HEADPHONE_BACKEND].samplerate_mixer_ctl =
+ strdup("SLIM_6_RX SampleRate");
+
my_data->edid_info = NULL;
free(snd_card_name);
free(snd_card_name_t);
@@ -1669,9 +1679,9 @@
int32_t dev;
for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
- if (backend_table[dev]) {
- free(backend_table[dev]);
- backend_table[dev]= NULL;
+ if (backend_tag_table[dev]) {
+ free(backend_tag_table[dev]);
+ backend_tag_table[dev]= NULL;
}
}
@@ -1748,7 +1758,7 @@
return;
}
- const char * suffix = backend_table[snd_device];
+ const char * suffix = backend_tag_table[snd_device];
if (suffix != NULL) {
strlcat(mixer_path, " ", MIXER_PATH_MAX_LENGTH);
@@ -1756,6 +1766,40 @@
}
}
+bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_device2)
+{
+ bool result = true;
+
+ ALOGV("%s: snd_device1 = %s, snd_device2 = %s", __func__,
+ platform_get_snd_device_name(snd_device1),
+ platform_get_snd_device_name(snd_device2));
+
+ if ((snd_device1 < SND_DEVICE_MIN) || (snd_device1 >= SND_DEVICE_OUT_END)) {
+ ALOGE("%s: Invalid snd_device = %s", __func__,
+ platform_get_snd_device_name(snd_device1));
+ return false;
+ }
+ if ((snd_device2 < SND_DEVICE_MIN) || (snd_device2 >= SND_DEVICE_OUT_END)) {
+ ALOGE("%s: Invalid snd_device = %s", __func__,
+ platform_get_snd_device_name(snd_device2));
+ return false;
+ }
+ const char * be_itf1 = hw_interface_table[snd_device1];
+ const char * be_itf2 = hw_interface_table[snd_device2];
+
+ if (NULL != be_itf1 && NULL != be_itf2) {
+ if (0 != strcmp(be_itf1, be_itf2))
+ result = false;
+ } else if (NULL == be_itf1 && NULL != be_itf2) {
+ result = false;
+ } else if (NULL != be_itf1 && NULL == be_itf2) {
+ result = false;
+ }
+
+ ALOGV("%s: be_itf1 = %s, be_itf2 = %s, match %d", __func__, be_itf1, be_itf2, result);
+ return result;
+}
+
int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type)
{
int device_id;
@@ -1879,6 +1923,8 @@
goto done;
}
+ ALOGV("%s: acdb_device_table[%s]: old = %d new = %d", __func__,
+ platform_get_snd_device_name(snd_device), acdb_device_table[snd_device], acdb_id);
acdb_device_table[snd_device] = acdb_id;
done:
return ret;
@@ -2069,21 +2115,26 @@
return ret;
}
-int platform_get_backend_index(snd_device_t snd_device)
+static int platform_get_backend_index(snd_device_t snd_device)
{
int32_t port = DEFAULT_CODEC_BACKEND;
if (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX) {
- if (backend_table[snd_device] != NULL &&
- strcmp(backend_table[snd_device], "headphones-44.1") == 0)
- port = HEADPHONE_44_1_BACKEND;
- else
- port = DEFAULT_CODEC_BACKEND;
+ if (backend_tag_table[snd_device] != NULL) {
+ if (strncmp(backend_tag_table[snd_device], "headphones-44.1",
+ sizeof("headphones-44.1")) == 0)
+ port = HEADPHONE_44_1_BACKEND;
+ else if (strncmp(backend_tag_table[snd_device], "headphones",
+ sizeof("headphones")) == 0)
+ port = HEADPHONE_BACKEND;
+ else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
+ port = HDMI_RX_BACKEND;
+ }
} else {
ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
}
- ALOGV("%s:napb: backend port - %d", __func__, port);
+ ALOGV("%s:napb: backend port - %d snd_device %d", __func__, port, snd_device);
return port;
}
@@ -2094,9 +2145,11 @@
int acdb_dev_id, acdb_dev_type;
struct audio_device *adev = my_data->adev;
int snd_device = SND_DEVICE_OUT_SPEAKER;
+ int new_snd_device[SND_DEVICE_OUT_END];
+ int i, num_devices = 1;
if (usecase->type == PCM_PLAYBACK)
- snd_device = usecase->out_snd_device;
+ snd_device = usecase->out_snd_device;
else if ((usecase->type == PCM_CAPTURE) &&
voice_is_in_call_rec_stream(usecase->stream.in))
snd_device = voice_get_incall_rec_snd_device(usecase->in_snd_device);
@@ -2109,17 +2162,32 @@
__func__, snd_device);
return -EINVAL;
}
- if (my_data->acdb_send_audio_cal) {
- ALOGV("%s: sending audio calibration for snd_device(%d) acdb_id(%d)",
- __func__, snd_device, acdb_dev_id);
- if (snd_device >= SND_DEVICE_OUT_BEGIN &&
- snd_device < SND_DEVICE_OUT_END)
- acdb_dev_type = ACDB_DEV_TYPE_OUT;
- else
- acdb_dev_type = ACDB_DEV_TYPE_IN;
- my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
- sample_rate);
+
+ if(!platform_can_split_snd_device(my_data, snd_device,
+ &num_devices, new_snd_device)) {
+ new_snd_device[0] = snd_device;
}
+
+ for (i = 0; i < num_devices; i++) {
+ acdb_dev_id = acdb_device_table[platform_get_spkr_prot_snd_device(new_snd_device[i])];
+ if (acdb_dev_id < 0) {
+ ALOGE("%s: Could not find acdb id for device(%d)",
+ __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;
+ my_data->acdb_send_audio_cal(acdb_dev_id, acdb_dev_type, app_type,
+ sample_rate);
+ }
+ }
+
return 0;
}
@@ -2388,6 +2456,43 @@
return ret;
}
+bool platform_can_split_snd_device(void *platform,
+ snd_device_t snd_device,
+ int *num_devices,
+ snd_device_t *new_snd_devices)
+{
+ bool status = false;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if (NULL == num_devices || NULL == new_snd_devices) {
+ ALOGE("%s: NULL pointer ..", __func__);
+ return false;
+ }
+
+ /*
+ * If wired headset/headphones/line devices share the same backend
+ * with speaker/earpiece this routine returns false.
+ */
+ if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_HEADPHONES)) {
+ *num_devices = 2;
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+ new_snd_devices[1] = SND_DEVICE_OUT_HEADPHONES;
+ status = true;
+ } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_HDMI)) {
+ *num_devices = 2;
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+ new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
+ status = true;
+ }
+
+ ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
+ snd_device, *num_devices, *new_snd_devices);
+
+ return status;
+}
+
snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
{
struct platform_data *my_data = (struct platform_data *)platform;
@@ -3712,7 +3817,7 @@
/*
* configures afe with bit width and Sample Rate
*/
-int platform_set_codec_backend_cfg(struct audio_device* adev,
+static int platform_set_codec_backend_cfg(struct audio_device* adev,
snd_device_t snd_device,
unsigned int bit_width, unsigned int sample_rate)
{
@@ -3810,7 +3915,7 @@
* goes through all the current usecases and picks the highest
* bitwidth & samplerate
*/
-bool platform_check_codec_backend_cfg(struct audio_device* adev,
+static bool platform_check_codec_backend_cfg(struct audio_device* adev,
struct audio_usecase* usecase,
snd_device_t snd_device,
unsigned int* new_bit_width,
@@ -3822,7 +3927,6 @@
unsigned int bit_width;
unsigned int sample_rate;
int backend_idx = DEFAULT_CODEC_BACKEND;
- int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
int na_mode = platform_get_native_support();
@@ -3861,8 +3965,6 @@
uc = node_to_item(node, struct audio_usecase, list);
struct stream_out *out = (struct stream_out*) uc->stream.out;
if (uc->type == PCM_PLAYBACK && out && usecase != uc) {
- usecase_backend_idx =
- platform_get_backend_index(uc->out_snd_device);
ALOGD("%s:napb: (%d) - (%s)id (%d) sr %d bw "
"(%d) device %s", __func__, i++, use_case_table[uc->id],
@@ -3870,7 +3972,7 @@
out->bit_width,
platform_get_snd_device_name(uc->out_snd_device));
- if (usecase_backend_idx == backend_idx) {
+ if (platform_check_backends_match(snd_device, uc->out_snd_device)) {
if (bit_width < out->bit_width)
bit_width = out->bit_width;
if (sample_rate < out->sample_rate)
@@ -3908,10 +4010,12 @@
* hifi playback not supported on spkr devices, limit the Sample Rate
* to 48 khz.
*/
- if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (SND_DEVICE_OUT_SPEAKER == snd_device ||
+ SND_DEVICE_OUT_SPEAKER_WSA == snd_device ||
+ SND_DEVICE_OUT_SPEAKER_VBAT == snd_device) {
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- ALOGD("%s:becf: afe: playback on speakers Configure afe to \
- default Sample Rate(48k)", __func__);
+ ALOGD("%s:becf: afe: playback on speaker device Configure afe to "
+ "default Sample Rate(48k)", __func__);
}
/*
@@ -3947,6 +4051,9 @@
unsigned int new_sample_rate;
int backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
+ int new_snd_devices[SND_DEVICE_OUT_END];
+ int i, num_devices = 1;
+ bool ret = false;
backend_idx = platform_get_backend_index(snd_device);
@@ -3958,17 +4065,25 @@
new_sample_rate, backend_idx, usecase->id,
platform_get_snd_device_name(snd_device));
- if (platform_check_codec_backend_cfg(adev, usecase, snd_device,
- &new_bit_width, &new_sample_rate)) {
- platform_set_codec_backend_cfg(adev, snd_device,
- new_bit_width, new_sample_rate);
- return true;
+
+ if (!platform_can_split_snd_device(my_data, snd_device, &num_devices, new_snd_devices))
+ new_snd_devices[0] = snd_device;
+
+ for (i = 0; i < num_devices; i++) {
+ ALOGI("%s: new_snd_devices[%d] is %d", __func__, i, new_snd_devices[i]);
+ if (platform_check_codec_backend_cfg(adev, usecase, new_snd_devices[i],
+ &new_bit_width, &new_sample_rate)) {
+ platform_set_codec_backend_cfg(adev, new_snd_devices[i],
+ new_bit_width, new_sample_rate);
+ ret = true;
+ }
}
- return false;
+ return ret;
}
-int platform_set_snd_device_backend(snd_device_t device, const char *backend)
+int platform_set_snd_device_backend(snd_device_t device, const char *backend_tag,
+ const char * hw_interface)
{
int ret = 0;
@@ -3979,10 +4094,22 @@
goto done;
}
- if (backend_table[device]) {
- free(backend_table[device]);
+ ALOGD("%s: backend_tag_table[%s]: old = %s new = %s", __func__,
+ platform_get_snd_device_name(device),
+ backend_tag_table[device] != NULL ? backend_tag_table[device]: "null",
+ backend_tag);
+ if (backend_tag_table[device]) {
+ free(backend_tag_table[device]);
}
- backend_table[device] = strdup(backend);
+ backend_tag_table[device] = strdup(backend_tag);
+
+ if (hw_interface != NULL) {
+ if (hw_interface_table[device])
+ free(hw_interface_table[device]);
+
+ ALOGD("%s: hw_interface_table[%d] = %s", __func__, device, hw_interface);
+ hw_interface_table[device] = strdup(hw_interface);
+ }
done:
return ret;
}
@@ -4000,6 +4127,7 @@
ALOGE("%s: invalid usecase type", __func__);
ret = -EINVAL;
}
+ ALOGV("%s: pcm_device_table[%d][%d] = %d", __func__, usecase, type, pcm_id);
pcm_device_table[usecase][type] = pcm_id;
done:
return ret;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 4f2bb3d..b7375e5 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -182,7 +182,12 @@
enum {
DEFAULT_CODEC_BACKEND,
+ SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
HEADPHONE_44_1_BACKEND,
+ SLIMBUS_5_RX = HEADPHONE_44_1_BACKEND,
+ HEADPHONE_BACKEND,
+ SLIMBUS_6_RX = HEADPHONE_BACKEND,
+ HDMI_RX_BACKEND,
MAX_CODEC_BACKENDS
};
diff --git a/hal/platform_api.h b/hal/platform_api.h
index fb72e40..65bcc98 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -54,7 +54,6 @@
int platform_get_snd_device_bit_width(snd_device_t snd_device);
int platform_set_native_support(int na_mode);
int platform_get_native_support();
-int platform_get_backend_index(snd_device_t snd_device);
int platform_send_audio_calibration(void *platform, struct audio_usecase *usecase,
int app_type, int sample_rate);
int platform_get_default_app_type(void *platform);
@@ -99,7 +98,8 @@
bool platform_sound_trigger_device_needs_event(snd_device_t snd_device);
bool platform_sound_trigger_usecase_needs_event(audio_usecase_t uc_id);
-int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend);
+int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend,
+ const char * hw_interface);
/* From platform_info.c */
int platform_info_init(const char *filename, void *);
@@ -138,4 +138,10 @@
int platform_get_spkr_prot_acdb_id(snd_device_t snd_device);
int platform_get_spkr_prot_snd_device(snd_device_t snd_device);
int platform_spkr_prot_is_wsa_analog_mode(void *adev);
+bool platform_can_split_snd_device(void *platform,
+ snd_device_t snd_device,
+ int *num_devices,
+ snd_device_t *new_snd_devices);
+
+bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_device2);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 92cc930..21c85a9 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -177,6 +177,7 @@
static void process_backend_name(const XML_Char **attr)
{
int index;
+ char *hw_interface = NULL;
if (strcmp(attr[0], "name") != 0) {
ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
@@ -196,7 +197,15 @@
goto done;
}
- if (platform_set_snd_device_backend(index, attr[3]) < 0) {
+ if (attr[4] != NULL) {
+ if (strcmp(attr[4], "interface") != 0) {
+ hw_interface = NULL;
+ } else {
+ hw_interface = (char *)attr[5];
+ }
+ }
+
+ if (platform_set_snd_device_backend(index, attr[3], hw_interface) < 0) {
ALOGE("%s: Device %s backend %s was not set!",
__func__, attr[1], attr[3]);
goto done;