Merge "hal: Add ACDB support for 8976 tasha lite"
diff --git a/hal/Android.mk b/hal/Android.mk
index 74de942..0545423 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -54,6 +54,7 @@
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_EDID)),true)
LOCAL_SRC_FILES += edid.c
+ LOCAL_CFLAGS := -DHDMI_EDID_ENABLED
endif
ifeq ($(strip $(AUDIO_USE_LL_AS_PRIMARY_OUTPUT)),true)
@@ -68,6 +69,10 @@
LOCAL_CFLAGS += -DANC_HEADSET_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_VBAT_MONITOR)),true)
+ LOCAL_CFLAGS += -DVBAT_MONITOR_ENABLED
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLUENCE)),true)
LOCAL_CFLAGS += -DFLUENCE_ENABLED
endif
@@ -251,6 +256,12 @@
LOCAL_SRC_FILES += audio_extn/listen.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_HDMI)),true)
+ LOCAL_CFLAGS += -DAUDIO_EXTERNAL_HDMI_ENABLED
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-parsers
+ LOCAL_SHARED_LIBRARIES += libaudioparsers
+endif
+
ifeq ($(strip $(BOARD_SUPPORTS_SOUND_TRIGGER)),true)
LOCAL_CFLAGS += -DSOUND_TRIGGER_ENABLED
LOCAL_CFLAGS += -DSOUND_TRIGGER_PLATFORM_NAME=$(TARGET_BOARD_PLATFORM)
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 67d30ca..34da4fe 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -62,6 +62,7 @@
bool custom_stereo_enabled;
uint32_t proxy_channel_num;
bool hpx_enabled;
+ bool vbat_enabled;
};
static struct audio_extn_module aextnmod = {
@@ -70,6 +71,7 @@
.custom_stereo_enabled = 0,
.proxy_channel_num = 2,
.hpx_enabled = 0,
+ .vbat_enabled = 0,
};
#define AUDIO_PARAMETER_KEY_ANC "anc_enabled"
@@ -216,6 +218,27 @@
}
#endif
+#ifdef VBAT_MONITOR_ENABLED
+bool audio_extn_is_vbat_enabled(void)
+{
+ ALOGD("%s: status: %d", __func__, aextnmod.vbat_enabled);
+ return (aextnmod.vbat_enabled ? true: false);
+}
+
+bool audio_extn_can_use_vbat(void)
+{
+ char prop_vbat_enabled[PROPERTY_VALUE_MAX] = "false";
+
+ property_get("persist.audio.vbat.enabled", prop_vbat_enabled, "0");
+ if (!strncmp("true", prop_vbat_enabled, 4)) {
+ aextnmod.vbat_enabled = 1;
+ }
+
+ ALOGD("%s: vbat.enabled property is set to %s", __func__, prop_vbat_enabled);
+ return (aextnmod.vbat_enabled ? true: false);
+}
+#endif
+
#ifndef ANC_HEADSET_ENABLED
#define audio_extn_set_anc_parameters(adev, parms) (0)
#else
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 8bcc885..9391bec 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -117,6 +117,14 @@
bool audio_extn_should_use_handset_anc(int in_channels);
#endif
+#ifndef VBAT_MONITOR_ENABLED
+#define audio_extn_is_vbat_enabled() (0)
+#define audio_extn_can_use_vbat() (0)
+#else
+bool audio_extn_is_vbat_enabled(void);
+bool audio_extn_can_use_vbat(void);
+#endif
+
#ifndef FLUENCE_ENABLED
#define audio_extn_set_fluence_parameters(adev, parms) (0)
#define audio_extn_get_fluence_parameters(adev, query, reply) (0)
@@ -476,6 +484,7 @@
int b64decode(char *inp, int ilen, uint8_t* outp);
int b64encode(uint8_t *inp, int ilen, char* outp);
+int read_line_from_file(const char *path, char *buf, size_t count);
#ifndef KPI_OPTIMIZE_ENABLED
#define audio_extn_perf_lock_init() (0)
@@ -486,4 +495,10 @@
void audio_extn_perf_lock_acquire(void);
void audio_extn_perf_lock_release(void);
#endif /* KPI_OPTIMIZE_ENABLED */
+
+#ifndef AUDIO_EXTERNAL_HDMI_ENABLED
+#define setChannelStatus(out, buffer, bytes) (0)
+#else
+void setChannelStatus(struct stream_out *out, char * buffer, size_t bytes);
+#endif
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index efc2307..0ef7c7e 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -251,7 +251,7 @@
* Currently, platform_get_wsa_mode will directly return
* 1 when wsa is in analog mode.
*/
- if (platform_get_wsa_mode(adev->platform) == 1) {
+ if (platform_get_wsa_mode(adev) == 1) {
fm_stop(adev);
fm_start(adev);
} else {
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c
index 3c16c88..c13c2f3 100644
--- a/hal/audio_extn/soundtrigger.c
+++ b/hal/audio_extn/soundtrigger.c
@@ -334,6 +334,18 @@
event.u.value = val;
st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
}
+
+ ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
+ if ((ret >= 0) && audio_is_input_device(val)) {
+ event.u.value = val;
+ st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
+ }
+
+ ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
+ if ((ret >= 0) && audio_is_input_device(val)) {
+ event.u.value = val;
+ st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
+ }
}
int audio_extn_sound_trigger_init(struct audio_device *adev)
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 391a501..858a00e 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -58,6 +58,10 @@
#define SAFE_SPKR_TEMP 40
#define SAFE_SPKR_TEMP_Q6 (SAFE_SPKR_TEMP * (1 << 6))
+/*Bongo Spkr temp range*/
+#define TZ_TEMP_MIN_THRESHOLD (5)
+#define TZ_TEMP_MAX_THRESHOLD (45)
+
/*Range of resistance values 2ohms to 40 ohms*/
#define MIN_RESISTANCE_SPKR_Q24 (2 * (1 << 24))
#define MAX_RESISTANCE_SPKR_Q24 (40 * (1 << 24))
@@ -90,6 +94,11 @@
#define SPKR_PROCESSING_IN_PROGRESS 1
#define SPKR_PROCESSING_IN_IDLE 0
+#ifdef PLATFORM_MSM8916
+#define ACDB_DEVICE_SPKR_PROT_WSA_ANALOG 136
+#define ACDB_DEVICE_VI_FEEDBACK_WSA_ANALOG 137
+#endif
+
#define MAX_PATH (256)
#define THERMAL_SYSFS "/sys/class/thermal"
#define TZ_TYPE "/sys/class/thermal/thermal_zone%d/type"
@@ -147,27 +156,6 @@
static struct speaker_prot_session handle;
static int vi_feed_no_channels;
-int read_line_from_file(const char *path, char *buf, size_t count)
-{
- char * fgets_ret;
- FILE * fd;
- int rv;
-
- fd = fopen(path, "r");
- if (fd == NULL)
- return -1;
-
- fgets_ret = fgets(buf, (int)count, fd);
- if (NULL != fgets_ret) {
- rv = (int)strlen(buf);
- } else {
- rv = ferror(fd);
- }
- fclose(fd);
-
- return rv;
-}
-
/*===========================================================================
FUNCTION get_tzn
@@ -214,7 +202,8 @@
snprintf(name, MAX_PATH, TZ_TYPE, tzn);
ALOGD("Opening %s\n", name);
read_line_from_file(name, buf, sizeof(buf));
- buf[strlen(buf)] = '\0';
+ if (strlen(buf) > 0)
+ buf[strlen(buf) - 1] = '\0';
if (!strcmp(buf, sensor_name)) {
found = 1;
break;
@@ -445,10 +434,16 @@
uc_info_rx->type = PCM_PLAYBACK;
uc_info_rx->in_snd_device = SND_DEVICE_NONE;
uc_info_rx->stream.out = adev->primary_output;
- uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED;
+ if (audio_extn_is_vbat_enabled())
+ uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT;
+ else
+ uc_info_rx->out_snd_device = SND_DEVICE_OUT_SPEAKER_PROTECTED;
disable_rx = true;
list_add_tail(&adev->usecase_list, &uc_info_rx->list);
- enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
+ if (audio_extn_is_vbat_enabled())
+ enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT);
+ else
+ enable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
enable_audio_route(adev, uc_info_rx);
pcm_dev_rx_id = platform_get_pcm_device_id(uc_info_rx->id, PCM_PLAYBACK);
@@ -485,6 +480,7 @@
enable_audio_route(adev, uc_info_tx);
pcm_dev_tx_id = platform_get_pcm_device_id(uc_info_tx->id, PCM_CAPTURE);
+ ALOGV("%s: pcm device id %d", __func__, pcm_dev_tx_id);
if (pcm_dev_tx_id < 0) {
ALOGE("%s: Invalid pcm device for usecase (%d)",
__func__, uc_info_tx->id);
@@ -606,7 +602,10 @@
}
if (disable_rx) {
list_remove(&uc_info_rx->list);
- disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
+ if (audio_extn_is_vbat_enabled())
+ disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT);
+ else
+ disable_snd_device(adev, SND_DEVICE_OUT_SPEAKER_PROTECTED);
disable_audio_route(adev, uc_info_rx);
}
if (disable_tx) {
@@ -647,6 +646,7 @@
char wsa_path[MAX_PATH] = {0};
int spk_1_tzn, spk_2_tzn;
char buf[32] = {0};
+ int ret;
/* If the value of this persist.spkr.cal.duration is 0
* then it means it will take 30min to calibrate
@@ -724,24 +724,23 @@
close(acdb_fd);
}
+ ALOGV("%s: start calibration", __func__);
while (1) {
- ALOGV("%s: start calibration", __func__);
if (handle.wsa_found) {
spk_1_tzn = handle.spkr_1_tzn;
spk_2_tzn = handle.spkr_2_tzn;
goahead = false;
pthread_mutex_lock(&adev->lock);
if (is_speaker_in_use(&sec)) {
- ALOGD("%s: WSA Speaker in use retry calibration", __func__);
+ ALOGV("%s: WSA Speaker in use retry calibration", __func__);
pthread_mutex_unlock(&adev->lock);
continue;
} else {
- ALOGD("%s: wsa speaker idle %ld min time %ld", __func__, sec, min_idle_time);
if (sec < min_idle_time) {
- ALOGD("%s: speaker idle is less retry", __func__);
pthread_mutex_unlock(&adev->lock);
continue;
}
+ ALOGV("%s: wsa speaker idle %ld min time %ld", __func__, sec, min_idle_time);
goahead = true;
}
if (!list_empty(&adev->usecase_list)) {
@@ -751,18 +750,22 @@
if (goahead) {
if (spk_1_tzn > 0) {
snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_1_tzn);
- ALOGD("%s: wsa_path: %s\n", __func__, wsa_path);
+ ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
thermal_fd = -1;
thermal_fd = open(wsa_path, O_RDONLY);
if (thermal_fd > 0) {
for (i = 0; i < NUM_ATTEMPTS; i++) {
- if (read(thermal_fd, buf, sizeof(buf))) {
+ if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
t0_spk_1 = atoi(buf);
- if (i > 0 && (t0_spk_1 != t0_spk_prior))
+ if (i > 0 && (t0_spk_1 != t0_spk_prior)) {
+ ALOGE("%s: spkr1 curr temp: %d, prev temp: %d\n",
+ __func__, t0_spk_1, t0_spk_prior);
break;
+ }
t0_spk_prior = t0_spk_1;
+ sleep(1);
} else {
- ALOGE("%s: read fail for %s\n", __func__, wsa_path);
+ ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
break;
}
}
@@ -771,28 +774,38 @@
ALOGE("%s: fd for %s is NULL\n", __func__, wsa_path);
}
if (i == NUM_ATTEMPTS) {
+ if (t0_spk_1 < TZ_TEMP_MIN_THRESHOLD ||
+ t0_spk_1 > TZ_TEMP_MAX_THRESHOLD) {
+ pthread_mutex_unlock(&adev->lock);
+ continue;
+ }
/*Convert temp into q6 format*/
t0_spk_1 = (t0_spk_1 * (1 << 6));
- ALOGE("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
+ ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
} else {
- ALOGE("%s: thermal equilibrium failed for spkr1 in %d readings\n",
- __func__, NUM_ATTEMPTS);
- t0_spk_1 = SAFE_SPKR_TEMP_Q6;
+ ALOGV("%s: thermal equilibrium failed for spkr1 in %d/%d readings\n",
+ __func__, i, NUM_ATTEMPTS);
+ pthread_mutex_unlock(&adev->lock);
+ continue;
}
}
if (spk_2_tzn > 0) {
snprintf(wsa_path, MAX_PATH, TZ_WSA, spk_2_tzn);
- ALOGE("%s: wsa_path: %s\n", __func__, wsa_path);
+ ALOGV("%s: wsa_path: %s\n", __func__, wsa_path);
thermal_fd = open(wsa_path, O_RDONLY);
if (thermal_fd > 0) {
for (i = 0; i < NUM_ATTEMPTS; i++) {
- if (read(thermal_fd, buf, sizeof(buf))) {
+ if ((ret = read(thermal_fd, buf, sizeof(buf))) >= 0) {
t0_spk_2 = atoi(buf);
- if (i > 0 && (t0_spk_2 != t0_spk_prior))
+ if (i > 0 && (t0_spk_2 != t0_spk_prior)) {
+ ALOGE("%s: spkr2 curr temp: %d, prev temp: %d\n",
+ __func__, t0_spk_2, t0_spk_prior);
break;
+ }
t0_spk_prior = t0_spk_2;
+ sleep(1);
} else {
- ALOGE("%s: read fail for %s\n", __func__, wsa_path);
+ ALOGE("%s: read fail for %s err:%d\n", __func__, wsa_path, ret);
break;
}
}
@@ -801,13 +814,19 @@
ALOGE("%s: fd for %s is NULL\n", __func__, wsa_path);
}
if (i == NUM_ATTEMPTS) {
+ if (t0_spk_2 < TZ_TEMP_MIN_THRESHOLD ||
+ t0_spk_2 > TZ_TEMP_MAX_THRESHOLD) {
+ pthread_mutex_unlock(&adev->lock);
+ continue;
+ }
/*Convert temp into q6 format*/
t0_spk_2 = (t0_spk_2 * (1 << 6));
- ALOGE("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
+ ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
} else {
- ALOGE("%s: thermal equilibrium failed for spkr2 in %d readings\n",
- __func__, NUM_ATTEMPTS);
- t0_spk_2 = SAFE_SPKR_TEMP_Q6;
+ ALOGV("%s: thermal equilibrium failed for spkr2 in %d/%d readings\n",
+ __func__, i, NUM_ATTEMPTS);
+ pthread_mutex_unlock(&adev->lock);
+ continue;
}
}
}
@@ -838,16 +857,15 @@
goahead = false;
pthread_mutex_lock(&adev->lock);
if (is_speaker_in_use(&sec)) {
- ALOGD("%s: Speaker in use retry calibration", __func__);
+ ALOGV("%s: Speaker in use retry calibration", __func__);
pthread_mutex_unlock(&adev->lock);
continue;
} else {
- ALOGD("%s: speaker idle %ld min time %ld", __func__, sec, min_idle_time);
if (sec < min_idle_time) {
- ALOGD("%s: speaker idle is less retry", __func__);
pthread_mutex_unlock(&adev->lock);
continue;
}
+ ALOGD("%s: speaker idle %ld min time %ld", __func__, sec, min_idle_time);
goahead = true;
}
if (!list_empty(&adev->usecase_list)) {
@@ -925,6 +943,24 @@
handle.spkr_prot_t0 = -1;
if (is_wsa_present()) {
+#ifdef PLATFORM_MSM8916
+ if (platform_get_wsa_mode(adev) == 1) {
+ ALOGD("%s: WSA analog mode", __func__);
+ platform_set_snd_device_backend(SND_DEVICE_OUT_VOICE_SPEAKER_WSA,
+ "speaker-protected");
+ platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED,
+ ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
+ platform_set_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+ ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
+ platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT,
+ ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
+ platform_set_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT,
+ ACDB_DEVICE_SPKR_PROT_WSA_ANALOG);
+ platform_set_snd_device_acdb_id(SND_DEVICE_IN_CAPTURE_VI_FEEDBACK,
+ ACDB_DEVICE_VI_FEEDBACK_WSA_ANALOG);
+ pcm_config_skr_prot.channels = 2;
+ }
+#endif
pthread_cond_init(&handle.spkr_calib_cancel, NULL);
pthread_cond_init(&handle.spkr_calibcancel_ack, NULL);
pthread_mutex_init(&handle.mutex_spkr_prot, NULL);
@@ -999,9 +1035,21 @@
switch(snd_device) {
case SND_DEVICE_OUT_SPEAKER:
+#ifdef PLATFORM_MSM8916
+ case SND_DEVICE_OUT_SPEAKER_WSA:
+#endif
acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED);
break;
+ case SND_DEVICE_OUT_SPEAKER_VBAT:
+ acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT);
+ break;
+ case SND_DEVICE_OUT_VOICE_SPEAKER_VBAT:
+ acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT);
+ break;
case SND_DEVICE_OUT_VOICE_SPEAKER:
+#ifdef PLATFORM_MSM8916
+ case SND_DEVICE_OUT_VOICE_SPEAKER_WSA:
+#endif
acdb_id = platform_get_snd_device_acdb_id(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED);
break;
default:
@@ -1018,8 +1066,18 @@
switch(snd_device) {
case SND_DEVICE_OUT_SPEAKER:
+#ifdef PLATFORM_MSM8916
+ case SND_DEVICE_OUT_SPEAKER_WSA:
+#endif
return SND_DEVICE_OUT_SPEAKER_PROTECTED;
+ case SND_DEVICE_OUT_SPEAKER_VBAT:
+ return SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT;
+ case SND_DEVICE_OUT_VOICE_SPEAKER_VBAT:
+ return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT;
case SND_DEVICE_OUT_VOICE_SPEAKER:
+#ifdef PLATFORM_MSM8916
+ case SND_DEVICE_OUT_VOICE_SPEAKER_WSA:
+#endif
return SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED;
default:
return snd_device;
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index a2b644e..dac6c26 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -35,6 +35,10 @@
#include "audio_extn.h"
#include "voice.h"
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#include "audio_parsers.h"
+#endif
+
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
#define OUTPUTS_TAG "outputs"
@@ -52,6 +56,21 @@
#define BASE_TABLE_SIZE 64
#define MAX_BASEINDEX_LEN 256
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#define PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
+#define NON_LPCM (1<<1) /* 0 = audio, 1 = non-audio */
+#define SR_44100 (0<<0) /* 44.1kHz */
+#define SR_NOTID (1<<0) /* non indicated */
+#define SR_48000 (2<<0) /* 48kHz */
+#define SR_32000 (3<<0) /* 32kHz */
+#define SR_22050 (4<<0) /* 22.05kHz */
+#define SR_24000 (6<<0) /* 24kHz */
+#define SR_88200 (8<<0) /* 88.2kHz */
+#define SR_96000 (10<<0) /* 96kHz */
+#define SR_176400 (12<<0) /* 176.4kHz */
+#define SR_192000 (14<<0) /* 192kHz */
+
+#endif
struct string_to_enum {
const char *name;
uint32_t value;
@@ -583,6 +602,27 @@
return rc;
}
+int read_line_from_file(const char *path, char *buf, size_t count)
+{
+ char * fgets_ret;
+ FILE * fd;
+ int rv;
+
+ fd = fopen(path, "r");
+ if (fd == NULL)
+ return -1;
+
+ fgets_ret = fgets(buf, (int)count, fd);
+ if (NULL != fgets_ret) {
+ rv = (int)strlen(buf);
+ } else {
+ rv = ferror(fd);
+ }
+ fclose(fd);
+
+ return rv;
+}
+
void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
struct audio_usecase *usecase)
{
@@ -747,3 +787,130 @@
outp[k] = '\0';
return k;
}
+
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+
+void get_default_compressed_channel_status(
+ unsigned char *channel_status)
+{
+ int32_t status = 0;
+ unsigned char bit_index;
+ memset(channel_status,0,24);
+
+ /* block start bit in preamble bit 3 */
+ channel_status[0] |= PROFESSIONAL;
+ //compre out
+ channel_status[0] |= NON_LPCM;
+ // sample rate; fixed 48K for default/transcode
+ channel_status[3] |= SR_48000;
+}
+
+int32_t get_compressed_channel_status(void *audio_stream_data,
+ uint32_t audio_frame_size,
+ unsigned char *channel_status,
+ enum audio_parser_code_type codec_type)
+ // codec_type - AUDIO_PARSER_CODEC_AC3
+ // - AUDIO_PARSER_CODEC_DTS
+{
+ unsigned char *streamPtr;
+ int ret = 0;
+ streamPtr = (unsigned char *)audio_stream_data;
+
+ if (audio_stream_data == NULL || audio_frame_size == 0) {
+ ALOGW("no buffer to get channel status, return default for compress");
+ get_default_compressed_channel_status(channel_status);
+ return ret;
+ }
+
+ memset(channel_status,0,24);
+ if(init_audio_parser(streamPtr, audio_frame_size, codec_type) == -1)
+ {
+ ALOGE("init audio parser failed");
+ return -1;
+ }
+ ret = get_channel_status(channel_status, codec_type);
+ return ret;
+
+}
+
+void get_linearpcm_channel_status(uint32_t sampleRate,
+ unsigned char *channel_status)
+{
+ int32_t status = 0;
+ unsigned char bit_index;
+ memset(channel_status,0,24);
+ /* block start bit in preamble bit 3 */
+ channel_status[0] |= PROFESSIONAL;
+ //LPCM OUT
+ channel_status[0] &= ~NON_LPCM;
+
+ switch (sampleRate) {
+ case 8000:
+ case 11025:
+ case 12000:
+ case 16000:
+ case 22050:
+ channel_status[3] |= SR_NOTID;
+ case 24000:
+ channel_status[3] |= SR_24000;
+ break;
+ case 32000:
+ channel_status[3] |= SR_32000;
+ break;
+ case 44100:
+ channel_status[3] |= SR_44100;
+ break;
+ case 48000:
+ channel_status[3] |= SR_48000;
+ break;
+ case 88200:
+ channel_status[3] |= SR_88200;
+ break;
+ case 96000:
+ channel_status[3] |= SR_96000;
+ break;
+ case 176400:
+ channel_status[3] |= SR_176400;
+ break;
+ case 192000:
+ channel_status[3] |= SR_192000;
+ break;
+ default:
+ ALOGV("Invalid sample_rate %u\n", sampleRate);
+ status = -1;
+ break;
+ }
+}
+
+void setChannelStatus(struct stream_out *out, char * buffer, size_t bytes)
+{
+ unsigned char channel_status[24]={0};
+ struct snd_aes_iec958 iec958;
+ const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
+ struct mixer_ctl *ctl;
+ int i=0;
+ if (audio_extn_is_dolby_format(out->format) &&
+ /*TODO:Extend code to support DTS passthrough*/
+ /*set compressed channel status bits*/
+ audio_extn_dolby_is_passthrough_stream(out->flags)){
+ get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
+ } else {
+ /*set channel status bit for LPCM*/
+ get_linearpcm_channel_status(out->sample_rate, channel_status);
+ }
+
+ memcpy(iec958.status, channel_status,sizeof(iec958.status));
+ ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return;
+ }
+ if (mixer_ctl_set_array(ctl, &iec958, sizeof(iec958)) < 0) {
+ ALOGE("%s: Could not set channel status for ext HDMI ",
+ __func__);
+ return;
+ }
+
+}
+#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 3286e6b..3b423f1 100755
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -421,7 +421,7 @@
audio_extn_utils_send_audio_calibration(adev, usecase);
audio_extn_utils_send_app_type_cfg(usecase);
strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
- platform_add_backend_name(mixer_path, snd_device);
+ platform_add_backend_name(mixer_path, snd_device, usecase);
ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
audio_route_apply_and_update_path(adev->audio_route, mixer_path);
ALOGV("%s: exit", __func__);
@@ -443,7 +443,7 @@
else
snd_device = usecase->out_snd_device;
strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
- platform_add_backend_name(mixer_path, snd_device);
+ platform_add_backend_name(mixer_path, snd_device, usecase);
ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
audio_route_reset_and_update_path(adev->audio_route, mixer_path);
audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
@@ -486,7 +486,8 @@
if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
audio_extn_usb_start_capture(adev);
- if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
+ if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
+ snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
audio_extn_spkr_prot_is_enabled()) {
if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
@@ -556,7 +557,8 @@
if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
audio_extn_usb_stop_capture();
- if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
+ if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
+ snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
audio_extn_spkr_prot_is_enabled()) {
audio_extn_spkr_prot_stop_processing(snd_device);
@@ -564,6 +566,12 @@
audio_route_reset_and_update_path(adev->audio_route, device_name);
}
+ if (snd_device == SND_DEVICE_OUT_HDMI)
+ adev->mChannelStatusSet = false;
+
+ if (snd_device == SND_DEVICE_OUT_HDMI)
+ adev->mChannelStatusSet = false;
+
audio_extn_dev_arbi_release(snd_device);
audio_extn_sound_trigger_update_device_status(snd_device,
ST_EVENT_SND_DEVICE_FREE);
@@ -658,10 +666,9 @@
specified usecase to new snd devices */
list_for_each(node, &adev->usecase_list) {
usecase = node_to_item(node, struct audio_usecase, list);
- /* Update the out_snd_device only before enabling the audio route */
- if (switch_device[usecase->id] ) {
- usecase->out_snd_device = snd_device;
- if (usecase->type != VOICE_CALL)
+ /* Update the out_snd_device only for the usecases that are enabled here */
+ if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
+ usecase->out_snd_device = snd_device;
enable_audio_route(adev, usecase);
}
}
@@ -695,7 +702,8 @@
if (usecase->type != PCM_PLAYBACK &&
usecase != uc_info &&
usecase->in_snd_device != snd_device &&
- (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+ ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+ ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
(usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
__func__, use_case_table[usecase->id],
@@ -2127,6 +2135,11 @@
}
}
+ if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
+ setChannelStatus(out, buffer, bytes);
+ adev->mChannelStatusSet = true;
+ }
+
if (is_offload_usecase(out->usecase)) {
ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
if (out->send_new_metadata) {
@@ -2783,7 +2796,6 @@
out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
out->non_blocking = 0;
out->use_small_bufs = false;
-
/* Init use case and pcm_config */
if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
@@ -2891,7 +2903,7 @@
}
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
out->compr_config.codec->sample_rate =
- compress_get_alsa_rate(config->offload_info.sample_rate);
+ config->offload_info.sample_rate;
out->compr_config.codec->bit_rate =
config->offload_info.bit_rate;
out->compr_config.codec->ch_in =
@@ -3348,6 +3360,7 @@
if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
voice_is_in_call(adev)) {
voice_stop_call(adev);
+ platform_set_gsm_mode(adev->platform, false);
adev->current_call_output = NULL;
}
}
@@ -3665,6 +3678,7 @@
list_init(&adev->usecase_list);
adev->cur_wfd_channels = 2;
adev->offload_usecases_state = 0;
+ adev->mChannelStatusSet = false;
pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 67f5279..45e90b7 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -311,6 +311,7 @@
int snd_card;
unsigned int cur_codec_backend_samplerate;
unsigned int cur_codec_backend_bit_width;
+ bool mChannelStatusSet;
void *platform;
unsigned int offload_usecases_state;
void *visualizer_lib;
diff --git a/hal/msm8916/hw_info.c b/hal/msm8916/hw_info.c
index fb36a95..613c1a7 100644
--- a/hal/msm8916/hw_info.c
+++ b/hal/msm8916/hw_info.c
@@ -257,6 +257,12 @@
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, "msm8976-skun-snd-card")) {
+ strlcpy(hw_info->type, "", sizeof(hw_info->type));
+ strlcpy(hw_info->name, "msm8976", 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 {
ALOGW("%s: Not an 8x16/8939/8909/8952 device", __func__);
}
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 76e8b8d..92b4f13 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -52,6 +52,7 @@
#define MIXER_XML_PATH_SKUE "/system/etc/mixer_paths_skue.xml"
#define MIXER_XML_PATH_SKUL "/system/etc/mixer_paths_skul.xml"
#define MIXER_XML_PATH_SKUM "/system/etc/mixer_paths_qrd_skum.xml"
+#define MIXER_XML_PATH_SKUN_CAJON "/system/etc/mixer_paths_qrd_skun_cajon.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
#define MIXER_XML_PATH_I2S "/system/etc/mixer_paths_i2s.xml"
@@ -137,6 +138,7 @@
char cal_name_info[WCD9XXX_MAX_CAL][MAX_CAL_NAME] = {
[WCD9XXX_ANC_CAL] = "anc_cal",
[WCD9XXX_MBHC_CAL] = "mbhc_cal",
+ [WCD9XXX_VBAT_CAL] = "vbat_cal",
};
#define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
@@ -189,6 +191,7 @@
acdb_loader_get_calibration_t acdb_loader_get_calibration;
typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
+typedef int (*acdb_set_codec_data_t) (void *, char *);
typedef struct codec_backend_cfg {
uint32_t sample_rate;
@@ -221,6 +224,9 @@
bool ec_ref_enabled;
bool is_wsa_speaker;
bool is_acdb_initialized;
+ /* Vbat monitor related flags */
+ bool is_vbat_speaker;
+ bool gsm_mode_enabled;
/* Audio calibration related functions */
void *acdb_handle;
int voice_feature_set;
@@ -232,6 +238,7 @@
acdb_send_voice_cal_t acdb_send_voice_cal;
acdb_reload_vocvoltable_t acdb_reload_vocvoltable;
acdb_get_default_app_type_t acdb_get_default_app_type;
+ acdb_set_codec_data_t acdb_set_codec_data;
#ifdef RECORD_PLAY_CONCURRENCY
bool rec_play_conc_set;
#endif
@@ -323,6 +330,7 @@
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = "speaker-ext-1",
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
[SND_DEVICE_OUT_SPEAKER_WSA] = "wsa-speaker",
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = "vbat-speaker",
[SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
[SND_DEVICE_OUT_HEADPHONES] = "headphones",
[SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
@@ -332,6 +340,7 @@
[SND_DEVICE_OUT_VOICE_HANDSET] = "voice-handset",
[SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
[SND_DEVICE_OUT_VOICE_SPEAKER_WSA] = "wsa-voice-speaker",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = "vbat-voice-speaker",
[SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
[SND_DEVICE_OUT_HDMI] = "hdmi",
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
@@ -353,6 +362,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = "anc-handset",
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = "speaker-protected",
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = "voice-speaker-protected",
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = "speaker-protected-vbat",
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = "voice-speaker-protected-vbat",
#ifdef RECORD_PLAY_CONCURRENCY
[SND_DEVICE_OUT_VOIP_HANDSET] = "voip-handset",
[SND_DEVICE_OUT_VOIP_SPEAKER] = "voip-speaker",
@@ -428,6 +439,7 @@
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_1] = 14,
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 14,
[SND_DEVICE_OUT_SPEAKER_WSA] = 135,
+ [SND_DEVICE_OUT_SPEAKER_VBAT] = 135,
[SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
[SND_DEVICE_OUT_HEADPHONES] = 10,
[SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
@@ -437,6 +449,7 @@
[SND_DEVICE_OUT_VOICE_HANDSET] = 7,
[SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
[SND_DEVICE_OUT_VOICE_SPEAKER_WSA] = 135,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_VBAT] = 135,
[SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
[SND_DEVICE_OUT_HDMI] = 18,
[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = 14,
@@ -458,6 +471,8 @@
[SND_DEVICE_OUT_ANC_HANDSET] = 103,
[SND_DEVICE_OUT_SPEAKER_PROTECTED] = 124,
[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = 101,
+ [SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT] = 124,
+ [SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT] = 101,
#ifdef RECORD_PLAY_CONCURRENCY
[SND_DEVICE_OUT_VOIP_HANDSET] = 133,
[SND_DEVICE_OUT_VOIP_SPEAKER] = 132,
@@ -535,6 +550,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_WSA)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES_44_1)},
@@ -544,6 +560,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_WSA)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_VBAT)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HDMI)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HDMI)},
@@ -565,6 +582,8 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_ANC_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT)},
#ifdef RECORD_PLAY_CONCURRENCY
{TO_NAME_INDEX(SND_DEVICE_OUT_VOIP_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_VOIP_SPEAKER)},
@@ -657,6 +676,7 @@
{TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
{TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
{TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
+ {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
};
#define NO_COLS 2
@@ -930,7 +950,13 @@
msm_device_to_be_id = msm_device_to_be_id_internal_codec;
msm_be_id_array_len =
sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
-
+ } else if (!strncmp(snd_card_name, "msm8976-skun-snd-card",
+ sizeof("msm8976-skun-snd-card"))) {
+ strlcpy(mixer_xml_path, MIXER_XML_PATH_SKUN_CAJON,
+ sizeof(MIXER_XML_PATH_SKUN_CAJON));
+ msm_device_to_be_id = msm_device_to_be_id_internal_codec;
+ msm_be_id_array_len =
+ sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
} else {
strlcpy(mixer_xml_path, MIXER_XML_PATH,
sizeof(MIXER_XML_PATH));
@@ -942,21 +968,43 @@
}
}
-void platform_set_echo_reference(void *platform, bool enable)
+void platform_set_gsm_mode(void *platform, bool enable)
{
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
+ if (my_data->gsm_mode_enabled) {
+ my_data->gsm_mode_enabled = false;
+ ALOGV("%s: disabling gsm mode", __func__);
+ audio_route_reset_and_update_path(adev->audio_route, "gsm-mode");
+ }
+
+ if (enable) {
+ my_data->gsm_mode_enabled = true;
+ ALOGD("%s: enabling gsm mode", __func__);
+ audio_route_apply_and_update_path(adev->audio_route, "gsm-mode");
+ }
+}
+
+void platform_set_echo_reference(void *platform, bool enable)
+{
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ char *mixer_path_name = "echo-reference";
+
+ if(my_data->is_vbat_speaker)
+ mixer_path_name = "vbat-speaker echo-reference";
+
if (my_data->ec_ref_enabled) {
my_data->ec_ref_enabled = false;
ALOGV("%s: disabling echo-reference", __func__);
- audio_route_reset_and_update_path(adev->audio_route, "echo-reference");
+ audio_route_reset_and_update_path(adev->audio_route, mixer_path_name);
}
if (enable) {
my_data->ec_ref_enabled = true;
ALOGD("%s: enabling echo-reference", __func__);
- audio_route_apply_and_update_path(adev->audio_route, "echo-reference");
+ audio_route_apply_and_update_path(adev->audio_route, mixer_path_name);
}
}
@@ -1135,6 +1183,7 @@
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");
}
void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1190,7 +1239,37 @@
void *buff;
};
-static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, int fd)
+static int send_vbat_adc_data_to_acdb(struct platform_data *plat_data, char *cal_type)
+{
+ int ret = 0;
+ struct mixer_ctl *ctl;
+ uint16_t vbat_adc_data[2];
+ struct platform_data *my_data = plat_data;
+ struct audio_device *adev = my_data->adev;
+
+ const char *mixer_ctl_name = "Vbat ADC data";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer ctl name - %s",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ vbat_adc_data[0] = mixer_ctl_get_value(ctl, 0);
+ vbat_adc_data[1] = mixer_ctl_get_value(ctl, 1);
+
+ ALOGD("%s: Vbat ADC output values: Dcp1: %d , Dcp2: %d",
+ __func__, vbat_adc_data[0], vbat_adc_data[1]);
+
+ ret = my_data->acdb_set_codec_data(&vbat_adc_data[0], cal_type);
+
+done:
+ return ret;
+}
+
+static int send_codec_cal(acdb_loader_get_calibration_t acdb_loader_get_calibration, struct platform_data *plat_data, int fd)
{
int ret = 0, type;
@@ -1198,6 +1277,12 @@
struct wcdcal_ioctl_buffer codec_buffer;
struct param_data calib;
+ if((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+ ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
+ if (ret < 0)
+ ALOGE("%s error in sending vbat adc data to acdb", __func__);
+ }
+
calib.get_size = 1;
ret = acdb_loader_get_calibration(cal_name_info[type], sizeof(struct param_data),
&calib);
@@ -1251,7 +1336,7 @@
dlerror());
return;
}
- if (send_codec_cal(acdb_loader_get_calibration, fd) < 0)
+ if (send_codec_cal(acdb_loader_get_calibration, plat_data, fd) < 0)
ALOGE("%s: Could not send anc cal", __FUNCTION__);
}
@@ -1307,6 +1392,67 @@
return result;
}
+#define MAX_PATH (256)
+#define THERMAL_SYSFS "/sys/class/thermal"
+#define TZ_TYPE "/sys/class/thermal/thermal_zone%d/type"
+#define TZ_WSA "/sys/class/thermal/thermal_zone%d/temp"
+
+static bool is_wsa_found(int *wsaCount)
+{
+ DIR *tdir = NULL;
+ struct dirent *tdirent = NULL;
+ int tzn = 0;
+ char name[MAX_PATH] = {0};
+ char cwd[MAX_PATH] = {0};
+ char file[10] = "wsa";
+ bool found = false;
+ int wsa_count = 0;
+
+ if (!getcwd(cwd, sizeof(cwd)))
+ return false;
+
+ chdir(THERMAL_SYSFS); /* Change dir to read the entries. Doesnt work
+ otherwise */
+ tdir = opendir(THERMAL_SYSFS);
+ if (!tdir) {
+ ALOGE("Unable to open %s\n", THERMAL_SYSFS);
+ return false;
+ }
+
+ while ((tdirent = readdir(tdir))) {
+ char buf[50];
+ struct dirent *tzdirent;
+ DIR *tzdir = NULL;
+
+ tzdir = opendir(tdirent->d_name);
+ if (!tzdir)
+ continue;
+ while ((tzdirent = readdir(tzdir))) {
+ if (strcmp(tzdirent->d_name, "type"))
+ continue;
+ snprintf(name, MAX_PATH, TZ_TYPE, tzn);
+ ALOGD("Opening %s\n", name);
+ read_line_from_file(name, buf, sizeof(buf));
+ if (strstr(buf, file)) {
+ wsa_count++;
+ /*We support max only two WSA speakers*/
+ if (wsa_count == 2)
+ break;
+ }
+ tzn++;
+ }
+ closedir(tzdir);
+ }
+ if (wsa_count > 0){
+ ALOGD("Found %d WSA present on the platform", wsa_count);
+ found = true;
+ *wsaCount = wsa_count;
+ }
+ closedir(tdir);
+ chdir(cwd); /* Restore current working dir */
+ return found;
+}
+
void *platform_init(struct audio_device *adev)
{
char platform[PROPERTY_VALUE_MAX];
@@ -1320,6 +1466,7 @@
const char *mixer_ctl_name = "Set HPX ActiveBe";
struct mixer_ctl *ctl = NULL;
int idx;
+ int wsaCount =0;
my_data = calloc(1, sizeof(struct platform_data));
if (!my_data) {
@@ -1430,6 +1577,17 @@
my_data->fluence_mode = FLUENCE_BROADSIDE;
}
}
+
+ if (is_wsa_found(&wsaCount)) {
+ /*Set ACDB ID of Stereo speaker if two WSAs are present*/
+ /*Default ACDB ID for wsa speaker is that for mono*/
+ if (wsaCount == 2) {
+ platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_WSA, 15);
+ platform_set_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_VBAT, 15);
+ }
+ my_data->is_wsa_speaker = true;
+ }
+
property_get("persist.audio.FFSP.enable", ffspEnable, "");
if (!strncmp("true", ffspEnable, sizeof("true"))) {
acdb_device_table[SND_DEVICE_OUT_SPEAKER] = 131;
@@ -1439,6 +1597,12 @@
acdb_device_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] = 131;
}
+ /* Check if Vbat speaker enabled property is set, this should be done before acdb init */
+ bool ret = false;
+ ret = audio_extn_can_use_vbat();
+ if (ret)
+ my_data->is_vbat_speaker = true;
+
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
if (my_data->acdb_handle == NULL) {
@@ -1488,6 +1652,14 @@
ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
__func__, LIB_ACDB_LOADER);
+ my_data->acdb_set_codec_data = (acdb_set_codec_data_t)dlsym(
+ my_data->acdb_handle,
+ "acdb_loader_set_codec_data");
+ if (!my_data->acdb_set_codec_data)
+ ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
+ __func__, LIB_ACDB_LOADER);
+
+
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_v2");
if (my_data->acdb_init == NULL) {
@@ -1498,25 +1670,6 @@
}
audio_extn_pm_vote();
- // Check if WSA speaker is supported in codec
- char CodecPeek[1024] = "/sys/kernel/debug/asoc/";
- DIR *dir;
- struct dirent *dirent;
- char file_name[10] = "wsa";
- strlcat(CodecPeek, snd_card_name, sizeof(CodecPeek));
-
- dir = opendir(CodecPeek);
- if (dir != NULL) {
- while (NULL != (dirent = readdir(dir))) {
- if (strstr (dirent->d_name,file_name))
- {
- my_data->is_wsa_speaker = true;
- break;
- }
- }
- closedir(dir);
- }
-
/* Configure active back end for HPX*/
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (ctl) {
@@ -1547,7 +1700,6 @@
audio_extn_dap_hal_init(adev->snd_card);
audio_extn_dolby_set_license(adev);
- audio_hwdep_send_cal(my_data);
/* init audio device arbitration */
audio_extn_dev_arbi_init();
@@ -1641,13 +1793,20 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
+ struct audio_usecase *usecase)
{
if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
return;
}
+ if((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ !(usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)) {
+ ALOGI("%s: Not adding vbat speaker device to non voice use cases", __func__);
+ return;
+ }
+
const char * suffix = backend_table[snd_device];
if (suffix != NULL) {
@@ -2012,9 +2171,12 @@
return ret;
if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2072,9 +2234,12 @@
return ret;
if (out_snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled())
- acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
- else
+ audio_extn_spkr_prot_is_enabled()) {
+ if (my_data->is_vbat_speaker)
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT];
+ else
+ acdb_rx_id = acdb_device_table[SND_DEVICE_OUT_SPEAKER_PROTECTED];
+ } else
acdb_rx_id = acdb_device_table[out_snd_device];
acdb_tx_id = acdb_device_table[in_snd_device];
@@ -2336,7 +2501,9 @@
else
snd_device = SND_DEVICE_OUT_BT_SCO;
} else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
- if (my_data->is_wsa_speaker)
+ if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WSA;
else
snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
@@ -2396,7 +2563,9 @@
snd_device = SND_DEVICE_OUT_SPEAKER_REVERSE;
else
{
- if (my_data->is_wsa_speaker)
+ if (my_data->is_vbat_speaker)
+ snd_device = SND_DEVICE_OUT_SPEAKER_VBAT;
+ else if (my_data->is_wsa_speaker)
snd_device = SND_DEVICE_OUT_SPEAKER_WSA;
else
snd_device = SND_DEVICE_OUT_SPEAKER;
@@ -4045,14 +4214,15 @@
edid_data[0] = count;
memcpy(&edid_data[1], block, count);
-#ifdef AUDIO_FEATURE_ENABLED_HDMI_EDID
+#ifdef HDMI_EDID_ENABLED
if (!edid_get_sink_caps(info, edid_data)) {
ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
goto fail;
}
+#endif
+
my_data->edid_valid = true;
return 0;
-#endif
fail:
if (my_data->edid_info) {
free(my_data->edid_info);
@@ -4528,13 +4698,14 @@
return ret;
}
-int platform_get_wsa_mode(void *platform)
+int platform_get_wsa_mode(void *adev)
{
- struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev_h = adev;
char *snd_card_name;
- snd_card_name = mixer_get_name(my_data->adev->mixer);
+ snd_card_name = mixer_get_name(adev_h->mixer);
if ((!strcmp(snd_card_name, "msm8952-skum-snd-card")) ||
+ (!strcmp(snd_card_name, "msm8952-snd-card")) ||
(!strcmp(snd_card_name, "msm8952-snd-card-mtp")))
return 1;
else
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 9f0015a..bf5e834 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -47,6 +47,15 @@
(AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
+/*
+ * Below are the input devices for which back end is same, SLIMBUS_0_TX.
+ * All these devices are handled by the internal HW codec. We can
+ * enable any one of these devices at any time
+ */
+#define AUDIO_DEVICE_IN_ALL_CODEC_BACKEND \
+ (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC | \
+ AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_VOICE_CALL) & ~AUDIO_DEVICE_BIT_IN
+
/* Sound devices specific to the platform
* The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
* devices to enable corresponding mixer paths
@@ -63,6 +72,7 @@
SND_DEVICE_OUT_SPEAKER_EXTERNAL_2,
SND_DEVICE_OUT_SPEAKER_REVERSE,
SND_DEVICE_OUT_SPEAKER_WSA,
+ SND_DEVICE_OUT_SPEAKER_VBAT,
SND_DEVICE_OUT_HEADPHONES,
SND_DEVICE_OUT_HEADPHONES_44_1,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
@@ -71,6 +81,7 @@
SND_DEVICE_OUT_VOICE_HANDSET,
SND_DEVICE_OUT_VOICE_SPEAKER,
SND_DEVICE_OUT_VOICE_SPEAKER_WSA,
+ SND_DEVICE_OUT_VOICE_SPEAKER_VBAT,
SND_DEVICE_OUT_VOICE_HEADPHONES,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_SPEAKER_AND_HDMI,
@@ -92,6 +103,8 @@
SND_DEVICE_OUT_ANC_HANDSET,
SND_DEVICE_OUT_SPEAKER_PROTECTED,
SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
+ SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT,
+ SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED_VBAT,
#ifdef RECORD_PLAY_CONCURRENCY
SND_DEVICE_OUT_VOIP_HANDSET,
SND_DEVICE_OUT_VOIP_SPEAKER,
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 038effa..d8801ab 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -382,7 +382,7 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device, struct audio_usecase *usecase)
{
if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
@@ -1181,7 +1181,7 @@
return -ENOSYS;
}
-int platform_get_wsa_mode(void *platform)
+int platform_get_wsa_mode(void *adev)
{
return 0;
}
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index 4b4d14e..aab5436 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2015 The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -35,6 +35,15 @@
(AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
+/*
+ * Below are the input devices for which back end is same, SLIMBUS_0_TX.
+ * All these devices are handled by the internal HW codec. We can
+ * enable any one of these devices at any time
+ */
+#define AUDIO_DEVICE_IN_ALL_CODEC_BACKEND \
+ (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC | \
+ AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_VOICE_CALL) & ~AUDIO_DEVICE_BIT_IN
+
/* Sound devices specific to the platform
* The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
* devices to enable corresponding mixer paths
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index c0c5fe1..d215a89 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1440,7 +1440,7 @@
return 0;
}
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device, struct audio_usecase *usecase)
{
if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
@@ -4097,7 +4097,7 @@
return ret;
}
-int platform_get_wsa_mode (void *platform)
+int platform_get_wsa_mode (void *adev)
{
return 0;
}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 4b90f8b..79e0816 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -45,6 +45,15 @@
(AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
+/*
+ * Below are the input devices for which back end is same, SLIMBUS_0_TX.
+ * All these devices are handled by the internal HW codec. We can
+ * enable any one of these devices at any time
+ */
+#define AUDIO_DEVICE_IN_ALL_CODEC_BACKEND \
+ (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC | \
+ AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_VOICE_CALL) & ~AUDIO_DEVICE_BIT_IN
+
/* Sound devices specific to the platform
* The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
* devices to enable corresponding mixer paths
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 3a6dc02..53ddb48 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -31,7 +31,7 @@
const char *platform_get_snd_device_name(snd_device_t snd_device);
int platform_get_snd_device_name_extn(void *platform, snd_device_t snd_device,
char *device_name);
-void platform_add_backend_name(char *mixer_path, snd_device_t snd_device);
+void platform_add_backend_name(char *mixer_path, snd_device_t snd_device, struct audio_usecase *usecase);
int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type);
int platform_get_snd_device_index(char *snd_device_index_name);
int platform_set_fluence_type(void *platform, char *value);
@@ -122,5 +122,6 @@
const char *spkr_1_tz_name, const char *spkr_2_tz_name);
const char *platform_get_spkr_1_tz_name(snd_device_t snd_device);
const char *platform_get_spkr_2_tz_name(snd_device_t snd_device);
-int platform_get_wsa_mode(void *platform);
+int platform_get_wsa_mode(void *adev);
+void platform_set_gsm_mode(void *platform, bool enable);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index 960b46e..3cf370d 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -42,6 +42,7 @@
#define AUDIO_PARAMETER_KEY_DEVICE_MUTE "device_mute"
#define AUDIO_PARAMETER_KEY_DIRECTION "direction"
#define AUDIO_PARAMETER_KEY_IN_CALL "in_call"
+#define AUDIO_PARAMETER_KEY_CALL_TYPE "call_type"
#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
@@ -515,6 +516,20 @@
}
}
+ err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CALL_TYPE, str_value,
+ sizeof(str_value));
+ if (err >= 0) {
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_CALL_TYPE);
+ ALOGD("%s: call type is %s",__func__,str_value);
+
+ /* Expected call types are CDMA/GSM/WCDMA/LTE/TDSDMA/WLAN/UNKNOWN */
+ if (!strncmp("GSM", str_value, sizeof("GSM"))) {
+ platform_set_gsm_mode(adev->platform, true);
+ } else {
+ platform_set_gsm_mode(adev->platform, false);
+ }
+ }
+
done:
ALOGV("%s: exit with code(%d)", __func__, ret);
free(kv_pairs);