release-request-d6bf2db5-83c3-41cb-ba89-644c366c2525-for-git_oc-mr1-release-4070602 snap-temp-L56000000070867102
Change-Id: I50b192e7290a481cf164d29780dde67db49d2f9c
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 85a5881..600c179 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -79,8 +79,8 @@
#define audio_extn_usb_enable_sidetone(device, enable) (0)
#define audio_extn_usb_set_sidetone_gain(parms, value, len) (0)
#define audio_extn_usb_is_capture_supported() (false)
-#define audio_extn_usb_get_max_channels() (0)
-#define audio_extn_usb_get_max_bit_width() (0)
+#define audio_extn_usb_get_max_channels(dir) (0)
+#define audio_extn_usb_get_max_bit_width(dir) (0)
#define audio_extn_usb_sup_sample_rates(t, s, l) (0)
#else
void audio_extn_usb_init(void *adev);
@@ -95,9 +95,9 @@
int audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
char *value, int len);
bool audio_extn_usb_is_capture_supported();
-int audio_extn_usb_get_max_channels();
-int audio_extn_usb_get_max_bit_width();
-int audio_extn_usb_sup_sample_rates(int type, uint32_t *sr, uint32_t l);
+int audio_extn_usb_get_max_channels(bool is_playback);
+int audio_extn_usb_get_max_bit_width(bool is_playback);
+int audio_extn_usb_sup_sample_rates(bool is_playback, uint32_t *sr, uint32_t l);
#endif
@@ -187,7 +187,7 @@
#endif
bool audio_extn_utils_resolve_config_file(char[]);
-void audio_extn_utils_get_platform_info(const char* snd_card_name,
- char* platform_info_file);
+int audio_extn_utils_get_platform_info(const char* snd_card_name,
+ char* platform_info_file);
int audio_extn_utils_get_snd_card_num();
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/sndmonitor.c b/hal/audio_extn/sndmonitor.c
index 58ab43d..3c91dda 100644
--- a/hal/audio_extn/sndmonitor.c
+++ b/hal/audio_extn/sndmonitor.c
@@ -152,7 +152,7 @@
size_t len = 0;
ssize_t bytes_read;
char path[128] = {0};
- char *ptr, *saveptr;
+ char *ptr, *saveptr, *card_id;
int line_no=0;
unsigned int num_cards=0, num_cpe=0;
FILE *fp;
@@ -180,6 +180,19 @@
if (!ptr)
continue;
+ card_id = strtok_r(saveptr+1, "]", &saveptr);
+ if (!card_id)
+ continue;
+
+ // Limit to sound cards associated with ADSP
+ if ((strncasecmp(card_id, "msm", 3) != 0) &&
+ (strncasecmp(card_id, "sdm", 3) != 0) &&
+ (strncasecmp(card_id, "sdc", 3) != 0) &&
+ (strncasecmp(card_id, "apq", 3) != 0)) {
+ ALOGW("Skip over non-ADSP snd card %s", card_id);
+ continue;
+ }
+
snprintf(path, sizeof(path), "/proc/asound/card%s/state", ptr);
ALOGV("Opening sound card state : %s", path);
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index a1af141..4e4c70d 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -290,6 +290,7 @@
char *bit_width_str = NULL;
struct usb_device_config * usb_device_info;
bool check = false;
+ int tries=5;
memset(path, 0, sizeof(path));
ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
@@ -298,12 +299,20 @@
/* TODO: convert the below to using alsa_utils */
ret = snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
card);
- if(ret < 0) {
+ if (ret < 0) {
ALOGE("%s: failed on snprintf (%d) to path %s\n",
__func__, ret, path);
goto done;
}
+ while (tries--) {
+ if (access(path, F_OK) < 0) {
+ ALOGW("stream %s doesn't exist retrying\n", path);
+ sleep(1);
+ continue;
+ }
+ }
+
fd = open(path, O_RDONLY);
if (fd <0) {
ALOGE("%s: error failed to open config file %s error: %d\n",
@@ -518,18 +527,26 @@
return;
}
+static inline bool usb_output_device(audio_devices_t device) {
+ // ignore accessory for now
+ if (device == AUDIO_DEVICE_OUT_USB_ACCESSORY) {
+ return false;
+ }
+ return audio_is_usb_out_device(device);
+}
+
+static inline bool usb_input_device(audio_devices_t device) {
+ // ignore accessory for now
+ if (device == AUDIO_DEVICE_IN_USB_ACCESSORY) {
+ return false;
+ }
+ return audio_is_usb_in_device(device);
+}
+
static bool usb_valid_device(audio_devices_t device)
{
- if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_USB_DEVICE))
- return true;
-
- if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
- device &= ~AUDIO_DEVICE_BIT_IN;
- if (popcount(device) == 1 && (device & AUDIO_DEVICE_IN_USB_DEVICE) != 0)
- return true;
- }
-
- return false;
+ return usb_output_device(device) ||
+ usb_input_device(device);
}
static void usb_print_active_device(void){
@@ -821,7 +838,7 @@
card_info = node_to_item(node_i, struct usb_card_config, list);
ALOGV("%s: card_dev_type (0x%x), card_no(%d)",
__func__, card_info->usb_device_type, card_info->usb_card);
- if (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+ if (usb_output_device(card_info->usb_device_type)) {
if ((i = card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX]) != -1) {
struct mixer_ctl *ctl = mixer_get_ctl_by_name(
card_info->usb_snd_mixer,
@@ -866,8 +883,8 @@
"%s: card_dev_type (0x%x), card_no(%d)",
__func__, card_info->usb_device_type, card_info->usb_card);
/* Currently only apply the first playback sound card configuration */
- if ((is_playback && card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) ||
- ((!is_playback) && card_info->usb_device_type == AUDIO_DEVICE_IN_USB_DEVICE)){
+ if ((is_playback && usb_output_device(card_info->usb_device_type)) ||
+ (!is_playback && usb_input_device(card_info->usb_device_type))) {
usb_audio_backend_apply_policy(&card_info->usb_device_conf_list,
bit_width,
sample_rate,
@@ -884,7 +901,7 @@
#define _MAX(x, y) (((x) >= (y)) ? (x) : (y))
#define _MIN(x, y) (((x) <= (y)) ? (x) : (y))
-int audio_extn_usb_get_max_channels()
+int audio_extn_usb_get_max_channels(bool is_playback)
{
struct listnode *node_i, *node_j;
struct usb_device_config *dev_info;
@@ -892,6 +909,11 @@
unsigned int max_ch = 1;
list_for_each(node_i, &usbmod->usb_card_conf_list) {
card_info = node_to_item(node_i, struct usb_card_config, list);
+ if (usb_output_device(card_info->usb_device_type) && !is_playback)
+ continue;
+ else if (usb_input_device(card_info->usb_device_type) && is_playback)
+ continue;
+
list_for_each(node_j, &card_info->usb_device_conf_list) {
dev_info = node_to_item(node_j, struct usb_device_config, list);
max_ch = _MAX(max_ch, dev_info->channel_count);
@@ -901,7 +923,7 @@
return max_ch;
}
-int audio_extn_usb_get_max_bit_width()
+int audio_extn_usb_get_max_bit_width(bool is_playback)
{
struct listnode *node_i, *node_j;
struct usb_device_config *dev_info;
@@ -909,6 +931,11 @@
unsigned int max_bw = 16;
list_for_each(node_i, &usbmod->usb_card_conf_list) {
card_info = node_to_item(node_i, struct usb_card_config, list);
+ if (usb_output_device(card_info->usb_device_type) && !is_playback)
+ continue;
+ else if (usb_input_device(card_info->usb_device_type) && is_playback)
+ continue;
+
list_for_each(node_j, &card_info->usb_device_conf_list) {
dev_info = node_to_item(node_j, struct usb_device_config, list);
max_bw = _MAX(max_bw, dev_info->bit_width);
@@ -918,7 +945,7 @@
return max_bw;
}
-int audio_extn_usb_sup_sample_rates(int type,
+int audio_extn_usb_sup_sample_rates(bool is_playback,
uint32_t *sample_rates,
uint32_t sample_rate_size)
{
@@ -926,8 +953,7 @@
struct usb_device_config *dev_info;
struct usb_card_config *card_info;
- if (type != USB_PLAYBACK && type != USB_CAPTURE)
- return -1;
+ int type = is_playback ? USB_PLAYBACK : USB_CAPTURE;
ALOGV("%s supported_sample_rates_mask 0x%x", __func__, supported_sample_rates_mask[type]);
uint32_t bm = supported_sample_rates_mask[type];
@@ -997,22 +1023,24 @@
goto exit;
}
list_init(&usb_card_info->usb_device_conf_list);
- if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ if (usb_output_device(device)) {
if (!usb_get_device_playback_config(usb_card_info, card)){
usb_card_info->usb_card = card;
- usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_DEVICE;
+ usb_card_info->usb_device_type = device;
usb_get_sidetone_mixer(usb_card_info);
list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
goto exit;
}
- } else if (device & AUDIO_DEVICE_IN_USB_DEVICE) {
+ } else if (usb_input_device(device)) {
if (!usb_get_device_capture_config(usb_card_info, card)) {
usb_card_info->usb_card = card;
- usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
+ usb_card_info->usb_device_type = device;
usbmod->is_capture_supported = true;
list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
goto exit;
}
+ } else {
+ ALOGW("%s: unknown device 0x%x", __func__, device);
}
/* free memory in error case */
if (usb_card_info != NULL)
@@ -1060,6 +1088,9 @@
free(node_to_item(node_j, struct usb_device_config, list));
}
list_remove(node_i);
+ if (card_info->usb_snd_mixer) {
+ mixer_close(card_info->usb_snd_mixer);
+ }
free(node_to_item(node_i, struct usb_card_config, list));
}
}
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index e41af96..eb0f9f6 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -324,14 +324,14 @@
}
/* platform_info_file should be size 'MIXER_PATH_MAX_LENGTH' */
-void audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
+int audio_extn_utils_get_platform_info(const char* snd_card_name, char* platform_info_file)
{
if (NULL == snd_card_name) {
- return;
+ return -1;
}
struct snd_card_split *snd_split_handle = NULL;
-
+ int ret = 0;
audio_extn_set_snd_card_split(snd_card_name);
snd_split_handle = audio_extn_get_snd_card_split();
@@ -347,9 +347,11 @@
if (!audio_extn_utils_resolve_config_file(platform_info_file)) {
memset(platform_info_file, 0, MIXER_PATH_MAX_LENGTH);
strlcpy(platform_info_file, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
- audio_extn_utils_resolve_config_file(platform_info_file);
+ ret = audio_extn_utils_resolve_config_file(platform_info_file) ? 0 : -1;
}
}
+
+ return ret;
}
int audio_extn_utils_get_snd_card_num()
@@ -399,10 +401,17 @@
snd_card_name = mixer_get_name(mixer);
hw_info = hw_info_init(snd_card_name);
- audio_extn_utils_get_platform_info(snd_card_name, platform_info_file);
+ if (audio_extn_utils_get_platform_info(snd_card_name, platform_info_file) < 0) {
+ ALOGE("Failed to find platform_info_file");
+ goto cleanup;
+ }
/* Initialize snd card name specific ids and/or backends*/
- snd_card_info_init(platform_info_file, my_data, &acdb_set_parameters);
+ if (snd_card_info_init(platform_info_file, my_data,
+ &acdb_set_parameters) < 0) {
+ ALOGE("Failed to find platform_info_file");
+ goto cleanup;
+ }
/* validate the sound card name
* my_data->snd_card_name can contain
@@ -419,17 +428,18 @@
min(strlen(snd_card_name), strlen(my_data->snd_card_name))) != 0) {
ALOGI("%s: found valid sound card %s, but not primary sound card %s",
__func__, snd_card_name, my_data->snd_card_name);
- ++snd_card_num;
- mixer_close(mixer);
- mixer = NULL;
- hw_info_deinit(hw_info);
- hw_info = NULL;
- continue;
+ goto cleanup;
}
- ALOGI("%s: found sound card %s, primary sound card expeted is %s",
+ ALOGI("%s: found sound card %s, primary sound card expected is %s",
__func__, snd_card_name, my_data->snd_card_name);
break;
+ cleanup:
+ ++snd_card_num;
+ mixer_close(mixer);
+ mixer = NULL;
+ hw_info_deinit(hw_info);
+ hw_info = NULL;
}
done:
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 3318cc1..e689b28 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -247,6 +247,7 @@
[USECASE_AUDIO_RECORD] = "audio-record",
[USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
[USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
+ [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
[USECASE_AUDIO_HFP_SCO] = "hfp-sco",
[USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
@@ -279,10 +280,12 @@
uint32_t value;
};
-static const struct string_to_enum out_channels_name_to_enum_table[] = {
+static const struct string_to_enum channels_name_to_enum_table[] = {
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
+ //TBD - string values for channel_in > 2?
};
static int set_voice_volume_l(struct audio_device *adev, float volume);
@@ -964,48 +967,95 @@
return ret;
}
-static int read_usb_sup_sample_rates(struct stream_out *out)
+static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
+ uint32_t *supported_sample_rates __unused,
+ uint32_t max_rates __unused)
{
- uint32_t *sr = out->supported_sample_rates;
- size_t count = audio_extn_usb_sup_sample_rates(0 /*playback*/,
- sr,
- MAX_SUPPORTED_SAMPLE_RATES);
+ ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
+ supported_sample_rates,
+ max_rates);
#if !LOG_NDEBUG
-
- for (size_t i=0; i<count; i++) {
- ALOGV("%s %d", __func__, out->supported_sample_rates[i]);
+ for (ssize_t i=0; i<count; i++) {
+ ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
+ supported_sample_rates[i]);
}
#endif
- return count > 0 ? 0 : -1;
+ return count;
}
-static int read_usb_sup_channel_masks(struct stream_out *out)
+static int read_usb_sup_channel_masks(bool is_playback,
+ audio_channel_mask_t *supported_channel_masks,
+ uint32_t max_masks __unused)
{
- int channels = audio_extn_usb_get_max_channels();
- out->supported_channel_masks[0] =
- channels < 3 ? audio_channel_out_mask_from_count(channels) :
- audio_channel_mask_for_index_assignment_from_count(channels);
- return 0;
+ int channels = audio_extn_usb_get_max_channels(is_playback);
+ if (is_playback) {
+ supported_channel_masks[0] =
+ channels < 3 ? audio_channel_out_mask_from_count(channels) :
+ audio_channel_mask_for_index_assignment_from_count(channels);
+ } else {
+ supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
+ }
+ ALOGV("%s: %s supported ch %d", __func__,
+ is_playback ? "P" : "C", channels);
+ return 1;
}
-static int read_usb_sup_formats(struct stream_out *out)
+static int read_usb_sup_formats(bool is_playback __unused,
+ audio_format_t *supported_formats,
+ uint32_t max_formats __unused)
{
- int bitwidth = audio_extn_usb_get_max_bit_width();
+ int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
switch (bitwidth) {
case 24:
// XXX : usb.c returns 24 for s24 and s24_le?
- out->supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
break;
case 32:
- out->supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
+ supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
break;
case 16:
default :
- out->supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
+ supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
break;
}
+ ALOGV("%s: %s supported format %d", __func__,
+ is_playback ? "P" : "C", bitwidth);
+ return 1;
+}
- return 0;
+static int read_usb_sup_params_and_compare(bool is_playback,
+ audio_format_t *format,
+ audio_format_t *supported_formats,
+ uint32_t max_formats,
+ audio_channel_mask_t *mask,
+ audio_channel_mask_t *supported_channel_masks,
+ uint32_t max_masks,
+ uint32_t *rate,
+ uint32_t *supported_sample_rates,
+ uint32_t max_rates) {
+ int ret = 0;
+ int num_formats;
+ int num_masks;
+ int num_rates;
+ int i;
+
+ num_formats = read_usb_sup_formats(is_playback, supported_formats,
+ max_formats);
+ num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
+ max_masks);
+ num_rates = read_usb_sup_sample_rates(is_playback,
+ supported_sample_rates, max_rates);
+
+#define LUT(table, len, what, dflt) \
+ for (i=0; i<len && (table[i] != what); i++); \
+ if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
+
+ LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
+ LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
+ LUT(supported_sample_rates, num_rates, *rate, 0);
+
+#undef LUT
+ return ret < 0 ? -EINVAL : 0; // HACK TBD
}
static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
@@ -1748,7 +1798,7 @@
goto error_open;
}
} else {
- unsigned int flags = PCM_OUT;
+ unsigned int flags = PCM_OUT | PCM_MONOTONIC;
unsigned int pcm_open_retry_count = 0;
if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
@@ -1756,8 +1806,7 @@
pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
} else if (out->realtime) {
flags |= PCM_MMAP | PCM_NOIRQ;
- } else
- flags |= PCM_MONOTONIC;
+ }
while (1) {
out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
@@ -1814,7 +1863,9 @@
audio_format_t format,
int channel_count)
{
- if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
+ if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
+ (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
+ (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
return -EINVAL;
}
@@ -1835,6 +1886,7 @@
case 32000:
case 44100:
case 48000:
+ case 96000:
break;
default:
ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
@@ -2138,29 +2190,25 @@
return status;
}
-static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
-{
- struct stream_out *out = (struct stream_out *)stream;
- struct str_parms *query = str_parms_create_str(keys);
- char *str;
+static bool stream_get_parameter_channels(struct str_parms *query,
+ struct str_parms *reply,
+ audio_channel_mask_t *supported_channel_masks) {
+ int ret = -1;
char value[256];
- struct str_parms *reply = str_parms_create();
- bool replied = false;
- size_t i, j;
- int ret;
bool first = true;
- ALOGV("%s: enter: keys - %s", __func__, keys);
- ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
- if (ret >= 0) {
+ size_t i, j;
+
+ if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
+ ret = 0;
value[0] = '\0';
i = 0;
- while (out->supported_channel_masks[i] != 0) {
- for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
- if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
+ while (supported_channel_masks[i] != 0) {
+ for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
+ if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
if (!first) {
strcat(value, "|");
}
- strcat(value, out_channels_name_to_enum_table[j].name);
+ strcat(value, channels_name_to_enum_table[j].name);
first = false;
break;
}
@@ -2168,13 +2216,21 @@
i++;
}
str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
- replied = true;
}
+ return ret >= 0;
+}
- ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
- if (ret >= 0) {
+static bool stream_get_parameter_formats(struct str_parms *query,
+ struct str_parms *reply,
+ audio_format_t *supported_formats) {
+ int ret = -1;
+ char value[256];
+ int i;
+
+ if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
+ ret = 0;
value[0] = '\0';
- switch (out->supported_formats[0]) {
+ switch (supported_formats[0]) {
case AUDIO_FORMAT_PCM_16_BIT:
strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
break;
@@ -2186,24 +2242,31 @@
break;
default:
ALOGE("%s: unsupported format %#x", __func__,
- out->supported_formats[0]);
+ supported_formats[0]);
break;
}
str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
- replied = true;
}
+ return ret >= 0;
+}
- ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
- value, sizeof(value));
- if (ret >= 0) {
+static bool stream_get_parameter_rates(struct str_parms *query,
+ struct str_parms *reply,
+ uint32_t *supported_sample_rates) {
+
+ int i;
+ char value[256];
+ int ret = -1;
+ if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
+ ret = 0;
value[0] = '\0';
i=0;
int cursor = 0;
- while (out->supported_sample_rates[i]) {
+ while (supported_sample_rates[i]) {
int avail = sizeof(value) - cursor;
ret = snprintf(value + cursor, avail, "%s%d",
cursor > 0 ? "|" : "",
- out->supported_sample_rates[i]);
+ supported_sample_rates[i]);
if (ret < 0 || ret >= avail) {
// if cursor is at the last element of the array
// overwrite with \0 is duplicate work as
@@ -2220,9 +2283,25 @@
}
str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
value);
- replied = true;
}
+ return ret >= 0;
+}
+static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
+{
+ struct stream_out *out = (struct stream_out *)stream;
+ struct str_parms *query = str_parms_create_str(keys);
+ char *str;
+ struct str_parms *reply = str_parms_create();
+ bool replied = false;
+ ALOGV("%s: enter: keys - %s", __func__, keys);
+
+ replied |= stream_get_parameter_channels(query, reply,
+ &out->supported_channel_masks[0]);
+ replied |= stream_get_parameter_formats(query, reply,
+ &out->supported_formats[0]);
+ replied |= stream_get_parameter_rates(query, reply,
+ &out->supported_sample_rates[0]);
if (replied) {
str = str_parms_to_str(reply);
} else {
@@ -2945,10 +3024,31 @@
return status;
}
-static char* in_get_parameters(const struct audio_stream *stream __unused,
- const char *keys __unused)
+static char* in_get_parameters(const struct audio_stream *stream,
+ const char *keys)
{
- return strdup("");
+ struct stream_in *in = (struct stream_in *)stream;
+ struct str_parms *query = str_parms_create_str(keys);
+ char *str;
+ struct str_parms *reply = str_parms_create();
+ bool replied = false;
+
+ ALOGV("%s: enter: keys - %s", __func__, keys);
+ replied |= stream_get_parameter_channels(query, reply,
+ &in->supported_channel_masks[0]);
+ replied |= stream_get_parameter_formats(query, reply,
+ &in->supported_formats[0]);
+ replied |= stream_get_parameter_rates(query, reply,
+ &in->supported_sample_rates[0]);
+ if (replied) {
+ str = str_parms_to_str(reply);
+ } else {
+ str = strdup(keys);
+ }
+ str_parms_destroy(query);
+ str_parms_destroy(reply);
+ ALOGV("%s: exit: returns - %s", __func__, str);
+ return str;
}
static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
@@ -3334,7 +3434,10 @@
struct audio_device *adev = (struct audio_device *)dev;
struct stream_out *out;
int i, ret;
- const uint32_t direct_dev = (AUDIO_DEVICE_OUT_HDMI|AUDIO_DEVICE_OUT_USB_DEVICE);
+ bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ bool is_usb_dev = audio_is_usb_out_device(devices) &&
+ (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
+ bool direct_dev = is_hdmi || is_usb_dev;
ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
__func__, config->sample_rate, config->channel_mask, devices, flags);
@@ -3356,18 +3459,27 @@
/* Init use case and pcm_config */
if (audio_is_linear_pcm(out->format) &&
(out->flags == AUDIO_OUTPUT_FLAG_NONE ||
- out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
- (out->devices & direct_dev)) {
-
- bool hdmi = (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL);
-
+ out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
pthread_mutex_lock(&adev->lock);
- if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ if (is_hdmi) {
ret = read_hdmi_channel_masks(out);
- } else if (out->devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
- ret = read_usb_sup_formats(out) ||
- read_usb_sup_channel_masks(out) ||
- read_usb_sup_sample_rates(out);
+ if (config->sample_rate == 0)
+ config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ if (config->channel_mask == 0)
+ config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
+ if (config->format == AUDIO_FORMAT_DEFAULT)
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ } else if (is_usb_dev) {
+ ret = read_usb_sup_params_and_compare(true /*is_playback*/,
+ &config->format,
+ &out->supported_formats[0],
+ MAX_SUPPORTED_FORMATS,
+ &config->channel_mask,
+ &out->supported_channel_masks[0],
+ MAX_SUPPORTED_CHANNEL_MASKS,
+ &config->sample_rate,
+ &out->supported_sample_rates[0],
+ MAX_SUPPORTED_SAMPLE_RATES);
ALOGV("plugged dev USB ret %d", ret);
} else {
ret = -1;
@@ -3376,24 +3488,12 @@
if (ret != 0)
goto error_open;
- if (config->sample_rate == 0) {
- out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
- } else {
- out->sample_rate = config->sample_rate;
- }
- if (config->channel_mask == 0) {
- out->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
- } else {
- out->channel_mask = config->channel_mask;
- }
- if (config->format == AUDIO_FORMAT_DEFAULT) {
- out->format = AUDIO_FORMAT_PCM_16_BIT;
- } else {
- out->format = config->format;
- }
+ out->channel_mask = config->channel_mask;
+ out->sample_rate = config->sample_rate;
+ out->format = config->format;
out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
// does this change?
- out->config = hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
+ out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
out->config.rate = config->sample_rate;
out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
@@ -3887,6 +3987,42 @@
false /* is_low_latency: since we don't know, be conservative */);
}
+static bool adev_input_allow_hifi_record(struct audio_device *adev,
+ audio_devices_t devices,
+ audio_input_flags_t flags,
+ audio_source_t source) {
+ const bool allowed = true;
+
+ if (!audio_is_usb_in_device(devices))
+ return !allowed;
+
+ switch (flags) {
+ case AUDIO_INPUT_FLAG_NONE:
+ case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
+ break;
+ default:
+ return !allowed;
+ }
+
+ switch (source) {
+ case AUDIO_SOURCE_DEFAULT:
+ case AUDIO_SOURCE_MIC:
+ case AUDIO_SOURCE_UNPROCESSED:
+ break;
+ default:
+ return !allowed;
+ }
+
+ switch (adev->mode) {
+ case 0:
+ break;
+ default:
+ return !allowed;
+ }
+
+ return allowed;
+}
+
static int adev_open_input_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
@@ -3901,13 +4037,26 @@
int ret = 0, buffer_size, frame_size;
int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
bool is_low_latency = false;
-
- ALOGV("%s: enter", __func__);
+ bool is_usb_dev = audio_is_usb_in_device(devices);
+ bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
+ devices,
+ flags,
+ source);
+ ALOGE("%s: enter", __func__);
*stream_in = NULL;
+
+ if (config->sample_rate == 0)
+ config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
+ if (config->channel_mask == AUDIO_CHANNEL_NONE)
+ config->channel_mask = AUDIO_CHANNEL_IN_MONO;
+ if (config->format == AUDIO_FORMAT_DEFAULT)
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+
if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
return -EINVAL;
- if (audio_extn_tfa_98xx_is_supported() && (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
+ if (audio_extn_tfa_98xx_is_supported() &&
+ (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
return -EINVAL;
in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
@@ -3940,9 +4089,24 @@
in->capture_handle = handle;
in->flags = flags;
- // restrict 24 bit capture for unprocessed source only
- // for other sources if 24 bit requested reject 24 and set 16 bit capture only
- if (config->format == AUDIO_FORMAT_DEFAULT) {
+ if (is_usb_dev && may_use_hifi_record) {
+ /* HiFi record selects an appropriate format, channel, rate combo
+ depending on sink capabilities*/
+ ret = read_usb_sup_params_and_compare(false /*is_playback*/,
+ &config->format,
+ &in->supported_formats[0],
+ MAX_SUPPORTED_FORMATS,
+ &config->channel_mask,
+ &in->supported_channel_masks[0],
+ MAX_SUPPORTED_CHANNEL_MASKS,
+ &config->sample_rate,
+ &in->supported_sample_rates[0],
+ MAX_SUPPORTED_SAMPLE_RATES);
+ if (ret != 0) {
+ ret = -EINVAL;
+ goto err_open;
+ }
+ } else if (config->format == AUDIO_FORMAT_DEFAULT) {
config->format = AUDIO_FORMAT_PCM_16_BIT;
} else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
@@ -3993,6 +4157,18 @@
in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
in->config = pcm_config_afe_proxy_record;
in->af_period_multiplier = 1;
+ } else if (is_usb_dev && may_use_hifi_record) {
+ in->usecase = USECASE_AUDIO_RECORD_HIFI;
+ in->config = pcm_config_audio_capture;
+ frame_size = audio_stream_in_frame_size(&in->stream);
+ buffer_size = get_input_buffer_size(config->sample_rate,
+ config->format,
+ channel_count,
+ false /*is_low_latency*/);
+ in->config.period_size = buffer_size / frame_size;
+ in->config.rate = config->sample_rate;
+ in->af_period_multiplier = 1;
+ in->config.format = pcm_format_from_audio_format(config->format);
} else {
in->usecase = USECASE_AUDIO_RECORD;
if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
@@ -4008,7 +4184,7 @@
buffer_size = get_input_buffer_size(config->sample_rate,
config->format,
channel_count,
- is_low_latency);
+ is_low_latency);
in->config.period_size = buffer_size / frame_size;
in->config.rate = config->sample_rate;
in->af_period_multiplier = 1;
@@ -4019,6 +4195,7 @@
}
} else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
+ // FIXME: Add support for multichannel capture over USB using MMAP
in->usecase = USECASE_AUDIO_RECORD_MMAP;
in->config = pcm_config_mmap_capture;
in->stream.start = in_start;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index e410d64..b1e5e45 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -96,6 +96,7 @@
USECASE_AUDIO_RECORD,
USECASE_AUDIO_RECORD_LOW_LATENCY,
USECASE_AUDIO_RECORD_MMAP,
+ USECASE_AUDIO_RECORD_HIFI,
/* Voice extension usecases
*
@@ -246,6 +247,14 @@
audio_format_t format;
card_status_t card_status;
int capture_started;
+
+ struct stream_app_type_cfg app_type_cfg;
+
+ /* Array of supported channel mask configurations.
+ +1 so that the last entry is always 0 */
+ audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
+ audio_format_t supported_formats[MAX_SUPPORTED_FORMATS + 1];
+ uint32_t supported_sample_rates[MAX_SUPPORTED_SAMPLE_RATES + 1];
};
typedef enum usecase_type_t {
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 6e1fb88..07dc1af 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -157,6 +157,7 @@
};
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#define DEFAULT_INPUT_SAMPLING_RATE 48000
#define ALL_SESSION_VSID 0xFFFFFFFF
#define DEFAULT_MUTE_RAMP_DURATION_MS 20
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index b879c0b..0835378 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -96,6 +96,7 @@
#define SOUND_CARD 0
#define MIXER_PATH_MAX_LENGTH 100
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#define DEFAULT_INPUT_SAMPLING_RATE 48000
/*
* tinyAlsa library interprets period size as number of frames
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index b9812b1..02512ea 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -165,6 +165,9 @@
[USECASE_AUDIO_RECORD_MMAP] = {MMAP_RECORD_PCM_DEVICE,
MMAP_RECORD_PCM_DEVICE},
+ [USECASE_AUDIO_RECORD_HIFI] = {MULTIMEDIA2_PCM_DEVICE,
+ MULTIMEDIA2_PCM_DEVICE},
+
[USECASE_VOICE_CALL] = {VOICE_CALL_PCM_DEVICE,
VOICE_CALL_PCM_DEVICE},
[USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
@@ -553,6 +556,7 @@
{TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_MMAP)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_HIFI)},
{TO_NAME_INDEX(USECASE_VOICE_CALL)},
{TO_NAME_INDEX(USECASE_VOICE2_CALL)},
{TO_NAME_INDEX(USECASE_VOLTE_CALL)},
@@ -1027,6 +1031,8 @@
hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_VCO_HEADPHONES] = strdup("SLIMBUS_0_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_HCO_HANDSET] = strdup("SLIMBUS_0_RX");
hw_interface_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("USB_AUDIO_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_FULL_USB] = strdup("USB_AUDIO_RX");
+ hw_interface_table[SND_DEVICE_OUT_VOICE_TTY_VCO_USB] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_USB_HEADSET] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_USB_HEADPHONES] = strdup("USB_AUDIO_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_USB_HEADPHONES] = strdup("USB_AUDIO_RX");
@@ -1034,6 +1040,18 @@
hw_interface_table[SND_DEVICE_OUT_VOICE_TX] = strdup("AFE_PCM_RX");
hw_interface_table[SND_DEVICE_OUT_SPEAKER_PROTECTED] = strdup("SLIMBUS_0_RX");
hw_interface_table[SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED] = strdup("SLIMBUS_0_RX");
+ hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_USB_HEADSET_MIC_AEC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_RECOG_USB_HEADSET_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_FULL_USB_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_VOICE_TTY_HCO_USB_MIC] = strdup("USB_AUDIO_TX");
+ hw_interface_table[SND_DEVICE_IN_SPEAKER_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HANDSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_HEADSET_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_UNPROCESSED_MIC] = strdup("SLIMBUS_0_TX");
+ hw_interface_table[SND_DEVICE_IN_CAMCORDER_MIC] = strdup("SLIMBUS_0_TX");
my_data->max_mic_count = PLATFORM_DEFAULT_MIC_COUNT;
}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 61da332..9df8a1d 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -182,6 +182,8 @@
};
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
#define OUTPUT_SAMPLING_RATE_44100 44100
+#define DEFAULT_INPUT_SAMPLING_RATE 48000
+
enum {
DEFAULT_CODEC_BACKEND,
SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
@@ -202,8 +204,6 @@
#define DEVICE_NAME_MAX_SIZE 128
#define HW_INFO_ARRAY_MAX_SIZE 32
-#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
-
#define ALL_SESSION_VSID 0xFFFFFFFF
#define DEFAULT_MUTE_RAMP_DURATION_MS 20
#define DEFAULT_VOLUME_RAMP_DURATION_MS 20
diff --git a/hal/platform_info.c b/hal/platform_info.c
index c63f244..cd2b5d4 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2017 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.