blob: eba36ff41ea02ba9121dde00a7d2fe7790d4aa6e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070078#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080079#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080080
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053081#ifdef DYNAMIC_LOG_ENABLED
82#include <log_xml_parser.h>
83#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
84#include <log_utils.h>
85#endif
86
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070087#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053088/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
89#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070091#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053092#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070093
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070094#define PROXY_OPEN_RETRY_COUNT 100
95#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080096
Mingming Yin08c7e312015-03-16 18:10:58 -070097#ifdef USE_LL_AS_PRIMARY_OUTPUT
98#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
99#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
100#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800101#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700102#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
103#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800104
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700105#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700106#define DEFAULT_VOIP_BUF_DURATION_MS 20
107#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
108#define DEFAULT_VOIP_SAMP_RATE 48000
109
110#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
111
112struct pcm_config default_pcm_config_voip_copp = {
113 .channels = 1,
114 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
115 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
116 .period_count = 2,
117 .format = PCM_FORMAT_S16_LE,
118};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700119
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700120#define MIN_CHANNEL_COUNT 1
121#define DEFAULT_CHANNEL_COUNT 2
122#define MAX_HIFI_CHANNEL_COUNT 8
123
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700124static unsigned int configured_low_latency_capture_period_size =
125 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
126
Haynes Mathew George16081042017-05-31 17:16:49 -0700127#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
128#define MMAP_PERIOD_COUNT_MIN 32
129#define MMAP_PERIOD_COUNT_MAX 512
130#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
131
Eric Laurentb23d5282013-05-14 15:27:20 -0700132struct pcm_config pcm_config_deep_buffer = {
133 .channels = 2,
134 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
135 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
136 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
137 .format = PCM_FORMAT_S16_LE,
138 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
139 .stop_threshold = INT_MAX,
140 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
141};
142
143struct pcm_config pcm_config_low_latency = {
144 .channels = 2,
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
146 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
147 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
150 .stop_threshold = INT_MAX,
151 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
152};
153
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700154static int af_period_multiplier = 4;
155struct pcm_config pcm_config_rt = {
156 .channels = 2,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = ULL_PERIOD_SIZE, //1 ms
159 .period_count = 512, //=> buffer size is 512ms
160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
162 .stop_threshold = INT_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = ULL_PERIOD_SIZE, //1 ms
166};
167
Eric Laurentb23d5282013-05-14 15:27:20 -0700168struct pcm_config pcm_config_hdmi_multi = {
169 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = HDMI_MULTI_PERIOD_SIZE,
172 .period_count = HDMI_MULTI_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Haynes Mathew George16081042017-05-31 17:16:49 -0700179struct pcm_config pcm_config_mmap_playback = {
180 .channels = 2,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = MMAP_PERIOD_SIZE,
183 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = MMAP_PERIOD_SIZE*8,
186 .stop_threshold = INT32_MAX,
187 .silence_threshold = 0,
188 .silence_size = 0,
189 .avail_min = MMAP_PERIOD_SIZE, //1 ms
190};
191
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700192struct pcm_config pcm_config_hifi = {
193 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
195 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
196 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S24_3LE,
198 .start_threshold = 0,
199 .stop_threshold = INT_MAX,
200 .avail_min = 0,
201};
202
Eric Laurentb23d5282013-05-14 15:27:20 -0700203struct pcm_config pcm_config_audio_capture = {
204 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700205 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209struct pcm_config pcm_config_audio_capture_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE,
213 .period_count = 512,
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = 0,
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Haynes Mathew George16081042017-05-31 17:16:49 -0700222struct pcm_config pcm_config_mmap_capture = {
223 .channels = 2,
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
225 .period_size = MMAP_PERIOD_SIZE,
226 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .silence_threshold = 0,
231 .silence_size = 0,
232 .avail_min = MMAP_PERIOD_SIZE, //1 ms
233};
234
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700235#define AFE_PROXY_CHANNEL_COUNT 2
236#define AFE_PROXY_SAMPLING_RATE 48000
237
238#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
239#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
240
241struct pcm_config pcm_config_afe_proxy_playback = {
242 .channels = AFE_PROXY_CHANNEL_COUNT,
243 .rate = AFE_PROXY_SAMPLING_RATE,
244 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
245 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
248 .stop_threshold = INT_MAX,
249 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
250};
251
252#define AFE_PROXY_RECORD_PERIOD_SIZE 768
253#define AFE_PROXY_RECORD_PERIOD_COUNT 4
254
255struct pcm_config pcm_config_afe_proxy_record = {
256 .channels = AFE_PROXY_CHANNEL_COUNT,
257 .rate = AFE_PROXY_SAMPLING_RATE,
258 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
259 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
262 .stop_threshold = INT_MAX,
263 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
264};
265
Ashish Jainf1eaa582016-05-23 20:54:24 +0530266#define AUDIO_MAX_PCM_FORMATS 7
267
268const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
269 [AUDIO_FORMAT_DEFAULT] = 0,
270 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
271 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
272 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
273 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
274 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
275 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
276};
277
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800278const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700279 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
280 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700281 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
282 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700283 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700284 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700285 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
286 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
287 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
288 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
289 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700293 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
294 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700295 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700296
Eric Laurentb23d5282013-05-14 15:27:20 -0700297 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700298 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530299 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
300 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
301 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700302 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700303 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700304 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700305 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700306
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800307 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800308 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700309 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700310
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700311 [USECASE_VOICE2_CALL] = "voice2-call",
312 [USECASE_VOLTE_CALL] = "volte-call",
313 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800314 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800315 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
316 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800317 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700318 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
319 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
320 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800321 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
322 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
323 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
324
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700325 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
326 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700327 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
328 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700329
330 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
331 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700332 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700333
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530334 /* Transcode loopback cases */
335 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700336
337 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
338 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530339 /* For Interactive Audio Streams */
340 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
341 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
342 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
343 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
344 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
345 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700348
349 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture"
Eric Laurentb23d5282013-05-14 15:27:20 -0700350};
351
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700352static const audio_usecase_t offload_usecases[] = {
353 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700354 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
355 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
356 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
357 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
358 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
359 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
360 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
361 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700362};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800363
Varun Balaraje49253e2017-07-06 19:48:56 +0530364static const audio_usecase_t interactive_usecases[] = {
365 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
366 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
367 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
368 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
369 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
370 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
371 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
372 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
373};
374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800375#define STRING_TO_ENUM(string) { #string, string }
376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800377struct string_to_enum {
378 const char *name;
379 uint32_t value;
380};
381
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700382static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800384 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
385 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
386 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700387 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800388 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
389 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800390 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700391 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
392 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
393 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
394 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
395 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
396 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
397 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
398 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
399 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
400 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
401 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800402};
403
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700404static const struct string_to_enum formats_name_to_enum_table[] = {
405 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
406 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
407 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700408 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
409 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
410 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700411 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800412 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
413 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700414 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800415};
416
417//list of all supported sample rates by HDMI specification.
418static const int out_hdmi_sample_rates[] = {
419 32000, 44100, 48000, 88200, 96000, 176400, 192000,
420};
421
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700422static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800423 STRING_TO_ENUM(32000),
424 STRING_TO_ENUM(44100),
425 STRING_TO_ENUM(48000),
426 STRING_TO_ENUM(88200),
427 STRING_TO_ENUM(96000),
428 STRING_TO_ENUM(176400),
429 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700430};
431
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432static struct audio_device *adev = NULL;
433static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700434static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700435//cache last MBDRC cal step level
436static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700437
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530438static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
439static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800440static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530441
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700442static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
443 int flags __unused)
444{
445 int dir = 0;
446 switch (uc_id) {
447 case USECASE_AUDIO_RECORD_LOW_LATENCY:
448 dir = 1;
449 case USECASE_AUDIO_PLAYBACK_ULL:
450 break;
451 default:
452 return false;
453 }
454
455 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
456 PCM_PLAYBACK : PCM_CAPTURE);
457 if (adev->adm_is_noirq_avail)
458 return adev->adm_is_noirq_avail(adev->adm_data,
459 adev->snd_card, dev_id, dir);
460 return false;
461}
462
463static void register_out_stream(struct stream_out *out)
464{
465 struct audio_device *adev = out->dev;
466 if (is_offload_usecase(out->usecase) ||
467 !adev->adm_register_output_stream)
468 return;
469
470 // register stream first for backward compatibility
471 adev->adm_register_output_stream(adev->adm_data,
472 out->handle,
473 out->flags);
474
475 if (!adev->adm_set_config)
476 return;
477
478 if (out->realtime)
479 adev->adm_set_config(adev->adm_data,
480 out->handle,
481 out->pcm, &out->config);
482}
483
484static void register_in_stream(struct stream_in *in)
485{
486 struct audio_device *adev = in->dev;
487 if (!adev->adm_register_input_stream)
488 return;
489
490 adev->adm_register_input_stream(adev->adm_data,
491 in->capture_handle,
492 in->flags);
493
494 if (!adev->adm_set_config)
495 return;
496
497 if (in->realtime)
498 adev->adm_set_config(adev->adm_data,
499 in->capture_handle,
500 in->pcm,
501 &in->config);
502}
503
504static void request_out_focus(struct stream_out *out, long ns)
505{
506 struct audio_device *adev = out->dev;
507
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700508 if (adev->adm_request_focus_v2)
509 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
510 else if (adev->adm_request_focus)
511 adev->adm_request_focus(adev->adm_data, out->handle);
512}
513
514static void request_in_focus(struct stream_in *in, long ns)
515{
516 struct audio_device *adev = in->dev;
517
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700518 if (adev->adm_request_focus_v2)
519 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
520 else if (adev->adm_request_focus)
521 adev->adm_request_focus(adev->adm_data, in->capture_handle);
522}
523
524static void release_out_focus(struct stream_out *out)
525{
526 struct audio_device *adev = out->dev;
527
528 if (adev->adm_abandon_focus)
529 adev->adm_abandon_focus(adev->adm_data, out->handle);
530}
531
532static void release_in_focus(struct stream_in *in)
533{
534 struct audio_device *adev = in->dev;
535 if (adev->adm_abandon_focus)
536 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
537}
538
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530539static int parse_snd_card_status(struct str_parms *parms, int *card,
540 card_status_t *status)
541{
542 char value[32]={0};
543 char state[32]={0};
544
545 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
546 if (ret < 0)
547 return -1;
548
549 // sscanf should be okay as value is of max length 32.
550 // same as sizeof state.
551 if (sscanf(value, "%d,%s", card, state) < 2)
552 return -1;
553
554 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
555 CARD_STATUS_OFFLINE;
556 return 0;
557}
558
vivek mehtaa76401a2015-04-24 14:12:15 -0700559__attribute__ ((visibility ("default")))
560bool audio_hw_send_gain_dep_calibration(int level) {
561 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700562 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700563
564 pthread_mutex_lock(&adev_init_lock);
565
566 if (adev != NULL && adev->platform != NULL) {
567 pthread_mutex_lock(&adev->lock);
568 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700569
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530570 // cache level info for any of the use case which
571 // was not started.
572 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700573
vivek mehtaa76401a2015-04-24 14:12:15 -0700574 pthread_mutex_unlock(&adev->lock);
575 } else {
576 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
577 }
578
579 pthread_mutex_unlock(&adev_init_lock);
580
581 return ret_val;
582}
583
Ashish Jain5106d362016-05-11 19:23:33 +0530584static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
585{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800586 bool gapless_enabled = false;
587 const char *mixer_ctl_name = "Compress Gapless Playback";
588 struct mixer_ctl *ctl;
589
590 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700591 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530592
593 /*Disable gapless if its AV playback*/
594 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800595
596 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
597 if (!ctl) {
598 ALOGE("%s: Could not get ctl for mixer cmd - %s",
599 __func__, mixer_ctl_name);
600 return -EINVAL;
601 }
602
603 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
604 ALOGE("%s: Could not set gapless mode %d",
605 __func__, gapless_enabled);
606 return -EINVAL;
607 }
608 return 0;
609}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700610
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700611__attribute__ ((visibility ("default")))
612int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
613 int table_size) {
614 int ret_val = 0;
615 ALOGV("%s: enter ... ", __func__);
616
617 pthread_mutex_lock(&adev_init_lock);
618 if (adev == NULL) {
619 ALOGW("%s: adev is NULL .... ", __func__);
620 goto done;
621 }
622
623 pthread_mutex_lock(&adev->lock);
624 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
625 pthread_mutex_unlock(&adev->lock);
626done:
627 pthread_mutex_unlock(&adev_init_lock);
628 ALOGV("%s: exit ... ", __func__);
629 return ret_val;
630}
631
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700632static bool is_supported_format(audio_format_t format)
633{
Eric Laurent86e17132013-09-12 17:49:30 -0700634 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530635 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530636 format == AUDIO_FORMAT_AAC_LC ||
637 format == AUDIO_FORMAT_AAC_HE_V1 ||
638 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530639 format == AUDIO_FORMAT_AAC_ADTS_LC ||
640 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
641 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530642 format == AUDIO_FORMAT_AAC_LATM_LC ||
643 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
644 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530645 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
646 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530647 format == AUDIO_FORMAT_PCM_FLOAT ||
648 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700649 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530650 format == AUDIO_FORMAT_AC3 ||
651 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700652 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530653 format == AUDIO_FORMAT_DTS ||
654 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800655 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530656 format == AUDIO_FORMAT_ALAC ||
657 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530658 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530659 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800660 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530661 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700662 format == AUDIO_FORMAT_APTX ||
663 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800664 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700665
666 return false;
667}
668
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700669static inline bool is_mmap_usecase(audio_usecase_t uc_id)
670{
671 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
672 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
673}
674
Avinash Vaish71a8b972014-07-24 15:36:33 +0530675static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
676 struct audio_usecase *uc_info)
677{
678 struct listnode *node;
679 struct audio_usecase *usecase;
680
681 if (uc_info == NULL)
682 return -EINVAL;
683
684 /* Re-route all voice usecases on the shared backend other than the
685 specified usecase to new snd devices */
686 list_for_each(node, &adev->usecase_list) {
687 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800688 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530689 enable_audio_route(adev, usecase);
690 }
691 return 0;
692}
693
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530694static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530695{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530696 ALOGV("%s", __func__);
697 audio_route_apply_and_update_path(adev->audio_route,
698 "asrc-mode");
699 adev->asrc_mode_enabled = true;
700}
701
702static void disable_asrc_mode(struct audio_device *adev)
703{
704 ALOGV("%s", __func__);
705 audio_route_reset_and_update_path(adev->audio_route,
706 "asrc-mode");
707 adev->asrc_mode_enabled = false;
708}
709
710/*
711 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
712 * 44.1 or Native DSD backends are enabled for any of current use case.
713 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
714 * - Disable current mix path use case(Headphone backend) and re-enable it with
715 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
716 * e.g. Naitve DSD or Headphone 44.1 -> + 48
717 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530718static void check_and_set_asrc_mode(struct audio_device *adev,
719 struct audio_usecase *uc_info,
720 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530721{
722 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530723 int i, num_new_devices = 0;
724 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
725 /*
726 *Split snd device for new combo use case
727 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
728 */
729 if (platform_split_snd_device(adev->platform,
730 snd_device,
731 &num_new_devices,
732 split_new_snd_devices) == 0) {
733 for (i = 0; i < num_new_devices; i++)
734 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
735 } else {
736 int new_backend_idx = platform_get_backend_index(snd_device);
737 if (((new_backend_idx == HEADPHONE_BACKEND) ||
738 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
739 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
740 !adev->asrc_mode_enabled) {
741 struct listnode *node = NULL;
742 struct audio_usecase *uc = NULL;
743 struct stream_out *curr_out = NULL;
744 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
745 int i, num_devices, ret = 0;
746 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530747
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530748 list_for_each(node, &adev->usecase_list) {
749 uc = node_to_item(node, struct audio_usecase, list);
750 curr_out = (struct stream_out*) uc->stream.out;
751 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
752 /*
753 *Split snd device for existing combo use case
754 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
755 */
756 ret = platform_split_snd_device(adev->platform,
757 uc->out_snd_device,
758 &num_devices,
759 split_snd_devices);
760 if (ret < 0 || num_devices == 0) {
761 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
762 split_snd_devices[0] = uc->out_snd_device;
763 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800764 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530765 for (i = 0; i < num_devices; i++) {
766 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
767 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
768 if((new_backend_idx == HEADPHONE_BACKEND) &&
769 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
770 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
771 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
772 __func__);
773 enable_asrc_mode(adev);
774 break;
775 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
776 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
777 (usecase_backend_idx == HEADPHONE_BACKEND)) {
778 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
779 __func__);
780 disable_audio_route(adev, uc);
781 disable_snd_device(adev, uc->out_snd_device);
782 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
783 if (new_backend_idx == DSD_NATIVE_BACKEND)
784 audio_route_apply_and_update_path(adev->audio_route,
785 "hph-true-highquality-mode");
786 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
787 (curr_out->bit_width >= 24))
788 audio_route_apply_and_update_path(adev->audio_route,
789 "hph-highquality-mode");
790 enable_asrc_mode(adev);
791 enable_snd_device(adev, uc->out_snd_device);
792 enable_audio_route(adev, uc);
793 break;
794 }
795 }
796 // reset split devices count
797 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800798 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530799 if (adev->asrc_mode_enabled)
800 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530801 }
802 }
803 }
804}
805
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700806int pcm_ioctl(struct pcm *pcm, int request, ...)
807{
808 va_list ap;
809 void * arg;
810 int pcm_fd = *(int*)pcm;
811
812 va_start(ap, request);
813 arg = va_arg(ap, void *);
814 va_end(ap);
815
816 return ioctl(pcm_fd, request, arg);
817}
818
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700819int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700820 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800821{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700823 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530824 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800825
826 if (usecase == NULL)
827 return -EINVAL;
828
829 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
830
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800831 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800833 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800835
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800836#ifdef DS1_DOLBY_DAP_ENABLED
837 audio_extn_dolby_set_dmid(adev);
838 audio_extn_dolby_set_endpoint(adev);
839#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700840 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700841 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530842 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700843 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530844 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530845 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
846 out = usecase->stream.out;
847 if (out && out->compr)
848 audio_extn_utils_compress_set_clk_rec_mode(usecase);
849 }
850
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800851 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700852 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700853 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700854 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855 ALOGV("%s: exit", __func__);
856 return 0;
857}
858
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700859int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700860 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800861{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700863 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800864
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530865 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800866 return -EINVAL;
867
868 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 if (usecase->type == PCM_CAPTURE)
870 snd_device = usecase->in_snd_device;
871 else
872 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800873 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700874 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700875 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700876 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700877 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530878 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800879 ALOGV("%s: exit", __func__);
880 return 0;
881}
882
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700883int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700884 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800885{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530886 int i, num_devices = 0;
887 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700888 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
889
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800890 if (snd_device < SND_DEVICE_MIN ||
891 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800892 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800893 return -EINVAL;
894 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895
896 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700897
898 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
899 ALOGE("%s: Invalid sound device returned", __func__);
900 return -EINVAL;
901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700903 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700904 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 return 0;
906 }
907
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530908
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700909 if (audio_extn_spkr_prot_is_enabled())
910 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700911
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800912 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
913 audio_extn_spkr_prot_is_enabled()) {
914 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700915 adev->snd_dev_ref_cnt[snd_device]--;
916 return -EINVAL;
917 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200918 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800919 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800920 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200921 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800922 return -EINVAL;
923 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700924 } else if (platform_split_snd_device(adev->platform,
925 snd_device,
926 &num_devices,
927 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530928 for (i = 0; i < num_devices; i++) {
929 enable_snd_device(adev, new_snd_devices[i]);
930 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800931 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700932 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530933
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530934
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530935 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
936 (audio_extn_a2dp_start_playback() < 0)) {
937 ALOGE(" fail to configure A2dp control path ");
938 return -EINVAL;
939 }
940
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700941 /* due to the possibility of calibration overwrite between listen
942 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700943 audio_extn_sound_trigger_update_device_status(snd_device,
944 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530945 audio_extn_listen_update_device_status(snd_device,
946 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700947 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700948 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700949 audio_extn_sound_trigger_update_device_status(snd_device,
950 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530951 audio_extn_listen_update_device_status(snd_device,
952 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700953 return -EINVAL;
954 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300955 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700956 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530957
958 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
959 !adev->native_playback_enabled &&
960 audio_is_true_native_stream_active(adev)) {
961 ALOGD("%s: %d: napb: enabling native mode in hardware",
962 __func__, __LINE__);
963 audio_route_apply_and_update_path(adev->audio_route,
964 "true-native-mode");
965 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530966 }
Garmond Leunge2433c32017-09-28 21:51:22 -0700967 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
968 (audio_extn_ffv_get_stream() == adev->active_input)) {
969 ALOGD("%s: init ec ref loopback", __func__);
970 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 return 0;
974}
975
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700976int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700977 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530979 int i, num_devices = 0;
980 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700981 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
982
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800983 if (snd_device < SND_DEVICE_MIN ||
984 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800985 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800986 return -EINVAL;
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
989 ALOGE("%s: device ref cnt is already 0", __func__);
990 return -EINVAL;
991 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700992
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700994
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700995 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
996 ALOGE("%s: Invalid sound device returned", __func__);
997 return -EINVAL;
998 }
999
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001001 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301002
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001003 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1004 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001005 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001006 } else if (platform_split_snd_device(adev->platform,
1007 snd_device,
1008 &num_devices,
1009 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301010 for (i = 0; i < num_devices; i++) {
1011 disable_snd_device(adev, new_snd_devices[i]);
1012 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001013 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001014 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001015 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001016
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301017 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1018 audio_extn_a2dp_stop_playback();
1019
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001020 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301021 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301022 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1023 adev->native_playback_enabled) {
1024 ALOGD("%s: %d: napb: disabling native mode in hardware",
1025 __func__, __LINE__);
1026 audio_route_reset_and_update_path(adev->audio_route,
1027 "true-native-mode");
1028 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301029 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1030 adev->asrc_mode_enabled) {
1031 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301032 disable_asrc_mode(adev);
1033 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301034 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001035 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1036 (audio_extn_ffv_get_stream() == adev->active_input)) {
1037 ALOGD("%s: deinit ec ref loopback", __func__);
1038 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1039 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001040 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001041 audio_extn_sound_trigger_update_device_status(snd_device,
1042 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301043 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001044 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001045 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 return 0;
1048}
1049
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001050/*
1051 legend:
1052 uc - existing usecase
1053 new_uc - new usecase
1054 d1, d11, d2 - SND_DEVICE enums
1055 a1, a2 - corresponding ANDROID device enums
1056 B1, B2 - backend strings
1057
1058case 1
1059 uc->dev d1 (a1) B1
1060 new_uc->dev d1 (a1), d2 (a2) B1, B2
1061
1062 resolution: disable and enable uc->dev on d1
1063
1064case 2
1065 uc->dev d1 (a1) B1
1066 new_uc->dev d11 (a1) B1
1067
1068 resolution: need to switch uc since d1 and d11 are related
1069 (e.g. speaker and voice-speaker)
1070 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1071
1072case 3
1073 uc->dev d1 (a1) B1
1074 new_uc->dev d2 (a2) B2
1075
1076 resolution: no need to switch uc
1077
1078case 4
1079 uc->dev d1 (a1) B1
1080 new_uc->dev d2 (a2) B1
1081
1082 resolution: disable enable uc-dev on d2 since backends match
1083 we cannot enable two streams on two different devices if they
1084 share the same backend. e.g. if offload is on speaker device using
1085 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1086 using the same backend, offload must also be switched to voice-handset.
1087
1088case 5
1089 uc->dev d1 (a1) B1
1090 new_uc->dev d1 (a1), d2 (a2) B1
1091
1092 resolution: disable enable uc-dev on d2 since backends match
1093 we cannot enable two streams on two different devices if they
1094 share the same backend.
1095
1096case 6
1097 uc->dev d1 (a1) B1
1098 new_uc->dev d2 (a1) B2
1099
1100 resolution: no need to switch
1101
1102case 7
1103 uc->dev d1 (a1), d2 (a2) B1, B2
1104 new_uc->dev d1 (a1) B1
1105
1106 resolution: no need to switch
1107
1108*/
1109static snd_device_t derive_playback_snd_device(void * platform,
1110 struct audio_usecase *uc,
1111 struct audio_usecase *new_uc,
1112 snd_device_t new_snd_device)
1113{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301114 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001115
1116 snd_device_t d1 = uc->out_snd_device;
1117 snd_device_t d2 = new_snd_device;
1118
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301119 switch (uc->type) {
1120 case TRANSCODE_LOOPBACK :
1121 a1 = uc->stream.inout->out_config.devices;
1122 a2 = new_uc->stream.inout->out_config.devices;
1123 break;
1124 default :
1125 a1 = uc->stream.out->devices;
1126 a2 = new_uc->stream.out->devices;
1127 break;
1128 }
1129
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001130 // Treat as a special case when a1 and a2 are not disjoint
1131 if ((a1 != a2) && (a1 & a2)) {
1132 snd_device_t d3[2];
1133 int num_devices = 0;
1134 int ret = platform_split_snd_device(platform,
1135 popcount(a1) > 1 ? d1 : d2,
1136 &num_devices,
1137 d3);
1138 if (ret < 0) {
1139 if (ret != -ENOSYS) {
1140 ALOGW("%s failed to split snd_device %d",
1141 __func__,
1142 popcount(a1) > 1 ? d1 : d2);
1143 }
1144 goto end;
1145 }
1146
1147 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1148 // But if it does happen, we need to give priority to d2 if
1149 // the combo devices active on the existing usecase share a backend.
1150 // This is because we cannot have a usecase active on a combo device
1151 // and a new usecase requests one device in this combo pair.
1152 if (platform_check_backends_match(d3[0], d3[1])) {
1153 return d2; // case 5
1154 } else {
1155 return d1; // case 1
1156 }
1157 } else {
1158 if (platform_check_backends_match(d1, d2)) {
1159 return d2; // case 2, 4
1160 } else {
1161 return d1; // case 6, 3
1162 }
1163 }
1164
1165end:
1166 return d2; // return whatever was calculated before.
1167}
1168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301170 struct audio_usecase *uc_info,
1171 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001172{
1173 struct listnode *node;
1174 struct audio_usecase *usecase;
1175 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301176 snd_device_t uc_derive_snd_device;
1177 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001179 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301180 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 /*
1182 * This function is to make sure that all the usecases that are active on
1183 * the hardware codec backend are always routed to any one device that is
1184 * handled by the hardware codec.
1185 * For example, if low-latency and deep-buffer usecases are currently active
1186 * on speaker and out_set_parameters(headset) is received on low-latency
1187 * output, then we have to make sure deep-buffer is also switched to headset,
1188 * because of the limitation that both the devices cannot be enabled
1189 * at the same time as they share the same backend.
1190 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001191 /*
1192 * This call is to check if we need to force routing for a particular stream
1193 * If there is a backend configuration change for the device when a
1194 * new stream starts, then ADM needs to be closed and re-opened with the new
1195 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001196 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001197 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001198 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1199 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301200 /* For a2dp device reconfigure all active sessions
1201 * with new AFE encoder format based on a2dp state
1202 */
1203 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1204 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1205 audio_extn_a2dp_is_force_device_switch()) {
1206 force_routing = true;
1207 force_restart_session = true;
1208 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301209 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1210
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001212 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001213 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001214 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1215 switch_device[i] = false;
1216
1217 list_for_each(node, &adev->usecase_list) {
1218 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001219
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301220 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1221 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301222 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301223 platform_get_snd_device_name(usecase->out_snd_device),
1224 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301225 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1226 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1227 usecase, uc_info, snd_device);
1228 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1229 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1230 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1231 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1232 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1233 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1234 ((force_restart_session) ||
1235 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301236 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1237 __func__, use_case_table[usecase->id],
1238 platform_get_snd_device_name(usecase->out_snd_device));
1239 disable_audio_route(adev, usecase);
1240 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301241 /* Enable existing usecase on derived playback device */
1242 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301243 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301244 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001245 }
1246 }
1247
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301248 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1249 num_uc_to_switch);
1250
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001251 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001252 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001253
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301254 /* Make sure the previous devices to be disabled first and then enable the
1255 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 list_for_each(node, &adev->usecase_list) {
1257 usecase = node_to_item(node, struct audio_usecase, list);
1258 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001259 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001260 }
1261 }
1262
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001263 list_for_each(node, &adev->usecase_list) {
1264 usecase = node_to_item(node, struct audio_usecase, list);
1265 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301266 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001267 }
1268 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001270 /* Re-route all the usecases on the shared backend other than the
1271 specified usecase to new snd devices */
1272 list_for_each(node, &adev->usecase_list) {
1273 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301274 /* Update the out_snd_device only before enabling the audio route */
1275 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301276 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301277 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301278 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301279 use_case_table[usecase->id],
1280 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001281 /* Update voc calibration before enabling VoIP route */
1282 if (usecase->type == VOIP_CALL)
1283 status = platform_switch_voice_call_device_post(adev->platform,
1284 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001285 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301286 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301287 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 }
1289 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001290 }
1291}
1292
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301293static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001294 struct audio_usecase *uc_info,
1295 snd_device_t snd_device)
1296{
1297 struct listnode *node;
1298 struct audio_usecase *usecase;
1299 bool switch_device[AUDIO_USECASE_MAX];
1300 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301301 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001302 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001303
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301304 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1305 snd_device);
1306 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301307
1308 /*
1309 * Make sure out devices is checked against out codec backend device and
1310 * also in devices against in codec backend. Checking out device against in
1311 * codec backend or vice versa causes issues.
1312 */
1313 if (uc_info->type == PCM_CAPTURE)
1314 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001315 /*
1316 * This function is to make sure that all the active capture usecases
1317 * are always routed to the same input sound device.
1318 * For example, if audio-record and voice-call usecases are currently
1319 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1320 * is received for voice call then we have to make sure that audio-record
1321 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1322 * because of the limitation that two devices cannot be enabled
1323 * at the same time if they share the same backend.
1324 */
1325 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1326 switch_device[i] = false;
1327
1328 list_for_each(node, &adev->usecase_list) {
1329 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301330 /*
1331 * TODO: Enhance below condition to handle BT sco/USB multi recording
1332 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001333 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001334 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301335 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301336 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301337 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301338 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001339 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001340 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1341 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001342 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001343 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001344 switch_device[usecase->id] = true;
1345 num_uc_to_switch++;
1346 }
1347 }
1348
1349 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001350 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001351
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301352 /* Make sure the previous devices to be disabled first and then enable the
1353 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001354 list_for_each(node, &adev->usecase_list) {
1355 usecase = node_to_item(node, struct audio_usecase, list);
1356 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001358 }
1359 }
1360
1361 list_for_each(node, &adev->usecase_list) {
1362 usecase = node_to_item(node, struct audio_usecase, list);
1363 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001364 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001365 }
1366 }
1367
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001368 /* Re-route all the usecases on the shared backend other than the
1369 specified usecase to new snd devices */
1370 list_for_each(node, &adev->usecase_list) {
1371 usecase = node_to_item(node, struct audio_usecase, list);
1372 /* Update the in_snd_device only before enabling the audio route */
1373 if (switch_device[usecase->id] ) {
1374 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001375 if (usecase->type != VOICE_CALL) {
1376 /* Update voc calibration before enabling VoIP route */
1377 if (usecase->type == VOIP_CALL)
1378 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001379 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001380 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301381 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001382 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001383 }
1384 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001385 }
1386}
1387
Mingming Yin3a941d42016-02-17 18:08:05 -08001388static void reset_hdmi_sink_caps(struct stream_out *out) {
1389 int i = 0;
1390
1391 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1392 out->supported_channel_masks[i] = 0;
1393 }
1394 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1395 out->supported_formats[i] = 0;
1396 }
1397 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1398 out->supported_sample_rates[i] = 0;
1399 }
1400}
1401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001403static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404{
Mingming Yin3a941d42016-02-17 18:08:05 -08001405 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001406 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407
Mingming Yin3a941d42016-02-17 18:08:05 -08001408 reset_hdmi_sink_caps(out);
1409
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001410 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001411 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001412 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001413 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001414 }
1415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001418 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001419 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001420 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1421 case 6:
1422 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1423 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1424 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1425 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1426 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1427 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 break;
1429 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001430 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001431 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 break;
1433 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001434
1435 // check channel format caps
1436 i = 0;
1437 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1438 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1439 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1440 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1441 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1442 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1443 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1444 }
1445
Ben Romberger1aaaf862017-04-06 17:49:46 -07001446 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1447 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1448 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1449 }
1450
Mingming Yin3a941d42016-02-17 18:08:05 -08001451 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1452 ALOGV(":%s HDMI supports DTS format", __func__);
1453 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1454 }
1455
1456 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1457 ALOGV(":%s HDMI supports DTS HD format", __func__);
1458 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1459 }
1460
Naresh Tanniru928f0862017-04-07 16:44:23 -07001461 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1462 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1463 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1464 }
1465
Mingming Yin3a941d42016-02-17 18:08:05 -08001466
1467 // check sample rate caps
1468 i = 0;
1469 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1470 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1471 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1472 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1473 }
1474 }
1475
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001476 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477}
1478
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001479static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1480 uint32_t *supported_sample_rates __unused,
1481 uint32_t max_rates __unused)
1482{
1483 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1484 supported_sample_rates,
1485 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301486 ssize_t i = 0;
1487
1488 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001489 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1490 supported_sample_rates[i]);
1491 }
1492 return count;
1493}
1494
1495static inline int read_usb_sup_channel_masks(bool is_playback,
1496 audio_channel_mask_t *supported_channel_masks,
1497 uint32_t max_masks)
1498{
1499 int channels = audio_extn_usb_get_max_channels(is_playback);
1500 int channel_count;
1501 uint32_t num_masks = 0;
1502 if (channels > MAX_HIFI_CHANNEL_COUNT)
1503 channels = MAX_HIFI_CHANNEL_COUNT;
1504
1505 if (is_playback) {
1506 // For playback we never report mono because the framework always outputs stereo
1507 channel_count = DEFAULT_CHANNEL_COUNT;
1508 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1509 // above 2 but we want indexed masks here. So we
1510 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1511 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1512 }
1513 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1514 supported_channel_masks[num_masks++] =
1515 audio_channel_mask_for_index_assignment_from_count(channel_count);
1516 }
1517 } else {
1518 // For capture we report all supported channel masks from 1 channel up.
1519 channel_count = MIN_CHANNEL_COUNT;
1520 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1521 // indexed mask
1522 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1523 supported_channel_masks[num_masks++] =
1524 audio_channel_in_mask_from_count(channel_count);
1525 }
1526 }
1527 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1528 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1529 return num_masks;
1530}
1531
1532static inline int read_usb_sup_formats(bool is_playback __unused,
1533 audio_format_t *supported_formats,
1534 uint32_t max_formats __unused)
1535{
1536 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1537 switch (bitwidth) {
1538 case 24:
1539 // XXX : usb.c returns 24 for s24 and s24_le?
1540 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1541 break;
1542 case 32:
1543 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1544 break;
1545 case 16:
1546 default :
1547 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1548 break;
1549 }
1550 ALOGV("%s: %s supported format %d", __func__,
1551 is_playback ? "P" : "C", bitwidth);
1552 return 1;
1553}
1554
1555static inline int read_usb_sup_params_and_compare(bool is_playback,
1556 audio_format_t *format,
1557 audio_format_t *supported_formats,
1558 uint32_t max_formats,
1559 audio_channel_mask_t *mask,
1560 audio_channel_mask_t *supported_channel_masks,
1561 uint32_t max_masks,
1562 uint32_t *rate,
1563 uint32_t *supported_sample_rates,
1564 uint32_t max_rates) {
1565 int ret = 0;
1566 int num_formats;
1567 int num_masks;
1568 int num_rates;
1569 int i;
1570
1571 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1572 max_formats);
1573 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1574 max_masks);
1575
1576 num_rates = read_usb_sup_sample_rates(is_playback,
1577 supported_sample_rates, max_rates);
1578
1579#define LUT(table, len, what, dflt) \
1580 for (i=0; i<len && (table[i] != what); i++); \
1581 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1582
1583 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1584 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1585 LUT(supported_sample_rates, num_rates, *rate, 0);
1586
1587#undef LUT
1588 return ret < 0 ? -EINVAL : 0; // HACK TBD
1589}
1590
Alexy Josephb1379942016-01-29 15:49:38 -08001591audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001592 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001593{
1594 struct audio_usecase *usecase;
1595 struct listnode *node;
1596
1597 list_for_each(node, &adev->usecase_list) {
1598 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001599 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001600 ALOGV("%s: usecase id %d", __func__, usecase->id);
1601 return usecase->id;
1602 }
1603 }
1604 return USECASE_INVALID;
1605}
1606
Alexy Josephb1379942016-01-29 15:49:38 -08001607struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001608 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001609{
1610 struct audio_usecase *usecase;
1611 struct listnode *node;
1612
1613 list_for_each(node, &adev->usecase_list) {
1614 usecase = node_to_item(node, struct audio_usecase, list);
1615 if (usecase->id == uc_id)
1616 return usecase;
1617 }
1618 return NULL;
1619}
1620
Dhananjay Kumard4833242016-10-06 22:09:12 +05301621struct stream_in *get_next_active_input(const struct audio_device *adev)
1622{
1623 struct audio_usecase *usecase;
1624 struct listnode *node;
1625
1626 list_for_each_reverse(node, &adev->usecase_list) {
1627 usecase = node_to_item(node, struct audio_usecase, list);
1628 if (usecase->type == PCM_CAPTURE)
1629 return usecase->stream.in;
1630 }
1631 return NULL;
1632}
1633
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301634/*
1635 * is a true native playback active
1636 */
1637bool audio_is_true_native_stream_active(struct audio_device *adev)
1638{
1639 bool active = false;
1640 int i = 0;
1641 struct listnode *node;
1642
1643 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1644 ALOGV("%s:napb: not in true mode or non hdphones device",
1645 __func__);
1646 active = false;
1647 goto exit;
1648 }
1649
1650 list_for_each(node, &adev->usecase_list) {
1651 struct audio_usecase *uc;
1652 uc = node_to_item(node, struct audio_usecase, list);
1653 struct stream_out *curr_out =
1654 (struct stream_out*) uc->stream.out;
1655
1656 if (curr_out && PCM_PLAYBACK == uc->type) {
1657 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1658 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1659 uc->id, curr_out->sample_rate,
1660 curr_out->bit_width,
1661 platform_get_snd_device_name(uc->out_snd_device));
1662
1663 if (is_offload_usecase(uc->id) &&
1664 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1665 active = true;
1666 ALOGD("%s:napb:native stream detected", __func__);
1667 }
1668 }
1669 }
1670exit:
1671 return active;
1672}
1673
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001674uint32_t adev_get_dsp_bit_width_enforce_mode()
1675{
1676 if (adev == NULL) {
1677 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1678 return 0;
1679 }
1680 return adev->dsp_bit_width_enforce_mode;
1681}
1682
1683static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1684{
1685 char value[PROPERTY_VALUE_MAX];
1686 int trial;
1687 uint32_t dsp_bit_width_enforce_mode = 0;
1688
1689 if (!mixer) {
1690 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1691 __func__);
1692 return 0;
1693 }
1694
1695 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1696 value, NULL) > 0) {
1697 trial = atoi(value);
1698 switch (trial) {
1699 case 16:
1700 dsp_bit_width_enforce_mode = 16;
1701 break;
1702 case 24:
1703 dsp_bit_width_enforce_mode = 24;
1704 break;
1705 case 32:
1706 dsp_bit_width_enforce_mode = 32;
1707 break;
1708 default:
1709 dsp_bit_width_enforce_mode = 0;
1710 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1711 break;
1712 }
1713 }
1714
1715 return dsp_bit_width_enforce_mode;
1716}
1717
1718static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1719 uint32_t enforce_mode,
1720 bool enable)
1721{
1722 struct mixer_ctl *ctl = NULL;
1723 const char *mixer_ctl_name = "ASM Bit Width";
1724 uint32_t asm_bit_width_mode = 0;
1725
1726 if (enforce_mode == 0) {
1727 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1728 return;
1729 }
1730
1731 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1732 if (!ctl) {
1733 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1734 __func__, mixer_ctl_name);
1735 return;
1736 }
1737
1738 if (enable)
1739 asm_bit_width_mode = enforce_mode;
1740 else
1741 asm_bit_width_mode = 0;
1742
1743 ALOGV("%s DSP bit width feature status is %d width=%d",
1744 __func__, enable, asm_bit_width_mode);
1745 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1746 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1747 asm_bit_width_mode);
1748
1749 return;
1750}
1751
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301752/*
1753 * if native DSD playback active
1754 */
1755bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1756{
1757 bool active = false;
1758 struct listnode *node = NULL;
1759 struct audio_usecase *uc = NULL;
1760 struct stream_out *curr_out = NULL;
1761
1762 list_for_each(node, &adev->usecase_list) {
1763 uc = node_to_item(node, struct audio_usecase, list);
1764 curr_out = (struct stream_out*) uc->stream.out;
1765
1766 if (curr_out && PCM_PLAYBACK == uc->type &&
1767 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1768 active = true;
1769 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301770 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301771 }
1772 }
1773 return active;
1774}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301775
1776static bool force_device_switch(struct audio_usecase *usecase)
1777{
1778 bool ret = false;
1779 bool is_it_true_mode = false;
1780
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001781 if(usecase->stream.out == NULL) {
1782 ALOGE("%s: stream.out is NULL", __func__);
1783 return false;
1784 }
1785
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301786 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001787 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1788 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1789 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301790 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1791 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1792 (!is_it_true_mode && adev->native_playback_enabled)){
1793 ret = true;
1794 ALOGD("napb: time to toggle native mode");
1795 }
1796 }
1797
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301798 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301799 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1800 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001801 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301802 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301803 ALOGD("Force a2dp device switch to update new encoder config");
1804 ret = true;
1805 }
1806
Manish Dewangan671a4202017-08-18 17:30:46 +05301807 if (usecase->stream.out->stream_config_changed) {
1808 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1809 return true;
1810 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301811 return ret;
1812}
1813
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301814bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1815{
1816 bool ret=false;
1817 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1818 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1819 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1820 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1821 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1822 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1823 ret = true;
1824
1825 return ret;
1826}
1827
1828bool is_a2dp_device(snd_device_t out_snd_device)
1829{
1830 bool ret=false;
1831 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1832 ret = true;
1833
1834 return ret;
1835}
1836
1837bool is_bt_soc_on(struct audio_device *adev)
1838{
1839 struct mixer_ctl *ctl;
1840 char *mixer_ctl_name = "BT SOC status";
1841 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1842 bool bt_soc_status = true;
1843 if (!ctl) {
1844 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1845 __func__, mixer_ctl_name);
1846 /*This is to ensure we dont break targets which dont have the kernel change*/
1847 return true;
1848 }
1849 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1850 ALOGD("BT SOC status: %d",bt_soc_status);
1851 return bt_soc_status;
1852}
1853
1854int out_standby_l(struct audio_stream *stream);
1855
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001856int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001858 snd_device_t out_snd_device = SND_DEVICE_NONE;
1859 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001860 struct audio_usecase *usecase = NULL;
1861 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001862 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001863 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301864 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001865 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001866 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301868 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1869
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 usecase = get_usecase_from_list(adev, uc_id);
1871 if (usecase == NULL) {
1872 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1873 return -EINVAL;
1874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001876 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001877 (usecase->type == VOIP_CALL) ||
1878 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301879 if(usecase->stream.out == NULL) {
1880 ALOGE("%s: stream.out is NULL", __func__);
1881 return -EINVAL;
1882 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001883 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001884 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001885 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301887 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1888 if (usecase->stream.inout == NULL) {
1889 ALOGE("%s: stream.inout is NULL", __func__);
1890 return -EINVAL;
1891 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301892 stream_out.devices = usecase->stream.inout->out_config.devices;
1893 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1894 stream_out.format = usecase->stream.inout->out_config.format;
1895 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1896 out_snd_device = platform_get_output_snd_device(adev->platform,
1897 &stream_out);
1898 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301899 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 } else {
1901 /*
1902 * If the voice call is active, use the sound devices of voice call usecase
1903 * so that it would not result any device switch. All the usecases will
1904 * be switched to new device when select_devices() is called for voice call
1905 * usecase. This is to avoid switching devices for voice call when
1906 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001907 * choose voice call device only if the use case device is
1908 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001909 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001910 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001911 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001912 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001913 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1914 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301915 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1916 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001917 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 in_snd_device = vc_usecase->in_snd_device;
1919 out_snd_device = vc_usecase->out_snd_device;
1920 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001921 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001922 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001923 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001924 if ((voip_usecase != NULL) &&
1925 (usecase->type == PCM_PLAYBACK) &&
1926 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001927 out_snd_device_backend_match = platform_check_backends_match(
1928 voip_usecase->out_snd_device,
1929 platform_get_output_snd_device(
1930 adev->platform,
1931 usecase->stream.out));
1932 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001933 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001934 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1935 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001936 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001937 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001938 in_snd_device = voip_usecase->in_snd_device;
1939 out_snd_device = voip_usecase->out_snd_device;
1940 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001941 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001942 hfp_ucid = audio_extn_hfp_get_usecase();
1943 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001944 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001945 in_snd_device = hfp_usecase->in_snd_device;
1946 out_snd_device = hfp_usecase->out_snd_device;
1947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948 }
1949 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301950 if (usecase->stream.out == NULL) {
1951 ALOGE("%s: stream.out is NULL", __func__);
1952 return -EINVAL;
1953 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001954 usecase->devices = usecase->stream.out->devices;
1955 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001956 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001957 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001958 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001959 if (usecase->stream.out == adev->primary_output &&
1960 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001961 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001962 select_devices(adev, adev->active_input->usecase);
1963 }
1964 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001965 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301966 if (usecase->stream.in == NULL) {
1967 ALOGE("%s: stream.in is NULL", __func__);
1968 return -EINVAL;
1969 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001970 usecase->devices = usecase->stream.in->device;
1971 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001972 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001973 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001974 if (adev->active_input &&
1975 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301976 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1977 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1978 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001979 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001980 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001981 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1982 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001983 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001984 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 }
1987 }
1988
1989 if (out_snd_device == usecase->out_snd_device &&
1990 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301991
1992 if (!force_device_switch(usecase))
1993 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 }
1995
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301996 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1997 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1998 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1999 return 0;
2000 }
2001
sangwoobc677242013-08-08 16:53:43 +09002002 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002003 out_snd_device, platform_get_snd_device_name(out_snd_device),
2004 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 /*
2007 * Limitation: While in call, to do a device switch we need to disable
2008 * and enable both RX and TX devices though one of them is same as current
2009 * device.
2010 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002011 if ((usecase->type == VOICE_CALL) &&
2012 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2013 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002014 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002015 }
2016
2017 if (((usecase->type == VOICE_CALL) ||
2018 (usecase->type == VOIP_CALL)) &&
2019 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2020 /* Disable sidetone only if voice/voip call already exists */
2021 if (voice_is_call_state_active(adev) ||
2022 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002023 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002024
2025 /* Disable aanc only if voice call exists */
2026 if (voice_is_call_state_active(adev))
2027 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002028 }
2029
Zhou Songc66eb7e2017-08-08 18:29:07 +08002030 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302031 (!audio_extn_a2dp_is_ready())) {
2032 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002033 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302034 }
2035
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002036 /* Disable current sound devices */
2037 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002038 disable_audio_route(adev, usecase);
2039 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 }
2041
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002042 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002043 disable_audio_route(adev, usecase);
2044 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 }
2046
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002047 /* Applicable only on the targets that has external modem.
2048 * New device information should be sent to modem before enabling
2049 * the devices to reduce in-call device switch time.
2050 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002051 if ((usecase->type == VOICE_CALL) &&
2052 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2053 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002054 status = platform_switch_voice_call_enable_device_config(adev->platform,
2055 out_snd_device,
2056 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002057 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 /* Enable new sound devices */
2060 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002061 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302062 if (platform_check_codec_asrc_support(adev->platform))
2063 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002064 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 }
2066
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002067 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302068 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002069 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002070 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002071
Avinash Vaish71a8b972014-07-24 15:36:33 +05302072 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002073 status = platform_switch_voice_call_device_post(adev->platform,
2074 out_snd_device,
2075 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302076 enable_audio_route_for_voice_usecases(adev, usecase);
2077 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002078
sangwoo170731f2013-06-08 15:36:36 +09002079 usecase->in_snd_device = in_snd_device;
2080 usecase->out_snd_device = out_snd_device;
2081
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302082 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2083 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302084 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002085 if ((24 == usecase->stream.out->bit_width) &&
2086 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2087 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2088 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2089 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2090 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2091 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2092 /*
2093 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2094 * configured device sample rate, if not update the COPP rate to be equal to the
2095 * device sample rate, else open COPP at stream sample rate
2096 */
2097 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2098 usecase->stream.out->sample_rate,
2099 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302100 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2101 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002102 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2103 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2104 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2105 }
2106
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002107 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002108 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002109 audio_extn_gef_notify_device_config(
2110 usecase->stream.out->devices,
2111 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002112 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002113 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002114 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302115 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002116 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002117
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002118 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002119 /* Enable aanc only if voice call exists */
2120 if (voice_is_call_state_active(adev))
2121 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2122
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002123 /* Enable sidetone only if other voice/voip call already exists */
2124 if (voice_is_call_state_active(adev) ||
2125 voice_extn_compress_voip_is_started(adev))
2126 voice_set_sidetone(adev, out_snd_device, true);
2127 }
2128
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002129 /* Applicable only on the targets that has external modem.
2130 * Enable device command should be sent to modem only after
2131 * enabling voice call mixer controls
2132 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002133 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002134 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2135 out_snd_device,
2136 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302137
2138 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2139
2140 if (usecase->type == VOIP_CALL) {
2141 if (adev->active_input != NULL &&
2142 !adev->active_input->standby) {
2143 if (is_bt_soc_on(adev) == false){
2144 ALOGD("BT SCO MIC disconnected while in connection");
2145 if (adev->active_input->pcm != NULL)
2146 pcm_stop(adev->active_input->pcm);
2147 }
2148 }
2149 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2150 && usecase->stream.out->started) {
2151 if (is_bt_soc_on(adev) == false) {
2152 ALOGD("BT SCO/A2DP disconnected while in connection");
2153 out_standby_l(&usecase->stream.out->stream.common);
2154 }
2155 }
2156 } else if ((usecase->stream.out != NULL) &&
2157 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2158 usecase->stream.out->started) {
2159 if (is_bt_soc_on(adev) == false) {
2160 ALOGD("BT SCO/A2dp disconnected while in connection");
2161 out_standby_l(&usecase->stream.out->stream.common);
2162 }
2163 }
2164 }
2165
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302166 ALOGD("%s: done",__func__);
2167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 return status;
2169}
2170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171static int stop_input_stream(struct stream_in *in)
2172{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302173 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 struct audio_usecase *uc_info;
2175 struct audio_device *adev = in->dev;
2176
Eric Laurent994a6932013-07-17 11:51:42 -07002177 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002178 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 uc_info = get_usecase_from_list(adev, in->usecase);
2180 if (uc_info == NULL) {
2181 ALOGE("%s: Could not find the usecase (%d) in the list",
2182 __func__, in->usecase);
2183 return -EINVAL;
2184 }
2185
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002186 /* Close in-call recording streams */
2187 voice_check_and_stop_incall_rec_usecase(adev, in);
2188
Eric Laurent150dbfe2013-02-27 14:31:02 -08002189 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002190 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002191
2192 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002193 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002195 list_remove(&uc_info->list);
2196 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002198 adev->active_input = get_next_active_input(adev);
2199
Eric Laurent994a6932013-07-17 11:51:42 -07002200 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 return ret;
2202}
2203
2204int start_input_stream(struct stream_in *in)
2205{
2206 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002207 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 struct audio_usecase *uc_info;
2209 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002210 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002211 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212
Mingming Yin2664a5b2015-09-03 10:53:11 -07002213 if (get_usecase_from_list(adev, usecase) == NULL)
2214 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302215 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2216 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002217
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302218 if (CARD_STATUS_OFFLINE == in->card_status||
2219 CARD_STATUS_OFFLINE == adev->card_status) {
2220 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302221 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302222 goto error_config;
2223 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302224
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302225 if (audio_is_bluetooth_sco_device(in->device)) {
2226 if (!adev->bt_sco_on) {
2227 ALOGE("%s: SCO profile is not ready, return error", __func__);
2228 ret = -EIO;
2229 goto error_config;
2230 }
2231 }
2232
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002233 /* Check if source matches incall recording usecase criteria */
2234 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2235 if (ret)
2236 goto error_config;
2237 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002238 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2239
2240 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2241 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2242 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002243 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002244 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002245
Eric Laurentb23d5282013-05-14 15:27:20 -07002246 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 if (in->pcm_device_id < 0) {
2248 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2249 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002250 ret = -EINVAL;
2251 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253
2254 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002256
2257 if (!uc_info) {
2258 ret = -ENOMEM;
2259 goto error_config;
2260 }
2261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 uc_info->id = in->usecase;
2263 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002264 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002265 uc_info->devices = in->device;
2266 uc_info->in_snd_device = SND_DEVICE_NONE;
2267 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002269 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302270 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2271 adev->perf_lock_opts,
2272 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002273 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274
Haynes Mathew George16081042017-05-31 17:16:49 -07002275 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302276 ret = audio_extn_cin_start_input_stream(in);
2277 if (ret)
2278 goto error_open;
2279 else
2280 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002281 }
2282
Haynes Mathew George16081042017-05-31 17:16:49 -07002283 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002284 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002285 ALOGE("%s: pcm stream not ready", __func__);
2286 goto error_open;
2287 }
2288 ret = pcm_start(in->pcm);
2289 if (ret < 0) {
2290 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2291 goto error_open;
2292 }
2293 } else {
2294 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2295 unsigned int pcm_open_retry_count = 0;
2296
2297 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2298 flags |= PCM_MMAP | PCM_NOIRQ;
2299 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2300 } else if (in->realtime) {
2301 flags |= PCM_MMAP | PCM_NOIRQ;
2302 }
2303
Garmond Leunge2433c32017-09-28 21:51:22 -07002304 if (audio_extn_ffv_get_stream() == in) {
2305 ALOGD("%s: ffv stream, update pcm config", __func__);
2306 audio_extn_ffv_update_pcm_config(&config);
2307 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002308 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2309 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2310
2311 while (1) {
2312 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002313 flags, &config);
Haynes Mathew George16081042017-05-31 17:16:49 -07002314 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2315 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2316 if (in->pcm != NULL) {
2317 pcm_close(in->pcm);
2318 in->pcm = NULL;
2319 }
2320 if (pcm_open_retry_count-- == 0) {
2321 ret = -EIO;
2322 goto error_open;
2323 }
2324 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2325 continue;
2326 }
2327 break;
2328 }
2329
2330 ALOGV("%s: pcm_prepare", __func__);
2331 ret = pcm_prepare(in->pcm);
2332 if (ret < 0) {
2333 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2334 pcm_close(in->pcm);
2335 in->pcm = NULL;
2336 goto error_open;
2337 }
2338 register_in_stream(in);
2339 if (in->realtime) {
2340 ret = pcm_start(in->pcm);
2341 if (ret < 0) {
2342 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002343 pcm_close(in->pcm);
2344 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002345 goto error_open;
2346 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002347 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002348 }
2349
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302350done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302351 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002352 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002353
Eric Laurentc8400632013-02-14 19:04:54 -08002354 return ret;
2355
2356error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302357 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002359error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302360 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302361 /*
2362 * sleep 50ms to allow sufficient time for kernel
2363 * drivers to recover incases like SSR.
2364 */
2365 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002366 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002367
2368 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369}
2370
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002371void lock_input_stream(struct stream_in *in)
2372{
2373 pthread_mutex_lock(&in->pre_lock);
2374 pthread_mutex_lock(&in->lock);
2375 pthread_mutex_unlock(&in->pre_lock);
2376}
2377
2378void lock_output_stream(struct stream_out *out)
2379{
2380 pthread_mutex_lock(&out->pre_lock);
2381 pthread_mutex_lock(&out->lock);
2382 pthread_mutex_unlock(&out->pre_lock);
2383}
2384
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385/* must be called with out->lock locked */
2386static int send_offload_cmd_l(struct stream_out* out, int command)
2387{
2388 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2389
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002390 if (!cmd) {
2391 ALOGE("failed to allocate mem for command 0x%x", command);
2392 return -ENOMEM;
2393 }
2394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 ALOGVV("%s %d", __func__, command);
2396
2397 cmd->cmd = command;
2398 list_add_tail(&out->offload_cmd_list, &cmd->node);
2399 pthread_cond_signal(&out->offload_cond);
2400 return 0;
2401}
2402
2403/* must be called iwth out->lock locked */
2404static void stop_compressed_output_l(struct stream_out *out)
2405{
2406 out->offload_state = OFFLOAD_STATE_IDLE;
2407 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002408 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 if (out->compr != NULL) {
2410 compress_stop(out->compr);
2411 while (out->offload_thread_blocked) {
2412 pthread_cond_wait(&out->cond, &out->lock);
2413 }
2414 }
2415}
2416
Varun Balaraje49253e2017-07-06 19:48:56 +05302417bool is_interactive_usecase(audio_usecase_t uc_id)
2418{
2419 unsigned int i;
2420 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2421 if (uc_id == interactive_usecases[i])
2422 return true;
2423 }
2424 return false;
2425}
2426
2427static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2428{
2429 audio_usecase_t ret_uc = USECASE_INVALID;
2430 unsigned int intract_uc_index;
2431 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2432
2433 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2434 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2435 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2436 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2437 ret_uc = interactive_usecases[intract_uc_index];
2438 break;
2439 }
2440 }
2441
2442 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2443 return ret_uc;
2444}
2445
2446static void free_interactive_usecase(struct audio_device *adev,
2447 audio_usecase_t uc_id)
2448{
2449 unsigned int interact_uc_index;
2450 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2451
2452 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2453 if (interactive_usecases[interact_uc_index] == uc_id) {
2454 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2455 break;
2456 }
2457 }
2458 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2459}
2460
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002461bool is_offload_usecase(audio_usecase_t uc_id)
2462{
2463 unsigned int i;
2464 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2465 if (uc_id == offload_usecases[i])
2466 return true;
2467 }
2468 return false;
2469}
2470
Dhananjay Kumarac341582017-02-23 23:42:25 +05302471static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002472{
vivek mehta446c3962015-09-14 10:57:35 -07002473 audio_usecase_t ret_uc = USECASE_INVALID;
2474 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002475 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002476 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302477 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002478 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2479 else
2480 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002481
vivek mehta446c3962015-09-14 10:57:35 -07002482 pthread_mutex_lock(&adev->lock);
2483 if (get_usecase_from_list(adev, ret_uc) != NULL)
2484 ret_uc = USECASE_INVALID;
2485 pthread_mutex_unlock(&adev->lock);
2486
2487 return ret_uc;
2488 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002489
2490 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002491 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2492 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2493 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2494 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002495 break;
2496 }
2497 }
vivek mehta446c3962015-09-14 10:57:35 -07002498
2499 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2500 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002501}
2502
2503static void free_offload_usecase(struct audio_device *adev,
2504 audio_usecase_t uc_id)
2505{
vivek mehta446c3962015-09-14 10:57:35 -07002506 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002507 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002508
2509 if (!adev->multi_offload_enable)
2510 return;
2511
2512 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2513 if (offload_usecases[offload_uc_index] == uc_id) {
2514 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002515 break;
2516 }
2517 }
2518 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2519}
2520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002521static void *offload_thread_loop(void *context)
2522{
2523 struct stream_out *out = (struct stream_out *) context;
2524 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002525 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002527 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2528 set_sched_policy(0, SP_FOREGROUND);
2529 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2530
2531 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002532 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 for (;;) {
2534 struct offload_cmd *cmd = NULL;
2535 stream_callback_event_t event;
2536 bool send_callback = false;
2537
2538 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2539 __func__, list_empty(&out->offload_cmd_list),
2540 out->offload_state);
2541 if (list_empty(&out->offload_cmd_list)) {
2542 ALOGV("%s SLEEPING", __func__);
2543 pthread_cond_wait(&out->offload_cond, &out->lock);
2544 ALOGV("%s RUNNING", __func__);
2545 continue;
2546 }
2547
2548 item = list_head(&out->offload_cmd_list);
2549 cmd = node_to_item(item, struct offload_cmd, node);
2550 list_remove(item);
2551
2552 ALOGVV("%s STATE %d CMD %d out->compr %p",
2553 __func__, out->offload_state, cmd->cmd, out->compr);
2554
2555 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2556 free(cmd);
2557 break;
2558 }
2559
2560 if (out->compr == NULL) {
2561 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002562 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563 pthread_cond_signal(&out->cond);
2564 continue;
2565 }
2566 out->offload_thread_blocked = true;
2567 pthread_mutex_unlock(&out->lock);
2568 send_callback = false;
2569 switch(cmd->cmd) {
2570 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002571 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002573 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 send_callback = true;
2575 event = STREAM_CBK_EVENT_WRITE_READY;
2576 break;
2577 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002578 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302579 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002580 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302581 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002582 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302583 if (ret < 0)
2584 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302585 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302586 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002587 compress_drain(out->compr);
2588 else
2589 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302590 if (ret != -ENETRESET) {
2591 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302592 pthread_mutex_lock(&out->lock);
2593 out->send_new_metadata = 1;
2594 out->send_next_track_params = true;
2595 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302596 event = STREAM_CBK_EVENT_DRAIN_READY;
2597 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2598 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302599 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002600 break;
2601 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002602 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002603 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002604 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002605 send_callback = true;
2606 event = STREAM_CBK_EVENT_DRAIN_READY;
2607 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302608 case OFFLOAD_CMD_ERROR:
2609 ALOGD("copl(%p): sending error callback to AF", out);
2610 send_callback = true;
2611 event = STREAM_CBK_EVENT_ERROR;
2612 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002613 default:
2614 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2615 break;
2616 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002617 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 out->offload_thread_blocked = false;
2619 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002620 if (send_callback && out->client_callback) {
2621 ALOGVV("%s: sending client_callback event %d", __func__, event);
2622 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002623 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 free(cmd);
2625 }
2626
2627 pthread_cond_signal(&out->cond);
2628 while (!list_empty(&out->offload_cmd_list)) {
2629 item = list_head(&out->offload_cmd_list);
2630 list_remove(item);
2631 free(node_to_item(item, struct offload_cmd, node));
2632 }
2633 pthread_mutex_unlock(&out->lock);
2634
2635 return NULL;
2636}
2637
2638static int create_offload_callback_thread(struct stream_out *out)
2639{
2640 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2641 list_init(&out->offload_cmd_list);
2642 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2643 offload_thread_loop, out);
2644 return 0;
2645}
2646
2647static int destroy_offload_callback_thread(struct stream_out *out)
2648{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002649 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002650 stop_compressed_output_l(out);
2651 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2652
2653 pthread_mutex_unlock(&out->lock);
2654 pthread_join(out->offload_thread, (void **) NULL);
2655 pthread_cond_destroy(&out->offload_cond);
2656
2657 return 0;
2658}
2659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660static int stop_output_stream(struct stream_out *out)
2661{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302662 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 struct audio_usecase *uc_info;
2664 struct audio_device *adev = out->dev;
2665
Eric Laurent994a6932013-07-17 11:51:42 -07002666 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002667 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 uc_info = get_usecase_from_list(adev, out->usecase);
2669 if (uc_info == NULL) {
2670 ALOGE("%s: Could not find the usecase (%d) in the list",
2671 __func__, out->usecase);
2672 return -EINVAL;
2673 }
2674
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002675 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302676 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002677 if (adev->visualizer_stop_output != NULL)
2678 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002679
2680 audio_extn_dts_remove_state_notifier_node(out->usecase);
2681
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002682 if (adev->offload_effects_stop_output != NULL)
2683 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2684 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002685
Eric Laurent150dbfe2013-02-27 14:31:02 -08002686 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002687 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002688
2689 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002690 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002692 if (is_offload_usecase(out->usecase)) {
2693 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2694 adev->dsp_bit_width_enforce_mode,
2695 false);
2696 }
2697
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002698 list_remove(&uc_info->list);
2699 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302700 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002701 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302702 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002703 ALOGV("Disable passthrough , reset mixer to pcm");
2704 /* NO_PASSTHROUGH */
2705 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002706 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002707 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2708 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002709
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302710 /* Must be called after removing the usecase from list */
2711 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302712 audio_extn_keep_alive_start();
2713
Manish Dewangan21a850a2017-08-14 12:03:55 +05302714 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002715 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2716 if (ret < 0)
2717 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2718 }
2719
Eric Laurent994a6932013-07-17 11:51:42 -07002720 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 return ret;
2722}
2723
2724int start_output_stream(struct stream_out *out)
2725{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 struct audio_usecase *uc_info;
2728 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002729 char mixer_ctl_name[128];
2730 struct mixer_ctl *ctl = NULL;
2731 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302732 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002734 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2735 ret = -EINVAL;
2736 goto error_config;
2737 }
2738
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302739 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2740 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2741 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302742
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302743 if (CARD_STATUS_OFFLINE == out->card_status ||
2744 CARD_STATUS_OFFLINE == adev->card_status) {
2745 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302746 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302747 goto error_config;
2748 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302749
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302750 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2751 if (!audio_extn_a2dp_is_ready()) {
2752 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302753 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302754 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302755 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2756 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2757 ret = -EAGAIN;
2758 goto error_config;
2759 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302760 }
2761 }
2762 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302763 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2764 if (!adev->bt_sco_on) {
2765 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2766 //combo usecase just by pass a2dp
2767 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2768 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2769 } else {
2770 ALOGE("%s: SCO profile is not ready, return error", __func__);
2771 ret = -EAGAIN;
2772 goto error_config;
2773 }
2774 }
2775 }
2776
Eric Laurentb23d5282013-05-14 15:27:20 -07002777 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 if (out->pcm_device_id < 0) {
2779 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2780 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002781 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002782 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 }
2784
2785 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002786
2787 if (!uc_info) {
2788 ret = -ENOMEM;
2789 goto error_config;
2790 }
2791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 uc_info->id = out->usecase;
2793 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002794 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002795 uc_info->devices = out->devices;
2796 uc_info->in_snd_device = SND_DEVICE_NONE;
2797 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002798 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302800 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2801 adev->perf_lock_opts,
2802 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302803
2804 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2805 audio_extn_keep_alive_stop();
2806 if (audio_extn_passthru_is_enabled() &&
2807 audio_extn_passthru_is_passthrough_stream(out)) {
2808 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302809 }
2810 }
2811
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302812 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2813 (!audio_extn_a2dp_is_ready())) {
2814 if (!a2dp_combo) {
2815 check_a2dp_restore_l(adev, out, false);
2816 } else {
2817 audio_devices_t dev = out->devices;
2818 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2819 select_devices(adev, out->usecase);
2820 out->devices = dev;
2821 }
2822 } else {
2823 select_devices(adev, out->usecase);
2824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002825
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002826 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2827 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002828
2829 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2830 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2831 ALOGE("%s: pcm stream not ready", __func__);
2832 goto error_open;
2833 }
2834 ret = pcm_start(out->pcm);
2835 if (ret < 0) {
2836 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2837 goto error_open;
2838 }
2839 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002840 unsigned int flags = PCM_OUT;
2841 unsigned int pcm_open_retry_count = 0;
2842 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2843 flags |= PCM_MMAP | PCM_NOIRQ;
2844 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002845 } else if (out->realtime) {
2846 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002847 } else
2848 flags |= PCM_MONOTONIC;
2849
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002850 if ((adev->vr_audio_mode_enabled) &&
2851 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2852 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2853 "PCM_Dev %d Topology", out->pcm_device_id);
2854 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2855 if (!ctl) {
2856 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2857 __func__, mixer_ctl_name);
2858 } else {
2859 //if success use ULLPP
2860 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2861 __func__, mixer_ctl_name, out->pcm_device_id);
2862 //There is a still a possibility that some sessions
2863 // that request for FAST|RAW when 3D audio is active
2864 //can go through ULLPP. Ideally we expects apps to
2865 //listen to audio focus and stop concurrent playback
2866 //Also, we will look for mode flag (voice_in_communication)
2867 //before enabling the realtime flag.
2868 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2869 }
2870 }
2871
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002872 while (1) {
2873 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2874 flags, &out->config);
2875 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2876 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2877 if (out->pcm != NULL) {
2878 pcm_close(out->pcm);
2879 out->pcm = NULL;
2880 }
2881 if (pcm_open_retry_count-- == 0) {
2882 ret = -EIO;
2883 goto error_open;
2884 }
2885 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2886 continue;
2887 }
2888 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002890
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002891 ALOGV("%s: pcm_prepare", __func__);
2892 if (pcm_is_ready(out->pcm)) {
2893 ret = pcm_prepare(out->pcm);
2894 if (ret < 0) {
2895 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2896 pcm_close(out->pcm);
2897 out->pcm = NULL;
2898 goto error_open;
2899 }
2900 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302901 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302902 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08002903 // apply volume for voip playback after path is set up
2904 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2905 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002907 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302908 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002909 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2910 adev->dsp_bit_width_enforce_mode,
2911 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002913 out->compr = compress_open(adev->snd_card,
2914 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 COMPRESS_IN, &out->compr_config);
2916 if (out->compr && !is_compress_ready(out->compr)) {
2917 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2918 compress_close(out->compr);
2919 out->compr = NULL;
2920 ret = -EIO;
2921 goto error_open;
2922 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302923 /* compress_open sends params of the track, so reset the flag here */
2924 out->is_compr_metadata_avail = false;
2925
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002926 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002928
Fred Oh3f43e742015-03-04 18:42:34 -08002929 /* Since small bufs uses blocking writes, a write will be blocked
2930 for the default max poll time (20s) in the event of an SSR.
2931 Reduce the poll time to observe and deal with SSR faster.
2932 */
Ashish Jain5106d362016-05-11 19:23:33 +05302933 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002934 compress_set_max_poll_wait(out->compr, 1000);
2935 }
2936
Manish Dewangan69426c82017-01-30 17:35:36 +05302937 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302938 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302939
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002940 audio_extn_dts_create_state_notifier_node(out->usecase);
2941 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2942 popcount(out->channel_mask),
2943 out->playback_started);
2944
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002945#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05302946 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002947 audio_extn_dolby_send_ddp_endp_params(adev);
2948#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302949 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2950 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002951 if (adev->visualizer_start_output != NULL)
2952 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2953 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302954 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002955 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002956 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002958
2959 if (ret == 0) {
2960 register_out_stream(out);
2961 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07002962 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2963 ALOGE("%s: pcm stream not ready", __func__);
2964 goto error_open;
2965 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002966 ret = pcm_start(out->pcm);
2967 if (ret < 0)
2968 goto error_open;
2969 }
2970 }
2971
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302972 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002973 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002974
Manish Dewangan21a850a2017-08-14 12:03:55 +05302975 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002976 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002977 if (ret < 0)
2978 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2979 }
2980
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002981 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302983 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002985error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302986 /*
2987 * sleep 50ms to allow sufficient time for kernel
2988 * drivers to recover incases like SSR.
2989 */
2990 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002991 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992}
2993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994static int check_input_parameters(uint32_t sample_rate,
2995 audio_format_t format,
2996 int channel_count)
2997{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002998 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303000 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3001 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3002 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003003 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003004 !audio_extn_compr_cap_format_supported(format))
3005 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003006
3007 switch (channel_count) {
3008 case 1:
3009 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303010 case 3:
3011 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003012 case 6:
3013 break;
3014 default:
3015 ret = -EINVAL;
3016 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017
3018 switch (sample_rate) {
3019 case 8000:
3020 case 11025:
3021 case 12000:
3022 case 16000:
3023 case 22050:
3024 case 24000:
3025 case 32000:
3026 case 44100:
3027 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303028 case 96000:
3029 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 break;
3031 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003032 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 }
3034
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003035 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036}
3037
3038static size_t get_input_buffer_size(uint32_t sample_rate,
3039 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003040 int channel_count,
3041 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042{
3043 size_t size = 0;
3044
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003045 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3046 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003048 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003049 if (is_low_latency)
3050 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303051
3052 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003054 /* make sure the size is multiple of 32 bytes
3055 * At 48 kHz mono 16-bit PCM:
3056 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3057 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3058 */
3059 size += 0x1f;
3060 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003061
3062 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063}
3064
Ashish Jain058165c2016-09-28 23:18:48 +05303065static size_t get_output_period_size(uint32_t sample_rate,
3066 audio_format_t format,
3067 int channel_count,
3068 int duration /*in millisecs*/)
3069{
3070 size_t size = 0;
3071 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3072
3073 if ((duration == 0) || (sample_rate == 0) ||
3074 (bytes_per_sample == 0) || (channel_count == 0)) {
3075 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3076 bytes_per_sample, channel_count);
3077 return -EINVAL;
3078 }
3079
3080 size = (sample_rate *
3081 duration *
3082 bytes_per_sample *
3083 channel_count) / 1000;
3084 /*
3085 * To have same PCM samples for all channels, the buffer size requires to
3086 * be multiple of (number of channels * bytes per sample)
3087 * For writes to succeed, the buffer must be written at address which is multiple of 32
3088 */
3089 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3090
3091 return (size/(channel_count * bytes_per_sample));
3092}
3093
Ashish Jain5106d362016-05-11 19:23:33 +05303094static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
3095{
3096 uint64_t actual_frames_rendered = 0;
3097 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3098
3099 /* This adjustment accounts for buffering after app processor.
3100 * It is based on estimated DSP latency per use case, rather than exact.
3101 */
3102 int64_t platform_latency = platform_render_latency(out->usecase) *
3103 out->sample_rate / 1000000LL;
3104
3105 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3106 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3107 * hence only estimate.
3108 */
3109 int64_t signed_frames = out->written - kernel_buffer_size;
3110
3111 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3112
3113 if (signed_frames > 0)
3114 actual_frames_rendered = signed_frames;
3115
3116 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3117 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3118 (long long int)out->written, (int)kernel_buffer_size,
3119 audio_bytes_per_sample(out->compr_config.codec->format),
3120 popcount(out->channel_mask));
3121
3122 return actual_frames_rendered;
3123}
3124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3126{
3127 struct stream_out *out = (struct stream_out *)stream;
3128
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130}
3131
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003132static int out_set_sample_rate(struct audio_stream *stream __unused,
3133 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134{
3135 return -ENOSYS;
3136}
3137
3138static size_t out_get_buffer_size(const struct audio_stream *stream)
3139{
3140 struct stream_out *out = (struct stream_out *)stream;
3141
Varun Balaraje49253e2017-07-06 19:48:56 +05303142 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303143 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303144 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303145 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3146 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3147 else
3148 return out->compr_config.fragment_size;
3149 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003150 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003151 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3152 return VOIP_IO_BUF_SIZE(out->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Dhananjay Kumarac341582017-02-23 23:42:25 +05303153 else if (is_offload_usecase(out->usecase) &&
3154 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303155 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003156
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003157 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003158 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159}
3160
3161static uint32_t out_get_channels(const struct audio_stream *stream)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164
3165 return out->channel_mask;
3166}
3167
3168static audio_format_t out_get_format(const struct audio_stream *stream)
3169{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 struct stream_out *out = (struct stream_out *)stream;
3171
3172 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173}
3174
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003175static int out_set_format(struct audio_stream *stream __unused,
3176 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177{
3178 return -ENOSYS;
3179}
3180
3181static int out_standby(struct audio_stream *stream)
3182{
3183 struct stream_out *out = (struct stream_out *)stream;
3184 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003185 struct audio_usecase *uc_info;
3186 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003187 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003188
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303189 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3190 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003192 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003194 if (adev->adm_deregister_stream)
3195 adev->adm_deregister_stream(adev->adm_data, out->handle);
3196
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003197 if (is_offload_usecase(out->usecase))
3198 stop_compressed_output_l(out);
3199
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003200 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003202 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3203 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303204 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003205 pthread_mutex_unlock(&adev->lock);
3206 pthread_mutex_unlock(&out->lock);
3207 ALOGD("VOIP output entered standby");
3208 return 0;
3209 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003210 if (out->pcm) {
3211 pcm_close(out->pcm);
3212 out->pcm = NULL;
3213 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003214 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3215 do_stop = out->playback_started;
3216 out->playback_started = false;
3217 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003218 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003219 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303220 out->send_next_track_params = false;
3221 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003222 out->gapless_mdata.encoder_delay = 0;
3223 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003224 if (out->compr != NULL) {
3225 compress_close(out->compr);
3226 out->compr = NULL;
3227 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003228 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 if (do_stop) {
3230 stop_output_stream(out);
3231 }
kunleiza9d11682017-08-04 14:14:09 +08003232 //restore output device for active usecase when current snd device and output device mismatch
3233 list_for_each(node, &adev->usecase_list) {
3234 uc_info = node_to_item(node, struct audio_usecase, list);
3235 if ((uc_info->type == PCM_PLAYBACK) &&
3236 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3237 select_devices(adev, uc_info->id);
3238 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003239 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 }
3241 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303242 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 return 0;
3244}
3245
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303246static int out_on_error(struct audio_stream *stream)
3247{
3248 struct stream_out *out = (struct stream_out *)stream;
3249 bool do_standby = false;
3250
3251 lock_output_stream(out);
3252 if (!out->standby) {
3253 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3254 stop_compressed_output_l(out);
3255 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3256 } else
3257 do_standby = true;
3258 }
3259 pthread_mutex_unlock(&out->lock);
3260
3261 if (do_standby)
3262 return out_standby(&out->stream.common);
3263
3264 return 0;
3265}
3266
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303267/*
3268 *standby implementation without locks, assumes that the callee already
3269 *has taken adev and out lock.
3270 */
3271int out_standby_l(struct audio_stream *stream)
3272{
3273 struct stream_out *out = (struct stream_out *)stream;
3274 struct audio_device *adev = out->dev;
3275
3276 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3277 stream, out->usecase, use_case_table[out->usecase]);
3278
3279 if (!out->standby) {
3280 if (adev->adm_deregister_stream)
3281 adev->adm_deregister_stream(adev->adm_data, out->handle);
3282
3283 if (is_offload_usecase(out->usecase))
3284 stop_compressed_output_l(out);
3285
3286 out->standby = true;
3287 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3288 voice_extn_compress_voip_close_output_stream(stream);
3289 out->started = 0;
3290 ALOGD("VOIP output entered standby");
3291 return 0;
3292 } else if (!is_offload_usecase(out->usecase)) {
3293 if (out->pcm) {
3294 pcm_close(out->pcm);
3295 out->pcm = NULL;
3296 }
3297 } else {
3298 ALOGD("copl(%p):standby", out);
3299 out->send_next_track_params = false;
3300 out->is_compr_metadata_avail = false;
3301 out->gapless_mdata.encoder_delay = 0;
3302 out->gapless_mdata.encoder_padding = 0;
3303 if (out->compr != NULL) {
3304 compress_close(out->compr);
3305 out->compr = NULL;
3306 }
3307 }
3308 stop_output_stream(out);
3309 }
3310 ALOGD("%s: exit", __func__);
3311 return 0;
3312}
3313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003314static int out_dump(const struct audio_stream *stream __unused,
3315 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return 0;
3318}
3319
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003320static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3321{
3322 int ret = 0;
3323 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003324
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003325 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003326 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003327 return -EINVAL;
3328 }
3329
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303330 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003331
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003332 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3333 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303334 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003335 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003336 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3337 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303338 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003339 }
3340
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003341 ALOGV("%s new encoder delay %u and padding %u", __func__,
3342 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3343
3344 return 0;
3345}
3346
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003347static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3348{
3349 return out == adev->primary_output || out == adev->voice_tx_output;
3350}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003351
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303352// note: this call is safe only if the stream_cb is
3353// removed first in close_output_stream (as is done now).
3354static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3355{
3356 if (!stream || !parms)
3357 return;
3358
3359 struct stream_out *out = (struct stream_out *)stream;
3360 struct audio_device *adev = out->dev;
3361
3362 card_status_t status;
3363 int card;
3364 if (parse_snd_card_status(parms, &card, &status) < 0)
3365 return;
3366
3367 pthread_mutex_lock(&adev->lock);
3368 bool valid_cb = (card == adev->snd_card);
3369 pthread_mutex_unlock(&adev->lock);
3370
3371 if (!valid_cb)
3372 return;
3373
3374 lock_output_stream(out);
3375 if (out->card_status != status)
3376 out->card_status = status;
3377 pthread_mutex_unlock(&out->lock);
3378
3379 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3380 use_case_table[out->usecase],
3381 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3382
3383 if (status == CARD_STATUS_OFFLINE)
3384 out_on_error(stream);
3385
3386 return;
3387}
3388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3390{
3391 struct stream_out *out = (struct stream_out *)stream;
3392 struct audio_device *adev = out->dev;
3393 struct str_parms *parms;
3394 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003395 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303396 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397
sangwoobc677242013-08-08 16:53:43 +09003398 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003399 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303401 if (!parms)
3402 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003403 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3404 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003406 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003407 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003409 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003410 * When HDMI cable is unplugged the music playback is paused and
3411 * the policy manager sends routing=0. But the audioflinger continues
3412 * to write data until standby time (3sec). As the HDMI core is
3413 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003414 * Avoid this by routing audio to speaker until standby.
3415 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003416 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3417 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303418 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003419 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3420 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003421 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303422 /*
3423 * When A2DP is disconnected the
3424 * music playback is paused and the policy manager sends routing=0
3425 * But the audioflingercontinues to write data until standby time
3426 * (3sec). As BT is turned off, the write gets blocked.
3427 * Avoid this by routing audio to speaker until standby.
3428 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003429 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303430 (val == AUDIO_DEVICE_NONE)) {
3431 val = AUDIO_DEVICE_OUT_SPEAKER;
3432 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303433 /* To avoid a2dp to sco overlapping / BT device improper state
3434 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303435 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303436 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3437 if (!audio_extn_a2dp_is_ready()) {
3438 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3439 //combo usecase just by pass a2dp
3440 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303441 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303442 } else {
3443 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3444 /* update device to a2dp and don't route as BT returned error
3445 * However it is still possible a2dp routing called because
3446 * of current active device disconnection (like wired headset)
3447 */
3448 out->devices = val;
3449 pthread_mutex_unlock(&out->lock);
3450 pthread_mutex_unlock(&adev->lock);
3451 goto error;
3452 }
3453 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303454 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003455 /*
3456 * select_devices() call below switches all the usecases on the same
3457 * backend to the new device. Refer to check_usecases_codec_backend() in
3458 * the select_devices(). But how do we undo this?
3459 *
3460 * For example, music playback is active on headset (deep-buffer usecase)
3461 * and if we go to ringtones and select a ringtone, low-latency usecase
3462 * will be started on headset+speaker. As we can't enable headset+speaker
3463 * and headset devices at the same time, select_devices() switches the music
3464 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3465 * So when the ringtone playback is completed, how do we undo the same?
3466 *
3467 * We are relying on the out_set_parameters() call on deep-buffer output,
3468 * once the ringtone playback is ended.
3469 * NOTE: We should not check if the current devices are same as new devices.
3470 * Because select_devices() must be called to switch back the music
3471 * playback to headset.
3472 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003473 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003474 audio_devices_t new_dev = val;
3475 bool same_dev = out->devices == new_dev;
3476 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003477
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003478 if (output_drives_call(adev, out)) {
3479 if(!voice_is_in_call(adev)) {
3480 if (adev->mode == AUDIO_MODE_IN_CALL) {
3481 adev->current_call_output = out;
3482 ret = voice_start_call(adev);
3483 }
3484 } else {
3485 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003486 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003487 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003488 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003489
3490 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003491 if (!same_dev) {
3492 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303493 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3494 adev->perf_lock_opts,
3495 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003496 if (adev->adm_on_routing_change)
3497 adev->adm_on_routing_change(adev->adm_data,
3498 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003499 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303500 if (!bypass_a2dp) {
3501 select_devices(adev, out->usecase);
3502 } else {
3503 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3504 select_devices(adev, out->usecase);
3505 out->devices = new_dev;
3506 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303507 if (!same_dev)
3508 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303509 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3510 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003511 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303512 pthread_mutex_lock(&out->compr_mute_lock);
3513 out->a2dp_compress_mute = false;
3514 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3515 pthread_mutex_unlock(&out->compr_mute_lock);
3516 }
3517
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003518 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003519 }
3520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003522 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003524
3525 if (out == adev->primary_output) {
3526 pthread_mutex_lock(&adev->lock);
3527 audio_extn_set_parameters(adev, parms);
3528 pthread_mutex_unlock(&adev->lock);
3529 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003530 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003531 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003532 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003533
3534 audio_extn_dts_create_state_notifier_node(out->usecase);
3535 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3536 popcount(out->channel_mask),
3537 out->playback_started);
3538
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003539 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003540 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003541
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303542 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3543 if (err >= 0) {
3544 strlcpy(out->profile, value, sizeof(out->profile));
3545 ALOGV("updating stream profile with value '%s'", out->profile);
3546 lock_output_stream(out);
3547 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3548 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003549 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303550 out->sample_rate, out->bit_width,
3551 out->channel_mask, out->profile,
3552 &out->app_type_cfg);
3553 pthread_mutex_unlock(&out->lock);
3554 }
3555
Alexy Joseph98988832017-01-13 14:56:59 -08003556 //suspend, resume handling block
3557 if (out->dynamic_pm_qos_enabled) {
3558 //check suspend parameter only for low latency and if the property
3559 //is enabled
3560 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3561 ALOGI("%s: got suspend_playback %s", __func__, value);
3562 lock_output_stream(out);
3563 if (!strncmp(value, "false", 5)) {
3564 //suspend_playback=false is supposed to set QOS value back to 75%
3565 //the mixer control sent with value Enable will achieve that
3566 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3567 } else if (!strncmp (value, "true", 4)) {
3568 //suspend_playback=true is supposed to remove QOS value
3569 //resetting the mixer control will set the default value
3570 //for the mixer control which is Disable and this removes the QOS vote
3571 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3572 } else {
3573 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3574 " got %s", __func__, value);
3575 ret = -1;
3576 }
3577
3578 if (ret != 0) {
3579 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3580 __func__, out->pm_qos_mixer_path, ret);
3581 }
3582
3583 pthread_mutex_unlock(&out->lock);
3584 }
3585 }
3586 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303588error:
Eric Laurent994a6932013-07-17 11:51:42 -07003589 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 return ret;
3591}
3592
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003593static bool stream_get_parameter_channels(struct str_parms *query,
3594 struct str_parms *reply,
3595 audio_channel_mask_t *supported_channel_masks) {
3596 int ret = -1;
3597 char value[512];
3598 bool first = true;
3599 size_t i, j;
3600
3601 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3602 ret = 0;
3603 value[0] = '\0';
3604 i = 0;
3605 while (supported_channel_masks[i] != 0) {
3606 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3607 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
3608 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303609 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003610
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303611 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003612 first = false;
3613 break;
3614 }
3615 }
3616 i++;
3617 }
3618 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3619 }
3620 return ret == 0;
3621}
3622
3623static bool stream_get_parameter_formats(struct str_parms *query,
3624 struct str_parms *reply,
3625 audio_format_t *supported_formats) {
3626 int ret = -1;
3627 char value[256];
3628 size_t i, j;
3629 bool first = true;
3630
3631 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3632 ret = 0;
3633 value[0] = '\0';
3634 i = 0;
3635 while (supported_formats[i] != 0) {
3636 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3637 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
3638 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303639 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003640 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303641 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003642 first = false;
3643 break;
3644 }
3645 }
3646 i++;
3647 }
3648 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
3649 }
3650 return ret == 0;
3651}
3652
3653static bool stream_get_parameter_rates(struct str_parms *query,
3654 struct str_parms *reply,
3655 uint32_t *supported_sample_rates) {
3656
3657 int i;
3658 char value[256];
3659 int ret = -1;
3660 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3661 ret = 0;
3662 value[0] = '\0';
3663 i=0;
3664 int cursor = 0;
3665 while (supported_sample_rates[i]) {
3666 int avail = sizeof(value) - cursor;
3667 ret = snprintf(value + cursor, avail, "%s%d",
3668 cursor > 0 ? "|" : "",
3669 supported_sample_rates[i]);
3670 if (ret < 0 || ret >= avail) {
3671 // if cursor is at the last element of the array
3672 // overwrite with \0 is duplicate work as
3673 // snprintf already put a \0 in place.
3674 // else
3675 // we had space to write the '|' at value[cursor]
3676 // (which will be overwritten) or no space to fill
3677 // the first element (=> cursor == 0)
3678 value[cursor] = '\0';
3679 break;
3680 }
3681 cursor += ret;
3682 ++i;
3683 }
3684 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3685 value);
3686 }
3687 return ret >= 0;
3688}
3689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3691{
3692 struct stream_out *out = (struct stream_out *)stream;
3693 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003694 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 char value[256];
3696 struct str_parms *reply = str_parms_create();
3697 size_t i, j;
3698 int ret;
3699 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003700
3701 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003702 if (reply) {
3703 str_parms_destroy(reply);
3704 }
3705 if (query) {
3706 str_parms_destroy(query);
3707 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003708 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3709 return NULL;
3710 }
3711
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003712 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3714 if (ret >= 0) {
3715 value[0] = '\0';
3716 i = 0;
3717 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003718 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3719 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003721 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003723 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 first = false;
3725 break;
3726 }
3727 }
3728 i++;
3729 }
3730 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3731 str = str_parms_to_str(reply);
3732 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003733 voice_extn_out_get_parameters(out, query, reply);
3734 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003736
Alexy Joseph62142aa2015-11-16 15:10:34 -08003737
3738 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3739 if (ret >= 0) {
3740 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303741 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3742 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003743 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303744 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003745 } else {
3746 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303747 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003748 }
3749 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003750 if (str)
3751 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003752 str = str_parms_to_str(reply);
3753 }
3754
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003755 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3756 if (ret >= 0) {
3757 value[0] = '\0';
3758 i = 0;
3759 first = true;
3760 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003761 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3762 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003763 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003764 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003765 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003766 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003767 first = false;
3768 break;
3769 }
3770 }
3771 i++;
3772 }
3773 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003774 if (str)
3775 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003776 str = str_parms_to_str(reply);
3777 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003778
3779 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3780 if (ret >= 0) {
3781 value[0] = '\0';
3782 i = 0;
3783 first = true;
3784 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003785 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
3786 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003787 if (!first) {
3788 strlcat(value, "|", sizeof(value));
3789 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003790 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08003791 first = false;
3792 break;
3793 }
3794 }
3795 i++;
3796 }
3797 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3798 if (str)
3799 free(str);
3800 str = str_parms_to_str(reply);
3801 }
3802
Alexy Joseph98988832017-01-13 14:56:59 -08003803 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3804 //only low latency track supports suspend_resume
3805 str_parms_add_int(reply, "supports_hw_suspend",
3806 (out->dynamic_pm_qos_enabled));
3807 if (str)
3808 free(str);
3809 str = str_parms_to_str(reply);
3810 }
3811
3812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 str_parms_destroy(query);
3814 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003815 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 return str;
3817}
3818
3819static uint32_t out_get_latency(const struct audio_stream_out *stream)
3820{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003821 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003823 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824
Alexy Josephaa54c872014-12-03 02:46:47 -08003825 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303826 lock_output_stream(out);
3827 latency = audio_extn_utils_compress_get_dsp_latency(out);
3828 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003829 } else if ((out->realtime) ||
3830 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003831 // since the buffer won't be filled up faster than realtime,
3832 // return a smaller number
3833 if (out->config.rate)
3834 period_ms = (out->af_period_multiplier * out->config.period_size *
3835 1000) / (out->config.rate);
3836 else
3837 period_ms = 0;
3838 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003839 } else {
3840 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003841 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003842 }
3843
yidongh0515e042017-07-06 15:00:34 +08003844 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003845 latency += audio_extn_a2dp_get_encoder_latency();
3846
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303847 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003848 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849}
3850
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303851static float AmpToDb(float amplification)
3852{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303853 float db = DSD_VOLUME_MIN_DB;
3854 if (amplification > 0) {
3855 db = 20 * log10(amplification);
3856 if(db < DSD_VOLUME_MIN_DB)
3857 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303858 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303859 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303860}
3861
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303862static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3863 float right)
3864{
3865 struct stream_out *out = (struct stream_out *)stream;
3866 int volume[2];
3867 char mixer_ctl_name[128];
3868 struct audio_device *adev = out->dev;
3869 struct mixer_ctl *ctl;
3870 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3871 PCM_PLAYBACK);
3872
3873 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3874 "Compress Playback %d Volume", pcm_device_id);
3875 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3876 if (!ctl) {
3877 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3878 __func__, mixer_ctl_name);
3879 return -EINVAL;
3880 }
3881 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3882 __func__, mixer_ctl_name, left, right);
3883 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3884 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3885 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3886
3887 return 0;
3888}
3889
Zhou Song2b8f28f2017-09-11 10:51:38 +08003890static int out_set_voip_volume(struct audio_stream_out *stream, float left,
3891 float right)
3892{
3893 struct stream_out *out = (struct stream_out *)stream;
3894 char mixer_ctl_name[] = "App Type Gain";
3895 struct audio_device *adev = out->dev;
3896 struct mixer_ctl *ctl;
3897 uint32_t set_values[4];
3898
3899 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3900 if (!ctl) {
3901 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3902 __func__, mixer_ctl_name);
3903 return -EINVAL;
3904 }
3905
3906 set_values[0] = 0; //0: Rx Session 1:Tx Session
3907 set_values[1] = out->app_type_cfg.app_type;
3908 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3909 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3910
3911 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3912 return 0;
3913}
3914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915static int out_set_volume(struct audio_stream_out *stream, float left,
3916 float right)
3917{
Eric Laurenta9024de2013-04-04 09:19:12 -07003918 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003919 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303920 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003921
Eric Laurenta9024de2013-04-04 09:19:12 -07003922 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3923 /* only take left channel into account: the API is for stereo anyway */
3924 out->muted = (left == 0.0f);
3925 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003926 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303927 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003928 /*
3929 * Set mute or umute on HDMI passthrough stream.
3930 * Only take left channel into account.
3931 * Mute is 0 and unmute 1
3932 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303933 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303934 } else if (out->format == AUDIO_FORMAT_DSD){
3935 char mixer_ctl_name[128] = "DSD Volume";
3936 struct audio_device *adev = out->dev;
3937 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3938
3939 if (!ctl) {
3940 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3941 __func__, mixer_ctl_name);
3942 return -EINVAL;
3943 }
3944 volume[0] = (int)(AmpToDb(left));
3945 volume[1] = (int)(AmpToDb(right));
3946 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3947 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003948 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303949 pthread_mutex_lock(&out->compr_mute_lock);
3950 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3951 if (!out->a2dp_compress_mute)
3952 ret = out_set_compr_volume(stream, left, right);
3953 out->volume_l = left;
3954 out->volume_r = right;
3955 pthread_mutex_unlock(&out->compr_mute_lock);
3956 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003957 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003958 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08003959 if (!out->standby)
3960 ret = out_set_voip_volume(stream, left, right);
3961 out->volume_l = left;
3962 out->volume_r = right;
3963 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07003964 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 return -ENOSYS;
3967}
3968
Zhou Songc9672822017-08-16 16:01:39 +08003969static void update_frames_written(struct stream_out *out, size_t bytes)
3970{
3971 size_t bpf = 0;
3972
3973 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3974 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3975 bpf = 1;
3976 else if (!is_offload_usecase(out->usecase))
3977 bpf = audio_bytes_per_sample(out->format) *
3978 audio_channel_count_from_out_mask(out->channel_mask);
3979 if (bpf != 0)
3980 out->written += bytes / bpf;
3981}
3982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3984 size_t bytes)
3985{
3986 struct stream_out *out = (struct stream_out *)stream;
3987 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003988 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303989 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003991 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303992
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303993 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003994
Dhananjay Kumarac341582017-02-23 23:42:25 +05303995 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303996 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303997 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3998 pthread_mutex_unlock(&out->lock);
3999 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304000 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304001 ALOGD(" %s: sound card is not active/SSR state", __func__);
4002 ret= -EIO;
4003 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304004 }
4005 }
4006
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304007 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304008 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304009 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304010 goto exit;
4011 }
4012
Haynes Mathew George16081042017-05-31 17:16:49 -07004013 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4014 ret = -EINVAL;
4015 goto exit;
4016 }
4017
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304018 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4019 !out->is_iec61937_info_available) {
4020
4021 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4022 out->is_iec61937_info_available = true;
4023 } else if (audio_extn_passthru_is_enabled()) {
4024 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304025 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304026
4027 if((out->format == AUDIO_FORMAT_DTS) ||
4028 (out->format == AUDIO_FORMAT_DTS_HD)) {
4029 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4030 buffer, bytes);
4031 if (ret) {
4032 if (ret != -ENOSYS) {
4033 out->is_iec61937_info_available = false;
4034 ALOGD("iec61937 transmission info not yet updated retry");
4035 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304036 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304037 /* if stream has started and after that there is
4038 * stream config change (iec transmission config)
4039 * then trigger select_device to update backend configuration.
4040 */
4041 out->stream_config_changed = true;
4042 pthread_mutex_lock(&adev->lock);
4043 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304044 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4045 ret = -EINVAL;
4046 goto exit;
4047 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304048 pthread_mutex_unlock(&adev->lock);
4049 out->stream_config_changed = false;
4050 out->is_iec61937_info_available = true;
4051 }
4052 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304053
Garmond Leung317cbf12017-09-13 16:20:50 -07004054 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304055 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4056 (out->is_iec61937_info_available == true)) {
4057 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4058 ret = -EINVAL;
4059 goto exit;
4060 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304061 }
4062 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304063
4064 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4065 (audio_extn_a2dp_is_suspended())) {
4066 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4067 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304068 ret = -EIO;
4069 goto exit;
4070 }
4071 }
4072 }
4073
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004075 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004076 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004077 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4078 ret = voice_extn_compress_voip_start_output_stream(out);
4079 else
4080 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004081 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004082 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004084 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 goto exit;
4086 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304087 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004088 if (last_known_cal_step != -1) {
4089 ALOGD("%s: retry previous failed cal level set", __func__);
4090 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304091 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004092 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304093
4094 if ((out->is_iec61937_info_available == true) &&
4095 (audio_extn_passthru_is_passthrough_stream(out))&&
4096 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4097 ret = -EINVAL;
4098 goto exit;
4099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101
Ashish Jain81eb2a82015-05-13 10:52:34 +05304102 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004103 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304104 adev->is_channel_status_set = true;
4105 }
4106
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004107 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004108 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004109 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004110 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004111 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4112 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304113 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4114 ALOGD("copl(%p):send next track params in gapless", out);
4115 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4116 out->send_next_track_params = false;
4117 out->is_compr_metadata_avail = false;
4118 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004119 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304120 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304121 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004122
Ashish Jain83a6cc22016-06-28 14:34:17 +05304123 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304124 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304125 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304126 pthread_mutex_unlock(&out->lock);
4127 return -EINVAL;
4128 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304129 audio_format_t dst_format = out->hal_op_format;
4130 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304131
4132 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4133 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4134
Ashish Jain83a6cc22016-06-28 14:34:17 +05304135 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304136 dst_format,
4137 buffer,
4138 src_format,
4139 frames);
4140
Ashish Jain83a6cc22016-06-28 14:34:17 +05304141 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304142 bytes_to_write);
4143
4144 /*Convert written bytes in audio flinger format*/
4145 if (ret > 0)
4146 ret = ((ret * format_to_bitwidth_table[out->format]) /
4147 format_to_bitwidth_table[dst_format]);
4148 }
4149 } else
4150 ret = compress_write(out->compr, buffer, bytes);
4151
Zhou Songc9672822017-08-16 16:01:39 +08004152 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4153 update_frames_written(out, bytes);
4154
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304155 if (ret < 0)
4156 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304157 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304158 /*msg to cb thread only if non blocking write is enabled*/
4159 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304160 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004161 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304162 } else if (-ENETRESET == ret) {
4163 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304164 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304165 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304166 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05304167 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004168 }
Ashish Jain5106d362016-05-11 19:23:33 +05304169
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304170 /* Call compr start only when non-zero bytes of data is there to be rendered */
4171 if (!out->playback_started && ret > 0) {
4172 int status = compress_start(out->compr);
4173 if (status < 0) {
4174 ret = status;
4175 ALOGE("%s: compr start failed with err %d", __func__, errno);
4176 goto exit;
4177 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004178 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004179 out->playback_started = 1;
4180 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004181
4182 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4183 popcount(out->channel_mask),
4184 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004185 }
4186 pthread_mutex_unlock(&out->lock);
4187 return ret;
4188 } else {
4189 if (out->pcm) {
4190 if (out->muted)
4191 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004192
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304193 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004194
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004195 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004196
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004197 if (out->config.rate)
4198 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4199 out->config.rate;
4200
4201 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4202
4203 request_out_focus(out, ns);
4204
4205 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004206 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004207 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304208 out->convert_buffer != NULL) {
4209
4210 memcpy_by_audio_format(out->convert_buffer,
4211 out->hal_op_format,
4212 buffer,
4213 out->hal_ip_format,
4214 out->config.period_size * out->config.channels);
4215
4216 ret = pcm_write(out->pcm, out->convert_buffer,
4217 (out->config.period_size *
4218 out->config.channels *
4219 format_to_bitwidth_table[out->hal_op_format]));
4220 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304221 /*
4222 * To avoid underrun in DSP when the application is not pumping
4223 * data at required rate, check for the no. of bytes and ignore
4224 * pcm_write if it is less than actual buffer size.
4225 * It is a work around to a change in compress VOIP driver.
4226 */
4227 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4228 bytes < (out->config.period_size * out->config.channels *
4229 audio_bytes_per_sample(out->format))) {
4230 size_t voip_buf_size =
4231 out->config.period_size * out->config.channels *
4232 audio_bytes_per_sample(out->format);
4233 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4234 __func__, bytes, voip_buf_size);
4235 usleep(((uint64_t)voip_buf_size - bytes) *
4236 1000000 / audio_stream_out_frame_size(stream) /
4237 out_get_sample_rate(&out->stream.common));
4238 ret = 0;
4239 } else
4240 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304241 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004242
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004243 release_out_focus(out);
4244
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304245 if (ret < 0)
4246 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004247 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304248 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 }
4251
4252exit:
Zhou Songc9672822017-08-16 16:01:39 +08004253 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304254 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304255 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304256 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257 pthread_mutex_unlock(&out->lock);
4258
4259 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004260 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004261 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304262 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304263 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304264 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304265 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304266 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304267 out->standby = true;
4268 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304269 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304270 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4271 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4272 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004273
4274 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07004275 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004276 return ret;
4277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278 }
4279 return bytes;
4280}
4281
4282static int out_get_render_position(const struct audio_stream_out *stream,
4283 uint32_t *dsp_frames)
4284{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004285 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004286
4287 if (dsp_frames == NULL)
4288 return -EINVAL;
4289
4290 *dsp_frames = 0;
4291 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004292 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304293
4294 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4295 * this operation and adev_close_output_stream(where out gets reset).
4296 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304297 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304298 *dsp_frames = get_actual_pcm_frames_rendered(out);
4299 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4300 return 0;
4301 }
4302
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004303 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304304 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304305 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004306 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304307 if (ret < 0)
4308 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004309 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304310 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004311 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304312 if (-ENETRESET == ret) {
4313 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304314 out->card_status = CARD_STATUS_OFFLINE;
4315 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304316 } else if(ret < 0) {
4317 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304318 ret = -EINVAL;
4319 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304320 /*
4321 * Handle corner case where compress session is closed during SSR
4322 * and timestamp is queried
4323 */
4324 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304325 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304326 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304327 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304328 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304329 pthread_mutex_unlock(&out->lock);
4330 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004331 } else if (audio_is_linear_pcm(out->format)) {
4332 *dsp_frames = out->written;
4333 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004334 } else
4335 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336}
4337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004338static int out_add_audio_effect(const struct audio_stream *stream __unused,
4339 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340{
4341 return 0;
4342}
4343
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004344static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4345 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346{
4347 return 0;
4348}
4349
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004350static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4351 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304353 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354}
4355
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004356static int out_get_presentation_position(const struct audio_stream_out *stream,
4357 uint64_t *frames, struct timespec *timestamp)
4358{
4359 struct stream_out *out = (struct stream_out *)stream;
4360 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004361 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004362
Ashish Jain5106d362016-05-11 19:23:33 +05304363 /* below piece of code is not guarded against any lock because audioFliner serializes
4364 * this operation and adev_close_output_stream( where out gets reset).
4365 */
4366 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304367 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304368 *frames = get_actual_pcm_frames_rendered(out);
4369 /* this is the best we can do */
4370 clock_gettime(CLOCK_MONOTONIC, timestamp);
4371 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4372 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4373 return 0;
4374 }
4375
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004376 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004377
Ashish Jain5106d362016-05-11 19:23:33 +05304378 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4379 ret = compress_get_tstamp(out->compr, &dsp_frames,
4380 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004381 // Adjustment accounts for A2dp encoder latency with offload usecases
4382 // Note: Encoder latency is returned in ms.
4383 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4384 unsigned long offset =
4385 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4386 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4387 }
Ashish Jain5106d362016-05-11 19:23:33 +05304388 ALOGVV("%s rendered frames %ld sample_rate %d",
4389 __func__, dsp_frames, out->sample_rate);
4390 *frames = dsp_frames;
4391 if (ret < 0)
4392 ret = -errno;
4393 if (-ENETRESET == ret) {
4394 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304395 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304396 ret = -EINVAL;
4397 } else
4398 ret = 0;
4399 /* this is the best we can do */
4400 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004401 } else {
4402 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004403 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004404 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4405 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004406 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004407 // This adjustment accounts for buffering after app processor.
4408 // It is based on estimated DSP latency per use case, rather than exact.
4409 signed_frames -=
4410 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4411
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004412 // Adjustment accounts for A2dp encoder latency with non offload usecases
4413 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4414 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4415 signed_frames -=
4416 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4417 }
4418
Eric Laurent949a0892013-09-20 09:20:13 -07004419 // It would be unusual for this value to be negative, but check just in case ...
4420 if (signed_frames >= 0) {
4421 *frames = signed_frames;
4422 ret = 0;
4423 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004424 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304425 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304426 *frames = out->written;
4427 clock_gettime(CLOCK_MONOTONIC, timestamp);
4428 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004429 }
4430 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004431 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004432 return ret;
4433}
4434
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004435static int out_set_callback(struct audio_stream_out *stream,
4436 stream_callback_t callback, void *cookie)
4437{
4438 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004439 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004440
4441 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004442 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004443 out->client_callback = callback;
4444 out->client_cookie = cookie;
4445 if (out->adsp_hdlr_stream_handle) {
4446 ret = audio_extn_adsp_hdlr_stream_set_callback(
4447 out->adsp_hdlr_stream_handle,
4448 callback,
4449 cookie);
4450 if (ret)
4451 ALOGW("%s:adsp hdlr callback registration failed %d",
4452 __func__, ret);
4453 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004454 pthread_mutex_unlock(&out->lock);
4455 return 0;
4456}
4457
4458static int out_pause(struct audio_stream_out* stream)
4459{
4460 struct stream_out *out = (struct stream_out *)stream;
4461 int status = -ENOSYS;
4462 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004463 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004464 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004466 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304467 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304468 status = compress_pause(out->compr);
4469
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004470 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004471
Mingming Yin21854652016-04-13 11:54:02 -07004472 if (audio_extn_passthru_is_active()) {
4473 ALOGV("offload use case, pause passthru");
4474 audio_extn_passthru_on_pause(out);
4475 }
4476
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304477 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004478 audio_extn_dts_notify_playback_state(out->usecase, 0,
4479 out->sample_rate, popcount(out->channel_mask),
4480 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004481 }
4482 pthread_mutex_unlock(&out->lock);
4483 }
4484 return status;
4485}
4486
4487static int out_resume(struct audio_stream_out* stream)
4488{
4489 struct stream_out *out = (struct stream_out *)stream;
4490 int status = -ENOSYS;
4491 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004492 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004493 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004494 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004495 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004496 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304497 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304498 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004499 }
4500 if (!status) {
4501 out->offload_state = OFFLOAD_STATE_PLAYING;
4502 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304503 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004504 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4505 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004506 }
4507 pthread_mutex_unlock(&out->lock);
4508 }
4509 return status;
4510}
4511
4512static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4513{
4514 struct stream_out *out = (struct stream_out *)stream;
4515 int status = -ENOSYS;
4516 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004517 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004518 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4520 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4521 else
4522 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4523 pthread_mutex_unlock(&out->lock);
4524 }
4525 return status;
4526}
4527
4528static int out_flush(struct audio_stream_out* stream)
4529{
4530 struct stream_out *out = (struct stream_out *)stream;
4531 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004532 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004533 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004534 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004535 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4536 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004537 } else {
4538 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4539 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004540 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004541 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004542 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004543 return 0;
4544 }
4545 return -ENOSYS;
4546}
4547
Haynes Mathew George16081042017-05-31 17:16:49 -07004548static int out_stop(const struct audio_stream_out* stream)
4549{
4550 struct stream_out *out = (struct stream_out *)stream;
4551 struct audio_device *adev = out->dev;
4552 int ret = -ENOSYS;
4553
4554 ALOGV("%s", __func__);
4555 pthread_mutex_lock(&adev->lock);
4556 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4557 out->playback_started && out->pcm != NULL) {
4558 pcm_stop(out->pcm);
4559 ret = stop_output_stream(out);
4560 out->playback_started = false;
4561 }
4562 pthread_mutex_unlock(&adev->lock);
4563 return ret;
4564}
4565
4566static int out_start(const struct audio_stream_out* stream)
4567{
4568 struct stream_out *out = (struct stream_out *)stream;
4569 struct audio_device *adev = out->dev;
4570 int ret = -ENOSYS;
4571
4572 ALOGV("%s", __func__);
4573 pthread_mutex_lock(&adev->lock);
4574 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4575 !out->playback_started && out->pcm != NULL) {
4576 ret = start_output_stream(out);
4577 if (ret == 0) {
4578 out->playback_started = true;
4579 }
4580 }
4581 pthread_mutex_unlock(&adev->lock);
4582 return ret;
4583}
4584
4585/*
4586 * Modify config->period_count based on min_size_frames
4587 */
4588static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4589{
4590 int periodCountRequested = (min_size_frames + config->period_size - 1)
4591 / config->period_size;
4592 int periodCount = MMAP_PERIOD_COUNT_MIN;
4593
4594 ALOGV("%s original config.period_size = %d config.period_count = %d",
4595 __func__, config->period_size, config->period_count);
4596
4597 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4598 periodCount *= 2;
4599 }
4600 config->period_count = periodCount;
4601
4602 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4603}
4604
4605static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4606 int32_t min_size_frames,
4607 struct audio_mmap_buffer_info *info)
4608{
4609 struct stream_out *out = (struct stream_out *)stream;
4610 struct audio_device *adev = out->dev;
4611 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07004612 unsigned int offset1 = 0;
4613 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07004614 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004615 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004616
4617 ALOGV("%s", __func__);
4618 pthread_mutex_lock(&adev->lock);
4619
4620 if (info == NULL || min_size_frames == 0) {
4621 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4622 ret = -EINVAL;
4623 goto exit;
4624 }
4625 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4626 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4627 ret = -ENOSYS;
4628 goto exit;
4629 }
4630 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4631 if (out->pcm_device_id < 0) {
4632 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4633 __func__, out->pcm_device_id, out->usecase);
4634 ret = -EINVAL;
4635 goto exit;
4636 }
4637
4638 adjust_mmap_period_count(&out->config, min_size_frames);
4639
4640 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4641 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4642 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4643 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4644 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4645 step = "open";
4646 ret = -ENODEV;
4647 goto exit;
4648 }
4649 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4650 if (ret < 0) {
4651 step = "begin";
4652 goto exit;
4653 }
4654 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4655 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004656 ret = platform_get_mmap_data_fd(adev->platform,
4657 out->pcm_device_id, 0 /*playback*/,
4658 &info->shared_memory_fd,
4659 &mmap_size);
4660 if (ret < 0) {
4661 step = "get_mmap_fd";
4662 goto exit;
4663 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004664 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004665 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004666
4667 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4668 if (ret < 0) {
4669 step = "commit";
4670 goto exit;
4671 }
4672
4673 out->standby = false;
4674 ret = 0;
4675
4676 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4677 __func__, info->shared_memory_address, info->buffer_size_frames);
4678
4679exit:
4680 if (ret != 0) {
4681 if (out->pcm == NULL) {
4682 ALOGE("%s: %s - %d", __func__, step, ret);
4683 } else {
4684 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4685 pcm_close(out->pcm);
4686 out->pcm = NULL;
4687 }
4688 }
4689 pthread_mutex_unlock(&adev->lock);
4690 return ret;
4691}
4692
4693static int out_get_mmap_position(const struct audio_stream_out *stream,
4694 struct audio_mmap_position *position)
4695{
4696 struct stream_out *out = (struct stream_out *)stream;
4697 ALOGVV("%s", __func__);
4698 if (position == NULL) {
4699 return -EINVAL;
4700 }
4701 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4702 return -ENOSYS;
4703 }
4704 if (out->pcm == NULL) {
4705 return -ENOSYS;
4706 }
4707
4708 struct timespec ts = { 0, 0 };
4709 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4710 if (ret < 0) {
4711 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4712 return ret;
4713 }
4714 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4715 return 0;
4716}
4717
4718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719/** audio_stream_in implementation **/
4720static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4721{
4722 struct stream_in *in = (struct stream_in *)stream;
4723
4724 return in->config.rate;
4725}
4726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004727static int in_set_sample_rate(struct audio_stream *stream __unused,
4728 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004729{
4730 return -ENOSYS;
4731}
4732
4733static size_t in_get_buffer_size(const struct audio_stream *stream)
4734{
4735 struct stream_in *in = (struct stream_in *)stream;
4736
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004737 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4738 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004739 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4740 return VOIP_IO_BUF_SIZE(in->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Mingming Yine62d7842013-10-25 16:26:03 -07004741 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4742 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304743 else if(audio_extn_cin_attached_usecase(in->usecase))
4744 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004745
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004746 return in->config.period_size * in->af_period_multiplier *
4747 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748}
4749
4750static uint32_t in_get_channels(const struct audio_stream *stream)
4751{
4752 struct stream_in *in = (struct stream_in *)stream;
4753
4754 return in->channel_mask;
4755}
4756
4757static audio_format_t in_get_format(const struct audio_stream *stream)
4758{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004759 struct stream_in *in = (struct stream_in *)stream;
4760
4761 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762}
4763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004764static int in_set_format(struct audio_stream *stream __unused,
4765 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766{
4767 return -ENOSYS;
4768}
4769
4770static int in_standby(struct audio_stream *stream)
4771{
4772 struct stream_in *in = (struct stream_in *)stream;
4773 struct audio_device *adev = in->dev;
4774 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304775 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4776 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004777 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304778
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004779 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004780 if (!in->standby && in->is_st_session) {
4781 ALOGD("%s: sound trigger pcm stop lab", __func__);
4782 audio_extn_sound_trigger_stop_lab(in);
4783 in->standby = 1;
4784 }
4785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004787 if (adev->adm_deregister_stream)
4788 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4789
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004790 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004792 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004793 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004794 voice_extn_compress_voip_close_input_stream(stream);
4795 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004796 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4797 do_stop = in->capture_started;
4798 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004799 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304800 if (audio_extn_cin_attached_usecase(in->usecase))
4801 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004802 }
4803
4804 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004805 if (in->pcm) {
4806 pcm_close(in->pcm);
4807 in->pcm = NULL;
4808 }
4809 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004810 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004811 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812 }
4813 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004814 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815 return status;
4816}
4817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004818static int in_dump(const struct audio_stream *stream __unused,
4819 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820{
4821 return 0;
4822}
4823
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304824static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4825{
4826 if (!stream || !parms)
4827 return;
4828
4829 struct stream_in *in = (struct stream_in *)stream;
4830 struct audio_device *adev = in->dev;
4831
4832 card_status_t status;
4833 int card;
4834 if (parse_snd_card_status(parms, &card, &status) < 0)
4835 return;
4836
4837 pthread_mutex_lock(&adev->lock);
4838 bool valid_cb = (card == adev->snd_card);
4839 pthread_mutex_unlock(&adev->lock);
4840
4841 if (!valid_cb)
4842 return;
4843
4844 lock_input_stream(in);
4845 if (in->card_status != status)
4846 in->card_status = status;
4847 pthread_mutex_unlock(&in->lock);
4848
4849 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4850 use_case_table[in->usecase],
4851 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4852
4853 // a better solution would be to report error back to AF and let
4854 // it put the stream to standby
4855 if (status == CARD_STATUS_OFFLINE)
4856 in_standby(&in->stream.common);
4857
4858 return;
4859}
4860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4862{
4863 struct stream_in *in = (struct stream_in *)stream;
4864 struct audio_device *adev = in->dev;
4865 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004867 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304869 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870 parms = str_parms_create_str(kvpairs);
4871
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304872 if (!parms)
4873 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004874 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004875 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004876
4877 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4878 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879 val = atoi(value);
4880 /* no audio source uses val == 0 */
4881 if ((in->source != val) && (val != 0)) {
4882 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004883 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4884 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4885 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004886 (in->config.rate == 8000 || in->config.rate == 16000 ||
4887 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004888 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004889 err = voice_extn_compress_voip_open_input_stream(in);
4890 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004891 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004892 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004893 }
4894 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895 }
4896 }
4897
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004898 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4899 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004900 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004901 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 in->device = val;
4903 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004904 if (!in->standby && !in->is_st_session) {
4905 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004906 if (adev->adm_on_routing_change)
4907 adev->adm_on_routing_change(adev->adm_data,
4908 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004909 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004910 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 }
4912 }
4913
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304914 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4915 if (err >= 0) {
4916 strlcpy(in->profile, value, sizeof(in->profile));
4917 ALOGV("updating stream profile with value '%s'", in->profile);
4918 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4919 &adev->streams_input_cfg_list,
4920 in->device, in->flags, in->format,
4921 in->sample_rate, in->bit_width,
4922 in->profile, &in->app_type_cfg);
4923 }
4924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004926 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927
4928 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304929error:
Eric Laurent994a6932013-07-17 11:51:42 -07004930 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 return ret;
4932}
4933
4934static char* in_get_parameters(const struct audio_stream *stream,
4935 const char *keys)
4936{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004937 struct stream_in *in = (struct stream_in *)stream;
4938 struct str_parms *query = str_parms_create_str(keys);
4939 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004940 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004941
4942 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004943 if (reply) {
4944 str_parms_destroy(reply);
4945 }
4946 if (query) {
4947 str_parms_destroy(query);
4948 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004949 ALOGE("in_get_parameters: failed to create query or reply");
4950 return NULL;
4951 }
4952
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004953 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004954
4955 voice_extn_in_get_parameters(in, query, reply);
4956
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004957 stream_get_parameter_channels(query, reply,
4958 &in->supported_channel_masks[0]);
4959 stream_get_parameter_formats(query, reply,
4960 &in->supported_formats[0]);
4961 stream_get_parameter_rates(query, reply,
4962 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004963 str = str_parms_to_str(reply);
4964 str_parms_destroy(query);
4965 str_parms_destroy(reply);
4966
4967 ALOGV("%s: exit: returns - %s", __func__, str);
4968 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004969}
4970
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004971static int in_set_gain(struct audio_stream_in *stream __unused,
4972 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973{
4974 return 0;
4975}
4976
4977static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4978 size_t bytes)
4979{
4980 struct stream_in *in = (struct stream_in *)stream;
4981 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304982 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304983 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004985 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304986
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004987 if (in->is_st_session) {
4988 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4989 /* Read from sound trigger HAL */
4990 audio_extn_sound_trigger_read(in, buffer, bytes);
4991 pthread_mutex_unlock(&in->lock);
4992 return bytes;
4993 }
4994
Haynes Mathew George16081042017-05-31 17:16:49 -07004995 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4996 ret = -ENOSYS;
4997 goto exit;
4998 }
4999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005001 pthread_mutex_lock(&adev->lock);
5002 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5003 ret = voice_extn_compress_voip_start_input_stream(in);
5004 else
5005 ret = start_input_stream(in);
5006 pthread_mutex_unlock(&adev->lock);
5007 if (ret != 0) {
5008 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009 }
5010 in->standby = 0;
5011 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005013 // what's the duration requested by the client?
5014 long ns = 0;
5015
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305016 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005017 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5018 in->config.rate;
5019
5020 request_in_focus(in, ns);
5021 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005022
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305023 if (audio_extn_cin_attached_usecase(in->usecase)) {
5024 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5025 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305026 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005027 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305028 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005029 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005030 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005031 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005032 } else if (audio_extn_ffv_get_stream() == in) {
5033 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305034 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005035 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305036 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5037 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5038 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5039 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305040 ret = -EINVAL;
5041 goto exit;
5042 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305043 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305044 ret = -errno;
5045 }
5046 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305047 /* bytes read is always set to bytes for non compress usecases */
5048 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049 }
5050
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005051 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005053 /*
5054 * Instead of writing zeroes here, we could trust the hardware
5055 * to always provide zeroes when muted.
5056 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305057 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5058 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059 memset(buffer, 0, bytes);
5060
5061exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005062 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305063 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064 pthread_mutex_unlock(&in->lock);
5065
5066 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305067 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305068 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305069 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305070 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305071 in->standby = true;
5072 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305073 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5074 bytes_read = bytes;
5075 memset(buffer, 0, bytes);
5076 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005077 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005078 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305079 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305080 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305082 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005083}
5084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005085static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086{
5087 return 0;
5088}
5089
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005090static int add_remove_audio_effect(const struct audio_stream *stream,
5091 effect_handle_t effect,
5092 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005093{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005094 struct stream_in *in = (struct stream_in *)stream;
5095 int status = 0;
5096 effect_descriptor_t desc;
5097
5098 status = (*effect)->get_descriptor(effect, &desc);
5099 if (status != 0)
5100 return status;
5101
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005102 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005103 pthread_mutex_lock(&in->dev->lock);
5104 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5105 in->enable_aec != enable &&
5106 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5107 in->enable_aec = enable;
5108 if (!in->standby)
5109 select_devices(in->dev, in->usecase);
5110 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005111 if (in->enable_ns != enable &&
5112 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5113 in->enable_ns = enable;
5114 if (!in->standby)
5115 select_devices(in->dev, in->usecase);
5116 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005117 pthread_mutex_unlock(&in->dev->lock);
5118 pthread_mutex_unlock(&in->lock);
5119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005120 return 0;
5121}
5122
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005123static int in_add_audio_effect(const struct audio_stream *stream,
5124 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005125{
Eric Laurent994a6932013-07-17 11:51:42 -07005126 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005127 return add_remove_audio_effect(stream, effect, true);
5128}
5129
5130static int in_remove_audio_effect(const struct audio_stream *stream,
5131 effect_handle_t effect)
5132{
Eric Laurent994a6932013-07-17 11:51:42 -07005133 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005134 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135}
5136
Haynes Mathew George16081042017-05-31 17:16:49 -07005137static int in_stop(const struct audio_stream_in* stream)
5138{
5139 struct stream_in *in = (struct stream_in *)stream;
5140 struct audio_device *adev = in->dev;
5141
5142 int ret = -ENOSYS;
5143 ALOGV("%s", __func__);
5144 pthread_mutex_lock(&adev->lock);
5145 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5146 in->capture_started && in->pcm != NULL) {
5147 pcm_stop(in->pcm);
5148 ret = stop_input_stream(in);
5149 in->capture_started = false;
5150 }
5151 pthread_mutex_unlock(&adev->lock);
5152 return ret;
5153}
5154
5155static int in_start(const struct audio_stream_in* stream)
5156{
5157 struct stream_in *in = (struct stream_in *)stream;
5158 struct audio_device *adev = in->dev;
5159 int ret = -ENOSYS;
5160
5161 ALOGV("%s in %p", __func__, in);
5162 pthread_mutex_lock(&adev->lock);
5163 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5164 !in->capture_started && in->pcm != NULL) {
5165 if (!in->capture_started) {
5166 ret = start_input_stream(in);
5167 if (ret == 0) {
5168 in->capture_started = true;
5169 }
5170 }
5171 }
5172 pthread_mutex_unlock(&adev->lock);
5173 return ret;
5174}
5175
5176static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5177 int32_t min_size_frames,
5178 struct audio_mmap_buffer_info *info)
5179{
5180 struct stream_in *in = (struct stream_in *)stream;
5181 struct audio_device *adev = in->dev;
5182 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005183 unsigned int offset1 = 0;
5184 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005185 const char *step = "";
5186
5187 pthread_mutex_lock(&adev->lock);
5188 ALOGV("%s in %p", __func__, in);
5189
5190 if (info == NULL || min_size_frames == 0) {
5191 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5192 ret = -EINVAL;
5193 goto exit;
5194 }
5195 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5196 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5197 ALOGV("%s in %p", __func__, in);
5198 ret = -ENOSYS;
5199 goto exit;
5200 }
5201 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5202 if (in->pcm_device_id < 0) {
5203 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5204 __func__, in->pcm_device_id, in->usecase);
5205 ret = -EINVAL;
5206 goto exit;
5207 }
5208
5209 adjust_mmap_period_count(&in->config, min_size_frames);
5210
5211 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5212 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5213 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5214 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5215 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5216 step = "open";
5217 ret = -ENODEV;
5218 goto exit;
5219 }
5220
5221 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5222 if (ret < 0) {
5223 step = "begin";
5224 goto exit;
5225 }
5226 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5227 info->burst_size_frames = in->config.period_size;
5228 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5229
5230 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5231 info->buffer_size_frames));
5232
5233 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5234 if (ret < 0) {
5235 step = "commit";
5236 goto exit;
5237 }
5238
5239 in->standby = false;
5240 ret = 0;
5241
5242 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5243 __func__, info->shared_memory_address, info->buffer_size_frames);
5244
5245exit:
5246 if (ret != 0) {
5247 if (in->pcm == NULL) {
5248 ALOGE("%s: %s - %d", __func__, step, ret);
5249 } else {
5250 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5251 pcm_close(in->pcm);
5252 in->pcm = NULL;
5253 }
5254 }
5255 pthread_mutex_unlock(&adev->lock);
5256 return ret;
5257}
5258
5259static int in_get_mmap_position(const struct audio_stream_in *stream,
5260 struct audio_mmap_position *position)
5261{
5262 struct stream_in *in = (struct stream_in *)stream;
5263 ALOGVV("%s", __func__);
5264 if (position == NULL) {
5265 return -EINVAL;
5266 }
5267 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5268 return -ENOSYS;
5269 }
5270 if (in->pcm == NULL) {
5271 return -ENOSYS;
5272 }
5273 struct timespec ts = { 0, 0 };
5274 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5275 if (ret < 0) {
5276 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5277 return ret;
5278 }
5279 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5280 return 0;
5281}
5282
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305283int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005284 audio_io_handle_t handle,
5285 audio_devices_t devices,
5286 audio_output_flags_t flags,
5287 struct audio_config *config,
5288 struct audio_stream_out **stream_out,
5289 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290{
5291 struct audio_device *adev = (struct audio_device *)dev;
5292 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305293 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005294 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005295 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305296 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005297 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5298 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5299 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5300 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5305
Mingming Yin3a941d42016-02-17 18:08:05 -08005306 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5307 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305308 devices, flags, &out->stream);
5309
5310
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005311 if (!out) {
5312 return -ENOMEM;
5313 }
5314
Haynes Mathew George204045b2015-02-25 20:32:03 -08005315 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005316 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305317 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005318 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 if (devices == AUDIO_DEVICE_NONE)
5321 devices = AUDIO_DEVICE_OUT_SPEAKER;
5322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005323 out->flags = flags;
5324 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005325 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005326 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005327 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305328 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305329 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5330 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5331 else
5332 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005333 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005334 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005335 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305336 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305337 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305338 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005339 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305341 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005342 (property_get_bool("audio.matrix.limiter.enable", false)))
5343 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5344
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005345 if (audio_is_linear_pcm(out->format) &&
5346 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5347 pthread_mutex_lock(&adev->lock);
5348 if (is_hdmi) {
5349 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5350 ret = read_hdmi_sink_caps(out);
5351 } else if (is_usb_dev) {
5352 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5353 &config->format,
5354 &out->supported_formats[0],
5355 MAX_SUPPORTED_FORMATS,
5356 &config->channel_mask,
5357 &out->supported_channel_masks[0],
5358 MAX_SUPPORTED_CHANNEL_MASKS,
5359 &config->sample_rate,
5360 &out->supported_sample_rates[0],
5361 MAX_SUPPORTED_SAMPLE_RATES);
5362 ALOGV("plugged dev USB ret %d", ret);
5363 } else {
5364 ret = -1;
5365 }
5366 pthread_mutex_unlock(&adev->lock);
5367 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005368 if (ret == -ENOSYS) {
5369 /* ignore and go with default */
5370 ret = 0;
5371 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005372 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005373 goto error_open;
5374 }
5375 }
5376 }
5377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305379#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005380 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5381 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5382 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5383 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5384 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5385 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5386
5387 out->config = default_pcm_config_voip_copp;
5388 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5389 out->config.rate = out->sample_rate;
5390
5391#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305392 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005393 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005394 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005395 ret = voice_extn_compress_voip_open_output_stream(out);
5396 if (ret != 0) {
5397 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5398 __func__, ret);
5399 goto error_open;
5400 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005401#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005402 } else if (audio_is_linear_pcm(out->format) &&
5403 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5404 out->channel_mask = config->channel_mask;
5405 out->sample_rate = config->sample_rate;
5406 out->format = config->format;
5407 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5408 // does this change?
5409 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5410 out->config.rate = config->sample_rate;
5411 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5412 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5413 audio_bytes_per_sample(config->format));
5414 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005415 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305416 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305417 pthread_mutex_lock(&adev->lock);
5418 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5419 pthread_mutex_unlock(&adev->lock);
5420
5421 // reject offload during card offline to allow
5422 // fallback to s/w paths
5423 if (offline) {
5424 ret = -ENODEV;
5425 goto error_open;
5426 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005427
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005428 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5429 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5430 ALOGE("%s: Unsupported Offload information", __func__);
5431 ret = -EINVAL;
5432 goto error_open;
5433 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005434
Mingming Yin3a941d42016-02-17 18:08:05 -08005435 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005436 if(config->offload_info.format == 0)
5437 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005438 if (config->offload_info.sample_rate == 0)
5439 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005440 }
5441
Mingming Yin90310102013-11-13 16:57:00 -08005442 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305443 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005444 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005445 ret = -EINVAL;
5446 goto error_open;
5447 }
5448
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005449 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5450 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5451 (audio_extn_passthru_is_passthrough_stream(out)) &&
5452 !((config->sample_rate == 48000) ||
5453 (config->sample_rate == 96000) ||
5454 (config->sample_rate == 192000))) {
5455 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5456 __func__, config->sample_rate, config->offload_info.format);
5457 ret = -EINVAL;
5458 goto error_open;
5459 }
5460
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005461 out->compr_config.codec = (struct snd_codec *)
5462 calloc(1, sizeof(struct snd_codec));
5463
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005464 if (!out->compr_config.codec) {
5465 ret = -ENOMEM;
5466 goto error_open;
5467 }
5468
Dhananjay Kumarac341582017-02-23 23:42:25 +05305469 out->stream.pause = out_pause;
5470 out->stream.resume = out_resume;
5471 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305472 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305473 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005474 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305475 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005476 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305477 } else {
5478 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5479 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005480 }
vivek mehta446c3962015-09-14 10:57:35 -07005481
5482 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005483 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5484 config->format == 0 && config->sample_rate == 0 &&
5485 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005486 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005487 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5488 } else {
5489 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5490 ret = -EEXIST;
5491 goto error_open;
5492 }
vivek mehta446c3962015-09-14 10:57:35 -07005493 }
5494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005495 if (config->offload_info.channel_mask)
5496 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005497 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005498 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005499 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005500 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305501 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005502 ret = -EINVAL;
5503 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005504 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005505
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005506 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005507 out->sample_rate = config->offload_info.sample_rate;
5508
Mingming Yin3ee55c62014-08-04 14:23:35 -07005509 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005510
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305511 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305512 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305513 audio_extn_dolby_send_ddp_endp_params(adev);
5514 audio_extn_dolby_set_dmid(adev);
5515 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005517 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005518 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005519 out->compr_config.codec->bit_rate =
5520 config->offload_info.bit_rate;
5521 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305522 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005523 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305524 /* Update bit width only for non passthrough usecases.
5525 * For passthrough usecases, the output will always be opened @16 bit
5526 */
5527 if (!audio_extn_passthru_is_passthrough_stream(out))
5528 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305529
5530 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5531 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5532 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5533
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005534 /*TODO: Do we need to change it for passthrough */
5535 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005536
Manish Dewangana6fc5442015-08-24 20:30:31 +05305537 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5538 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305539 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305540 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305541 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5542 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305543
5544 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5545 AUDIO_FORMAT_PCM) {
5546
5547 /*Based on platform support, configure appropriate alsa format for corresponding
5548 *hal input format.
5549 */
5550 out->compr_config.codec->format = hal_format_to_alsa(
5551 config->offload_info.format);
5552
Ashish Jain83a6cc22016-06-28 14:34:17 +05305553 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305554 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305555 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305556
Dhananjay Kumarac341582017-02-23 23:42:25 +05305557 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305558 *hal input format and alsa format might differ based on platform support.
5559 */
5560 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305561 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305562
5563 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5564
5565 /* Check if alsa session is configured with the same format as HAL input format,
5566 * if not then derive correct fragment size needed to accomodate the
5567 * conversion of HAL input format to alsa format.
5568 */
5569 audio_extn_utils_update_direct_pcm_fragment_size(out);
5570
5571 /*if hal input and output fragment size is different this indicates HAL input format is
5572 *not same as the alsa format
5573 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305574 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305575 /*Allocate a buffer to convert input data to the alsa configured format.
5576 *size of convert buffer is equal to the size required to hold one fragment size
5577 *worth of pcm data, this is because flinger does not write more than fragment_size
5578 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305579 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5580 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305581 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5582 ret = -ENOMEM;
5583 goto error_open;
5584 }
5585 }
5586 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5587 out->compr_config.fragment_size =
5588 audio_extn_passthru_get_buffer_size(&config->offload_info);
5589 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5590 } else {
5591 out->compr_config.fragment_size =
5592 platform_get_compress_offload_buffer_size(&config->offload_info);
5593 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5594 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005595
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305596 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5597 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5598 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005599 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305600 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005601
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305602 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5603 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5604 }
5605
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005606 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5607 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005608
Manish Dewangan69426c82017-01-30 17:35:36 +05305609 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5610 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5611 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5612 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5613 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5614 } else {
5615 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5616 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005617
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305618 memset(&out->channel_map_param, 0,
5619 sizeof(struct audio_out_channel_map_param));
5620
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005621 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305622 out->send_next_track_params = false;
5623 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005624 out->offload_state = OFFLOAD_STATE_IDLE;
5625 out->playback_started = 0;
5626
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005627 audio_extn_dts_create_state_notifier_node(out->usecase);
5628
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005629 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5630 __func__, config->offload_info.version,
5631 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305632
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305633 /* Check if DSD audio format is supported in codec
5634 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305635 */
5636
5637 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305638 (!platform_check_codec_dsd_support(adev->platform) ||
5639 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305640 ret = -EINVAL;
5641 goto error_open;
5642 }
5643
Ashish Jain5106d362016-05-11 19:23:33 +05305644 /* Disable gapless if any of the following is true
5645 * passthrough playback
5646 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305647 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305648 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305649 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305650 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005651 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305652 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305653 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305654 check_and_set_gapless_mode(adev, false);
5655 } else
5656 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005657
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305658 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005659 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5660 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305661 if (config->format == AUDIO_FORMAT_DSD) {
5662 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5663 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5664 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005665
5666 create_offload_callback_thread(out);
5667
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005668 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305669 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005670 if (ret != 0) {
5671 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5672 __func__, ret);
5673 goto error_open;
5674 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005675 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5676 if (config->sample_rate == 0)
5677 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5678 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5679 config->sample_rate != 8000) {
5680 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5681 ret = -EINVAL;
5682 goto error_open;
5683 }
5684 out->sample_rate = config->sample_rate;
5685 out->config.rate = config->sample_rate;
5686 if (config->format == AUDIO_FORMAT_DEFAULT)
5687 config->format = AUDIO_FORMAT_PCM_16_BIT;
5688 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5689 config->format = AUDIO_FORMAT_PCM_16_BIT;
5690 ret = -EINVAL;
5691 goto error_open;
5692 }
5693 out->format = config->format;
5694 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5695 out->config = pcm_config_afe_proxy_playback;
5696 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005697 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305698 unsigned int channels = 0;
5699 /*Update config params to default if not set by the caller*/
5700 if (config->sample_rate == 0)
5701 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5702 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5703 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5704 if (config->format == AUDIO_FORMAT_DEFAULT)
5705 config->format = AUDIO_FORMAT_PCM_16_BIT;
5706
5707 channels = audio_channel_count_from_out_mask(out->channel_mask);
5708
Varun Balaraje49253e2017-07-06 19:48:56 +05305709 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5710 out->usecase = get_interactive_usecase(adev);
5711 out->config = pcm_config_low_latency;
5712 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305713 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005714 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5715 out->flags);
5716 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005717 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5718 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5719 out->config = pcm_config_mmap_playback;
5720 out->stream.start = out_start;
5721 out->stream.stop = out_stop;
5722 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5723 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305724 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5725 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005726 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5727 if (!out->dynamic_pm_qos_enabled) {
5728 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5729 } else {
5730 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5731 //the mixer path will be a string similar to "low-latency-playback resume"
5732 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5733 strlcat(out->pm_qos_mixer_path,
5734 " resume", MAX_MIXER_PATH_LEN);
5735 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5736 out->pm_qos_mixer_path);
5737 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305738 out->config = pcm_config_low_latency;
5739 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5740 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5741 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305742 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5743 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5744 if (out->config.period_size <= 0) {
5745 ALOGE("Invalid configuration period size is not valid");
5746 ret = -EINVAL;
5747 goto error_open;
5748 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305749 } else {
5750 /* primary path is the default path selected if no other outputs are available/suitable */
5751 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5752 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5753 }
5754 out->hal_ip_format = format = out->format;
5755 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5756 out->hal_op_format = pcm_format_to_hal(out->config.format);
5757 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5758 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005759 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305760 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305761 if (out->hal_ip_format != out->hal_op_format) {
5762 uint32_t buffer_size = out->config.period_size *
5763 format_to_bitwidth_table[out->hal_op_format] *
5764 out->config.channels;
5765 out->convert_buffer = calloc(1, buffer_size);
5766 if (out->convert_buffer == NULL){
5767 ALOGE("Allocation failed for convert buffer for size %d",
5768 out->compr_config.fragment_size);
5769 ret = -ENOMEM;
5770 goto error_open;
5771 }
5772 ALOGD("Convert buffer allocated of size %d", buffer_size);
5773 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005774 }
5775
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005776 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5777 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305778
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005779 /* TODO remove this hardcoding and check why width is zero*/
5780 if (out->bit_width == 0)
5781 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305782 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005783 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07005784 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305785 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305786 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005787 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5788 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5789 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005790 if(adev->primary_output == NULL)
5791 adev->primary_output = out;
5792 else {
5793 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005794 ret = -EEXIST;
5795 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005796 }
5797 }
5798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005799 /* Check if this usecase is already existing */
5800 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005801 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5802 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005803 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005805 ret = -EEXIST;
5806 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005807 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005809 pthread_mutex_unlock(&adev->lock);
5810
5811 out->stream.common.get_sample_rate = out_get_sample_rate;
5812 out->stream.common.set_sample_rate = out_set_sample_rate;
5813 out->stream.common.get_buffer_size = out_get_buffer_size;
5814 out->stream.common.get_channels = out_get_channels;
5815 out->stream.common.get_format = out_get_format;
5816 out->stream.common.set_format = out_set_format;
5817 out->stream.common.standby = out_standby;
5818 out->stream.common.dump = out_dump;
5819 out->stream.common.set_parameters = out_set_parameters;
5820 out->stream.common.get_parameters = out_get_parameters;
5821 out->stream.common.add_audio_effect = out_add_audio_effect;
5822 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5823 out->stream.get_latency = out_get_latency;
5824 out->stream.set_volume = out_set_volume;
5825 out->stream.write = out_write;
5826 out->stream.get_render_position = out_get_render_position;
5827 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005828 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829
Haynes Mathew George16081042017-05-31 17:16:49 -07005830 if (out->realtime)
5831 out->af_period_multiplier = af_period_multiplier;
5832 else
5833 out->af_period_multiplier = 1;
5834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005835 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005836 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005837 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005838
5839 config->format = out->stream.common.get_format(&out->stream.common);
5840 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5841 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5842
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305843 /*
5844 By locking output stream before registering, we allow the callback
5845 to update stream's state only after stream's initial state is set to
5846 adev state.
5847 */
5848 lock_output_stream(out);
5849 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5850 pthread_mutex_lock(&adev->lock);
5851 out->card_status = adev->card_status;
5852 pthread_mutex_unlock(&adev->lock);
5853 pthread_mutex_unlock(&out->lock);
5854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005855 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305856 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005857 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005858
5859 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5860 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5861 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005862 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305863 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005864 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005865 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305866 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005867 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5868 out->usecase, PCM_PLAYBACK);
5869 hdlr_stream_cfg.flags = out->flags;
5870 hdlr_stream_cfg.type = PCM_PLAYBACK;
5871 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5872 &hdlr_stream_cfg);
5873 if (ret) {
5874 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5875 out->adsp_hdlr_stream_handle = NULL;
5876 }
5877 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305878 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005879 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005880 if (ret < 0) {
5881 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5882 out->ip_hdlr_handle = NULL;
5883 }
5884 }
Eric Laurent994a6932013-07-17 11:51:42 -07005885 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005886 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005887
5888error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305889 if (out->convert_buffer)
5890 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005891 free(out);
5892 *stream_out = NULL;
5893 ALOGD("%s: exit: ret %d", __func__, ret);
5894 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005895}
5896
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305897void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005898 struct audio_stream_out *stream)
5899{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005900 struct stream_out *out = (struct stream_out *)stream;
5901 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005902 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005903
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005904 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305905
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305906 // must deregister from sndmonitor first to prevent races
5907 // between the callback and close_stream
5908 audio_extn_snd_mon_unregister_listener(out);
5909
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005910 /* close adsp hdrl session before standby */
5911 if (out->adsp_hdlr_stream_handle) {
5912 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5913 if (ret)
5914 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5915 out->adsp_hdlr_stream_handle = NULL;
5916 }
5917
Manish Dewangan21a850a2017-08-14 12:03:55 +05305918 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005919 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5920 out->ip_hdlr_handle = NULL;
5921 }
5922
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005923 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305924 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005925 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305926 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305927 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005928 if(ret != 0)
5929 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5930 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005931 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005932 out_standby(&stream->common);
5933
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005934 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005935 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005936 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005937 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005938 if (out->compr_config.codec != NULL)
5939 free(out->compr_config.codec);
5940 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005941
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305942 out->a2dp_compress_mute = false;
5943
Varun Balaraje49253e2017-07-06 19:48:56 +05305944 if (is_interactive_usecase(out->usecase))
5945 free_interactive_usecase(adev, out->usecase);
5946
Ashish Jain83a6cc22016-06-28 14:34:17 +05305947 if (out->convert_buffer != NULL) {
5948 free(out->convert_buffer);
5949 out->convert_buffer = NULL;
5950 }
5951
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005952 if (adev->voice_tx_output == out)
5953 adev->voice_tx_output = NULL;
5954
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305955 if (adev->primary_output == out)
5956 adev->primary_output = NULL;
5957
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005958 pthread_cond_destroy(&out->cond);
5959 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005960 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005961 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005962}
5963
5964static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5965{
5966 struct audio_device *adev = (struct audio_device *)dev;
5967 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005968 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005969 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005970 int ret;
5971 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005972
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005973 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005974 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305976 if (!parms)
5977 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305978
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305979 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5980 if (ret >= 0) {
5981 /* When set to false, HAL should disable EC and NS */
5982 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5983 adev->bt_sco_on = true;
5984 else
5985 adev->bt_sco_on = false;
5986 }
5987
Naresh Tanniru4c630392014-05-12 01:05:52 +05305988 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005989 status = voice_set_parameters(adev, parms);
5990 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005991 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005992
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005993 status = platform_set_parameters(adev->platform, parms);
5994 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005995 goto done;
5996
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5998 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005999 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006000 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6001 adev->bluetooth_nrec = true;
6002 else
6003 adev->bluetooth_nrec = false;
6004 }
6005
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006006 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6007 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006008 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6009 adev->screen_off = false;
6010 else
6011 adev->screen_off = true;
6012 }
6013
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006014 ret = str_parms_get_int(parms, "rotation", &val);
6015 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006016 bool reverse_speakers = false;
6017 switch(val) {
6018 // FIXME: note that the code below assumes that the speakers are in the correct placement
6019 // relative to the user when the device is rotated 90deg from its default rotation. This
6020 // assumption is device-specific, not platform-specific like this code.
6021 case 270:
6022 reverse_speakers = true;
6023 break;
6024 case 0:
6025 case 90:
6026 case 180:
6027 break;
6028 default:
6029 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006030 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006031 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006032 if (status == 0) {
6033 if (adev->speaker_lr_swap != reverse_speakers) {
6034 adev->speaker_lr_swap = reverse_speakers;
6035 // only update the selected device if there is active pcm playback
6036 struct audio_usecase *usecase;
6037 struct listnode *node;
6038 list_for_each(node, &adev->usecase_list) {
6039 usecase = node_to_item(node, struct audio_usecase, list);
6040 if (usecase->type == PCM_PLAYBACK) {
6041 select_devices(adev, usecase->id);
6042 break;
6043 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006044 }
6045 }
6046 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006047 }
6048
Mingming Yin514a8bc2014-07-29 15:22:21 -07006049 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6050 if (ret >= 0) {
6051 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6052 adev->bt_wb_speech_enabled = true;
6053 else
6054 adev->bt_wb_speech_enabled = false;
6055 }
6056
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006057 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6058 if (ret >= 0) {
6059 val = atoi(value);
6060 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006061 ALOGV("cache new ext disp type and edid");
6062 ret = platform_get_ext_disp_type(adev->platform);
6063 if (ret < 0) {
6064 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08006065 status = ret;
6066 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006067 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006068 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006069 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08006070 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07006071 /*
6072 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6073 * Per AudioPolicyManager, USB device is higher priority than WFD.
6074 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6075 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6076 * starting voice call on USB
6077 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006078 ret = str_parms_get_str(parms, "card", value, sizeof(value));
6079 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08006080 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
6081 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006082 }
vivek mehta344576a2016-04-12 18:56:03 -07006083 ALOGV("detected USB connect .. disable proxy");
6084 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006085 }
6086 }
6087
6088 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6089 if (ret >= 0) {
6090 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07006091 /*
6092 * The HDMI / Displayport disconnect handling has been moved to
6093 * audio extension to ensure that its parameters are not
6094 * invalidated prior to updating sysfs of the disconnect event
6095 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6096 */
6097 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08006098 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006099 ret = str_parms_get_str(parms, "card", value, sizeof(value));
6100 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05306101 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
6102 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006103 }
vivek mehta344576a2016-04-12 18:56:03 -07006104 ALOGV("detected USB disconnect .. enable proxy");
6105 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006106 }
6107 }
6108
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306109 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6110 if (ret >= 0) {
6111 struct audio_usecase *usecase;
6112 struct listnode *node;
6113 list_for_each(node, &adev->usecase_list) {
6114 usecase = node_to_item(node, struct audio_usecase, list);
6115 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006116 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306117 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006118
6119 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306120 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006121 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306122 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306123 //force device switch to re configure encoder
6124 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306125 audio_extn_a2dp_set_handoff_mode(false);
6126 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306127 break;
6128 }
6129 }
6130 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006131
6132 //handle vr audio setparam
6133 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6134 value, sizeof(value));
6135 if (ret >= 0) {
6136 ALOGI("Setting vr mode to be %s", value);
6137 if (!strncmp(value, "true", 4)) {
6138 adev->vr_audio_mode_enabled = true;
6139 ALOGI("Setting vr mode to true");
6140 } else if (!strncmp(value, "false", 5)) {
6141 adev->vr_audio_mode_enabled = false;
6142 ALOGI("Setting vr mode to false");
6143 } else {
6144 ALOGI("wrong vr mode set");
6145 }
6146 }
6147
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306148 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006149done:
6150 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006151 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306152error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006153 ALOGV("%s: exit with code(%d)", __func__, status);
6154 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155}
6156
6157static char* adev_get_parameters(const struct audio_hw_device *dev,
6158 const char *keys)
6159{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006160 struct audio_device *adev = (struct audio_device *)dev;
6161 struct str_parms *reply = str_parms_create();
6162 struct str_parms *query = str_parms_create_str(keys);
6163 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306164 char value[256] = {0};
6165 int ret = 0;
6166
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006167 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006168 if (reply) {
6169 str_parms_destroy(reply);
6170 }
6171 if (query) {
6172 str_parms_destroy(query);
6173 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006174 ALOGE("adev_get_parameters: failed to create query or reply");
6175 return NULL;
6176 }
6177
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006178 //handle vr audio getparam
6179
6180 ret = str_parms_get_str(query,
6181 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6182 value, sizeof(value));
6183
6184 if (ret >= 0) {
6185 bool vr_audio_enabled = false;
6186 pthread_mutex_lock(&adev->lock);
6187 vr_audio_enabled = adev->vr_audio_mode_enabled;
6188 pthread_mutex_unlock(&adev->lock);
6189
6190 ALOGI("getting vr mode to %d", vr_audio_enabled);
6191
6192 if (vr_audio_enabled) {
6193 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6194 "true");
6195 goto exit;
6196 } else {
6197 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6198 "false");
6199 goto exit;
6200 }
6201 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006202
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006203 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006204 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006205 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006206 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306207 pthread_mutex_unlock(&adev->lock);
6208
Naresh Tannirud7205b62014-06-20 02:54:48 +05306209exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006210 str = str_parms_to_str(reply);
6211 str_parms_destroy(query);
6212 str_parms_destroy(reply);
6213
6214 ALOGV("%s: exit: returns - %s", __func__, str);
6215 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216}
6217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006218static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006219{
6220 return 0;
6221}
6222
6223static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6224{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006225 int ret;
6226 struct audio_device *adev = (struct audio_device *)dev;
6227 pthread_mutex_lock(&adev->lock);
6228 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006229 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006230 pthread_mutex_unlock(&adev->lock);
6231 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006232}
6233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006234static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6235 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006236{
6237 return -ENOSYS;
6238}
6239
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006240static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6241 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006242{
6243 return -ENOSYS;
6244}
6245
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006246static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6247 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006248{
6249 return -ENOSYS;
6250}
6251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006252static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6253 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006254{
6255 return -ENOSYS;
6256}
6257
6258static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6259{
6260 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006262 pthread_mutex_lock(&adev->lock);
6263 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006264 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006265 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006266 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006267 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006268 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006269 adev->current_call_output = NULL;
6270 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006271 }
6272 pthread_mutex_unlock(&adev->lock);
6273 return 0;
6274}
6275
6276static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6277{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006278 int ret;
6279
6280 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006281 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006282 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6283 pthread_mutex_unlock(&adev->lock);
6284
6285 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006286}
6287
6288static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6289{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006290 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006291 return 0;
6292}
6293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006294static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295 const struct audio_config *config)
6296{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006297 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006299 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6300 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006301}
6302
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006303static bool adev_input_allow_hifi_record(struct audio_device *adev,
6304 audio_devices_t devices,
6305 audio_input_flags_t flags,
6306 audio_source_t source) {
6307 const bool allowed = true;
6308
6309 if (!audio_is_usb_in_device(devices))
6310 return !allowed;
6311
6312 switch (flags) {
6313 case AUDIO_INPUT_FLAG_NONE:
6314 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
6315 break;
6316 default:
6317 return !allowed;
6318 }
6319
6320 switch (source) {
6321 case AUDIO_SOURCE_DEFAULT:
6322 case AUDIO_SOURCE_MIC:
6323 case AUDIO_SOURCE_UNPROCESSED:
6324 break;
6325 default:
6326 return !allowed;
6327 }
6328
6329 switch (adev->mode) {
6330 case 0:
6331 break;
6332 default:
6333 return !allowed;
6334 }
6335
6336 return allowed;
6337}
6338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006339static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006340 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006341 audio_devices_t devices,
6342 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006343 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306344 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006345 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006346 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006347{
6348 struct audio_device *adev = (struct audio_device *)dev;
6349 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006350 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006351 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006352 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306353 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006354 bool is_usb_dev = audio_is_usb_in_device(devices);
6355 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6356 devices,
6357 flags,
6358 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006360 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006361
6362 if (!(is_usb_dev && may_use_hifi_record)) {
6363 if (config->sample_rate == 0)
6364 config->sample_rate = 48000;
6365 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6366 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6367 if (config->format == AUDIO_FORMAT_DEFAULT)
6368 config->format = AUDIO_FORMAT_PCM_16_BIT;
6369
6370 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6371
6372 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6373 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006375
6376 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006377
6378 if (!in) {
6379 ALOGE("failed to allocate input stream");
6380 return -ENOMEM;
6381 }
6382
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306383 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306384 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6385 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006386 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006387 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006389 in->stream.common.get_sample_rate = in_get_sample_rate;
6390 in->stream.common.set_sample_rate = in_set_sample_rate;
6391 in->stream.common.get_buffer_size = in_get_buffer_size;
6392 in->stream.common.get_channels = in_get_channels;
6393 in->stream.common.get_format = in_get_format;
6394 in->stream.common.set_format = in_set_format;
6395 in->stream.common.standby = in_standby;
6396 in->stream.common.dump = in_dump;
6397 in->stream.common.set_parameters = in_set_parameters;
6398 in->stream.common.get_parameters = in_get_parameters;
6399 in->stream.common.add_audio_effect = in_add_audio_effect;
6400 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6401 in->stream.set_gain = in_set_gain;
6402 in->stream.read = in_read;
6403 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6404
6405 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006406 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006409 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006410 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006411
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306412 /* restrict 24 bit capture for unprocessed source only
6413 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6414 */
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006415 if (is_usb_dev && may_use_hifi_record) {
6416 /* HiFi record selects an appropriate format, channel, rate combo
6417 depending on sink capabilities*/
6418 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
6419 &config->format,
6420 &in->supported_formats[0],
6421 MAX_SUPPORTED_FORMATS,
6422 &config->channel_mask,
6423 &in->supported_channel_masks[0],
6424 MAX_SUPPORTED_CHANNEL_MASKS,
6425 &config->sample_rate,
6426 &in->supported_sample_rates[0],
6427 MAX_SUPPORTED_SAMPLE_RATES);
6428 if (ret != 0) {
6429 ret = -EINVAL;
6430 goto err_open;
6431 }
6432 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6433 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306434 config->format = AUDIO_FORMAT_PCM_16_BIT;
6435 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6436 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6437 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6438 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6439 bool ret_error = false;
6440 in->bit_width = 24;
6441 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6442 from HAL is 24_packed and 8_24
6443 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6444 24_packed return error indicating supported format is 24_packed
6445 *> In case of any other source requesting 24 bit or float return error
6446 indicating format supported is 16 bit only.
6447
6448 on error flinger will retry with supported format passed
6449 */
6450 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6451 (source != AUDIO_SOURCE_CAMCORDER)) {
6452 config->format = AUDIO_FORMAT_PCM_16_BIT;
6453 if (config->sample_rate > 48000)
6454 config->sample_rate = 48000;
6455 ret_error = true;
6456 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6457 in->config.format = PCM_FORMAT_S24_3LE;
6458 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6459 in->config.format = PCM_FORMAT_S24_LE;
6460 } else {
6461 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6462 ret_error = true;
6463 }
6464
6465 if (ret_error) {
6466 ret = -EINVAL;
6467 goto err_open;
6468 }
6469 }
6470
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006471 in->channel_mask = config->channel_mask;
6472 in->format = config->format;
6473
6474 in->usecase = USECASE_AUDIO_RECORD;
6475 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
6476 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
6477 is_low_latency = true;
6478#if LOW_LATENCY_CAPTURE_USE_CASE
6479 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6480#endif
6481 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6482 }
6483
6484 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6485 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6486 in->realtime = 0;
6487 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6488 in->config = pcm_config_mmap_capture;
6489 in->stream.start = in_start;
6490 in->stream.stop = in_stop;
6491 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6492 in->stream.get_mmap_position = in_get_mmap_position;
6493 in->af_period_multiplier = 1;
6494 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6495 } else if (in->realtime) {
6496 in->config = pcm_config_audio_capture_rt;
6497 in->sample_rate = in->config.rate;
6498 in->af_period_multiplier = af_period_multiplier;
6499 } else {
6500 in->config = pcm_config_audio_capture;
6501 in->config.rate = config->sample_rate;
6502 in->sample_rate = config->sample_rate;
6503 in->af_period_multiplier = 1;
6504 }
6505 in->bit_width = 16;
6506
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306507 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306508 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6509 (adev->mode != AUDIO_MODE_IN_CALL)) {
6510 ret = -EINVAL;
6511 goto err_open;
6512 }
6513
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006514 if (is_usb_dev && may_use_hifi_record) {
6515 in->usecase = USECASE_AUDIO_RECORD_HIFI;
6516 in->config = pcm_config_audio_capture;
6517 frame_size = audio_stream_in_frame_size(&in->stream);
6518 buffer_size = get_input_buffer_size(config->sample_rate,
6519 config->format,
6520 channel_count,
6521 false /*is_low_latency*/);
6522 in->config.period_size = buffer_size / frame_size;
6523 in->config.rate = config->sample_rate;
6524 in->af_period_multiplier = 1;
6525 in->config.format = pcm_format_from_audio_format(config->format);
6526 in->config.channels = channel_count;
6527 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306528 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006529 if (config->sample_rate == 0)
6530 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6531 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6532 config->sample_rate != 8000) {
6533 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6534 ret = -EINVAL;
6535 goto err_open;
6536 }
6537 if (config->format == AUDIO_FORMAT_DEFAULT)
6538 config->format = AUDIO_FORMAT_PCM_16_BIT;
6539 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6540 config->format = AUDIO_FORMAT_PCM_16_BIT;
6541 ret = -EINVAL;
6542 goto err_open;
6543 }
6544
6545 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6546 in->config = pcm_config_afe_proxy_record;
6547 in->config.channels = channel_count;
6548 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306549 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306550 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6551 in, config, &channel_mask_updated)) {
6552 if (channel_mask_updated == true) {
6553 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6554 __func__, config->channel_mask);
6555 ret = -EINVAL;
6556 goto err_open;
6557 }
Garmond Leunge2433c32017-09-28 21:51:22 -07006558 ALOGD("%s: created multi-channel session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006559 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006560 audio_extn_compr_cap_format_supported(config->format) &&
6561 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006562 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306563 } else if (audio_extn_cin_applicable_stream(in)) {
6564 ret = audio_extn_cin_configure_input_stream(in);
6565 if (ret)
6566 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006567 } else {
6568 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006569 if (!in->realtime) {
6570 in->format = config->format;
6571 frame_size = audio_stream_in_frame_size(&in->stream);
6572 buffer_size = get_input_buffer_size(config->sample_rate,
6573 config->format,
6574 channel_count,
6575 is_low_latency);
6576 in->config.period_size = buffer_size / frame_size;
6577 }
6578
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006579#ifndef COMPRESS_VOIP_ENABLED
6580 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6581 (in->config.rate == 8000 || in->config.rate == 16000 ||
6582 in->config.rate == 32000 || in->config.rate == 48000) &&
6583 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6584
6585 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6586 in->config = default_pcm_config_voip_copp;
6587 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6588 in->config.rate = in->sample_rate;
6589#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006590 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006591 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6592 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006593 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006594 (in->config.rate == 8000 || in->config.rate == 16000 ||
6595 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006596 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6597 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006598#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006599 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006600 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006601
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306602 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6603 &adev->streams_input_cfg_list,
6604 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306605 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306606
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006607 /* This stream could be for sound trigger lab,
6608 get sound trigger pcm if present */
6609 audio_extn_sound_trigger_check_and_get_session(in);
6610
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306611 lock_input_stream(in);
6612 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6613 pthread_mutex_lock(&adev->lock);
6614 in->card_status = adev->card_status;
6615 pthread_mutex_unlock(&adev->lock);
6616 pthread_mutex_unlock(&in->lock);
6617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006619 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006620 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006621
6622err_open:
6623 free(in);
6624 *stream_in = NULL;
6625 return ret;
6626}
6627
6628static void adev_close_input_stream(struct audio_hw_device *dev,
6629 struct audio_stream_in *stream)
6630{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006631 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006632 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006633 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306634
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306635 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006636
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306637 // must deregister from sndmonitor first to prevent races
6638 // between the callback and close_stream
6639 audio_extn_snd_mon_unregister_listener(stream);
6640
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306641 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006642 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306643
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006644 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306645 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006646 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306647 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006648 if (ret != 0)
6649 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6650 __func__, ret);
6651 } else
6652 in_standby(&stream->common);
6653
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006654 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006655 audio_extn_ssr_deinit();
6656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006657
Garmond Leunge2433c32017-09-28 21:51:22 -07006658 if (audio_extn_ffv_get_stream() == in) {
6659 audio_extn_ffv_stream_deinit();
6660 }
6661
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306662 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006663 audio_extn_compr_cap_format_supported(in->config.format))
6664 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306665
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306666 if (audio_extn_cin_attached_usecase(in->usecase))
6667 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006668
Mingming Yinfd7607b2016-01-22 12:48:44 -08006669 if (in->is_st_session) {
6670 ALOGV("%s: sound trigger pcm stop lab", __func__);
6671 audio_extn_sound_trigger_stop_lab(in);
6672 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006673 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006674 return;
6675}
6676
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306677int adev_create_audio_patch(struct audio_hw_device *dev,
6678 unsigned int num_sources,
6679 const struct audio_port_config *sources,
6680 unsigned int num_sinks,
6681 const struct audio_port_config *sinks,
6682 audio_patch_handle_t *handle)
6683{
6684
6685
6686 return audio_extn_hw_loopback_create_audio_patch(dev,
6687 num_sources,
6688 sources,
6689 num_sinks,
6690 sinks,
6691 handle);
6692
6693}
6694
6695int adev_release_audio_patch(struct audio_hw_device *dev,
6696 audio_patch_handle_t handle)
6697{
6698 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6699}
6700
6701int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6702{
6703 return audio_extn_hw_loopback_get_audio_port(dev, config);
6704}
6705
6706int adev_set_audio_port_config(struct audio_hw_device *dev,
6707 const struct audio_port_config *config)
6708{
6709 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6710}
6711
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006712static int adev_dump(const audio_hw_device_t *device __unused,
6713 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714{
6715 return 0;
6716}
6717
6718static int adev_close(hw_device_t *device)
6719{
6720 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006721
6722 if (!adev)
6723 return 0;
6724
6725 pthread_mutex_lock(&adev_init_lock);
6726
6727 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306728 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006729 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006730 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306731 audio_extn_utils_release_streams_cfg_lists(
6732 &adev->streams_output_cfg_list,
6733 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306734 if (audio_extn_qaf_is_enabled())
6735 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006736 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006737 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006738 free(adev->snd_dev_ref_cnt);
6739 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006740 if (adev->adm_deinit)
6741 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306742 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006743 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306744 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306745 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006746 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306747 if (adev->device_cfg_params) {
6748 free(adev->device_cfg_params);
6749 adev->device_cfg_params = NULL;
6750 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006751 free(device);
6752 adev = NULL;
6753 }
6754 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006756 return 0;
6757}
6758
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006759/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6760 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6761 * just that it _might_ work.
6762 */
6763static int period_size_is_plausible_for_low_latency(int period_size)
6764{
6765 switch (period_size) {
6766 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006767 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006768 case 240:
6769 case 320:
6770 case 480:
6771 return 1;
6772 default:
6773 return 0;
6774 }
6775}
6776
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306777static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6778{
6779 bool is_snd_card_status = false;
6780 bool is_ext_device_status = false;
6781 char value[32];
6782 int card = -1;
6783 card_status_t status;
6784
6785 if (cookie != adev || !parms)
6786 return;
6787
6788 if (!parse_snd_card_status(parms, &card, &status)) {
6789 is_snd_card_status = true;
6790 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6791 is_ext_device_status = true;
6792 } else {
6793 // not a valid event
6794 return;
6795 }
6796
6797 pthread_mutex_lock(&adev->lock);
6798 if (card == adev->snd_card || is_ext_device_status) {
6799 if (is_snd_card_status && adev->card_status != status) {
6800 adev->card_status = status;
6801 platform_snd_card_update(adev->platform, status);
6802 audio_extn_fm_set_parameters(adev, parms);
6803 } else if (is_ext_device_status) {
6804 platform_set_parameters(adev->platform, parms);
6805 }
6806 }
6807 pthread_mutex_unlock(&adev->lock);
6808 return;
6809}
6810
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306811/* out and adev lock held */
6812static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6813{
6814 struct audio_usecase *uc_info;
6815 float left_p;
6816 float right_p;
6817 audio_devices_t devices;
6818
6819 uc_info = get_usecase_from_list(adev, out->usecase);
6820 if (uc_info == NULL) {
6821 ALOGE("%s: Could not find the usecase (%d) in the list",
6822 __func__, out->usecase);
6823 return -EINVAL;
6824 }
6825
6826 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6827 out->usecase, use_case_table[out->usecase]);
6828
6829 if (restore) {
6830 // restore A2DP device for active usecases and unmute if required
6831 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6832 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6833 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6834 select_devices(adev, uc_info->id);
6835 pthread_mutex_lock(&out->compr_mute_lock);
6836 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6837 (out->a2dp_compress_mute)) {
6838 out->a2dp_compress_mute = false;
6839 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6840 }
6841 pthread_mutex_unlock(&out->compr_mute_lock);
6842 }
6843 } else {
6844 // mute compress stream if suspended
6845 pthread_mutex_lock(&out->compr_mute_lock);
6846 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6847 (!out->a2dp_compress_mute)) {
6848 if (!out->standby) {
6849 ALOGD("%s: selecting speaker and muting stream", __func__);
6850 devices = out->devices;
6851 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6852 left_p = out->volume_l;
6853 right_p = out->volume_r;
6854 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6855 compress_pause(out->compr);
6856 out_set_compr_volume(&out->stream, (float)0, (float)0);
6857 out->a2dp_compress_mute = true;
6858 select_devices(adev, out->usecase);
6859 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6860 compress_resume(out->compr);
6861 out->devices = devices;
6862 out->volume_l = left_p;
6863 out->volume_r = right_p;
6864 }
6865 }
6866 pthread_mutex_unlock(&out->compr_mute_lock);
6867 }
6868 ALOGV("%s: exit", __func__);
6869 return 0;
6870}
6871
6872int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6873{
6874 int ret = 0;
6875
6876 lock_output_stream(out);
6877 pthread_mutex_lock(&adev->lock);
6878
6879 ret = check_a2dp_restore_l(adev, out, restore);
6880
6881 pthread_mutex_unlock(&adev->lock);
6882 pthread_mutex_unlock(&out->lock);
6883 return ret;
6884}
6885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006886static int adev_open(const hw_module_t *module, const char *name,
6887 hw_device_t **device)
6888{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306889 int ret;
6890
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006891 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006892 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6893
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006894 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006895 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006896 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006897 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006898 ALOGD("%s: returning existing instance of adev", __func__);
6899 ALOGD("%s: exit", __func__);
6900 pthread_mutex_unlock(&adev_init_lock);
6901 return 0;
6902 }
6903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006904 adev = calloc(1, sizeof(struct audio_device));
6905
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006906 if (!adev) {
6907 pthread_mutex_unlock(&adev_init_lock);
6908 return -ENOMEM;
6909 }
6910
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006911 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6912
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306913#ifdef DYNAMIC_LOG_ENABLED
6914 register_for_dynamic_logging("hal");
6915#endif
6916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006917 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6918 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6919 adev->device.common.module = (struct hw_module_t *)module;
6920 adev->device.common.close = adev_close;
6921
6922 adev->device.init_check = adev_init_check;
6923 adev->device.set_voice_volume = adev_set_voice_volume;
6924 adev->device.set_master_volume = adev_set_master_volume;
6925 adev->device.get_master_volume = adev_get_master_volume;
6926 adev->device.set_master_mute = adev_set_master_mute;
6927 adev->device.get_master_mute = adev_get_master_mute;
6928 adev->device.set_mode = adev_set_mode;
6929 adev->device.set_mic_mute = adev_set_mic_mute;
6930 adev->device.get_mic_mute = adev_get_mic_mute;
6931 adev->device.set_parameters = adev_set_parameters;
6932 adev->device.get_parameters = adev_get_parameters;
6933 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6934 adev->device.open_output_stream = adev_open_output_stream;
6935 adev->device.close_output_stream = adev_close_output_stream;
6936 adev->device.open_input_stream = adev_open_input_stream;
6937 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306938 adev->device.create_audio_patch = adev_create_audio_patch;
6939 adev->device.release_audio_patch = adev_release_audio_patch;
6940 adev->device.get_audio_port = adev_get_audio_port;
6941 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006942 adev->device.dump = adev_dump;
6943
6944 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006945 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006946 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006947 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006948 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006949 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006950 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006951 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306952 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006953 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006954 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006955 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006956 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006957 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006958 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306959 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306960 adev->perf_lock_opts[0] = 0x101;
6961 adev->perf_lock_opts[1] = 0x20E;
6962 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006963 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006965 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006966 adev->platform = platform_init(adev);
6967 if (!adev->platform) {
6968 free(adev->snd_dev_ref_cnt);
6969 free(adev);
6970 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6971 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006972 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306973 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006974 return -EINVAL;
6975 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006976
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306977 if (audio_extn_qaf_is_enabled()) {
6978 ret = audio_extn_qaf_init(adev);
6979 if (ret < 0) {
6980 free(adev);
6981 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6982 *device = NULL;
6983 pthread_mutex_unlock(&adev_init_lock);
6984 pthread_mutex_destroy(&adev->lock);
6985 return ret;
6986 }
6987
6988 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6989 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6990 }
6991
Eric Laurentc4aef752013-09-12 17:45:53 -07006992 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6993 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6994 if (adev->visualizer_lib == NULL) {
6995 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6996 } else {
6997 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6998 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006999 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007000 "visualizer_hal_start_output");
7001 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007002 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007003 "visualizer_hal_stop_output");
7004 }
7005 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307006 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007007 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007008 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307009 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007010 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007011
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007012 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7013 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7014 if (adev->offload_effects_lib == NULL) {
7015 ALOGE("%s: DLOPEN failed for %s", __func__,
7016 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7017 } else {
7018 ALOGV("%s: DLOPEN successful for %s", __func__,
7019 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7020 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307021 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007022 "offload_effects_bundle_hal_start_output");
7023 adev->offload_effects_stop_output =
7024 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7025 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007026 adev->offload_effects_set_hpx_state =
7027 (int (*)(bool))dlsym(adev->offload_effects_lib,
7028 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307029 adev->offload_effects_get_parameters =
7030 (void (*)(struct str_parms *, struct str_parms *))
7031 dlsym(adev->offload_effects_lib,
7032 "offload_effects_bundle_get_parameters");
7033 adev->offload_effects_set_parameters =
7034 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7035 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007036 }
7037 }
7038
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007039 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7040 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7041 if (adev->adm_lib == NULL) {
7042 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7043 } else {
7044 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7045 adev->adm_init = (adm_init_t)
7046 dlsym(adev->adm_lib, "adm_init");
7047 adev->adm_deinit = (adm_deinit_t)
7048 dlsym(adev->adm_lib, "adm_deinit");
7049 adev->adm_register_input_stream = (adm_register_input_stream_t)
7050 dlsym(adev->adm_lib, "adm_register_input_stream");
7051 adev->adm_register_output_stream = (adm_register_output_stream_t)
7052 dlsym(adev->adm_lib, "adm_register_output_stream");
7053 adev->adm_deregister_stream = (adm_deregister_stream_t)
7054 dlsym(adev->adm_lib, "adm_deregister_stream");
7055 adev->adm_request_focus = (adm_request_focus_t)
7056 dlsym(adev->adm_lib, "adm_request_focus");
7057 adev->adm_abandon_focus = (adm_abandon_focus_t)
7058 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007059 adev->adm_set_config = (adm_set_config_t)
7060 dlsym(adev->adm_lib, "adm_set_config");
7061 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7062 dlsym(adev->adm_lib, "adm_request_focus_v2");
7063 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7064 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7065 adev->adm_on_routing_change = (adm_on_routing_change_t)
7066 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007067 }
7068 }
7069
Mingming Yin514a8bc2014-07-29 15:22:21 -07007070 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007071 //initialize this to false for now,
7072 //this will be set to true through set param
7073 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007074
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007075 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007076 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007077 adev->dsp_bit_width_enforce_mode =
7078 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007079
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307080 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7081 &adev->streams_output_cfg_list,
7082 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007083
Kiran Kandi910e1862013-10-29 13:29:42 -07007084 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007085
7086 char value[PROPERTY_VALUE_MAX];
7087 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007088 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007089 trial = atoi(value);
7090 if (period_size_is_plausible_for_low_latency(trial)) {
7091 pcm_config_low_latency.period_size = trial;
7092 pcm_config_low_latency.start_threshold = trial / 4;
7093 pcm_config_low_latency.avail_min = trial / 4;
7094 configured_low_latency_capture_period_size = trial;
7095 }
7096 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007097 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007098 trial = atoi(value);
7099 if (period_size_is_plausible_for_low_latency(trial)) {
7100 configured_low_latency_capture_period_size = trial;
7101 }
7102 }
7103
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007104 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007105 af_period_multiplier = atoi(value);
7106 if (af_period_multiplier < 0)
7107 af_period_multiplier = 2;
7108 else if (af_period_multiplier > 4)
7109 af_period_multiplier = 4;
7110
7111 ALOGV("new period_multiplier = %d", af_period_multiplier);
7112 }
7113
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007114 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007115 pthread_mutex_unlock(&adev_init_lock);
7116
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007117 if (adev->adm_init)
7118 adev->adm_data = adev->adm_init();
7119
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307120 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307121 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007122 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307123
7124 audio_extn_snd_mon_init();
7125 pthread_mutex_lock(&adev->lock);
7126 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7127 adev->card_status = CARD_STATUS_ONLINE;
7128 pthread_mutex_unlock(&adev->lock);
7129 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307130 /* Allocate memory for Device config params */
7131 adev->device_cfg_params = (struct audio_device_config_param*)
7132 calloc(platform_get_max_codec_backend(),
7133 sizeof(struct audio_device_config_param));
7134 if (adev->device_cfg_params == NULL)
7135 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307136
Eric Laurent994a6932013-07-17 11:51:42 -07007137 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138 return 0;
7139}
7140
7141static struct hw_module_methods_t hal_module_methods = {
7142 .open = adev_open,
7143};
7144
7145struct audio_module HAL_MODULE_INFO_SYM = {
7146 .common = {
7147 .tag = HARDWARE_MODULE_TAG,
7148 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7149 .hal_api_version = HARDWARE_HAL_API_VERSION,
7150 .id = AUDIO_HARDWARE_MODULE_ID,
7151 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007152 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007153 .methods = &hal_module_methods,
7154 },
7155};