Merge "hal: Support Multichannel Speaker playback"
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index bd3fa7c..198d871 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -990,7 +990,14 @@
if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
usecase->stream.out->app_type_cfg.sample_rate = usecase->stream.out->sample_rate;
} else if (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
- usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ if (platform_spkr_use_default_sample_rate(adev->platform)) {
+ usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ } else {
+ platform_check_and_update_copp_sample_rate(adev->platform, snd_device,
+ usecase->stream.out->sample_rate,
+ &usecase->stream.out->app_type_cfg.sample_rate);
+ }
+
} else if ((snd_device == SND_DEVICE_OUT_HDMI ||
snd_device == SND_DEVICE_OUT_USB_HEADSET ||
snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index cb2d786..dcc75de 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -4502,6 +4502,15 @@
audio_format_t dst_format = out->hal_op_format;
audio_format_t src_format = out->hal_ip_format;
+ /* prevent division-by-zero */
+ uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
+ uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
+ if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
+ ALOGE("%s: Error bitwidth == 0", __func__);
+ ATRACE_END();
+ return -EINVAL;
+ }
+
uint32_t frames = bytes / format_to_bitwidth_table[src_format];
uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
@@ -4642,10 +4651,18 @@
out->standby = true;
}
out_on_error(&out->stream.common);
- if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
- usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
- out_get_sample_rate(&out->stream.common));
+ if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
+ /* prevent division-by-zero */
+ uint32_t stream_size = audio_stream_out_frame_size(stream);
+ uint32_t srate = out_get_sample_rate(&out->stream.common);
+ if ((stream_size == 0) || (srate == 0)) {
+ ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
+ ATRACE_END();
+ return -EINVAL;
+ }
+ usleep((uint64_t)bytes * 1000000 / stream_size / srate);
+ }
if (audio_extn_passthru_is_passthrough_stream(out)) {
ALOGE("%s: write error, ret = %zd", __func__, ret);
ATRACE_END();
@@ -7079,6 +7096,13 @@
config->format,
channel_count,
is_low_latency);
+ /* prevent division-by-zero */
+ if (frame_size == 0) {
+ ALOGE("%s: Error frame_size==0", __func__);
+ ret = -EINVAL;
+ goto err_open;
+ }
+
in->config.period_size = buffer_size / frame_size;
if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
diff --git a/hal/edid.h b/hal/edid.h
index da5c592..f920a82 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -57,6 +57,27 @@
#define PCM_CHANNEL_FRC 14 /* Front right of center. */
#define PCM_CHANNEL_RLC 15 /* Rear left of center. */
#define PCM_CHANNEL_RRC 16 /* Rear right of center. */
+#define PCM_CHANNEL_LFE2 17 /* Second low frequency channel. */
+#define PCM_CHANNEL_SL 18 /* Side left channel. */
+#define PCM_CHANNEL_SR 19 /* Side right channel. */
+#define PCM_CHANNEL_TFL 20 /* Top front left channel. */
+#define PCM_CHANNEL_LVH 20 /* Left vertical height channel. */
+#define PCM_CHANNEL_TFR 21 /* Top front right channel. */
+#define PCM_CHANNEL_RVH 21 /* Right vertical height channel. */
+#define PCM_CHANNEL_TC 22 /* Top center channel. */
+#define PCM_CHANNEL_TBL 23 /* Top back left channel. */
+#define PCM_CHANNEL_TBR 24 /* Top back right channel. */
+#define PCM_CHANNEL_TSL 25 /* Top side left channel. */
+#define PCM_CHANNEL_TSR 26 /* Top side right channel. */
+#define PCM_CHANNEL_TBC 27 /* Top back center channel. */
+#define PCM_CHANNEL_BFC 28 /* Bottom front center channel. */
+#define PCM_CHANNEL_BFL 29 /* Bottom front left channel. */
+#define PCM_CHANNEL_BFR 30 /* Bottom front right channel. */
+#define PCM_CHANNEL_LW 31 /* Left wide channel. */
+#define PCM_CHANNEL_RW 32 /* Right wide channel. */
+#define PCM_CHANNEL_LSD 33 /* Left side direct channel. */
+#define PCM_CHANNEL_RSD 34 /* Right side direct channel. */
+
#define MAX_HDMI_CHANNEL_CNT 8
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
old mode 100755
new mode 100644
index 82fafc7..76b339b
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -298,6 +298,7 @@
struct acdb_init_data_v4 acdb_init_data;
bool use_generic_handset;
struct spkr_device_chmap *spkr_ch_map;
+ bool use_sprk_default_sample_rate;
};
struct spkr_device_chmap {
@@ -2290,6 +2291,7 @@
my_data->hw_dep_fd = -1;
my_data->mono_speaker = SPKR_1;
my_data->spkr_ch_map = NULL;
+ my_data->use_sprk_default_sample_rate = true;
be_dai_name_table = NULL;
@@ -7385,6 +7387,11 @@
platform_get_edid_info(platform);
}
+bool platform_spkr_use_default_sample_rate(void *platform) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ return my_data->use_sprk_default_sample_rate;
+}
+
void platform_invalidate_backend_config(void * platform,snd_device_t snd_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index b265ce8..ca3dbd8 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -276,6 +276,7 @@
struct acdb_init_data_v4 acdb_init_data;
bool use_generic_handset;
struct spkr_device_chmap *spkr_ch_map;
+ bool use_sprk_default_sample_rate;
};
struct spkr_device_chmap {
@@ -2096,7 +2097,7 @@
my_data->mono_speaker = SPKR_1;
my_data->speaker_lr_swap = false;
my_data->spkr_ch_map = NULL;
-
+ my_data->use_sprk_default_sample_rate = true;
be_dai_name_table = NULL;
property_get("ro.vendor.audio.sdk.fluencetype", my_data->fluence_cap, "");
@@ -2182,6 +2183,15 @@
else
platform_info_init(PLATFORM_INFO_XML_PATH, my_data, PLATFORM);
+ /* CSRA devices support multiple sample rates via I2S at spkr out */
+ if (!strncmp(snd_card_name, "qcs405-csra", strlen("qcs405-csra"))) {
+ ALOGE("%s: soundcard: %s supports multiple sample rates", __func__, snd_card_name);
+ my_data->use_sprk_default_sample_rate = false;
+ } else {
+ my_data->use_sprk_default_sample_rate = true;
+ ALOGE("%s: soundcard: %s supports only default sample rate", __func__, snd_card_name);
+ }
+
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) {
@@ -2437,11 +2447,18 @@
} else {
if (!strncmp(snd_card_name, "qcs405", strlen("qcs405"))) {
- my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
- strdup("WSA_CDC_DMA_RX_0 Format");
- my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
- strdup("WSA_CDC_DMA_RX_0 SampleRate");
+ if (!strncmp(snd_card_name, "qcs405-csra", strlen("qcs405-csra"))) {
+ my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+ strdup("PRIM_MI2S_RX Format");
+ my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+ strdup("PRIM_MI2S_RX SampleRate");
+ } else {
+ my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+ strdup("WSA_CDC_DMA_RX_0 Format");
+ my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+ strdup("WSA_CDC_DMA_RX_0 SampleRate");
+ }
my_data->current_backend_cfg[DEFAULT_CODEC_TX_BACKEND].bitwidth_mixer_ctl =
strdup("VA_CDC_DMA_TX_0 Format");
my_data->current_backend_cfg[DEFAULT_CODEC_TX_BACKEND].samplerate_mixer_ctl =
@@ -6281,9 +6298,15 @@
bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
ALOGD("%s:becf: afe: reset to default bitwidth %d", __func__, bit_width);
}
- sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
- ALOGD("%s:becf: afe: playback on codec device not supporting native playback set "
+ /*
+ * In case of CSRA speaker out, all sample rates are supported, so
+ * check platform here
+ */
+ if (platform_spkr_use_default_sample_rate(adev->platform)) {
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ ALOGD("%s:becf: afe: playback on codec device not supporting native playback set "
"default Sample Rate(48k)", __func__);
+ }
}
if (backend_idx == USB_AUDIO_RX_BACKEND) {
@@ -6954,6 +6977,40 @@
channel_map[6] = PCM_CHANNEL_LS;
channel_map[7] = PCM_CHANNEL_RS;
break;
+ case 12:
+ /* AUDIO_CHANNEL_OUT_7POINT1POINT4 */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_LFE;
+ channel_map[4] = PCM_CHANNEL_LB;
+ channel_map[5] = PCM_CHANNEL_RB;
+ channel_map[6] = PCM_CHANNEL_LS;
+ channel_map[7] = PCM_CHANNEL_RS;
+ channel_map[8] = PCM_CHANNEL_TFL;
+ channel_map[9] = PCM_CHANNEL_TFR;
+ channel_map[10] = PCM_CHANNEL_TSL;
+ channel_map[11] = PCM_CHANNEL_TSR;
+ break;
+ case 16:
+ /* 16 channels */
+ channel_map[0] = PCM_CHANNEL_FL;
+ channel_map[1] = PCM_CHANNEL_FR;
+ channel_map[2] = PCM_CHANNEL_FC;
+ channel_map[3] = PCM_CHANNEL_LFE;
+ channel_map[4] = PCM_CHANNEL_LB;
+ channel_map[5] = PCM_CHANNEL_RB;
+ channel_map[6] = PCM_CHANNEL_LS;
+ channel_map[7] = PCM_CHANNEL_RS;
+ channel_map[8] = PCM_CHANNEL_TFL;
+ channel_map[9] = PCM_CHANNEL_TFR;
+ channel_map[10] = PCM_CHANNEL_TSL;
+ channel_map[11] = PCM_CHANNEL_TSR;
+ channel_map[12] = PCM_CHANNEL_FLC;
+ channel_map[13] = PCM_CHANNEL_FRC;
+ channel_map[14] = PCM_CHANNEL_RLC;
+ channel_map[15] = PCM_CHANNEL_RRC;
+ break;
default:
ALOGE("unsupported channels %d for setting channel map", channels);
return -1;
@@ -7078,12 +7135,21 @@
struct mixer_ctl *ctl;
char mixer_ctl_name[44] = {0}; // max length of name is 44 as defined
int ret;
- unsigned int i;
- long set_values[FCC_8] = {0};
+ unsigned int i=0, n=0;
+ long set_values[AUDIO_MAX_DSP_CHANNELS];
struct platform_data *my_data = (struct platform_data *)platform;
struct audio_device *adev = my_data->adev;
ALOGV("%s channel_count:%d",__func__, ch_count);
- if (NULL == ch_map || (ch_count < 1) || (ch_count > FCC_8)) {
+
+ /*
+ * FIXME:
+ * Currently the channel mask in audio.h is limited to 30 channels,
+ * (=AUDIO_CHANNEL_COUNT_MAX), whereas the mixer controls already
+ * allow up to AUDIO_MAX_DSP_CHANNELS channels as per final requirement.
+ * Until channel mask definition is not changed from a uint32_t value
+ * to something else, a sanity check is needed here.
+ */
+ if (NULL == ch_map || (ch_count < 1) || (ch_count > AUDIO_CHANNEL_COUNT_MAX)) {
ALOGE("%s: Invalid channel mapping or channel count value", __func__);
return -EINVAL;
}
@@ -7101,12 +7167,34 @@
ALOGD("%s mixer_ctl_name:%s", __func__, mixer_ctl_name);
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
__func__, mixer_ctl_name);
return -EINVAL;
}
- for (i = 0; i < (unsigned int)ch_count; i++) {
+
+ /* find out how many values the control can set */
+ n = mixer_ctl_get_num_values(ctl);
+
+ if (n != ch_count)
+ ALOGV("%s chcnt %d != mixerctl elem size %d",__func__, ch_count, n);
+
+ if (n < ch_count) {
+ ALOGE("%s chcnt %d > mixerctl elem size %d",__func__, ch_count, n);
+ return -EINVAL;
+ }
+
+ if (n > AUDIO_MAX_DSP_CHANNELS) {
+ ALOGE("%s mixerctl elem size %d > AUDIO_MAX_DSP_CHANNELS %d",__func__, n, AUDIO_MAX_DSP_CHANNELS);
+ return -EINVAL;
+ }
+
+ /* initialize all set_values to zero */
+ memset (set_values, 0, sizeof(set_values));
+
+ /* copy only as many values as corresponding mixer_ctrl allows */
+ for (i = 0; i < ch_count; i++) {
set_values[i] = ch_map[i];
}
@@ -7114,7 +7202,8 @@
set_values[0], set_values[1], set_values[2], set_values[3], set_values[4],
set_values[5], set_values[6], set_values[7], ch_count);
- ret = mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
+ ret = mixer_ctl_set_array(ctl, set_values, n);
+
if (ret < 0) {
ALOGE("%s: Could not set ctl, error:%d ch_count:%d",
__func__, ret, ch_count);
@@ -7279,6 +7368,11 @@
return 0;
}
+bool platform_spkr_use_default_sample_rate(void *platform) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ return my_data->use_sprk_default_sample_rate;
+}
+
int platform_set_edid_channels_configuration(void *platform, int channels) {
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index c8ddaec..e1f433c 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -280,6 +280,8 @@
#define AUDIO_PARAMETER_KEY_TRUE_32_BIT "true_32_bit"
+#define AUDIO_MAX_DSP_CHANNELS 32
+
#define ALL_SESSION_VSID 0xFFFFFFFF
#define DEFAULT_MUTE_RAMP_DURATION_MS 20
#define DEFAULT_VOLUME_RAMP_DURATION_MS 20
diff --git a/hal/platform_api.h b/hal/platform_api.h
old mode 100755
new mode 100644
index 09c69de..1563673
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -218,6 +218,7 @@
snd_device_t snd_device,
struct mix_matrix_params mm_params);
int platform_set_edid_channels_configuration(void *platform, int channels);
+bool platform_spkr_use_default_sample_rate(void *platform);
unsigned char platform_map_to_edid_format(int format);
bool platform_is_edid_supported_format(void *platform, int format);
bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate);