Merge "configs: update sound trigger to support hotsound" into av-userspace.lnx.2.0-dev
diff --git a/configs/msm8996/audio_output_policy.conf b/configs/msm8996/audio_output_policy.conf
index 93cd0c2..0563503 100644
--- a/configs/msm8996/audio_output_policy.conf
+++ b/configs/msm8996/audio_output_policy.conf
@@ -46,11 +46,18 @@
bit_width 24
app_type 69940
}
- compress_passthrough {
+ compress_passthrough_16 {
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
sampling_rates 32000|44100|48000|88200|96000|176400|192000
- bit_width 16|24
+ bit_width 16
+ app_type 69941
+ }
+ compress_passthrough_24 {
+ flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
+ formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
+ sampling_rates 32000|44100|48000|88200|96000|176400|192000
+ bit_width 24
app_type 69941
}
compress_offload_16 {
diff --git a/configs/msm8996/mixer_paths_tasha.xml b/configs/msm8996/mixer_paths_tasha.xml
index 360e80b..596b016 100644
--- a/configs/msm8996/mixer_paths_tasha.xml
+++ b/configs/msm8996/mixer_paths_tasha.xml
@@ -120,6 +120,7 @@
<ctl name="HDMI Mixer MultiMedia4" value="0" />
<ctl name="HDMI Mixer MultiMedia5" value="0" />
<ctl name="HDMI Mixer MultiMedia7" value="0" />
+ <ctl name="HDMI Mixer MultiMedia9" value="0" />
<ctl name="HDMI Mixer MultiMedia10" value="0" />
<ctl name="HDMI Mixer MultiMedia11" value="0" />
<ctl name="HDMI Mixer MultiMedia12" value="0" />
@@ -755,6 +756,10 @@
<ctl name="HDMI Mixer MultiMedia4" value="1" />
</path>
+ <path name="silence-playback hdmi">
+ <ctl name="HDMI Mixer MultiMedia9" value="1" />
+ </path>
+
<path name="compress-offload-playback bt-sco">
<ctl name="AUX_PCM_RX Audio Mixer MultiMedia4" value="1" />
</path>
diff --git a/configs/msm8996/msm8996.mk b/configs/msm8996/msm8996.mk
index 2b70a81..d0ddf24 100644
--- a/configs/msm8996/msm8996.mk
+++ b/configs/msm8996/msm8996.mk
@@ -19,7 +19,8 @@
AUDIO_FEATURE_ENABLED_FLUENCE := true
AUDIO_FEATURE_ENABLED_HDMI_SPK := true
AUDIO_FEATURE_ENABLED_HDMI_EDID := true
-AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
+#AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
+#AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
AUDIO_FEATURE_ENABLED_HFP := true
AUDIO_FEATURE_ENABLED_INCALL_MUSIC := false
AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true
@@ -45,8 +46,8 @@
MM_AUDIO_ENABLED_SAFX := true
TARGET_USES_QCOM_MM_AUDIO := true
AUDIO_FEATURE_ENABLED_HW_ACCELERATED_EFFECTS := false
-DOLBY_DDP := true
#AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := true
+#DOLBY_DDP := true
AUDIO_FEATURE_ENABLED_SOURCE_TRACKING := true
AUDIO_FEATURE_ENABLED_AUDIOSPHERE := true
##AUDIO_FEATURE_FLAGS
diff --git a/configs/msmcobalt/audio_output_policy.conf b/configs/msmcobalt/audio_output_policy.conf
index 46fa191..67d79bf 100644
--- a/configs/msmcobalt/audio_output_policy.conf
+++ b/configs/msmcobalt/audio_output_policy.conf
@@ -46,6 +46,20 @@
bit_width 24
app_type 69940
}
+ compress_passthrough_16 {
+ flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
+ formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
+ sampling_rates 32000|44100|48000|88200|96000|176400|192000
+ bit_width 16
+ app_type 69941
+ }
+ compress_passthrough_24 {
+ flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING|AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH
+ formats AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_E_AC3_JOC|AUDIO_FORMAT_DTS|AUDIO_FORMAT_DTS_HD
+ sampling_rates 32000|44100|48000|88200|96000|176400|192000
+ bit_width 24
+ app_type 69941
+ }
compress_offload_16 {
flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING
formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_PCM_16_BIT_OFFLOAD|AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2|AUDIO_FORMAT_WMA|AUDIO_FORMAT_WMA_PRO|AUDIO_FORMAT_VORBIS|AUDIO_FORMAT_AAC_ADTS_LC|AUDIO_FORMAT_AAC_ADTS_HE_V1|AUDIO_FORMAT_AAC_ADTS_HE_V2
diff --git a/configs/msmcobalt/audio_platform_info.xml b/configs/msmcobalt/audio_platform_info.xml
index f0962f0..ae252bc 100644
--- a/configs/msmcobalt/audio_platform_info.xml
+++ b/configs/msmcobalt/audio_platform_info.xml
@@ -33,6 +33,7 @@
<device name="SND_DEVICE_OUT_SPEAKER" bit_width="24"/>
</bit_width_configs>
<pcm_ids>
+ <usecase name="USECASE_AUDIO_PLAYBACK_LOW_LATENCY" type="out" id="13"/>
<usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD" type="out" id="8"/>
<usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD2" type="out" id="15"/>
<usecase name="USECASE_AUDIO_PLAYBACK_OFFLOAD3" type="out" id="16"/>
@@ -56,9 +57,10 @@
<usecase name="USECASE_QCHAT_CALL" type="out" id="-1"/>
<usecase name="USECASE_VOWLAN_CALL" type="in" id="-1"/>
<usecase name="USECASE_VOWLAN_CALL" type="out" id="-1"/>
- <usecase name="USECASE_AUDIO_SPKR_CALIB_TX" type="in" id="35"/>
<usecase name="USECASE_AUDIO_PLAYBACK_FM" type="out" id="5"/>
<usecase name="USECASE_AUDIO_PLAYBACK_FM" type="in" id="34"/>
+ <usecase name="USECASE_AUDIO_SPKR_CALIB_RX" type="out" id="5"/>
+ <usecase name="USECASE_AUDIO_SPKR_CALIB_TX" type="in" id="35"/>
</pcm_ids>
<config_params>
<param key="spkr_1_tz_name" value="wsatz.11"/>
@@ -67,6 +69,8 @@
<!-- followed by perf lock options -->
<param key="perf_lock_opts" value="4, 0x101, 0x704, 0x20F, 0x1E01"/>
<param key="input_mic_max_count" value="4"/>
+ <!-- In the below value string, the value indicates sidetone gain in dB -->
+ <param key="usb_sidetone_gain" value="35"/>
</config_params>
<backend_names>
<device name="SND_DEVICE_OUT_HEADPHONES" backend="headphones" interface="SLIMBUS_6_RX"/>
diff --git a/configs/msmcobalt/audio_policy.conf b/configs/msmcobalt/audio_policy.conf
index efd1ef3..08997e0 100644
--- a/configs/msmcobalt/audio_policy.conf
+++ b/configs/msmcobalt/audio_policy.conf
@@ -43,6 +43,13 @@
devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_FM
flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER
}
+ compress_passthrough {
+ sampling_rates dynamic
+ channel_masks dynamic
+ formats dynamic
+ devices AUDIO_DEVICE_OUT_AUX_DIGITAL
+ flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING
+ }
multichannel {
sampling_rates 8000|11025|16000|22050|32000|44100|48000|64000|88200|96000|128000|176400|192000
channel_masks dynamic
diff --git a/configs/msmcobalt/audio_policy_configuration.xml b/configs/msmcobalt/audio_policy_configuration.xml
index 56848ad..a3876ef 100644
--- a/configs/msmcobalt/audio_policy_configuration.xml
+++ b/configs/msmcobalt/audio_policy_configuration.xml
@@ -73,6 +73,11 @@
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
+ <mixPort name="compress_passthrough" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ <profile name="" format="dynamic"
+ samplingRates="dynamic" channelMasks="dynamic"/>
+ </mixPort>
<mixPort name="multichannel" role="source"
flags="AUDIO_OUTPUT_FLAG_DIRECT">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
@@ -266,7 +271,7 @@
<route type="mix" sink="Line"
sources="primary output,raw,deep_buffer,direct_pcm,compressed_offload,voip_rx"/>
<route type="mix" sink="HDMI"
- sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload"/>
+ sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload,compress_passthrough"/>
<route type="mix" sink="Proxy"
sources="primary output,raw,deep_buffer,multichannel,direct_pcm,compressed_offload"/>
<route type="mix" sink="FM"
diff --git a/configs/msmcobalt/mixer_paths_tasha.xml b/configs/msmcobalt/mixer_paths_tasha.xml
index 14bba4e..8d30f6b 100644
--- a/configs/msmcobalt/mixer_paths_tasha.xml
+++ b/configs/msmcobalt/mixer_paths_tasha.xml
@@ -131,6 +131,7 @@
<ctl name="HDMI Mixer MultiMedia4" value="0" />
<ctl name="HDMI Mixer MultiMedia5" value="0" />
<ctl name="HDMI Mixer MultiMedia7" value="0" />
+ <ctl name="HDMI Mixer MultiMedia9" value="0" />
<ctl name="HDMI Mixer MultiMedia10" value="0" />
<ctl name="HDMI Mixer MultiMedia11" value="0" />
<ctl name="HDMI Mixer MultiMedia12" value="0" />
@@ -173,6 +174,28 @@
<ctl name="SLIMBUS_0_RX Audio Mixer MultiMedia16" value="0" />
<ctl name="SLIMBUS_5_RX Audio Mixer MultiMedia16" value="0" />
<ctl name="SLIMBUS_6_RX Audio Mixer MultiMedia16" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia1" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia2" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia3" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia4" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia5" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia7" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia10" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia11" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia12" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia13" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia14" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="0" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="0" />
+ <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="0" />
+ <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="0" />
+ <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="0" />
+ <ctl name="USB_AUDIO_RX Channels" value="One" />
+ <ctl name="USB_AUDIO_RX SampleRate" value="KHZ_48" />
+ <ctl name="USB_AUDIO_RX Format" value="S16_LE" />
+ <ctl name="USB_AUDIO_TX Channels" value="One" />
+ <ctl name="USB_AUDIO_TX SampleRate" value="KHZ_48" />
+ <ctl name="USB_AUDIO_TX Format" value="S16_LE" />
<ctl name="MultiMedia6 Mixer SLIM_0_TX" value="0" />
<ctl name="IIR0 INP0 MUX" value="ZERO" />
<ctl name="IIR0 INP1 MUX" value="ZERO" />
@@ -419,6 +442,8 @@
<!-- Multimode Voice1 USB headset -->
<ctl name="AFE_PCM_RX_Voice Mixer VoiceMMode1" value="0" />
<ctl name="VoiceMMode1_Tx Mixer AFE_PCM_TX_MMode1" value="0" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoiceMMode1" value="0" />
+ <ctl name="VoiceMMode1_Tx Mixer USB_AUDIO_TX_MMode1" value="0" />
<!-- Miltimode Voice1 end-->
<!-- Multimode Voice2 -->
@@ -433,6 +458,8 @@
<!-- Multimode Voice2 USB headset -->
<ctl name="AFE_PCM_RX_Voice Mixer VoiceMMode2" value="0" />
<ctl name="VoiceMMode2_Tx Mixer AFE_PCM_TX_MMode2" value="0" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoiceMMode2" value="0" />
+ <ctl name="VoiceMMode2_Tx Mixer USB_AUDIO_TX_MMode2" value="0" />
<!-- Multimode Voice2 end-->
<!-- Voice external ec. reference -->
@@ -455,7 +482,6 @@
<!-- Incall Music -->
<ctl name="Incall_Music Audio Mixer MultiMedia2" value="0" />
- <ctl name="Incall_Music_2 Audio Mixer MultiMedia9" value="0" />
<!-- Incall Music End -->
<!-- compress-voip-call start -->
@@ -466,6 +492,8 @@
<ctl name="Voip_Tx Mixer SLIM_7_TX_Voip" value="0" />
<ctl name="AFE_PCM_RX_Voice Mixer Voip" value="0" />
<ctl name="Voip_Tx Mixer AFE_PCM_TX_Voip" value="0" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer Voip" value="0" />
+ <ctl name="Voip_Tx Mixer USB_AUDIO_TX_Voip" value="0" />
<!-- compress-voip-call end-->
<!-- QCHAT start -->
@@ -474,6 +502,8 @@
<ctl name="QCHAT_Tx Mixer SLIM_0_TX_QCHAT" value="0" />
<ctl name="SLIM_7_RX_Voice Mixer QCHAT" value="0" />
<ctl name="QCHAT_Tx Mixer SLIM_7_TX_QCHAT" value="0" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer QCHAT" value="0" />
+ <ctl name="QCHAT_Tx Mixer USB_AUDIO_TX_QCHAT" value="0" />
<!-- QCHAT end-->
<!-- VoWLAN start -->
@@ -485,6 +515,8 @@
<ctl name="VoWLAN_Tx Mixer SLIM_7_TX_VoWLAN" value="0" />
<ctl name="AFE_PCM_RX_Voice Mixer VoWLAN" value="0" />
<ctl name="VoWLAN_Tx Mixer AFE_PCM_TX_VoWLAN" value="0" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoWLAN" value="0" />
+ <ctl name="VoWLAN_Tx Mixer USB_AUDIO_TX_VoWLAN" value="0" />
<!-- VoWLAN end-->
<!-- Audio BTSCO -->
@@ -641,7 +673,7 @@
</path>
<path name="deep-buffer-playback usb-headphones">
- <path name="deep-buffer-playback afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia1" value="1" />
</path>
<path name="deep-buffer-playback speaker-and-usb-headphones">
@@ -689,7 +721,7 @@
</path>
<path name="low-latency-playback usb-headphones">
- <path name="low-latency-playback afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia5" value="1" />
</path>
<path name="low-latency-playback speaker-and-usb-headphones">
@@ -744,6 +776,11 @@
<path name="audio-ull-playback afe-proxy">
<ctl name="AFE_PCM_RX Audio Mixer MultiMedia3" value="1" />
</path>
+
+ <path name="audio-ull-playback usb-headphones">
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia3" value="1" />
+ </path>
+
<path name="multi-channel-playback hdmi">
<ctl name="HDMI Mixer MultiMedia2" value="1" />
</path>
@@ -764,6 +801,10 @@
<ctl name="HDMI Mixer MultiMedia4" value="1" />
</path>
+ <path name="silence-playback hdmi">
+ <ctl name="HDMI Mixer MultiMedia9" value="1" />
+ </path>
+
<path name="compress-offload-playback bt-sco">
<ctl name="SLIMBUS_7_RX Audio Mixer MultiMedia4" value="1" />
</path>
@@ -783,7 +824,7 @@
</path>
<path name="compress-offload-playback usb-headphones">
- <path name="compress-offload-playback afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia4" value="1" />
</path>
<path name="compress-offload-playback speaker-and-usb-headphones">
@@ -831,7 +872,7 @@
</path>
<path name="compress-offload-playback2 usb-headphones">
- <path name="compress-offload-playback2 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia7" value="1" />
</path>
<path name="compress-offload-playback2 speaker-and-usb-headphones">
@@ -879,7 +920,7 @@
</path>
<path name="compress-offload-playback3 usb-headphones">
- <path name="compress-offload-playback3 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia10" value="1" />
</path>
<path name="compress-offload-playback3 speaker-and-usb-headphones">
@@ -927,7 +968,7 @@
</path>
<path name="compress-offload-playback4 usb-headphones">
- <path name="compress-offload-playback4 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia11" value="1" />
</path>
<path name="compress-offload-playback4 speaker-and-usb-headphones">
@@ -975,7 +1016,7 @@
</path>
<path name="compress-offload-playback5 usb-headphones">
- <path name="compress-offload-playback5 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia12" value="1" />
</path>
<path name="compress-offload-playback5 speaker-and-usb-headphones">
@@ -1023,7 +1064,7 @@
</path>
<path name="compress-offload-playback6 usb-headphones">
- <path name="compress-offload-playback6 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia13" value="1" />
</path>
<path name="compress-offload-playback6 speaker-and-usb-headphones">
@@ -1071,7 +1112,7 @@
</path>
<path name="compress-offload-playback7 usb-headphones">
- <path name="compress-offload-playback7 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia14" value="1" />
</path>
<path name="compress-offload-playback7 speaker-and-usb-headphones">
@@ -1119,7 +1160,7 @@
</path>
<path name="compress-offload-playback8 usb-headphones">
- <path name="compress-offload-playback8 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia15" value="1" />
</path>
<path name="compress-offload-playback8 speaker-and-usb-headphones">
@@ -1167,7 +1208,7 @@
</path>
<path name="compress-offload-playback9 usb-headphones">
- <path name="compress-offload-playback9 afe-proxy" />
+ <ctl name="USB_AUDIO_RX Audio Mixer MultiMedia16" value="1" />
</path>
<path name="compress-offload-playback9 speaker-and-usb-headphones">
@@ -1193,7 +1234,7 @@
</path>
<path name="audio-record usb-headset-mic">
- <ctl name="MultiMedia1 Mixer AFE_PCM_TX" value="1" />
+ <ctl name="MultiMedia1 Mixer USB_AUDIO_TX" value="1" />
</path>
<path name="audio-record bt-sco">
@@ -1223,7 +1264,7 @@
</path>
<path name="audio-record-compress usb-headset-mic">
- <ctl name="MultiMedia8 Mixer AFE_PCM_TX" value="1" />
+ <ctl name="MultiMedia8 Mixer USB_AUDIO_TX" value="1" />
</path>
<path name="low-latency-record">
@@ -1240,7 +1281,7 @@
</path>
<path name="low-latency-record usb-headset-mic">
- <ctl name="MultiMedia5 Mixer AFE_PCM_TX" value="1" />
+ <ctl name="MultiMedia5 Mixer USB_AUDIO_TX" value="1" />
</path>
<path name="low-latency-record capture-fm">
@@ -1277,8 +1318,8 @@
</path>
<path name="voice-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer CSVoice" value="1" />
- <ctl name="Voice_Tx Mixer AFE_PCM_TX_Voice" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer CSVoice" value="1" />
+ <ctl name="Voice_Tx Mixer USB_AUDIO_TX_Voice" value="1" />
</path>
<path name="voice-call headphones">
@@ -1317,8 +1358,8 @@
</path>
<path name="voice2-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer Voice2" value="1" />
- <ctl name="Voice2_Tx Mixer AFE_PCM_TX_Voice2" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer Voice2" value="1" />
+ <ctl name="Voice2_Tx Mixer USB_AUDIO_TX_Voice2" value="1" />
</path>
<path name="voice2-call voice-speaker-vbat">
@@ -1522,8 +1563,8 @@
</path>
<path name="volte-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer VoLTE" value="1" />
- <ctl name="VoLTE_Tx Mixer AFE_PCM_TX_VoLTE" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoLTE" value="1" />
+ <ctl name="VoLTE_Tx Mixer USB_AUDIO_TX_VoLTE" value="1" />
</path>
<path name="volte-call voice-speaker-vbat">
@@ -1558,8 +1599,8 @@
</path>
<path name="compress-voip-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer Voip" value="1" />
- <ctl name="Voip_Tx Mixer AFE_PCM_TX_Voip" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer Voip" value="1" />
+ <ctl name="Voip_Tx Mixer USB_AUDIO_TX_Voip" value="1" />
</path>
<path name="compress-voip-call voice-speaker-vbat">
@@ -1598,8 +1639,8 @@
</path>
<path name="vowlan-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer VoWLAN" value="1" />
- <ctl name="VoWLAN_Tx Mixer AFE_PCM_TX_VoWLAN" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoWLAN" value="1" />
+ <ctl name="VoWLAN_Tx Mixer USB_AUDIO_TX_VoWLAN" value="1" />
</path>
<path name="vowlan-call voice-speaker-vbat">
@@ -1638,8 +1679,8 @@
</path>
<path name="voicemmode1-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer VoiceMMode1" value="1" />
- <ctl name="VoiceMMode1_Tx Mixer AFE_PCM_TX_MMode1" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoiceMMode1" value="1" />
+ <ctl name="VoiceMMode1_Tx Mixer USB_AUDIO_TX_MMode1" value="1" />
</path>
<path name="voicemmode1-call voice-speaker-vbat">
@@ -1678,8 +1719,8 @@
</path>
<path name="voicemmode2-call usb-headphones">
- <ctl name="AFE_PCM_RX_Voice Mixer VoiceMMode2" value="1" />
- <ctl name="VoiceMMode2_Tx Mixer AFE_PCM_TX_MMode2" value="1" />
+ <ctl name="USB_AUDIO_RX_Voice Mixer VoiceMMode2" value="1" />
+ <ctl name="VoiceMMode2_Tx Mixer USB_AUDIO_TX_MMode2" value="1" />
</path>
<path name="voicemmode2-call voice-speaker-vbat">
diff --git a/configs/msmcobalt/msmcobalt.mk b/configs/msmcobalt/msmcobalt.mk
index c6a7cc9..8244d6b 100644
--- a/configs/msmcobalt/msmcobalt.mk
+++ b/configs/msmcobalt/msmcobalt.mk
@@ -19,6 +19,10 @@
AUDIO_FEATURE_ENABLED_FLUENCE := true
AUDIO_FEATURE_ENABLED_HDMI_SPK := true
AUDIO_FEATURE_ENABLED_HDMI_EDID := true
+#AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH := true
+#AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
+#AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := true
+#DOLBY_DDP := true
AUDIO_FEATURE_ENABLED_HFP := true
AUDIO_FEATURE_ENABLED_INCALL_MUSIC := false
AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 8b8632e..49e649c 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -677,11 +677,7 @@
ret = str_parms_get_str(query, AUDIO_PARAMETER_CAN_OPEN_PROXY, value,
sizeof(value));
if (ret >= 0) {
- if (audio_extn_usb_is_proxy_inuse() ||
- !adev->allow_afe_proxy_usage)
- val = 0;
- else
- val = 1;
+ val = (adev->allow_afe_proxy_usage ? 1: 0);
str_parms_add_int(reply, AUDIO_PARAMETER_CAN_OPEN_PROXY, val);
}
ALOGV("%s: called ... can_use_proxy %d", __func__, val);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 3ce83b1..090e6b0 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -151,24 +151,24 @@
#endif
#ifndef USB_HEADSET_ENABLED
-#define audio_extn_usb_init(adev) (0)
-#define audio_extn_usb_deinit() (0)
-#define audio_extn_usb_start_playback(adev) (0)
-#define audio_extn_usb_stop_playback() (0)
-#define audio_extn_usb_start_capture(adev) (0)
-#define audio_extn_usb_stop_capture() (0)
-#define audio_extn_usb_set_proxy_sound_card(sndcard_idx) (0)
-#define audio_extn_usb_is_proxy_inuse() (0)
+#define audio_extn_usb_init(adev) (0)
+#define audio_extn_usb_deinit() (0)
+#define audio_extn_usb_add_device(device, card) (0)
+#define audio_extn_usb_remove_device(device, card) (0)
+#define audio_extn_usb_is_config_supported(bit_width, sample_rate, ch) (0)
+#define audio_extn_usb_enable_sidetone(device, enable) (0)
+#define audio_extn_usb_set_sidetone_gain(parms, value, len) (0)
#else
-void initPlaybackVolume();
void audio_extn_usb_init(void *adev);
void audio_extn_usb_deinit();
-void audio_extn_usb_start_playback(void *adev);
-void audio_extn_usb_stop_playback();
-void audio_extn_usb_start_capture(void *adev);
-void audio_extn_usb_stop_capture();
-void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx);
-bool audio_extn_usb_is_proxy_inuse();
+void audio_extn_usb_add_device(audio_devices_t device, int card);
+void audio_extn_usb_remove_device(audio_devices_t device, int card);
+bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
+ unsigned int *sample_rate,
+ unsigned int ch);
+int audio_extn_usb_enable_sidetone(int device, bool enable);
+int audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
+ char *value, int len);
#endif
#ifndef SSR_ENABLED
@@ -354,7 +354,6 @@
AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_BACK_CENTER)
#endif
-
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
void audio_extn_dolby_set_license(struct audio_device *adev);
#else
@@ -389,13 +388,13 @@
#endif
#ifndef HDMI_PASSTHROUGH_ENABLED
-#define audio_extn_dolby_update_passt_stream_configuration(adev, out) (0)
-#define audio_extn_dolby_is_passt_convert_supported(adev, out) (0)
-#define audio_extn_dolby_is_passt_supported(adev, out) (0)
-#define audio_extn_dolby_is_passthrough_stream(out) (0)
-#define audio_extn_dolby_get_passt_buffer_size(info) (0)
-#define audio_extn_dolby_set_passt_volume(out, mute) (0)
-#define audio_extn_dolby_set_passt_latency(out, latency) (0)
+#define audio_extn_passthru_update_stream_configuration(adev, out) (0)
+#define audio_extn_passthru_is_convert_supported(adev, out) (0)
+#define audio_extn_passthru_is_passt_supported(adev, out) (0)
+#define audio_extn_passthru_is_passthrough_stream(out) (0)
+#define audio_extn_passthru_get_buffer_size(info) (0)
+#define audio_extn_passthru_set_volume(out, mute) (0)
+#define audio_extn_passthru_set_latency(out, latency) (0)
#define audio_extn_passthru_is_supported_format(f) (0)
#define audio_extn_passthru_should_drop_data(o) (0)
#define audio_extn_passthru_on_start(o) do {} while(0)
@@ -409,16 +408,16 @@
#define AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH 0x1000
#else
-bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
+bool audio_extn_passthru_is_convert_supported(struct audio_device *adev,
struct stream_out *out);
-bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
+bool audio_extn_passthru_is_passt_supported(struct audio_device *adev,
struct stream_out *out);
-void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev,
+void audio_extn_passthru_update_stream_configuration(struct audio_device *adev,
struct stream_out *out);
-bool audio_extn_dolby_is_passthrough_stream(struct stream_out *out);
-int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info);
-int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute);
-int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency);
+bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out);
+int audio_extn_passthru_get_buffer_size(audio_offload_info_t* info);
+int audio_extn_passthru_set_volume(struct stream_out *out, int mute);
+int audio_extn_passthru_set_latency(struct stream_out *out, int latency);
bool audio_extn_passthru_is_supported_format(audio_format_t format);
bool audio_extn_passthru_should_drop_data(struct stream_out * out);
void audio_extn_passthru_on_start(struct stream_out *out);
@@ -430,7 +429,6 @@
bool audio_extn_passthru_is_active();
void audio_extn_passthru_init(struct audio_device *adev);
bool audio_extn_passthru_should_standby(struct stream_out *out);
-
#endif
#ifndef HFP_ENABLED
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index ad8f8a4..f07c66a 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -357,45 +357,6 @@
#endif /* DS1_DOLBY_DDP_ENABLED */
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED)
-int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev,
- struct stream_out *out,
- audio_format_t format)
-{
- int id = 0;
- /*
- * Use wfd /hdmi sink channel cap for dolby params if device is wfd
- * or hdmi. Otherwise use stereo configuration
- */
- int channel_cap = out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ?
- adev->cur_hdmi_channels :
- out->devices & AUDIO_DEVICE_OUT_PROXY ?
- adev->cur_wfd_channels : 2;
-
- switch (format) {
- case AUDIO_FORMAT_AC3:
- id = SND_AUDIOCODEC_AC3;
-#ifdef DS1_DOLBY_DDP_ENABLED
- send_ddp_endp_params_stream(out, out->devices,
- channel_cap, true /* set_cache */);
-#endif
- audio_extn_dolby_set_dmid(adev);
- break;
- case AUDIO_FORMAT_E_AC3:
- case AUDIO_FORMAT_E_AC3_JOC:
- id = SND_AUDIOCODEC_EAC3;
-#ifdef DS1_DOLBY_DDP_ENABLED
- send_ddp_endp_params_stream(out, out->devices,
- channel_cap, true /* set_cache */);
-#endif
- audio_extn_dolby_set_dmid(adev);
- break;
- default:
- ALOGE("%s: Unsupported audio format :%x", __func__, format);
- }
-
- return id;
-}
-
bool audio_extn_is_dolby_format(audio_format_t format)
{
if (format == AUDIO_FORMAT_AC3 ||
@@ -407,121 +368,6 @@
}
#endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */
-#ifdef HDMI_PASSTHROUGH_ENABLED
-bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev,
- struct stream_out *out) {
-
- bool convert = false;
- switch (out->format) {
- case AUDIO_FORMAT_E_AC3:
- case AUDIO_FORMAT_E_AC3_JOC:
- if (!platform_is_edid_supported_format(adev->platform,
- AUDIO_FORMAT_E_AC3)) {
- ALOGV("%s:PASSTHROUGH_CONVERT supported", __func__);
- convert = true;
- }
- break;
- default:
- ALOGE("%s: PASSTHROUGH_CONVERT not supported for format 0x%x",
- __func__, out->format);
- break;
- }
- ALOGE("%s: convert %d", __func__, convert);
- return convert;
-}
-
-bool audio_extn_dolby_is_passt_supported(struct audio_device *adev,
- struct stream_out *out) {
- bool passt = false;
- switch (out->format) {
- case AUDIO_FORMAT_E_AC3:
- if (platform_is_edid_supported_format(adev->platform, out->format)) {
- ALOGV("%s:PASSTHROUGH supported for format %x",
- __func__, out->format);
- passt = true;
- }
- break;
- case AUDIO_FORMAT_AC3:
- if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)
- || platform_is_edid_supported_format(adev->platform,
- AUDIO_FORMAT_E_AC3)) {
- ALOGV("%s:PASSTHROUGH supported for format %x",
- __func__, out->format);
- passt = true;
- }
- break;
- case AUDIO_FORMAT_E_AC3_JOC:
- /* Check for DDP capability in edid for JOC contents.*/
- if (platform_is_edid_supported_format(adev->platform,
- AUDIO_FORMAT_E_AC3)) {
- ALOGV("%s:PASSTHROUGH supported for format %x",
- __func__, out->format);
- passt = true;
- }
- default:
- ALOGV("%s:Passthrough not supported", __func__);
- }
- return passt;
-}
-
-void audio_extn_dolby_update_passt_stream_configuration(
- struct audio_device *adev, struct stream_out *out) {
- if (audio_extn_dolby_is_passt_supported(adev, out)) {
- ALOGV("%s:PASSTHROUGH", __func__);
- out->compr_config.codec->compr_passthr = PASSTHROUGH;
- } else if (audio_extn_dolby_is_passt_convert_supported(adev, out)){
- ALOGV("%s:PASSTHROUGH CONVERT", __func__);
- out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT;
- } else {
- ALOGV("%s:NO PASSTHROUGH", __func__);
- out->compr_config.codec->compr_passthr = LEGACY_PCM;
- }
-}
-
-bool audio_extn_dolby_is_passthrough_stream(struct stream_out *out) {
-
- //check passthrough system property
- if (!property_get_bool("audio.offload.passthrough", false)) {
- return false;
- }
-
- //check supported device, currently only on HDMI.
- if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
- //passthrough flag
- if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
- return true;
- //direct flag, check supported formats.
- if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
- if (audio_extn_passthru_is_supported_format(out->format)) {
- if (platform_is_edid_supported_format(out->dev->platform,
- out->format)) {
- return true;
- } else if (audio_extn_is_dolby_format(out->format) &&
- platform_is_edid_supported_format(out->dev->platform,
- AUDIO_FORMAT_AC3)){
- //return true for EAC3/EAC3_JOC formats
- //if sink supports only AC3
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) {
- return platform_get_compress_passthrough_buffer_size(info);
-}
-
-int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute) {
- return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute);
-}
-
-int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency) {
- return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
-}
-#endif /* HDMI_PASSTHROUGH_ENABLED */
#ifdef DS1_DOLBY_DAP_ENABLED
void audio_extn_dolby_set_endpoint(struct audio_device *adev)
diff --git a/hal/audio_extn/keep_alive.c b/hal/audio_extn/keep_alive.c
index ab663ef..1a4f135 100644
--- a/hal/audio_extn/keep_alive.c
+++ b/hal/audio_extn/keep_alive.c
@@ -37,7 +37,7 @@
#include <platform.h>
#define SILENCE_MIXER_PATH "silence-playback hdmi"
-#define SILENCE_DEV_ID 5 /* index into machine driver */
+#define SILENCE_DEV_ID 32 /* index into machine driver */
#define SILENCE_INTERVAL_US 2000000
typedef enum {
@@ -147,22 +147,71 @@
void audio_extn_keep_alive_start()
{
struct audio_device * adev = (struct audio_device *)ka.userdata;
-
- if (ka.state == STATE_DEINIT)
- return;
-
- if (audio_extn_passthru_is_active())
- return;
+ char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
+ int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
+ struct mixer_ctl *ctl;
+ int acdb_dev_id, snd_device;
+ int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
pthread_mutex_lock(&ka.lock);
- if (ka.state == STATE_ACTIVE)
+ if (ka.state == STATE_DEINIT) {
+ ALOGE(" %s : Invalid state ",__func__);
+ return;
+ }
+
+ if (audio_extn_passthru_is_active()) {
+ ALOGE(" %s : Pass through is already active", __func__);
+ return;
+ }
+
+ if (ka.state == STATE_ACTIVE) {
+ ALOGV(" %s : Keep alive state is already Active",__func__ );
goto exit;
+ }
ka.done = false;
- //todo: platform_send_audio_calibration is replaced by audio_extn_utils_send_audio_calibration
- //check why audio cal needs to be set
- //platform_send_audio_calibration(adev->platform, SND_DEVICE_OUT_HDMI);
+
+ /*configure app type */
+ snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+ "Audio Stream %d App Type Cfg",SILENCE_DEV_ID);
+
+ 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);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ snd_device = SND_DEVICE_OUT_HDMI;
+ acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+ if (acdb_dev_id < 0) {
+ ALOGE("%s: Couldn't get the acdb dev id", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ app_type_cfg[len++] = platform_get_default_app_type(adev->platform);
+ app_type_cfg[len++] = acdb_dev_id;
+ app_type_cfg[len++] = sample_rate;
+
+ ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
+ __func__, __LINE__,
+ platform_get_default_app_type(adev->platform),
+ acdb_dev_id, sample_rate);
+ mixer_ctl_set_array(ctl, app_type_cfg, len);
+
+ /*send calibration*/
+ struct audio_usecase *usecase = calloc(1, sizeof(struct audio_usecase));
+ usecase->type = PCM_PLAYBACK;
+ usecase->out_snd_device = SND_DEVICE_OUT_HDMI;
+
+ platform_send_audio_calibration(adev->platform, usecase,
+ platform_get_default_app_type(adev->platform), sample_rate);
+
+ /*apply audio route */
audio_route_apply_and_update_path(adev->audio_route, SILENCE_MIXER_PATH);
if (open_silence_stream() == 0) {
@@ -181,11 +230,11 @@
{
struct audio_device * adev = (struct audio_device *)ka.userdata;
+ pthread_mutex_lock(&ka.lock);
+
if (ka.state == STATE_DEINIT)
return;
- pthread_mutex_lock(&ka.lock);
-
if (ka.state == STATE_IDLE)
goto exit;
@@ -211,7 +260,7 @@
char value[32];
int ret;
- ret = str_parms_get_str(parms, "connect", value, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
if (ret >= 0) {
int val = atoi(value);
if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
@@ -237,12 +286,10 @@
static void * keep_alive_loop(void * context __unused)
{
- struct audio_device *adev = (struct audio_device *)ka.userdata;
struct keep_alive_cmd *cmd = NULL;
struct listnode *item;
uint8_t * silence = NULL;
- int32_t bytes = 0, count = 0, i;
- struct stream_out * p_out = NULL;
+ int32_t bytes = 0;
while (true) {
pthread_mutex_lock(&ka.lock);
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index d87303b..e6ac4dd 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -37,10 +37,14 @@
#include "audio_extn.h"
#include "platform_api.h"
#include <platform.h>
+#include <cutils/properties.h>
+
+#include "sound/compress_params.h"
static const audio_format_t audio_passthru_formats[] = {
AUDIO_FORMAT_AC3,
AUDIO_FORMAT_E_AC3,
+ AUDIO_FORMAT_E_AC3_JOC,
AUDIO_FORMAT_DTS,
AUDIO_FORMAT_DTS_HD
};
@@ -63,9 +67,11 @@
for (i = 0; i < num_passthru_formats; i++) {
if (format == audio_passthru_formats[i]) {
+ ALOGD("%s : pass through format is true", __func__);
return true;
}
}
+ ALOGD("%s : pass through format is false", __func__);
return false;
}
@@ -76,11 +82,6 @@
*/
bool audio_extn_passthru_should_drop_data(struct stream_out * out)
{
- /* Make this product specific */
- if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
- ALOGI("drop data as end device 0x%x is unsupported", out->devices);
- return true;
- }
if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
if (android_atomic_acquire_load(&compress_passthru_active) > 0) {
@@ -158,8 +159,6 @@
{
if (android_atomic_acquire_load(&compress_passthru_active) == 0)
return;
-
- android_atomic_dec(&compress_passthru_active);
}
int audio_extn_passthru_set_parameters(struct audio_device *adev __unused,
@@ -183,3 +182,143 @@
{
return true;
}
+
+bool audio_extn_passthru_is_convert_supported(struct audio_device *adev,
+ struct stream_out *out)
+{
+
+ bool convert = false;
+ switch (out->format) {
+ case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_E_AC3_JOC:
+ case AUDIO_FORMAT_DTS_HD:
+ if (!platform_is_edid_supported_format(adev->platform,
+ out->format)) {
+ ALOGD("%s:PASSTHROUGH_CONVERT supported", __func__);
+ convert = true;
+ }
+ break;
+ default:
+ ALOGD("%s: PASSTHROUGH_CONVERT not supported for format 0x%x",
+ __func__, out->format);
+ break;
+ }
+ ALOGD("%s: convert %d", __func__, convert);
+ return convert;
+}
+
+bool audio_extn_passthru_is_passt_supported(struct audio_device *adev,
+ struct stream_out *out)
+{
+ bool passt = false;
+ switch (out->format) {
+ case AUDIO_FORMAT_E_AC3:
+ if (platform_is_edid_supported_format(adev->platform, out->format)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_AC3:
+ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3)
+ || platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_E_AC3_JOC:
+ /* Check for DDP capability in edid for JOC contents.*/
+ if (platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_E_AC3)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_DTS:
+ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_DTS)
+ || platform_is_edid_supported_format(adev->platform,
+ AUDIO_FORMAT_DTS_HD)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ case AUDIO_FORMAT_DTS_HD:
+ if (platform_is_edid_supported_format(adev->platform, out->format)) {
+ ALOGV("%s:PASSTHROUGH supported for format %x",
+ __func__, out->format);
+ passt = true;
+ }
+ break;
+ default:
+ ALOGV("%s:Passthrough not supported", __func__);
+ }
+ return passt;
+}
+
+void audio_extn_passthru_update_stream_configuration(
+ struct audio_device *adev, struct stream_out *out)
+{
+ if (audio_extn_passthru_is_passt_supported(adev, out)) {
+ ALOGV("%s:PASSTHROUGH", __func__);
+ out->compr_config.codec->compr_passthr = PASSTHROUGH;
+ } else if (audio_extn_passthru_is_convert_supported(adev, out)){
+ ALOGV("%s:PASSTHROUGH CONVERT", __func__);
+ out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT;
+ } else {
+ ALOGV("%s:NO PASSTHROUGH", __func__);
+ out->compr_config.codec->compr_passthr = LEGACY_PCM;
+ }
+}
+
+bool audio_extn_passthru_is_passthrough_stream(struct stream_out *out)
+{
+ //check passthrough system property
+ if (!property_get_bool("audio.offload.passthrough", false)) {
+ return false;
+ }
+
+ //check supported device, currently only on HDMI.
+ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
+ //passthrough flag
+ if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)
+ return true;
+ //direct flag, check supported formats.
+ if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ if (audio_extn_passthru_is_supported_format(out->format)) {
+ if (platform_is_edid_supported_format(out->dev->platform,
+ out->format)) {
+ ALOGV("%s : return true",__func__);
+ return true;
+ } else if (audio_extn_is_dolby_format(out->format) &&
+ platform_is_edid_supported_format(out->dev->platform,
+ AUDIO_FORMAT_AC3)){
+ //return true for EAC3/EAC3_JOC formats
+ //if sink supports only AC3
+ ALOGV("%s : return true",__func__);
+ return true;
+ }
+ }
+ }
+ }
+ ALOGV("%s : return false",__func__);
+ return false;
+}
+
+int audio_extn_passthru_get_buffer_size(audio_offload_info_t* info)
+{
+ return platform_get_compress_passthrough_buffer_size(info);
+}
+
+int audio_extn_passthru_set_volume(struct stream_out *out, int mute)
+{
+ return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute);
+}
+
+int audio_extn_passthru_set_latency(struct stream_out *out, int latency)
+{
+ return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency);
+}
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 13e3138..da80422 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -29,151 +29,296 @@
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/stat.h>
-
#include <system/audio.h>
#include <tinyalsa/asoundlib.h>
+#include <audio_hw.h>
+#include <cutils/properties.h>
+#include <ctype.h>
+#include <math.h>
#ifdef USB_HEADSET_ENABLED
-#define USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE 512
-#define USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT 8
-#define USB_DEFAULT_OUTPUT_SAMPLING_RATE 48000
+#define USB_BUFF_SIZE 2048
+#define CHANNEL_NUMBER_STR "Channels: "
+#define PLAYBACK_PROFILE_STR "Playback:"
+#define CAPTURE_PROFILE_STR "Capture:"
+#define USB_SIDETONE_GAIN_STR "usb_sidetone_gain"
+#define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A)))
+#define SAMPLE_RATE_8000 8000
+#define SAMPLE_RATE_11025 11025
+// Supported sample rates for USB
+static uint32_t supported_sample_rates[] =
+ {44100, 48000, 64000, 88200, 96000, 176400, 192000};
-#define USB_PROXY_DEFAULT_SAMPLING_RATE 48000
-#define USB_PROXY_OPEN_RETRY_COUNT 100
-#define USB_PROXY_OPEN_WAIT_TIME 20
-#define USB_PROXY_PERIOD_SIZE 3072
-#define USB_PROXY_RATE_8000 8000
-#define USB_PROXY_RATE_16000 16000
-#define USB_PROXY_RATE_48000 48000
-#define USB_PERIOD_SIZE 2048
-#define USB_BUFF_SIZE 2048
-#define AFE_PROXY_PERIOD_COUNT 32
-#define AFE_PROXY_PLAYBACK_DEVICE 8
-#define AFE_PROXY_CAPTURE_DEVICE 7
+#define MAX_SAMPLE_RATE_SIZE sizeof(supported_sample_rates)/sizeof(supported_sample_rates[0])
+
+enum usb_usecase_type{
+ USB_PLAYBACK = 0,
+ USB_CAPTURE,
+};
+
+enum {
+ USB_SIDETONE_ENABLE_INDEX = 0,
+ USB_SIDETONE_VOLUME_INDEX,
+ USB_SIDETONE_MAX_INDEX,
+};
+
+struct usb_device_config {
+ struct listnode list;
+ unsigned int bit_width;
+ unsigned int channels;
+ unsigned int rate_size;
+ unsigned int rates[MAX_SAMPLE_RATE_SIZE];
+};
+
+struct usb_card_config {
+ struct listnode list;
+ audio_devices_t usb_device_type;
+ int usb_card;
+ struct listnode usb_device_conf_list;
+ struct mixer *usb_snd_mixer;
+ int usb_sidetone_index[USB_SIDETONE_MAX_INDEX];
+ int usb_sidetone_vol_min;
+ int usb_sidetone_vol_max;
+};
struct usb_module {
- uint32_t usb_card;
- uint32_t proxy_card;
- uint32_t usb_device_id;
- uint32_t proxy_device_id;
-
- int32_t channels_playback;
- int32_t sample_rate_playback;
- int32_t channels_record;
- int32_t sample_rate_record;
-
- bool is_playback_running;
- bool is_record_running;
-
- pthread_t usb_playback_thr;
- pthread_t usb_record_thr;
- pthread_mutex_t usb_playback_lock;
- pthread_mutex_t usb_record_lock;
-
- struct pcm *proxy_pcm_playback_handle;
- struct pcm *usb_pcm_playback_handle;
- struct pcm *proxy_pcm_record_handle;
- struct pcm *usb_pcm_record_handle;
+ struct listnode usb_card_conf_list;
struct audio_device *adev;
+ int sidetone_gain;
};
static struct usb_module *usbmod = NULL;
-static pthread_once_t alloc_usbmod_once_ctl = PTHREAD_ONCE_INIT;
+static bool usb_audio_debug_enable = false;
+static int usb_sidetone_gain = 0;
-struct pcm_config pcm_config_usbmod = {
- .channels = 2,
- .rate = USB_DEFAULT_OUTPUT_SAMPLING_RATE,
- .period_size = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE,
- .period_count = USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT,
- .format = PCM_FORMAT_S16_LE,
- .start_threshold = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
- .stop_threshold = INT_MAX,
- .avail_min = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
+static const char * const usb_sidetone_enable_str[] = {
+ "Sidetone Playback Switch",
+ "Mic Playback Switchs",
};
-static void usb_alloc()
+static const char * const usb_sidetone_volume_str[] = {
+ "Sidetone Playback Volume",
+ "Mic Playback Volume",
+};
+
+static void usb_mixer_print_enum(struct mixer_ctl *ctl)
{
- usbmod = calloc(1, sizeof(struct usb_module));
-}
+ unsigned int num_enums;
+ unsigned int i;
+ const char *string;
-// Some USB audio accessories have a really low default volume set. Look for a suitable
-// volume control and set the volume to default volume level.
-static void initPlaybackVolume() {
- ALOGD("initPlaybackVolume");
- struct mixer *usbMixer = mixer_open(1);
+ num_enums = mixer_ctl_get_num_enums(ctl);
- if (usbMixer) {
- struct mixer_ctl *ctl = NULL;
- unsigned int usbPlaybackVolume;
- unsigned int i;
- unsigned int num_ctls = mixer_get_num_ctls(usbMixer);
-
- // Look for the first control named ".*Playback Volume" that isn't for a microphone
- for (i = 0; i < num_ctls; i++) {
- ctl = mixer_get_ctl(usbMixer, i);
- if ((ctl) && (strstr((const char *)mixer_ctl_get_name(ctl), "Playback Volume") &&
- !strstr((const char *)mixer_ctl_get_name(ctl), "Mic"))) {
- break;
- }
- }
- if (ctl != NULL) {
- ALOGD("Found a volume control for USB: %s", mixer_ctl_get_name(ctl) );
- usbPlaybackVolume = mixer_ctl_get_value(ctl, 0);
- ALOGD("Value got from mixer_ctl_get is:%u", usbPlaybackVolume);
- if (mixer_ctl_set_value(ctl,0,usbPlaybackVolume) < 0) {
- ALOGE("Failed to set volume; default volume might be used");
- }
- } else {
- ALOGE("No playback volume control found; default volume will be used");
- }
- mixer_close(usbMixer);
- } else {
- ALOGE("Failed to open mixer for card 1");
+ for (i = 0; i < num_enums; i++) {
+ string = mixer_ctl_get_enum_string(ctl, i);
+ ALOGI("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "", string);
}
}
-static int usb_get_numof_rates(char *rates_str)
+static void usb_soundcard_detail_control(struct mixer *mixer, const char *control)
{
- int i, size = 0;
+ struct mixer_ctl *ctl;
+ enum mixer_ctl_type type;
+ unsigned int num_values;
+ unsigned int i;
+ int min, max;
+
+ if (isdigit(control[0]))
+ ctl = mixer_get_ctl(mixer, atoi(control));
+ else
+ ctl = mixer_get_ctl_by_name(mixer, control);
+
+ if (!ctl) {
+ fprintf(stderr, "Invalid mixer control\n");
+ return;
+ }
+
+ type = mixer_ctl_get_type(ctl);
+ num_values = mixer_ctl_get_num_values(ctl);
+
+ ALOGI("%s:", mixer_ctl_get_name(ctl));
+
+ for (i = 0; i < num_values; i++) {
+ switch (type) {
+ case MIXER_CTL_TYPE_INT:
+ ALOGI(" %d", mixer_ctl_get_value(ctl, i));
+ break;
+ case MIXER_CTL_TYPE_BOOL:
+ ALOGI(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
+ break;
+ case MIXER_CTL_TYPE_ENUM:
+ usb_mixer_print_enum(ctl);
+ break;
+ case MIXER_CTL_TYPE_BYTE:
+ ALOGI(" 0x%02x", mixer_ctl_get_value(ctl, i));
+ break;
+ default:
+ ALOGI(" unknown");
+ break;
+ }
+ }
+
+ if (type == MIXER_CTL_TYPE_INT) {
+ min = mixer_ctl_get_range_min(ctl);
+ max = mixer_ctl_get_range_max(ctl);
+ ALOGI(" (range %d->%d)", min, max);
+ }
+}
+
+static void usb_soundcard_list_controls(struct mixer *mixer)
+{
+ struct mixer_ctl *ctl;
+ const char *name, *type;
+ unsigned int num_ctls, num_values;
+ unsigned int i;
+
+ num_ctls = mixer_get_num_ctls(mixer);
+
+ ALOGI("Number of controls: %d\n", num_ctls);
+
+ ALOGI("ctl\ttype\tnum\t%-40s value\n", "name");
+ for (i = 0; i < num_ctls; i++) {
+ ctl = mixer_get_ctl(mixer, i);
+ if (ctl != NULL) {
+ name = mixer_ctl_get_name(ctl);
+ type = mixer_ctl_get_type_string(ctl);
+ num_values = mixer_ctl_get_num_values(ctl);
+ ALOGI("%d\t%s\t%d\t%-40s", i, type, num_values, name);
+ if (name != NULL)
+ usb_soundcard_detail_control(mixer, name);
+ }
+ }
+}
+
+static int usb_set_channel_mixer_ctl(int channel,
+ char *ch_mixer_ctl_name)
+{
+ struct mixer_ctl *ctl;
+
+ ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, ch_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, ch_mixer_ctl_name);
+ return -EINVAL;
+ }
+ switch (channel) {
+ case 1:
+ mixer_ctl_set_enum_by_string(ctl, "One");
+ break;
+ case 2:
+ mixer_ctl_set_enum_by_string(ctl, "Two");
+ break;
+ default:
+ ALOGV("%s: channel(%d) not supported, set as default 2 channels",
+ __func__, channel);
+ mixer_ctl_set_enum_by_string(ctl, "Two");
+ break;
+ }
+ return 0;
+}
+
+static int usb_set_dev_id_mixer_ctl(unsigned int usb_usecase_type, int card,
+ char *dev_mixer_ctl_name)
+{
+ struct mixer_ctl *ctl;
+ unsigned int dev_token;
+ unsigned int pcm_device_number = 0;
+
+ /*
+ * usb_dev_token_id is 32 bit number and is defined as below:
+ * usb_sound_card_idx(31:16) | usb PCM device ID(15:8) | usb_usecase_type(7:0)
+ */
+ dev_token = (card << 16 ) |
+ (pcm_device_number << 8) | (usb_usecase_type & 0xFF);
+
+ ctl = mixer_get_ctl_by_name(usbmod->adev->mixer, dev_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, dev_mixer_ctl_name);
+ return -EINVAL;
+ }
+ mixer_ctl_set_value(ctl, 0, dev_token);
+
+ return 0;
+}
+
+static int usb_get_sample_rates(char *rates_str,
+ struct usb_device_config *config)
+{
+ uint32_t i;
char *next_sr_string, *temp_ptr;
- next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
+ uint32_t sr, min_sr, max_sr, sr_size = 0;
- if (next_sr_string == NULL) {
- ALOGE("%s: get_numof_rates: could not find rates string", __func__);
- return 0;
- }
-
- for (i = 1; next_sr_string != NULL; i++) {
- size ++;
+ /* Sample rate string can be in any of the folloing two bit_widthes:
+ * Rates: 8000 - 48000 (continuous)
+ * Rates: 8000, 44100, 48000
+ * Support both the bit_widths
+ */
+ ALOGV("%s: rates_str %s", __func__, rates_str);
+ if (strstr(rates_str, "continuous") != NULL) {
+ next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
+ if (next_sr_string == NULL) {
+ ALOGE("%s: could not find min rates string", __func__);
+ return -EINVAL;
+ }
+ min_sr = atoi(next_sr_string);
next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
+ if (next_sr_string == NULL) {
+ ALOGE("%s: could not find max rates string", __func__);
+ return -EINVAL;
+ }
+ max_sr = atoi(next_sr_string);
+
+ for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++)
+ if (supported_sample_rates[i] >= min_sr &&
+ supported_sample_rates[i] <= max_sr)
+ config->rates[sr_size++] = supported_sample_rates[i];
+ } else {
+ next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);
+ if (next_sr_string == NULL) {
+ ALOGE("%s: get_numof_rates: could not find rates string", __func__);
+ return -EINVAL;
+ }
+ do {
+ sr = (uint32_t)atoi(next_sr_string);
+ for (i = 0; i < MAX_SAMPLE_RATE_SIZE; i++) {
+ if (supported_sample_rates[i] == sr) {
+ ALOGI_IF(usb_audio_debug_enable,
+ "%s: sr %d, supported_sample_rates[%d] %d -> matches!!",
+ __func__, sr, i, supported_sample_rates[i]);
+ config->rates[sr_size++] = supported_sample_rates[i];
+ }
+ }
+ next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
+ } while (next_sr_string != NULL);
}
- return size;
+ config->rate_size = sr_size;
+ return 0;
}
-static int usb_get_capability(char *type, int32_t *channels,
- int32_t *sample_rate)
+static int usb_get_capability(int type,
+ struct usb_card_config *usb_card_info,
+ int card)
{
- ALOGD("%s: for %s", __func__, type);
- long unsigned file_size;
- FILE *fp;
- char *buffer;
int32_t err = 1;
int32_t size = 0;
- int32_t fd=-1, i, channels_playback;
- char *str_start, *channel_start, *rates_str_start, *next_sr_str,
- *next_sr_string, *temp_ptr;
- struct stat st;
+ int32_t fd=-1;
+ int32_t altset_index = 1;
+ int32_t channels_no;
+ char *str_start, *channel_start, *bit_width_start, *rates_str_start,
+ *target;
char *read_buf = NULL;
char *rates_str = NULL;
- char *rates_str_for_val = NULL;
- int *rates_supported = NULL;
- char path[128];
+ char path[128], altset[9];
int ret = 0;
+ char *bit_width_str = NULL;
+ struct usb_device_config * usb_device_info;
- memset(&st, 0x0, sizeof(struct stat));
- *sample_rate = 0;
+ ALOGV("%s: for %s", __func__, (type == USB_PLAYBACK) ?
+ PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
+
snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
- usbmod->usb_card);
+ card);
fd = open(path, O_RDONLY);
if (fd <0) {
@@ -183,15 +328,6 @@
goto done;
}
- if (fstat(fd, &st) < 0) {
- ALOGE("%s: error failed to stat %s error %d\n",
- __func__, path, errno);
- ret = -EINVAL;
- goto done;
- }
-
- file_size = st.st_size;
-
read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
if (!read_buf) {
@@ -201,530 +337,707 @@
}
err = read(fd, read_buf, USB_BUFF_SIZE);
- str_start = strstr(read_buf, type);
+ str_start = strstr(read_buf, ((type == USB_PLAYBACK) ?
+ PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
if (str_start == NULL) {
ALOGE("%s: error %s section not found in usb config file",
- __func__, type);
+ __func__, ((type == USB_PLAYBACK) ?
+ PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR));
ret = -EINVAL;
goto done;
}
+ ALOGV("%s: usb_config = %s\n", __func__, str_start);
- channel_start = strstr(str_start, "Channels:");
- if (channel_start == NULL) {
- ALOGE("%s: error could not find Channels information", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- channel_start = strstr(channel_start, " ");
- if (channel_start == NULL) {
- ALOGE("%s: error channel section not found in usb config file",
- __func__);
- ret = -EINVAL;
- goto done;
- }
-
- channels_playback = atoi(channel_start);
- if (channels_playback == 1) {
- *channels = 1;
- } else {
- *channels = 2;
- }
-
- ALOGD("%s: channels supported by device: %d", __func__, *channels);
- rates_str_start = strstr(str_start, "Rates:");
- if (rates_str_start == NULL) {
- ALOGE("%s: error cant find rates information", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- rates_str_start = strstr(rates_str_start, " ");
- if (rates_str_start == NULL) {
- ALOGE("%s: error channel section not found in usb config file",
- __func__);
- ret = -EINVAL;
- goto done;
- }
-
- char *target = strchr(rates_str_start, '\n');
- if (target == NULL) {
- ALOGE("%s: error end of line not found", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- size = target - rates_str_start;
- if ((rates_str = (char *)malloc(size + 1)) == NULL) {
- ALOGE("%s: error unable to allocate memory to hold sample rate strings",
- __func__);
- ret = -EINVAL;
- goto done;
- }
-
- if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
- ALOGE("%s: error unable to allocate memory to hold sample rate string",
- __func__);
- ret = -EINVAL;
- goto done;
- }
-
- memcpy(rates_str, rates_str_start, size);
- memcpy(rates_str_for_val, rates_str_start, size);
- rates_str[size] = '\0';
- rates_str_for_val[size] = '\0';
-
- size = usb_get_numof_rates(rates_str);
- if (!size) {
- ALOGE("%s: error could not get rate size, returning", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- rates_supported = (int *)malloc(sizeof(int) * size);
-
- if (!rates_supported) {
- ALOGE("couldn't allocate mem for rates_supported");
- ret = -EINVAL;
- goto done;
- }
-
- next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
- if (next_sr_string == NULL) {
- ALOGE("%s: error could not get first rate val", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- rates_supported[0] = atoi(next_sr_string);
- ALOGD("%s: rates_supported[0] for playback: %d",
- __func__, rates_supported[0]);
- for (i = 1; i<size; i++) {
- next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
- if (next_sr_string == NULL) {
- rates_supported[i] = -1; // fill in an invalid sr for the rest
+ while (str_start != NULL) {
+ sprintf(altset, "Altset %d", altset_index);
+ ALOGV("%s: altset_index %d\n", __func__, altset_index);
+ str_start = strstr(str_start, altset);
+ if (str_start == NULL) {
+ if (altset_index == 1) {
+ ALOGE("%s: error %s section not found in usb config file",
+ __func__, (type == USB_PLAYBACK) ?
+ PLAYBACK_PROFILE_STR : CAPTURE_PROFILE_STR);
+ ret = -EINVAL;
+ }
+ break;
+ }
+ usb_device_info = calloc(1, sizeof(struct usb_device_config));
+ if (usb_device_info == NULL) {
+ ALOGE("%s: error unable to allocate memory",
+ __func__);
+ ret = -ENOMEM;
+ break;
+ }
+ altset_index++;
+ /* Bit bit_width parsing */
+ bit_width_start = strstr(str_start, "Format: ");
+ if (bit_width_start == NULL) {
+ ALOGI("%s: Could not find bit_width string", __func__);
+ free(usb_device_info);
continue;
}
- rates_supported[i] = atoi(next_sr_string);
- ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
- }
-
- for (i = 0; i<size; i++) {
- if ((rates_supported[i] > *sample_rate) &&
- (rates_supported[i] <= 48000)) {
- /* Sample Rate should be one of the proxy supported rates only
- This is because proxy port is used to read from/write to DSP */
- if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
- (rates_supported[i] == USB_PROXY_RATE_16000) ||
- (rates_supported[i] == USB_PROXY_RATE_48000)) {
- *sample_rate = rates_supported[i];
- }
+ target = strchr(bit_width_start, '\n');
+ if (target == NULL) {
+ ALOGI("%s:end of line not found", __func__);
+ free(usb_device_info);
+ continue;
}
+ size = target - bit_width_start;
+ if ((bit_width_str = (char *)malloc(size + 1)) == NULL) {
+ ALOGE("%s: unable to allocate memory to hold bit width strings",
+ __func__);
+ ret = -EINVAL;
+ free(usb_device_info);
+ break;
+ }
+ memcpy(bit_width_str, bit_width_start, size);
+ bit_width_str[size] = '\0';
+ if (strstr(bit_width_str, "S16_LE"))
+ usb_device_info->bit_width = 16;
+ else if (strstr(bit_width_str, "S24_LE"))
+ usb_device_info->bit_width = 24;
+ else if (strstr(bit_width_str, "S24_3LE"))
+ usb_device_info->bit_width = 24;
+ else if (strstr(bit_width_str, "S32_LE"))
+ usb_device_info->bit_width = 32;
+
+ if (bit_width_str)
+ free(bit_width_str);
+
+ /* channels parsing */
+ channel_start = strstr(str_start, CHANNEL_NUMBER_STR);
+ if (channel_start == NULL) {
+ ALOGI("%s: could not find Channels string", __func__);
+ free(usb_device_info);
+ continue;
+ }
+ channels_no = atoi(channel_start + strlen(CHANNEL_NUMBER_STR));
+ usb_device_info->channels = channels_no;
+
+ /* Sample rates parsing */
+ rates_str_start = strstr(str_start, "Rates: ");
+ if (rates_str_start == NULL) {
+ ALOGI("%s: cant find rates string", __func__);
+ free(usb_device_info);
+ continue;
+ }
+ target = strchr(rates_str_start, '\n');
+ if (target == NULL) {
+ ALOGI("%s: end of line not found", __func__);
+ free(usb_device_info);
+ continue;
+ }
+ size = target - rates_str_start;
+ if ((rates_str = (char *)malloc(size + 1)) == NULL) {
+ ALOGE("%s: unable to allocate memory to hold sample rate strings",
+ __func__);
+ ret = -EINVAL;
+ free(usb_device_info);
+ break;
+ }
+ memcpy(rates_str, rates_str_start, size);
+ rates_str[size] = '\0';
+ ret = usb_get_sample_rates(rates_str, usb_device_info);
+ if (rates_str)
+ free(rates_str);
+ if (ret < 0) {
+ ALOGI("%s: error unable to get sample rate values",
+ __func__);
+ free(usb_device_info);
+ continue;
+ }
+ /* Add to list if every field is valid */
+ list_add_tail(&usb_card_info->usb_device_conf_list,
+ &usb_device_info->list);
}
- ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
done:
if (fd >= 0) close(fd);
- if (rates_str_for_val) free(rates_str_for_val);
- if (rates_str) free(rates_str);
- if (rates_supported) free(rates_supported);
if (read_buf) free(read_buf);
return ret;
}
-static int32_t usb_playback_entry(void *adev)
+static int usb_get_device_pb_config(struct usb_card_config *usb_card_info,
+ int card)
{
- unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
- int32_t ret, bytes, proxy_open_retry_count;
-
- ALOGD("%s: entry", __func__);
- /* update audio device pointer */
- usbmod->adev = (struct audio_device*)adev;
- proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
+ int ret;
+ struct listnode *node_d;
+ struct usb_device_config *dev_info;
/* get capabilities */
- pthread_mutex_lock(&usbmod->usb_playback_lock);
- ret = usb_get_capability((char *)"Playback:",
- &usbmod->channels_playback, &usbmod->sample_rate_playback);
- if (ret) {
- ALOGE("%s: could not get playback capabilities from usb device",
+ if ((ret = usb_get_capability(USB_PLAYBACK, usb_card_info, card))) {
+ ALOGE("%s: could not get Playback capabilities from usb device",
__func__);
- pthread_mutex_unlock(&usbmod->usb_playback_lock);
- return -EINVAL;
+ goto exit;
}
- /* update config for usb
- 1 pcm frame(sample)= 4 bytes since two channels*/
- pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
- pcm_config_usbmod.channels = usbmod->channels_playback;
- pcm_config_usbmod.rate = usbmod->sample_rate_playback;
- ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
- pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
- pcm_config_usbmod.rate);
-
- usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
- usbmod->usb_device_id, PCM_OUT |
- PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
-
- if ((usbmod->usb_pcm_playback_handle \
- && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
- || (!usbmod->is_playback_running)) {
- ALOGE("%s: failed: %s", __func__,
- pcm_get_error(usbmod->usb_pcm_playback_handle));
- pcm_close(usbmod->usb_pcm_playback_handle);
- usbmod->usb_pcm_playback_handle = NULL;
- pthread_mutex_unlock(&usbmod->usb_playback_lock);
- return -ENOMEM;
- }
- ALOGD("%s: USB configured for playback", __func__);
-
- /* update config for proxy*/
- pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
- pcm_config_usbmod.rate = usbmod->sample_rate_playback;
- pcm_config_usbmod.channels = usbmod->channels_playback;
- pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
- usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
- ALOGD("%s: proxy device %u:period %u:channels %u:sample", __func__,
- pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
- pcm_config_usbmod.rate);
-
- while(proxy_open_retry_count){
- usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
- usbmod->proxy_device_id, PCM_IN |
- PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
- if(usbmod->proxy_pcm_playback_handle
- && !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
- pcm_close(usbmod->proxy_pcm_playback_handle);
- proxy_open_retry_count--;
- usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
- ALOGE("%s: pcm_open for proxy failed retrying = %d",
- __func__, proxy_open_retry_count);
- }
- else{
- break;
- }
- }
-
- if ((usbmod->proxy_pcm_playback_handle
- && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
- || (!usbmod->is_playback_running)) {
- ALOGE("%s: failed: %s", __func__,
- pcm_get_error(usbmod->proxy_pcm_playback_handle));
- pcm_close(usbmod->proxy_pcm_playback_handle);
- usbmod->proxy_pcm_playback_handle = NULL;
- pthread_mutex_unlock(&usbmod->usb_playback_lock);
- return -ENOMEM;
- }
- ALOGD("%s: PROXY configured for playback", __func__);
- pthread_mutex_unlock(&usbmod->usb_playback_lock);
-
- ALOGD("Init USB volume");
- initPlaybackVolume();
- /* main loop to read from proxy and write to usb */
- while (usbmod->is_playback_running) {
- /* read data from proxy */
- ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
- (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
- /* Write to usb */
- ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
- (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
- if(!usbmod->is_playback_running)
+ /* Currently only use the first profile using to configure channel for simplification */
+ list_for_each(node_d, &usb_card_info->usb_device_conf_list) {
+ dev_info = node_to_item(node_d, struct usb_device_config, list);
+ if (dev_info != NULL) {
+ usb_set_channel_mixer_ctl(dev_info->channels, "USB_AUDIO_RX Channels");
break;
-
- memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
- } /* main loop end */
-
- ALOGD("%s: exiting USB playback thread",__func__);
- return 0;
-}
-
-static void* usb_playback_launcher(void *adev)
-{
- int32_t ret;
-
- usbmod->is_playback_running = true;
- ret = usb_playback_entry(adev);
-
- if (ret) {
- ALOGE("%s: failed with err:%d", __func__, ret);
- usbmod->is_playback_running = false;
+ }
}
- return NULL;
+ usb_set_dev_id_mixer_ctl(USB_PLAYBACK, card, "USB_AUDIO_RX dev_token");
+
+exit:
+
+ return ret;
}
-static int32_t usb_record_entry(void *adev)
+static int usb_get_device_cap_config(struct usb_card_config *usb_card_info,
+ int card)
{
- unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
- int32_t ret, bytes, proxy_open_retry_count;
- ALOGD("%s: entry", __func__);
-
- /* update audio device pointer */
- usbmod->adev = (struct audio_device*)adev;
- proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;
+ int ret;
+ struct listnode *node_d;
+ struct usb_device_config *dev_info;
/* get capabilities */
- pthread_mutex_lock(&usbmod->usb_record_lock);
- ret = usb_get_capability((char *)"Capture:",
- &usbmod->channels_record, &usbmod->sample_rate_record);
- if (ret) {
- ALOGE("%s: could not get capture capabilities from usb device",
+ if ((ret = usb_get_capability(USB_CAPTURE, usb_card_info, card))) {
+ ALOGE("%s: could not get Playback capabilities from usb device",
__func__);
- pthread_mutex_unlock(&usbmod->usb_record_lock);
- return -EINVAL;
+ goto exit;
}
- /* update config for usb
- 1 pcm frame(sample)= 4 bytes since two channels*/
- pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
- pcm_config_usbmod.channels = usbmod->channels_record;
- pcm_config_usbmod.rate = usbmod->sample_rate_record;
- ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
- pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
- pcm_config_usbmod.rate);
-
- usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
- usbmod->usb_device_id, PCM_IN |
- PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);
-
- if ((usbmod->usb_pcm_record_handle \
- && !pcm_is_ready(usbmod->usb_pcm_record_handle))
- || (!usbmod->is_record_running)) {
- ALOGE("%s: failed: %s", __func__,
- pcm_get_error(usbmod->usb_pcm_record_handle));
- pcm_close(usbmod->usb_pcm_record_handle);
- usbmod->usb_pcm_record_handle = NULL;
- pthread_mutex_unlock(&usbmod->usb_record_lock);
- return -ENOMEM;
- }
- ALOGD("%s: USB configured for capture", __func__);
-
- /* update config for proxy*/
- pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
- pcm_config_usbmod.rate = usbmod->sample_rate_record;
- pcm_config_usbmod.channels = usbmod->channels_record;
- pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
- usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
- ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
- pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
- pcm_config_usbmod.rate);
-
- while(proxy_open_retry_count){
- usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
- usbmod->proxy_device_id, PCM_OUT |
- PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
- if(usbmod->proxy_pcm_record_handle
- && !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
- pcm_close(usbmod->proxy_pcm_record_handle);
- proxy_open_retry_count--;
- usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
- ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
- __func__, proxy_open_retry_count);
- }
- else{
- break;
- }
- }
- if ((usbmod->proxy_pcm_record_handle
- && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
- || (!usbmod->is_record_running)) {
- ALOGE("%s: failed: %s", __func__,
- pcm_get_error(usbmod->proxy_pcm_record_handle));
- pcm_close(usbmod->proxy_pcm_record_handle);
- usbmod->proxy_pcm_record_handle = NULL;
- pthread_mutex_unlock(&usbmod->usb_record_lock);
- return -ENOMEM;
- }
- ALOGD("%s: PROXY configured for capture", __func__);
- pthread_mutex_unlock(&usbmod->usb_record_lock);
-
- /* main loop to read from usb and write to proxy */
- while (usbmod->is_record_running) {
- /* read data from usb */
- ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
- (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
- /* Write to proxy */
- ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
- (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
- if(!usbmod->is_record_running)
+ /* Currently only use the first profile using to configure channel for simplification */
+ list_for_each(node_d, &usb_card_info->usb_device_conf_list) {
+ dev_info = node_to_item(node_d, struct usb_device_config, list);
+ if (dev_info != NULL) {
+ usb_set_channel_mixer_ctl(dev_info->channels, "USB_AUDIO_TX Channels");
break;
+ }
+ }
+ usb_set_dev_id_mixer_ctl(USB_CAPTURE, card, "USB_AUDIO_TX dev_token");
- memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
- } /* main loop end */
-
- ALOGD("%s: exiting USB capture thread",__func__);
- return 0;
+exit:
+ return ret;
}
-static void* usb_capture_launcher(void *adev)
+static void usb_get_sidetone_mixer(struct usb_card_config *usb_card_info)
{
- int32_t ret;
+ struct mixer_ctl *ctl;
+ unsigned int index;
- usbmod->is_record_running = true;
- ret = usb_record_entry(adev);
+ for (index = 0; index < USB_SIDETONE_MAX_INDEX; index++)
+ usb_card_info->usb_sidetone_index[index] = -1;
- if (ret) {
- ALOGE("%s: failed with err:%d", __func__, ret);
- usbmod->is_record_running = false;
+ usb_card_info->usb_snd_mixer = mixer_open(usb_card_info->usb_card);
+ for (index = 0;
+ index < sizeof(usb_sidetone_enable_str)/sizeof(usb_sidetone_enable_str[0]);
+ index++) {
+ ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
+ usb_sidetone_enable_str[index]);
+ if (ctl) {
+ usb_card_info->usb_sidetone_index[USB_SIDETONE_ENABLE_INDEX] = index;
+ /* Disable device sidetone by default */
+ mixer_ctl_set_value(ctl, 0, false);
+ break;
+ }
}
- return NULL;
+ for (index = 0;
+ index < sizeof(usb_sidetone_volume_str)/sizeof(usb_sidetone_volume_str[0]);
+ index++) {
+ ctl = mixer_get_ctl_by_name(usb_card_info->usb_snd_mixer,
+ usb_sidetone_volume_str[index]);
+ if (ctl) {
+ usb_card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX] = index;
+ usb_card_info->usb_sidetone_vol_min = mixer_ctl_get_range_min(ctl);
+ usb_card_info->usb_sidetone_vol_max = mixer_ctl_get_range_max(ctl);
+ break;
+ }
+ }
+
+ if ((usb_card_info->usb_snd_mixer != NULL) && (usb_audio_debug_enable))
+ usb_soundcard_list_controls(usb_card_info->usb_snd_mixer);
+
+ return;
+}
+
+static bool usb_valid_device(int device)
+{
+ bool is_usb_device = false;
+ if ((device & AUDIO_DEVICE_OUT_USB_DEVICE) ||
+ (device & AUDIO_DEVICE_IN_USB_DEVICE))
+ is_usb_device = true;
+ return is_usb_device;
+}
+
+static void usb_print_active_device(void){
+ struct listnode *node_i, *node_j;
+ struct usb_device_config *dev_info;
+ struct usb_card_config *card_info;
+ unsigned int i;
+
+ ALOGI("%s", __func__);
+ list_for_each(node_i, &usbmod->usb_card_conf_list) {
+ card_info = node_to_item(node_i, struct usb_card_config, list);
+ ALOGI("%s: card_dev_type (0x%x), card_no(%d)",
+ __func__, card_info->usb_device_type, card_info->usb_card);
+ list_for_each(node_j, &card_info->usb_device_conf_list) {
+ dev_info = node_to_item(node_j, struct usb_device_config, list);
+ ALOGI("%s: bit-width(%d) channel(%d)",
+ __func__, dev_info->bit_width, dev_info->channels);
+ for (i = 0; i < dev_info->rate_size; i++)
+ ALOGI("%s: rate %d", __func__, dev_info->rates[i]);
+ }
+ }
+}
+
+static bool usb_get_best_match_for_bit_width(
+ struct listnode *dev_list,
+ unsigned int stream_bit_width,
+ unsigned int *bit_width)
+{
+ struct listnode *node_i;
+ struct usb_device_config *dev_info;
+ unsigned int candidate = 0;
+
+ list_for_each(node_i, dev_list) {
+ dev_info = node_to_item(node_i, struct usb_device_config, list);
+ ALOGI_IF(usb_audio_debug_enable,
+ "%s: USB bw(%d), stream bw(%d), candidate(%d)",
+ __func__, dev_info->bit_width,
+ stream_bit_width, candidate);
+ if (dev_info->bit_width == stream_bit_width) {
+ *bit_width = dev_info->bit_width;
+ ALOGV("%s: Found match bit-width (%d)",
+ __func__, dev_info->bit_width);
+ goto exit;
+ } else if (candidate == 0) {
+ candidate = dev_info->bit_width;
+ }
+ /*
+ * If stream bit is 24, USB supports both 16 bit and 32 bit, then
+ * higher bit width 32 is picked up instead of 16-bit
+ */
+ else if (ABS_SUB(stream_bit_width, dev_info->bit_width) <
+ ABS_SUB(stream_bit_width, candidate)) {
+ candidate = dev_info->bit_width;
+ }
+ else if ((ABS_SUB(stream_bit_width, dev_info->bit_width) ==
+ ABS_SUB(stream_bit_width, candidate)) &&
+ (dev_info->bit_width > candidate)) {
+ candidate = dev_info->bit_width;
+ }
+ }
+ ALOGV("%s: No match found, use the best candidate bw(%d)",
+ __func__, candidate);
+ *bit_width = candidate;
+exit:
+ return true;
+}
+
+static bool usb_get_best_match_for_channels(
+ struct listnode *dev_list,
+ unsigned int bit_width,
+ unsigned int stream_ch,
+ unsigned int *ch)
+{
+ struct listnode *node_i;
+ struct usb_device_config *dev_info;
+ unsigned int candidate = 0;
+
+ list_for_each(node_i, dev_list) {
+ dev_info = node_to_item(node_i, struct usb_device_config, list);
+ ALOGI_IF(usb_audio_debug_enable,
+ "%s: USB ch(%d)bw(%d), stream ch(%d)bw(%d), candidate(%d)",
+ __func__, dev_info->channels, dev_info->bit_width,
+ stream_ch, bit_width, candidate);
+ if (dev_info->bit_width != bit_width)
+ continue;
+ if (dev_info->channels== stream_ch) {
+ *ch = dev_info->channels;
+ ALOGV("%s: Found match channels (%d)",
+ __func__, dev_info->channels);
+ goto exit;
+ } else if (candidate == 0)
+ candidate = dev_info->channels;
+ /*
+ * If stream channel is 4, USB supports both 3 and 5, then
+ * higher channel 5 is picked up instead of 3
+ */
+ else if (ABS_SUB(stream_ch, dev_info->channels) <
+ ABS_SUB(stream_ch, candidate)) {
+ candidate = dev_info->channels;
+ } else if ((ABS_SUB(stream_ch, dev_info->channels) ==
+ ABS_SUB(stream_ch, candidate)) &&
+ (dev_info->channels > candidate)) {
+ candidate = dev_info->channels;
+ }
+ }
+ ALOGV("%s: No match found, use the best candidate ch(%d)",
+ __func__, candidate);
+ *ch = candidate;
+exit:
+ return true;
+
+}
+
+static bool usb_sample_rate_multiple(
+ unsigned int stream_sample_rate,
+ unsigned int base)
+{
+ return (((stream_sample_rate / base) * base) == stream_sample_rate);
+}
+
+static bool usb_find_sample_rate_candidate(unsigned int base,
+ unsigned stream_rate,
+ unsigned int usb_rate,
+ unsigned int cur_candidate,
+ unsigned int *update_candidate)
+{
+ /* For sample rate, we should consider fracational sample rate as high priority.
+ * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
+ * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
+ */
+ if (!usb_sample_rate_multiple(cur_candidate, base) &&
+ usb_sample_rate_multiple(usb_rate, base)) {
+ *update_candidate = usb_rate;
+ } else if (usb_sample_rate_multiple(cur_candidate, base) &&
+ usb_sample_rate_multiple(usb_rate, base)) {
+ if (ABS_SUB(stream_rate, usb_rate) <
+ ABS_SUB(stream_rate, cur_candidate)) {
+ *update_candidate = usb_rate;
+ } else if ((ABS_SUB(stream_rate, usb_rate) ==
+ ABS_SUB(stream_rate, cur_candidate)) &&
+ (usb_rate > cur_candidate)) {
+ *update_candidate = usb_rate;
+ }
+ } else if (!usb_sample_rate_multiple(cur_candidate, base) &&
+ !usb_sample_rate_multiple(usb_rate, base)) {
+ if (ABS_SUB(stream_rate, usb_rate) <
+ ABS_SUB(stream_rate, cur_candidate)) {
+ *update_candidate = usb_rate;
+ } else if ((ABS_SUB(stream_rate, usb_rate) ==
+ ABS_SUB(stream_rate, cur_candidate)) &&
+ (usb_rate > cur_candidate)) {
+ *update_candidate = usb_rate;
+ }
+ }
+ return true;
+}
+
+static bool usb_get_best_match_for_sample_rate(
+ struct listnode *dev_list,
+ unsigned int bit_width,
+ unsigned int ch,
+ unsigned int stream_sample_rate,
+ unsigned int *sr)
+{
+ struct listnode *node_i;
+ struct usb_device_config *dev_info;
+ unsigned int candidate = 48000;
+ unsigned int base = SAMPLE_RATE_8000;
+ bool multiple_8k = usb_sample_rate_multiple(stream_sample_rate, base);
+ unsigned int i;
+
+ ALOGV("%s: stm ch(%d)bw(%d)sr(%d), stream sample multiple of 8kHz(%d)",
+ __func__, ch, bit_width, stream_sample_rate, multiple_8k);
+
+ list_for_each(node_i, dev_list) {
+ dev_info = node_to_item(node_i, struct usb_device_config, list);
+ ALOGI_IF(usb_audio_debug_enable,
+ "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
+ __func__, dev_info->channels, dev_info->bit_width,
+ ch, bit_width, stream_sample_rate, candidate);
+ if ((dev_info->bit_width != bit_width) && dev_info->channels != ch)
+ continue;
+
+ candidate = 0;
+ for (i = 0; i < dev_info->rate_size; i++) {
+ ALOGI_IF(usb_audio_debug_enable,
+ "%s: USB ch(%d)bw(%d)sr(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)",
+ __func__, dev_info->channels,
+ dev_info->bit_width, dev_info->rates[i],
+ ch, bit_width, stream_sample_rate, candidate);
+ if (stream_sample_rate == dev_info->rates[i]) {
+ *sr = dev_info->rates[i];
+ ALOGV("%s: Found match sample rate (%d)",
+ __func__, dev_info->rates[i]);
+ goto exit;
+ } else if (candidate == 0) {
+ candidate = dev_info->rates[i];
+ /*
+ * For sample rate, we should consider fracational sample rate as high priority.
+ * For example, if the stream is 88.2kHz and USB device support both 44.1kH and
+ * 48kHz sample rate, we should pick 44.1kHz instead of 48kHz
+ */
+ } else if (multiple_8k) {
+ usb_find_sample_rate_candidate(SAMPLE_RATE_8000,
+ stream_sample_rate,
+ dev_info->rates[i],
+ candidate,
+ &candidate);
+ } else {
+ usb_find_sample_rate_candidate(SAMPLE_RATE_11025,
+ stream_sample_rate,
+ dev_info->rates[i],
+ candidate,
+ &candidate);
+ }
+ }
+ }
+ ALOGV("%s: No match found, use the best candidate sr(%d)",
+ __func__, candidate);
+ *sr = candidate;
+exit:
+ return true;
+}
+
+static bool usb_audio_backend_apply_policy(struct listnode *dev_list,
+ unsigned int *bit_width,
+ unsigned int *sample_rate,
+ unsigned int ch)
+{
+ unsigned int channel;
+ bool is_usb_supported = true;
+
+ ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) channels (%d)",
+ __func__, *bit_width, *sample_rate, ch);
+ if (list_empty(dev_list)) {
+ *sample_rate = 48000;
+ *bit_width = 16;
+ channel = 2;
+ ALOGI("%s: list is empty,fall back to default setting", __func__);
+ goto exit;
+ }
+ usb_get_best_match_for_bit_width(dev_list, *bit_width, bit_width);
+ usb_get_best_match_for_channels(dev_list,
+ *bit_width,
+ ch,
+ &channel);
+ usb_get_best_match_for_sample_rate(dev_list,
+ *bit_width,
+ channel,
+ *sample_rate,
+ sample_rate);
+exit:
+ ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)",
+ __func__, *bit_width, *sample_rate, channel);
+ usb_set_channel_mixer_ctl(channel, "USB_AUDIO_RX Channels");
+ return is_usb_supported;
+}
+
+static int usb_get_sidetone_gain(struct usb_card_config *card_info)
+{
+ int gain = card_info->usb_sidetone_vol_min + usbmod->sidetone_gain;
+ if (gain > card_info->usb_sidetone_vol_max)
+ gain = card_info->usb_sidetone_vol_max;
+ return gain;
+}
+
+void audio_extn_usb_set_sidetone_gain(struct str_parms *parms,
+ char *value, int len)
+{
+ int err;
+
+ err = str_parms_get_str(parms, USB_SIDETONE_GAIN_STR,
+ value, len);
+ if (err >= 0) {
+ usb_sidetone_gain = pow(10.0, (float)(atoi(value))/10.0);
+ ALOGV("%s: sidetone gain(%s) decimal %d",
+ __func__, value, usb_sidetone_gain);
+ str_parms_del(parms, USB_SIDETONE_GAIN_STR);
+ }
+ return;
+}
+
+int audio_extn_usb_enable_sidetone(int device, bool enable)
+{
+ int ret = -ENODEV;
+ struct listnode *node_i;
+ struct usb_card_config *card_info;
+ int i;
+ ALOGV("%s: card_dev_type (0x%x), sidetone enable(%d)",
+ __func__, device, enable);
+
+ list_for_each(node_i, &usbmod->usb_card_conf_list) {
+ 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 ((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,
+ usb_sidetone_enable_str[i]);
+ if (ctl)
+ mixer_ctl_set_value(ctl, 0, enable);
+ else
+ break;
+
+ if ((i = card_info->usb_sidetone_index[USB_SIDETONE_VOLUME_INDEX]) != -1) {
+ ctl = mixer_get_ctl_by_name(
+ card_info->usb_snd_mixer,
+ usb_sidetone_volume_str[i]);
+ if (ctl == NULL)
+ ALOGV("%s: sidetone gain mixer command is not found",
+ __func__);
+ else if (enable)
+ mixer_ctl_set_value(ctl, 0,
+ usb_get_sidetone_gain(card_info));
+ }
+ ret = 0;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+bool audio_extn_usb_is_config_supported(unsigned int *bit_width,
+ unsigned int *sample_rate,
+ unsigned int ch)
+{
+ struct listnode *node_i;
+ struct usb_card_config *card_info;
+ bool is_usb_supported = false;
+
+ ALOGV("%s: from stream: bit-width(%d) sample_rate(%d) ch(%d)",
+ __func__, *bit_width, *sample_rate, ch);
+ list_for_each(node_i, &usbmod->usb_card_conf_list) {
+ card_info = node_to_item(node_i, struct usb_card_config, list);
+ ALOGI_IF(usb_audio_debug_enable,
+ "%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 (card_info->usb_device_type == AUDIO_DEVICE_OUT_USB_DEVICE) {
+ is_usb_supported = usb_audio_backend_apply_policy(
+ &card_info->usb_device_conf_list,
+ bit_width,
+ sample_rate,
+ ch);
+ break;
+ }
+ }
+ ALOGV("%s: updated: bit-width(%d) sample_rate(%d)",
+ __func__, *bit_width, *sample_rate);
+
+ return is_usb_supported;
+}
+
+void audio_extn_usb_add_device(audio_devices_t device, int card)
+{
+ struct usb_card_config *usb_card_info;
+ char check_debug_enable[PROPERTY_VALUE_MAX];
+
+ property_get("audio.usb.enable.debug", check_debug_enable, NULL);
+ if (atoi(check_debug_enable)) {
+ usb_audio_debug_enable = true;
+ }
+
+ ALOGI_IF(usb_audio_debug_enable,
+ "%s: parameters device(0x%x), card(%d)",
+ __func__, device, card);
+ if (usbmod == NULL) {
+ ALOGE("%s: USB device object is NULL", __func__);
+ goto exit;
+ }
+
+ if (!(usb_valid_device(device)) || (card < 0)) {
+ ALOGE("%s:device(0x%x), card(%d)",
+ __func__, device, card);
+ goto exit;
+ }
+
+ usb_card_info = calloc(1, sizeof(struct usb_card_config));
+ if (usb_card_info == NULL) {
+ ALOGE("%s: error unable to allocate memory",
+ __func__);
+ goto exit;
+ }
+ list_init(&usb_card_info->usb_device_conf_list);
+ if (device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ if (!usb_get_device_pb_config(usb_card_info, card)){
+ usb_card_info->usb_card = card;
+ usb_card_info->usb_device_type = AUDIO_DEVICE_OUT_USB_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) {
+ if (!usb_get_device_cap_config(usb_card_info, card)) {
+ usb_card_info->usb_card = card;
+ usb_card_info->usb_device_type = AUDIO_DEVICE_IN_USB_DEVICE;
+ list_add_tail(&usbmod->usb_card_conf_list, &usb_card_info->list);
+ goto exit;
+ }
+ }
+ /* free memory in error case */
+ if (usb_card_info != NULL)
+ free(usb_card_info);
+exit:
+ if (usb_audio_debug_enable)
+ usb_print_active_device();
+ return;
+}
+
+void audio_extn_usb_remove_device(audio_devices_t device, int card)
+{
+ struct listnode *node_i, *temp_i;
+ struct listnode *node_j, *temp_j;
+ struct usb_device_config *dev_info;
+ struct usb_card_config *card_info;
+ unsigned int i;
+
+ ALOGV("%s: device(0x%x), card(%d)",
+ __func__, device, card);
+
+ if (usbmod == NULL) {
+ ALOGE("%s: USB device object is NULL", __func__);
+ goto exit;
+ }
+
+ if (!(usb_valid_device(device)) || (card < 0)) {
+ ALOGE("%s: Invalid parameters device(0x%x), card(%d)",
+ __func__, device, card);
+ goto exit;
+ }
+ list_for_each_safe(node_i, temp_i, &usbmod->usb_card_conf_list) {
+ 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 ((device == card_info->usb_device_type) && (card == card_info->usb_card)){
+ list_for_each_safe(node_j, temp_j, &card_info->usb_device_conf_list) {
+ dev_info = node_to_item(node_j, struct usb_device_config, list);
+ ALOGV("%s: bit-width(%d) channel(%d)",
+ __func__, dev_info->bit_width, dev_info->channels);
+ for (i = 0; i < dev_info->rate_size; i++)
+ ALOGV("%s: rate %d", __func__, dev_info->rates[i]);
+
+ list_remove(node_j);
+ free(node_to_item(node_j, struct usb_device_config, list));
+ }
+ list_remove(node_i);
+ free(node_to_item(node_i, struct usb_card_config, list));
+ }
+ }
+exit:
+ if (usb_audio_debug_enable)
+ usb_print_active_device();
+
+ return;
}
void audio_extn_usb_init(void *adev)
{
- pthread_once(&alloc_usbmod_once_ctl, usb_alloc);
-
- usbmod->is_playback_running = false;
- usbmod->is_record_running = false;
-
- usbmod->usb_pcm_playback_handle = NULL;
- usbmod->proxy_pcm_playback_handle = NULL;
-
- usbmod->usb_pcm_record_handle = NULL;
- usbmod->proxy_pcm_record_handle = NULL;
-
- usbmod->usb_card = 1;
- usbmod->usb_device_id = 0;
- usbmod->proxy_card = 0;
- usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
+ if (usbmod == NULL) {
+ usbmod = calloc(1, sizeof(struct usb_module));
+ if (usbmod == NULL) {
+ ALOGE("%s: error unable to allocate memory", __func__);
+ goto exit;
+ }
+ }
+ list_init(&usbmod->usb_card_conf_list);
usbmod->adev = (struct audio_device*)adev;
-
- pthread_mutex_init(&usbmod->usb_playback_lock,
- (const pthread_mutexattr_t *) NULL);
- pthread_mutex_init(&usbmod->usb_record_lock,
- (const pthread_mutexattr_t *) NULL);
+ usbmod->sidetone_gain = usb_sidetone_gain;
+exit:
+ return;
}
-void audio_extn_usb_deinit()
+void audio_extn_usb_deinit(void)
{
if (NULL != usbmod){
free(usbmod);
usbmod = NULL;
}
}
-
-void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
-{
- /* Proxy port and USB headset are related to two different sound cards */
- if (sndcard_idx == usbmod->usb_card) {
- usbmod->usb_card = usbmod->proxy_card;
- }
-
- usbmod->proxy_card = sndcard_idx;
-}
-
-void audio_extn_usb_start_playback(void *adev)
-{
- int32_t ret;
-
- if (NULL == usbmod){
- ALOGE("%s: USB device object is NULL", __func__);
- return;
- }
-
- if (usbmod->is_playback_running){
- ALOGE("%s: USB playback thread already running", __func__);
- return;
- }
-
- ALOGD("%s: creating USB playback thread", __func__);
- ret = pthread_create(&usbmod->usb_playback_thr, NULL,
- usb_playback_launcher, (void*)adev);
- if (ret)
- ALOGE("%s: failed to create USB playback thread with err:%d",
- __func__, ret);
-}
-
-void audio_extn_usb_stop_playback()
-{
- int32_t ret;
- ALOGD("%s: entry", __func__);
-
- usbmod->is_playback_running = false;
- if (NULL != usbmod->proxy_pcm_playback_handle)
- pcm_stop(usbmod->proxy_pcm_playback_handle);
-
- if (NULL != usbmod->usb_pcm_playback_handle)
- pcm_stop(usbmod->usb_pcm_playback_handle);
-
- if(usbmod->usb_playback_thr) {
- ret = pthread_join(usbmod->usb_playback_thr,NULL);
- ALOGE("%s: return for pthread_join = %d", __func__, ret);
- usbmod->usb_playback_thr = (pthread_t)NULL;
- }
-
- pthread_mutex_lock(&usbmod->usb_playback_lock);
- if (NULL != usbmod->usb_pcm_playback_handle){
- pcm_close(usbmod->usb_pcm_playback_handle);
- usbmod->usb_pcm_playback_handle = NULL;
- }
-
- if (NULL != usbmod->proxy_pcm_playback_handle){
- pcm_close(usbmod->proxy_pcm_playback_handle);
- usbmod->proxy_pcm_playback_handle = NULL;
- }
- pthread_mutex_unlock(&usbmod->usb_playback_lock);
-
- ALOGD("%s: exiting",__func__);
-}
-
-void audio_extn_usb_start_capture(void *adev)
-{
- int32_t ret;
-
- if (NULL == usbmod){
- ALOGE("%s: USB device object is NULL", __func__);
- return;
- }
-
- if (usbmod->is_record_running){
- ALOGE("%s: USB capture thread already running", __func__);
- return;
- }
-
- ALOGD("%s: creating USB capture thread", __func__);
- ret = pthread_create(&usbmod->usb_record_thr, NULL,
- usb_capture_launcher, (void*)adev);
- if (ret)
- ALOGE("%s: failed to create USB capture thread with err:%d",
- __func__, ret);
-}
-
-void audio_extn_usb_stop_capture()
-{
- int32_t ret;
- ALOGD("%s: entry", __func__);
-
- usbmod->is_record_running = false;
- if (NULL != usbmod->proxy_pcm_record_handle)
- pcm_stop(usbmod->proxy_pcm_record_handle);
-
- if (NULL != usbmod->usb_pcm_record_handle)
- pcm_stop(usbmod->usb_pcm_record_handle);
-
- if(usbmod->usb_record_thr) {
- ret = pthread_join(usbmod->usb_record_thr,NULL);
- ALOGE("%s: return for pthread_join = %d", __func__, ret);
- usbmod->usb_record_thr = (pthread_t)NULL;
- }
-
- pthread_mutex_lock(&usbmod->usb_record_lock);
- if (NULL != usbmod->usb_pcm_record_handle){
- pcm_close(usbmod->usb_pcm_record_handle);
- usbmod->usb_pcm_record_handle = NULL;
- }
-
- if (NULL != usbmod->proxy_pcm_record_handle){
- pcm_close(usbmod->proxy_pcm_record_handle);
- usbmod->proxy_pcm_record_handle = NULL;
- }
- pthread_mutex_unlock(&usbmod->usb_record_lock);
-
- ALOGD("%s: exiting",__func__);
-}
-
-bool audio_extn_usb_is_proxy_inuse()
-{
- if( usbmod->is_record_running || usbmod->is_playback_running)
- return true;
- else
- return false;
-}
#endif /*USB_HEADSET_ENABLED end*/
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index cd9ead7..cb646cf 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -107,8 +107,10 @@
STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
STRING_TO_ENUM(AUDIO_FORMAT_AC3),
STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
-#ifdef AUDIO_EXTN_FORMATS_ENABLED
STRING_TO_ENUM(AUDIO_FORMAT_DTS),
+ STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
+#ifdef AUDIO_EXTN_FORMATS_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
STRING_TO_ENUM(AUDIO_FORMAT_WMA),
STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
@@ -639,20 +641,6 @@
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
}
- app_type_cfg[len++] = usecase->stream.out->app_type_cfg.app_type;
- app_type_cfg[len++] = acdb_dev_id;
- if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
- (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC)) &&
- (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH))
- app_type_cfg[len++] = sample_rate * 4;
- else
- app_type_cfg[len++] = sample_rate;
-
- ALOGI("%s:%d PLAYBACK app_type %d, acdb_dev_id %d, sample_rate %d",
- __func__, __LINE__,
- platform_get_default_app_type(adev->platform),
- acdb_dev_id, sample_rate);
-
if ((24 == usecase->stream.out->bit_width) &&
(usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
@@ -667,7 +655,7 @@
app_type_cfg[len++] = acdb_dev_id;
if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
(usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
- && audio_extn_dolby_is_passthrough_stream(usecase->stream.out)) {
+ && audio_extn_passthru_is_passthrough_stream(usecase->stream.out)) {
app_type_cfg[len++] = sample_rate * 4;
} else {
app_type_cfg[len++] = sample_rate;
@@ -1009,7 +997,7 @@
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)){
+ audio_extn_passthru_is_passthrough_stream(out)){
get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
} else
#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index aabb656..d6e81b2 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -338,6 +338,10 @@
format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
format == AUDIO_FORMAT_PCM_8_24_BIT ||
format == AUDIO_FORMAT_PCM_16_BIT ||
+ format == AUDIO_FORMAT_AC3 ||
+ format == AUDIO_FORMAT_E_AC3 ||
+ format == AUDIO_FORMAT_DTS ||
+ format == AUDIO_FORMAT_DTS_HD ||
format == AUDIO_FORMAT_FLAC ||
format == AUDIO_FORMAT_ALAC ||
format == AUDIO_FORMAT_APE ||
@@ -384,6 +388,17 @@
case AUDIO_FORMAT_WMA_PRO:
id = SND_AUDIOCODEC_WMA_PRO;
break;
+ case AUDIO_FORMAT_AC3:
+ id = SND_AUDIOCODEC_AC3;
+ break;
+ case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_E_AC3_JOC:
+ id = SND_AUDIOCODEC_EAC3;
+ break;
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_HD:
+ id = SND_AUDIOCODEC_DTS;
+ break;
default:
ALOGE("%s: Unsupported audio format :%x", __func__, format);
}
@@ -537,14 +552,7 @@
if (audio_extn_spkr_prot_is_enabled())
audio_extn_spkr_prot_calib_cancel(adev);
- /* start usb playback thread */
- if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
- SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
- audio_extn_usb_start_playback(adev);
- /* start usb capture thread */
- if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
- audio_extn_usb_start_capture(adev);
if (platform_can_enable_spkr_prot_on_device(snd_device) &&
audio_extn_spkr_prot_is_enabled()) {
@@ -553,7 +561,7 @@
return -EINVAL;
}
audio_extn_dev_arbi_acquire(snd_device);
- if (audio_extn_spkr_prot_start_processing(snd_device)) {
+ if (audio_extn_spkr_prot_start_processing(snd_device)) {
ALOGE("%s: spkr_start_processing failed", __func__);
audio_extn_dev_arbi_release(snd_device);
return -EINVAL;
@@ -621,15 +629,6 @@
if (adev->snd_dev_ref_cnt[snd_device] == 0) {
ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
- /* exit usb play back thread */
- if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
- SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
- audio_extn_usb_stop_playback();
-
- /* exit usb capture thread */
- if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
- audio_extn_usb_stop_capture();
-
if (platform_can_enable_spkr_prot_on_device(snd_device) &&
audio_extn_spkr_prot_is_enabled()) {
audio_extn_spkr_prot_stop_processing(snd_device);
@@ -872,9 +871,6 @@
out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
- case 2:
- ALOGV("%s: HDMI supports 2 channels", __func__);
- out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
break;
default:
ALOGE("invalid/nonstandard channal count[%d]",channels);
@@ -1157,8 +1153,7 @@
/* Enable new sound devices */
if (out_snd_device != SND_DEVICE_NONE) {
- if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
- check_usecases_codec_backend(adev, usecase, out_snd_device);
+ check_usecases_codec_backend(adev, usecase, out_snd_device);
enable_snd_device(adev, out_snd_device);
}
@@ -1511,6 +1506,7 @@
if (out->compr == NULL) {
ALOGE("%s: Compress handle is NULL", __func__);
+ free(cmd);
pthread_cond_signal(&out->cond);
continue;
}
@@ -1755,8 +1751,9 @@
ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
if (is_offload_usecase(out->usecase) &&
- audio_extn_dolby_is_passthrough_stream(out)) {
+ audio_extn_passthru_is_passthrough_stream(out)) {
enable_passthru = true;
+ ALOGV("%s : enable_passthru is set to true", __func__);
}
/* Check if change in HDMI channel config is allowed */
@@ -1770,7 +1767,7 @@
if (enable_passthru) {
audio_extn_passthru_on_start(out);
- audio_extn_dolby_update_passt_stream_configuration(adev, out);
+ audio_extn_passthru_update_stream_configuration(adev, out);
}
/* For pass through case, the backend should be configured as stereo */
@@ -1805,7 +1802,7 @@
}
if (is_offload_usecase(out->usecase) &&
- !(audio_extn_dolby_is_passthrough_stream(out))) {
+ !(audio_extn_passthru_is_passthrough_stream(out))) {
if (adev->visualizer_stop_output != NULL)
adev->visualizer_stop_output(out->handle, out->pcm_device_id);
@@ -1825,21 +1822,21 @@
free(uc_info);
if (is_offload_usecase(out->usecase) &&
- (audio_extn_dolby_is_passthrough_stream(out))) {
+ (audio_extn_passthru_is_passthrough_stream(out))) {
ALOGV("Disable passthrough , reset mixer to pcm");
/* NO_PASSTHROUGH */
out->compr_config.codec->compr_passthr = 0;
- /* Must be called after removing the usecase from list */
- if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
- check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
- DEFAULT_HDMI_OUT_SAMPLE_RATE,
- DEFAULT_HDMI_OUT_FORMAT,
- false);
audio_extn_passthru_on_stop(out);
audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
}
+ /* Must be called after removing the usecase from list */
+ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
+ check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
+ DEFAULT_HDMI_OUT_SAMPLE_RATE,
+ DEFAULT_HDMI_OUT_FORMAT,
+ false);
ALOGV("%s: exit: status(%d)", __func__, ret);
return ret;
}
@@ -1980,7 +1977,7 @@
if (audio_extn_is_dolby_format(out->format))
audio_extn_dolby_send_ddp_endp_params(adev);
#endif
- if (!(audio_extn_dolby_is_passthrough_stream(out))) {
+ if (!(audio_extn_passthru_is_passthrough_stream(out))) {
if (adev->visualizer_start_output != NULL)
adev->visualizer_start_output(out->handle, out->pcm_device_id);
if (adev->offload_effects_start_output != NULL)
@@ -2264,7 +2261,7 @@
*/
if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
(val == AUDIO_DEVICE_NONE) &&
- !audio_extn_dolby_is_passthrough_stream(out) &&
+ !audio_extn_passthru_is_passthrough_stream(out) &&
(platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
val = AUDIO_DEVICE_OUT_SPEAKER;
}
@@ -2487,13 +2484,13 @@
out->muted = (left == 0.0f);
return 0;
} else if (is_offload_usecase(out->usecase)) {
- if (audio_extn_dolby_is_passthrough_stream(out)) {
+ if (audio_extn_passthru_is_passthrough_stream(out)) {
/*
* Set mute or umute on HDMI passthrough stream.
* Only take left channel into account.
* Mute is 0 and unmute 1
*/
- audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
+ audio_extn_passthru_set_volume(out, (left == 0.0f));
} else {
char mixer_ctl_name[128];
struct audio_device *adev = out->dev;
@@ -2547,6 +2544,13 @@
}
}
+ if (audio_extn_passthru_should_drop_data(out)) {
+ ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
+ usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
+ out_get_sample_rate(&out->stream.common));
+ goto exit;
+ }
+
if (out->standby) {
out->standby = false;
pthread_mutex_lock(&adev->lock);
@@ -3395,7 +3399,7 @@
}
if (!is_supported_format(config->offload_info.format) &&
- !audio_extn_is_dolby_format(config->offload_info.format)) {
+ !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
ret = -EINVAL;
goto error_open;
@@ -3449,21 +3453,19 @@
out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
- if (audio_extn_is_dolby_format(config->offload_info.format))
- out->compr_config.codec->id =
- audio_extn_dolby_get_snd_codec_id(adev, out,
- config->offload_info.format);
- else
- out->compr_config.codec->id =
- get_snd_codec_id(config->offload_info.format);
+ out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
+ if (audio_extn_is_dolby_format(config->offload_info.format)) {
+ audio_extn_dolby_send_ddp_endp_params(adev);
+ audio_extn_dolby_set_dmid(adev);
+ }
if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
out->compr_config.fragment_size =
platform_get_pcm_offload_buffer_size(&config->offload_info);
out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
- } else if (audio_extn_dolby_is_passthrough_stream(out)) {
+ } else if (audio_extn_passthru_is_passthrough_stream(out)) {
out->compr_config.fragment_size =
- audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
+ audio_extn_passthru_get_buffer_size(&config->offload_info);
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
} else {
out->compr_config.fragment_size =
@@ -3517,14 +3519,14 @@
* AV playback
* Direct PCM playback
*/
- if (audio_extn_dolby_is_passthrough_stream(out) ||
+ if (audio_extn_passthru_is_passthrough_stream(out) ||
config->offload_info.has_video ||
out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
check_and_set_gapless_mode(adev, false);
} else
check_and_set_gapless_mode(adev, true);
- if (audio_extn_dolby_is_passthrough_stream(out)) {
+ if (audio_extn_passthru_is_passthrough_stream(out)) {
out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
}
} else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
@@ -3819,7 +3821,8 @@
if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
ALOGV("cache new edid");
platform_cache_edid(adev->platform);
- } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
+ (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
/*
* Do not allow AFE proxy port usage by WFD source when USB headset is connected.
* Per AudioPolicyManager, USB device is higher priority than WFD.
@@ -3827,6 +3830,10 @@
* If WFD use case occupies AFE proxy, it may result unintended behavior while
* starting voice call on USB
*/
+ ret = str_parms_get_str(parms, "card", value, sizeof(value));
+ if (ret >= 0) {
+ audio_extn_usb_add_device(val, atoi(value));
+ }
ALOGV("detected USB connect .. disable proxy");
adev->allow_afe_proxy_usage = false;
}
@@ -3837,8 +3844,13 @@
val = atoi(value);
if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
ALOGV("invalidate cached edid");
- platform_invalidate_edid(adev->platform);
- } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ platform_invalidate_hdmi_config(adev->platform);
+ } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
+ (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
+ ret = str_parms_get_str(parms, "card", value, sizeof(value));
+ if (ret >= 0) {
+ audio_extn_usb_remove_device(val, atoi(value));
+ }
ALOGV("detected USB disconnect .. enable proxy");
adev->allow_afe_proxy_usage = true;
}
diff --git a/hal/edid.c b/hal/edid.c
index 06e1e05..8f183d0 100644
--- a/hal/edid.c
+++ b/hal/edid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2014 The Android Open Source Project
@@ -685,3 +685,44 @@
dump_edid_data(info);
return true;
}
+
+bool edid_is_supported_sr(edid_audio_info* info, int sr)
+{
+ int i = 0;
+ if (info != NULL && sr != 0) {
+ for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+ if (info->audio_blocks_array[i].sampling_freq == sr) {
+ ALOGV("%s: returns true for sample rate [%d]",
+ __func__, sr);
+ return true;
+ }
+ }
+ }
+ ALOGV("%s: returns false for sample rate [%d]",
+ __func__, sr);
+ return false;
+}
+
+bool edid_is_supported_bps(edid_audio_info* info, int bps)
+{
+ int i = 0;
+
+ if (bps == 16) {
+ //16 bit bps is always supported
+ //some oem may not update 16bit support in their edid info
+ return true;
+ }
+
+ if (info != NULL && bps != 0) {
+ for (i = 0; i < info->audio_blocks && i < MAX_EDID_BLOCKS; i++) {
+ if (info->audio_blocks_array[i].bits_per_sample == bps) {
+ ALOGV("%s: returns true for bit width [%d]",
+ __func__, bps);
+ return true;
+ }
+ }
+ }
+ ALOGV("%s: returns false for bit width [%d]",
+ __func__, bps);
+ return false;
+}
diff --git a/hal/edid.h b/hal/edid.h
index 0d7fbe6..387b17e 100644
--- a/hal/edid.h
+++ b/hal/edid.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -97,4 +97,8 @@
#else
bool edid_get_sink_caps(edid_audio_info* info, char *edid_data);
#endif
+
+bool edid_is_supported_sr(edid_audio_info* info, int sr);
+bool edid_is_supported_bps(edid_audio_info* info, int bps);
+
#endif /* EDID_H */
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index b39b668..2403c55 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -1837,8 +1837,6 @@
/* init usb */
audio_extn_usb_init(adev);
- /* update sound cards appropriately */
- audio_extn_usb_set_proxy_sound_card(adev->snd_card);
/* Read one time ssr property */
audio_extn_ssr_update_enabled();
@@ -1899,6 +1897,16 @@
strdup("MI2S_TX SampleRate");
}
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("USB_AUDIO_RX Format");
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("USB_AUDIO_RX SampleRate");
+
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("HDMI_RX Bit Format");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("HDMI_RX SampleRate");
+
ret = audio_extn_utils_get_codec_version(snd_card_name,
my_data->adev->snd_card,
my_data->codec_version);
@@ -2403,6 +2411,8 @@
port = HEADPHONE_BACKEND;
else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
port = HDMI_RX_BACKEND;
+ else if (strcmp(backend_tag_table[snd_device], "usb-headphones") == 0)
+ port = USB_AUDIO_RX_BACKEND;
}
} else {
ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
@@ -2763,6 +2773,12 @@
new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
status = true;
+ } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
+ *num_devices = 2;
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+ new_snd_devices[1] = SND_DEVICE_OUT_USB_HEADSET;
+ status = true;
}
ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
@@ -2832,6 +2848,9 @@
} else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
AUDIO_DEVICE_OUT_SPEAKER)) {
snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
+ } else if (devices == (AUDIO_DEVICE_OUT_USB_DEVICE |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
} else {
ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
goto exit;
@@ -2970,6 +2989,8 @@
ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
audio_extn_set_afe_proxy_channel_mixer(adev, 2);
snd_device = SND_DEVICE_OUT_USB_HEADSET;
+ } else if (devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ snd_device = SND_DEVICE_OUT_USB_HEADSET;
} else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
} else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
@@ -3329,6 +3350,8 @@
snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
} else if (in_device & AUDIO_DEVICE_IN_FM_TUNER) {
snd_device = SND_DEVICE_IN_CAPTURE_FM;
+ } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE ) {
+ snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
} else {
ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
ALOGW("%s: Using default handset-mic", __func__);
@@ -3364,6 +3387,8 @@
} else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
+ } else if (out_device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
} else {
ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
ALOGW("%s: Using default handset-mic", __func__);
@@ -4021,6 +4046,8 @@
mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
else
mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+ } else if (bit_width == 32) {
+ mixer_ctl_set_enum_by_string(ctl, "S24_LE");
} else {
mixer_ctl_set_enum_by_string(ctl, "S16_LE");
}
@@ -4113,6 +4140,7 @@
int backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
int na_mode = platform_get_native_support();
+ edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
backend_idx = platform_get_backend_index(snd_device);
@@ -4188,8 +4216,6 @@
}
}
-
-
/*
* hifi playback not supported on spkr devices, limit the Sample Rate
* to 48 khz.
@@ -4221,6 +4247,19 @@
sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
}
+ if (backend_idx == HDMI_RX_BACKEND) {
+ //Check EDID info for supported samplerate
+ if (!edid_is_supported_sr(edid_info,sample_rate)) {
+ //reset to current sample rate
+ sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+ }
+ //Check EDID info for supported bit widhth
+ if (!edid_is_supported_bps(edid_info,bit_width)) {
+ //reset to current sample rate
+ bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+ }
+ }
+
//check if mulitchannel clip needs to be down sampled to 48k
property_get("audio.playback.mch.downsample",value,"");
if (!strncmp("true", value, sizeof("true"))) {
@@ -4236,6 +4275,13 @@
}
}
+ if (backend_idx == USB_AUDIO_RX_BACKEND) {
+ unsigned int channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
+ audio_extn_usb_is_config_supported(&bit_width, &sample_rate, channels);
+ ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
+ __func__, bit_width, sample_rate, channels);
+ }
+
ALOGI("%s:becf: afe: Codec selected backend: %d updated bit width: %d and sample rate: %d",
__func__,
backend_idx, bit_width, sample_rate);
@@ -4945,13 +4991,17 @@
platform_get_edid_info(platform);
}
-void platform_invalidate_edid(void * platform)
+void platform_invalidate_hdmi_config(void * platform)
{
struct platform_data *my_data = (struct platform_data *)platform;
my_data->edid_valid = false;
if (my_data->edid_info) {
memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
}
+
+ //reset HDMI_RX_BACKEND to default values
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
@@ -5294,3 +5344,26 @@
return snd_device;
}
}
+
+int platform_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device,
+ bool enable,
+ char *str)
+{
+ int ret;
+ if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET) {
+ ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
+ if (ret)
+ ALOGI("%s: usb device %d does not support device sidetone\n",
+ __func__, out_snd_device);
+ } else {
+ ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
+ __func__, out_snd_device, str);
+
+ if (enable)
+ audio_route_apply_and_update_path(adev->audio_route, str);
+ else
+ audio_route_reset_and_update_path(adev->audio_route, str);
+ }
+ return 0;
+}
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index aef905d..7ff9c46 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -211,6 +211,7 @@
HEADPHONE_BACKEND,
SLIMBUS_6_RX = HEADPHONE_BACKEND,
HDMI_RX_BACKEND,
+ USB_AUDIO_RX_BACKEND,
MAX_CODEC_BACKENDS
};
#define AUDIO_PARAMETER_KEY_NATIVE_AUDIO "audio.nat.codec.enabled"
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 2c60f3b..2b6a1d7 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1165,7 +1165,7 @@
}
-void platform_invalidate_edid(void * platform __unused)
+void platform_invalidate_hdmi_config(void * platform __unused)
{
}
@@ -1234,3 +1234,26 @@
{
return true;
}
+
+int platform_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device,
+ bool enable,
+ char *str)
+{
+ int ret;
+ if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET) {
+ ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
+ if (ret)
+ ALOGI("%s: usb device %d does not support device sidetone\n",
+ __func__, out_snd_device);
+ } else {
+ ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
+ __func__, out_snd_device, str);
+
+ if (enable)
+ audio_route_apply_and_update_path(adev->audio_route, str);
+ else
+ audio_route_reset_and_update_path(adev->audio_route, str);
+ }
+ return 0;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index fe7e1c1..cd63143 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -698,6 +698,8 @@
{TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
{TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_FM)},
{TO_NAME_INDEX(USECASE_AUDIO_RECORD_FM_VIRTUAL)},
+ {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_RX)},
+ {TO_NAME_INDEX(USECASE_AUDIO_SPKR_CALIB_TX)},
};
#define NO_COLS 2
@@ -1640,6 +1642,9 @@
platform_acdb_init(my_data);
}
+ /* init keep-alive for compress passthru */
+ audio_extn_keep_alive_init(adev);
+
acdb_init_fail:
set_platform_defaults(my_data);
@@ -1673,8 +1678,6 @@
/* init usb */
audio_extn_usb_init(adev);
- /* update sound cards appropriately */
- audio_extn_usb_set_proxy_sound_card(adev->snd_card);
/* init dap hal */
audio_extn_dap_hal_init(adev->snd_card);
@@ -1735,6 +1738,15 @@
strdup("SLIM_6_RX Format");
my_data->current_backend_cfg[HEADPHONE_BACKEND].samplerate_mixer_ctl =
strdup("SLIM_6_RX SampleRate");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("HDMI_RX Bit Format");
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("HDMI_RX SampleRate");
+
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].bitwidth_mixer_ctl =
+ strdup("USB_AUDIO_RX Format");
+ my_data->current_backend_cfg[USB_AUDIO_RX_BACKEND].samplerate_mixer_ctl =
+ strdup("USB_AUDIO_RX SampleRate");
my_data->edid_info = NULL;
free(snd_card_name);
@@ -2211,6 +2223,8 @@
port = HEADPHONE_BACKEND;
else if (strcmp(backend_tag_table[snd_device], "hdmi") == 0)
port = HDMI_RX_BACKEND;
+ else if (strcmp(backend_tag_table[snd_device], "usb-headphones") == 0)
+ port = USB_AUDIO_RX_BACKEND;
}
} else {
ALOGV("%s:napb: Invalid device - %d ", __func__, snd_device);
@@ -2566,6 +2580,12 @@
new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
new_snd_devices[1] = SND_DEVICE_OUT_HDMI;
status = true;
+ } else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET &&
+ !platform_check_backends_match(SND_DEVICE_OUT_SPEAKER, SND_DEVICE_OUT_USB_HEADSET)) {
+ *num_devices = 2;
+ new_snd_devices[0] = SND_DEVICE_OUT_SPEAKER;
+ new_snd_devices[1] = SND_DEVICE_OUT_USB_HEADSET;
+ status = true;
}
ALOGD("%s: snd_device(%d) num devices(%d) new_snd_devices(%d)", __func__,
@@ -2623,6 +2643,9 @@
} else if (devices == (AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
AUDIO_DEVICE_OUT_SPEAKER)) {
snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
+ } else if (devices == (AUDIO_DEVICE_OUT_USB_DEVICE |
+ AUDIO_DEVICE_OUT_SPEAKER)) {
+ snd_device = SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET;
} else {
ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
goto exit;
@@ -2734,6 +2757,8 @@
ALOGD("%s: setting USB hadset channel capability(2) for Proxy", __func__);
audio_extn_set_afe_proxy_channel_mixer(adev, 2);
snd_device = SND_DEVICE_OUT_USB_HEADSET;
+ } else if (devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ snd_device = SND_DEVICE_OUT_USB_HEADSET;
} else if (devices & AUDIO_DEVICE_OUT_FM_TX) {
snd_device = SND_DEVICE_OUT_TRANSMISSION_FM;
} else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
@@ -3068,6 +3093,8 @@
snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
} else if (in_device & AUDIO_DEVICE_IN_FM_TUNER) {
snd_device = SND_DEVICE_IN_CAPTURE_FM;
+ } else if (in_device & AUDIO_DEVICE_IN_USB_DEVICE ) {
+ snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
} else {
ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
ALOGW("%s: Using default handset-mic", __func__);
@@ -3111,6 +3138,8 @@
} else if (out_device & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
+ } else if (out_device & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ snd_device = SND_DEVICE_IN_USB_HEADSET_MIC;
} else {
ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
ALOGW("%s: Using default handset-mic", __func__);
@@ -3545,6 +3574,7 @@
set_audiocal(platform, parms, value, len);
native_audio_set_params(platform, parms, value, len);
audio_extn_spkr_prot_set_parameters(parms, value, len);
+ audio_extn_usb_set_sidetone_gain(parms, value, len);
perf_lock_set_params(platform, parms, value, len);
done:
ALOGV("%s: exit with code(%d)", __func__, ret);
@@ -3995,6 +4025,8 @@
mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
else
mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+ } else if (bit_width == 32) {
+ mixer_ctl_set_enum_by_string(ctl, "S24_LE");
} else {
mixer_ctl_set_enum_by_string(ctl, "S16_LE");
}
@@ -4077,6 +4109,7 @@
int backend_idx = DEFAULT_CODEC_BACKEND;
struct platform_data *my_data = (struct platform_data *)adev->platform;
int na_mode = platform_get_native_support();
+ edid_audio_info *edid_info = (edid_audio_info *)my_data->edid_info;
backend_idx = platform_get_backend_index(snd_device);
@@ -4176,8 +4209,28 @@
__func__);
}
+ if (backend_idx == USB_AUDIO_RX_BACKEND) {
+ unsigned int channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
+ audio_extn_usb_is_config_supported(&bit_width, &sample_rate, channels);
+ ALOGV("%s: USB BE configured as bit_width(%d)sample_rate(%d)channels(%d)",
+ __func__, bit_width, sample_rate, channels);
+ }
+
+ if (backend_idx == HDMI_RX_BACKEND) {
+ //Check EDID info for supported samplerate
+ if (!edid_is_supported_sr(edid_info,sample_rate)) {
+ //reset to current sample rate
+ sample_rate = my_data->current_backend_cfg[backend_idx].sample_rate;
+ }
+ //Check EDID info for supported bit widhth
+ if (!edid_is_supported_bps(edid_info,bit_width)) {
+ //reset to current sample rate
+ bit_width = my_data->current_backend_cfg[backend_idx].bit_width;
+ }
+ }
ALOGI("%s:becf: afe: Codec selected backend: %d updated bit width: %d and sample rate: %d",
__func__, backend_idx , bit_width, sample_rate);
+
// Force routing if the expected bitwdith or samplerate
// is not same as current backend comfiguration
if ((bit_width != my_data->current_backend_cfg[backend_idx].bit_width) ||
@@ -4882,13 +4935,18 @@
platform_get_edid_info(platform);
}
-void platform_invalidate_edid(void * platform)
+void platform_invalidate_hdmi_config(void * platform)
{
+ //reset HDMI EDID info
struct platform_data *my_data = (struct platform_data *)platform;
my_data->edid_valid = false;
if (my_data->edid_info) {
memset(my_data->edid_info, 0, sizeof(struct edid_audio_info));
}
+
+ //reset HDMI_RX_BACKEND to default values
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_backend_cfg[HDMI_RX_BACKEND].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
int platform_set_mixer_control(struct stream_out *out, const char * mixer_ctl_name,
@@ -5132,4 +5190,25 @@
return ret;
}
+int platform_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device,
+ bool enable,
+ char *str)
+{
+ int ret;
+ if (out_snd_device == SND_DEVICE_OUT_USB_HEADSET) {
+ ret = audio_extn_usb_enable_sidetone(out_snd_device, enable);
+ if (ret)
+ ALOGI("%s: usb device %d does not support device sidetone\n",
+ __func__, out_snd_device);
+ } else {
+ ALOGV("%s: sidetone out device(%d) mixer cmd = %s\n",
+ __func__, out_snd_device, str);
+ if (enable)
+ audio_route_apply_and_update_path(adev->audio_route, str);
+ else
+ audio_route_reset_and_update_path(adev->audio_route, str);
+ }
+ return 0;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 52f0bac..eb04109 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -201,6 +201,7 @@
HEADPHONE_BACKEND,
SLIMBUS_6_RX = HEADPHONE_BACKEND,
HDMI_RX_BACKEND,
+ USB_AUDIO_RX_BACKEND,
MAX_CODEC_BACKENDS
};
diff --git a/hal/platform_api.h b/hal/platform_api.h
index cb177b6..fc1c440 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -130,7 +130,6 @@
bool platform_is_edid_supported_format(void *platform, int format);
bool platform_is_edid_supported_sample_rate(void *platform, int sample_rate);
void platform_cache_edid(void * platform);
-void platform_invalidate_edid(void * platform);
void platform_invalidate_hdmi_config(void * platform);
int platform_set_hdmi_config(void *platform, uint32_t channel_count,
uint32_t sample_rate, bool enable_passthrough);
@@ -148,4 +147,8 @@
snd_device_t *new_snd_devices);
bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_device2);
+int platform_set_sidetone(struct audio_device *adev,
+ snd_device_t out_snd_device,
+ bool enable,
+ char * str);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/voice.c b/hal/voice.c
index 5fef205..f86483e 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -72,6 +72,9 @@
is_sidetone_dev = true;
strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH);
break;
+ case SND_DEVICE_OUT_USB_HEADSET:
+ is_sidetone_dev = true;
+ break;
default:
is_sidetone_dev = false;
break;
@@ -84,28 +87,11 @@
snd_device_t out_snd_device, bool enable)
{
char mixer_path[MIXER_PATH_MAX_LENGTH];
- bool is_sidetone_dev;
-
ALOGD("%s: %s, out_snd_device: %d\n",
__func__, (enable ? "enable" : "disable"),
out_snd_device);
-
- is_sidetone_dev = voice_is_sidetone_device(out_snd_device, mixer_path);
-
- if (!is_sidetone_dev) {
- ALOGD("%s: device %d does not support sidetone\n",
- __func__, out_snd_device);
- return;
- }
-
- ALOGD("%s: sidetone out device = %s\n",
- __func__, mixer_path);
-
- if (enable)
- audio_route_apply_and_update_path(adev->audio_route, mixer_path);
- else
- audio_route_reset_and_update_path(adev->audio_route, mixer_path);
-
+ if (voice_is_sidetone_device(out_snd_device, mixer_path))
+ platform_set_sidetone(adev, out_snd_device, enable, mixer_path);
return;
}
diff --git a/policy_hal/Android.mk b/policy_hal/Android.mk
index 811c2c9..854eaee 100644
--- a/policy_hal/Android.mk
+++ b/policy_hal/Android.mk
@@ -65,6 +65,10 @@
LOCAL_CFLAGS += -DFM_POWER_OPT
endif
+ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
+LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
+endif
+
LOCAL_MODULE := libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 9008936..8b12475 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -97,6 +97,37 @@
return flag;
}
#endif /*VOICE_CONCURRENCY*/
+
+void AudioPolicyManagerCustom::moveGlobalEffect()
+{
+ audio_io_handle_t dstOutput = getOutputForEffect();
+ if (hasPrimaryOutput() && dstOutput != mPrimaryOutput->mIoHandle) {
+#ifdef DOLBY_ENABLE
+ status_t status =
+ mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX,
+ mPrimaryOutput->mIoHandle,
+ dstOutput);
+ if (status == NO_ERROR) {
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ sp<EffectDescriptor> desc = mEffects.valueAt(i);
+ if (desc->mSession == AUDIO_SESSION_OUTPUT_MIX) {
+ // update the mIo member of EffectDescriptor
+ // for the global effect
+ ALOGV("%s updating mIo", __FUNCTION__);
+ desc->mIo = dstOutput;
+ }
+ }
+ } else {
+ ALOGW("%s moveEffects from %d to %d failed", __FUNCTION__,
+ mPrimaryOutput->mIoHandle, dstOutput);
+ }
+#else // DOLBY_END
+ mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX,
+ mPrimaryOutput->mIoHandle, dstOutput);
+#endif
+ }
+}
+
// ----------------------------------------------------------------------------
// AudioPolicyInterface implementation
// ----------------------------------------------------------------------------
@@ -771,6 +802,10 @@
}
}
}
+ // If effects where present on any of the above closed outputs,
+ // audioflinger moved them to the primary output by default
+ // move them back to the appropriate output.
+ moveGlobalEffect();
}
if ((AUDIO_MODE_IN_CALL == oldState || AUDIO_MODE_IN_COMMUNICATION == oldState) &&
@@ -839,6 +874,10 @@
closeOutput(mOutputs.keyAt(i));
}
}
+ // If effects where present on any of the above closed outputs,
+ // audioflinger moved them to the primary output by default
+ // move them back to the appropriate output.
+ moveGlobalEffect();
} else if ((oldState == AUDIO_MODE_IN_COMMUNICATION) &&
(mEngine->getPhoneState() == AUDIO_MODE_NORMAL)) {
// call invalidate for music so that music can fallback to compress
@@ -1782,16 +1821,22 @@
// for non direct outputs, only PCM is supported
if (audio_is_linear_pcm(format)) {
- if (forced_deep) {
- flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
- ALOGI("setting force DEEP buffer now ");
- }
// get which output is suitable for the specified stream. The actual
// routing change will happen when startOutput() will be called
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
// at this stage we should ignore the DIRECT flag as no direct output could be found earlier
flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+
+ if (forced_deep) {
+ flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+ ALOGI("setting force DEEP buffer now ");
+ } else if(flags == AUDIO_OUTPUT_FLAG_NONE) {
+ // no deep buffer playback is requested hence fallback to primary
+ flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_PRIMARY);
+ ALOGI("FLAG None hence request for a primary output");
+ }
+
output = selectOutput(outputs, flags, format);
}
ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d,"
@@ -1984,6 +2029,10 @@
closeOutput(mOutputs.keyAt(i));
}
}
+ // If effects where present on any of the above closed outputs,
+ // audioflinger moved them to the primary output by default
+ // move them back to the appropriate output.
+ moveGlobalEffect();
}
#endif
@@ -2101,6 +2150,12 @@
mFMIsActive(false)
{
+#ifdef USE_XML_AUDIO_POLICY_CONF
+ ALOGD("USE_XML_AUDIO_POLICY_CONF is TRUE");
+#else
+ ALOGD("USE_XML_AUDIO_POLICY_CONF is FALSE");
+#endif
+
//TODO: Check the new logic to parse policy conf and update the below code
// Need this when SSR encoding is enabled
char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
diff --git a/policy_hal/AudioPolicyManager.h b/policy_hal/AudioPolicyManager.h
index 6f47a54..dfda1c9 100644
--- a/policy_hal/AudioPolicyManager.h
+++ b/policy_hal/AudioPolicyManager.h
@@ -114,6 +114,7 @@
static audio_output_flags_t getFallBackPath();
int mFallBackflag;
#endif /*VOICE_CONCURRENCY*/
+ void moveGlobalEffect();
// handle special cases for sonification strategy while in call: mute streams or replace by
// a special tone in the device used for communication