hal: Add support for Native Audio(44.1kHz)
- Changes for device/Usecase selection
- Add new and combo devices for headphones
- Combo device handling
- Add new backend and logic to handle multiple
backends
- Remove hardcoded mixers and select them
dynamically based on the device
Change-Id: I7207291f2c27da13ba0cc77c66de1144f4b9888a
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 82b596f..dbfac87 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -430,6 +430,7 @@
* than all sample rates in list for the input bit width.
*/
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+
list_for_each(node_i, &so_info->sample_rate_list) {
ss_info = node_to_item(node_i, struct stream_sample_rate, list);
if ((sample_rate <= ss_info->sample_rate) &&
@@ -437,7 +438,7 @@
app_type_cfg->app_type = so_info->app_type_cfg.app_type;
app_type_cfg->sample_rate = sample_rate;
app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
- ALOGV("%s Assuming default sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
+ ALOGV("%s Assuming sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
__func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
return true;
}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 3d157da..266dbd9 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -603,7 +603,12 @@
bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
/* Disable all the usecases on the shared backend other than the
- specified usecase */
+ * specified usecase.
+ * For native(44.1k) usecases, we don't need this as it uses a different
+ * backend, but we need to make sure that we reconfigure the backend
+ * if there is bit_width change, this should not affect shared backend
+ * usecases.
+ */
for (i = 0; i < AUDIO_USECASE_MAX; i++)
switch_device[i] = false;
@@ -612,13 +617,20 @@
if (usecase->type != PCM_CAPTURE &&
usecase != uc_info &&
(usecase->out_snd_device != snd_device || force_routing) &&
- usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
+ usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND
+ && usecase->stream.out->sample_rate != OUTPUT_SAMPLING_RATE_44100) {
ALOGV("%s: Usecase (%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++;
+ } else if (usecase->type == PCM_PLAYBACK &&
+ usecase->stream.out->sample_rate ==
+ OUTPUT_SAMPLING_RATE_44100 && force_routing){
+ disable_audio_route(adev, usecase);
+ switch_device[usecase->id] = true;
+ num_uc_to_switch++;
}
}
@@ -814,7 +826,7 @@
(usecase->type == VOIP_CALL) ||
(usecase->type == PCM_HFP_CALL)) {
out_snd_device = platform_get_output_snd_device(adev->platform,
- usecase->stream.out->devices);
+ usecase->stream.out);
in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
usecase->devices = usecase->stream.out->devices;
} else {
@@ -854,7 +866,7 @@
in_snd_device = SND_DEVICE_NONE;
if (out_snd_device == SND_DEVICE_NONE) {
out_snd_device = platform_get_output_snd_device(adev->platform,
- usecase->stream.out->devices);
+ usecase->stream.out);
if (usecase->stream.out == adev->primary_output &&
adev->active_input &&
adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
@@ -3637,8 +3649,6 @@
adev->bluetooth_nrec = true;
adev->acdb_settings = TTY_MODE_OFF;
/* adev->cur_hdmi_channels = 0; by calloc() */
- adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
voice_init(adev);
list_init(&adev->usecase_list);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 67f5279..0fc52f4 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -309,8 +309,6 @@
bool bt_wb_speech_enabled;
int snd_card;
- unsigned int cur_codec_backend_samplerate;
- unsigned int cur_codec_backend_bit_width;
void *platform;
unsigned int offload_usecases_state;
void *visualizer_lib;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index b4c4c44..7b8f2d3 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -171,6 +171,11 @@
typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);
typedef int (*acdb_get_audio_cal_t) (void *, void *, uint32_t*);
+typedef struct codec_backend_cfg {
+ uint32_t sample_rate;
+ uint32_t bit_width;
+}codec_backend_t;
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -203,6 +208,7 @@
struct csd_data *csd;
void *edid_info;
bool edid_valid;
+ codec_backend_t backend_cfg[MAX_PORT];
};
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -287,6 +293,7 @@
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = "speaker-ext-2",
[SND_DEVICE_OUT_SPEAKER_REVERSE] = "speaker-reverse",
[SND_DEVICE_OUT_HEADPHONES] = "headphones",
+ [SND_DEVICE_OUT_HEADPHONES_44_1] = "headphones-44.1",
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = "speaker-and-headphones-ext-1",
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = "speaker-and-headphones-ext-2",
@@ -384,9 +391,10 @@
[SND_DEVICE_OUT_SPEAKER_EXTERNAL_2] = 130,
[SND_DEVICE_OUT_SPEAKER_REVERSE] = 14,
[SND_DEVICE_OUT_HEADPHONES] = 10,
+ [SND_DEVICE_OUT_HEADPHONES_44_1] = 10,
[SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = 10,
- [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = 130,
- [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 130,
+ [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1] = 10,
+ [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2] = 10,
[SND_DEVICE_OUT_VOICE_HANDSET] = 7,
[SND_DEVICE_OUT_VOICE_SPEAKER] = 14,
[SND_DEVICE_OUT_VOICE_HEADPHONES] = 10,
@@ -475,7 +483,7 @@
#define TO_NAME_INDEX(X) #X, X
-/* Used to get index from parsed sting */
+/* Used to get index from parsed string */
static struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
{TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
@@ -483,6 +491,7 @@
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_2)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_REVERSE)},
{TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES)},
+ {TO_NAME_INDEX(SND_DEVICE_OUT_HEADPHONES_44_1)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2)},
@@ -901,6 +910,8 @@
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");
}
void get_cvd_version(char *cvd_version, struct audio_device *adev)
@@ -1028,6 +1039,7 @@
char *snd_internal_name = NULL;
char *tmp = NULL;
char mixer_xml_file[MIXER_PATH_MAX_LENGTH]= {0};
+ int idx;
my_data = calloc(1, sizeof(struct platform_data));
@@ -1291,6 +1303,12 @@
/* init audio device arbitration */
audio_extn_dev_arbi_init();
+ /* initialize backend config */
+ for (idx = 0; idx < MAX_PORT; idx++) {
+ my_data->backend_cfg[idx].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->backend_cfg[idx].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ }
+
my_data->edid_info = NULL;
return my_data;
}
@@ -1550,7 +1568,7 @@
if (usecase->type == PCM_PLAYBACK)
snd_device = platform_get_output_snd_device(adev->platform,
- usecase->stream.out->devices);
+ usecase->stream.out);
else if ((usecase->type == PCM_HFP_CALL) || (usecase->type == PCM_CAPTURE))
snd_device = platform_get_input_snd_device(adev->platform,
adev->primary_output->devices);
@@ -1831,12 +1849,14 @@
return ret;
}
-snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices)
+snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out)
{
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
audio_mode_t mode = adev->mode;
snd_device_t snd_device = SND_DEVICE_NONE;
+ audio_devices_t devices = out->devices;
+ unsigned int sample_rate = out->sample_rate;
audio_channel_mask_t channel_mask = (adev->active_input == NULL) ?
AUDIO_CHANNEL_IN_MONO : adev->active_input->channel_mask;
@@ -1949,8 +1969,10 @@
snd_device = SND_DEVICE_OUT_ANC_FB_HEADSET;
else
snd_device = SND_DEVICE_OUT_ANC_HEADSET;
- } else
- snd_device = SND_DEVICE_OUT_HEADPHONES;
+ } else if (OUTPUT_SAMPLING_RATE_44100 == sample_rate)
+ snd_device = SND_DEVICE_OUT_HEADPHONES_44_1;
+ else
+ snd_device = SND_DEVICE_OUT_HEADPHONES;
} else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
if (my_data->external_spk_1)
snd_device = SND_DEVICE_OUT_SPEAKER_EXTERNAL_1;
@@ -2507,6 +2529,7 @@
uint8_t *dptr = NULL;
int32_t dlen;
int err, ret;
+ struct stream_out out;
if(value == NULL || platform == NULL || parms == NULL) {
ALOGE("[%s] received null pointer, failed",__func__);
goto done_key_audcal;
@@ -2539,7 +2562,8 @@
if(audio_is_input_device(cal.dev_id)) {
cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
} else {
- cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
+ out.devices = cal.dev_id;
+ cal.snd_dev_id = platform_get_output_snd_device(platform, &out);
}
}
cal.acdb_dev_id = platform_get_snd_device_acdb_id(cal.snd_dev_id);
@@ -2770,6 +2794,7 @@
char *rparms=NULL;
int ret=0, err;
uint32_t param_len;
+ struct stream_out out;
if(query==NULL || platform==NULL || reply==NULL) {
ALOGE("[%s] received null pointer",__func__);
@@ -2792,7 +2817,8 @@
if(cal.dev_id & AUDIO_DEVICE_BIT_IN) {
cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
} else if(cal.dev_id) {
- cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
+ out.devices = cal.dev_id;
+ cal.snd_dev_id = platform_get_output_snd_device(platform, &out);
}
cal.acdb_dev_id = platform_get_snd_device_acdb_id(cal.snd_dev_id);
if (cal.acdb_dev_id < 0) {
@@ -3036,13 +3062,27 @@
}
int platform_set_codec_backend_cfg(struct audio_device* adev,
+ struct audio_usecase *usecase,
unsigned int bit_width, unsigned int sample_rate)
{
+ int ret = 0;
+ char backend_port = ALL_CODEC_BACKEND_PORT;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
ALOGV("%s bit width: %d, sample rate: %d", __func__, bit_width, sample_rate);
- int ret = 0;
- if (bit_width != adev->cur_codec_backend_bit_width) {
- const char * mixer_ctl_name = "SLIM_0_RX Format";
+ if(usecase->stream.out->devices & SND_DEVICE_OUT_HEADPHONES_44_1)
+ backend_port = HEADPHONE_44_1_BACKEND_PORT;
+
+ // form the mixer string with appropriate backend port
+ char * mixer_ctl_name = "SLIM_";
+ strlcat(mixer_ctl_name, &backend_port, sizeof(mixer_ctl_name));
+ strlcat(mixer_ctl_name, "_RX Format", sizeof(mixer_ctl_name));
+ ALOGV("%s: Format mixer command - %s", __func__, mixer_ctl_name);
+
+ if (bit_width !=
+ my_data->backend_cfg[(int)backend_port].bit_width) {
+
struct mixer_ctl *ctl;
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
if (!ctl) {
@@ -3057,7 +3097,7 @@
mixer_ctl_set_enum_by_string(ctl, "S16_LE");
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
}
- adev->cur_codec_backend_bit_width = bit_width;
+ my_data->backend_cfg[(int)backend_port].bit_width = bit_width;
ALOGE("Backend bit width is set to %d ", bit_width);
}
@@ -3070,9 +3110,15 @@
* Upper limit is inclusive in the sample rate range.
*/
// TODO: This has to be more dynamic based on policy file
- if (sample_rate != adev->cur_codec_backend_samplerate) {
+ // form the mixer string with appropriate backend port
+ mixer_ctl_name = "SLIM_";
+ strlcat(mixer_ctl_name, &backend_port, sizeof(mixer_ctl_name));
+ strlcat(mixer_ctl_name, "_RX SampleRate", sizeof(mixer_ctl_name));
+ ALOGV("%s: SampleRate mixer command - %s", __func__, mixer_ctl_name);
+
+ if (sample_rate !=
+ my_data->backend_cfg[(int)backend_port].sample_rate) {
char *rate_str = NULL;
- const char * mixer_ctl_name = "SLIM_0_RX SampleRate";
struct mixer_ctl *ctl;
switch (sample_rate) {
@@ -3108,7 +3154,7 @@
ALOGV("Set sample rate as rate_str = %s", rate_str);
mixer_ctl_set_enum_by_string(ctl, rate_str);
- adev->cur_codec_backend_samplerate = sample_rate;
+ my_data->backend_cfg[(int)backend_port].sample_rate = sample_rate;
}
return ret;
@@ -3124,6 +3170,11 @@
struct stream_out *out = NULL;
unsigned int bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
unsigned int sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ char backend_port = ALL_CODEC_BACKEND_PORT;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ if(usecase->stream.out->devices & SND_DEVICE_OUT_HEADPHONES_44_1)
+ backend_port = HEADPHONE_44_1_BACKEND_PORT;
// For voice calls use default configuration
// force routing is not required here, caller will do it anyway
@@ -3172,8 +3223,8 @@
}
// Force routing if the expected bitwdith or samplerate
// is not same as current backend comfiguration
- if ((bit_width != adev->cur_codec_backend_bit_width) ||
- (sample_rate != adev->cur_codec_backend_samplerate)) {
+ if ((bit_width != my_data->backend_cfg[(int)backend_port].bit_width) ||
+ (sample_rate != my_data->backend_cfg[(int)backend_port].sample_rate)) {
*new_bit_width = bit_width;
*new_sample_rate = sample_rate;
backend_change = true;
@@ -3186,18 +3237,23 @@
bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase)
{
- ALOGV("platform_check_and_set_codec_backend_cfg usecase = %d",usecase->id );
-
unsigned int new_bit_width, old_bit_width;
unsigned int new_sample_rate, old_sample_rate;
+ char backend_port = ALL_CODEC_BACKEND_PORT;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
- new_bit_width = old_bit_width = adev->cur_codec_backend_bit_width;
- new_sample_rate = old_sample_rate = adev->cur_codec_backend_samplerate;
+ ALOGV("platform_check_and_set_codec_backend_cfg usecase = %d",usecase->id );
+
+ if(usecase->stream.out->devices & SND_DEVICE_OUT_HEADPHONES_44_1)
+ backend_port = HEADPHONE_44_1_BACKEND_PORT;
+
+ new_bit_width = old_bit_width = my_data->backend_cfg[(int)backend_port].bit_width;
+ new_sample_rate = old_sample_rate = my_data->backend_cfg[(int)backend_port].sample_rate;
ALOGW("Codec backend bitwidth %d, samplerate %d", old_bit_width, old_sample_rate);
if (platform_check_codec_backend_cfg(adev, usecase,
&new_bit_width, &new_sample_rate)) {
- platform_set_codec_backend_cfg(adev, new_bit_width, new_sample_rate);
+ platform_set_codec_backend_cfg(adev, usecase, new_bit_width, new_sample_rate);
return true;
}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 83922d5..b863a22 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -35,7 +35,11 @@
/*
* Below are the devices for which is back end is same, SLIMBUS_0_RX.
* All these devices are handled by the internal HW codec. We can
- * enable any one of these devices at any time
+ * enable any one of these devices at any time. An exception here is
+ * 44.1k headphone which uses different backend. This is filtered
+ * as different hal internal device in the code but remains same
+ * as standard android device AUDIO_DEVICE_OUT_WIRED_HEADPHONE
+ * for other layers.
*/
#define AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND \
(AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | \
@@ -57,7 +61,9 @@
SND_DEVICE_OUT_SPEAKER_EXTERNAL_2,
SND_DEVICE_OUT_SPEAKER_REVERSE,
SND_DEVICE_OUT_HEADPHONES,
+ SND_DEVICE_OUT_HEADPHONES_44_1,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
+ SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_44_1,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_1,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES_EXTERNAL_2,
SND_DEVICE_OUT_VOICE_HANDSET,
@@ -151,7 +157,11 @@
};
-#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#define OUTPUT_SAMPLING_RATE_44100 44100
+#define MAX_PORT 6
+#define ALL_CODEC_BACKEND_PORT 0
+#define HEADPHONE_44_1_BACKEND_PORT 5
#define ALL_SESSION_VSID 0xFFFFFFFF
#define DEFAULT_MUTE_RAMP_DURATION_MS 20
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 4ecdd36..0ae35e6 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -57,7 +57,7 @@
int platform_set_mic_mute(void *platform, bool state);
int platform_get_sample_rate(void *platform, uint32_t *rate);
int platform_set_device_mute(void *platform, bool state, char *dir);
-snd_device_t platform_get_output_snd_device(void *platform, audio_devices_t devices);
+snd_device_t platform_get_output_snd_device(void *platform, struct stream_out *out);
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);
int platform_edid_get_max_channels(void *platform);