blob: 6468e7ef526785746f52d0880009515c0242128b [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
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700806#ifdef DYNAMIC_ECNS_ENABLED
807static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
808 struct audio_effect_config effect_config,
809 unsigned int param_value)
810{
811 char mixer_ctl_name[] = "Audio Effect";
812 struct mixer_ctl *ctl;
813 long set_values[6];
814 struct stream_in *in = adev->active_input;
815
816 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
817 if (!ctl) {
818 ALOGE("%s: Could not get mixer ctl - %s",
819 __func__, mixer_ctl_name);
820 return -EINVAL;
821 }
822
823 set_values[0] = 1; //0:Rx 1:Tx
824 set_values[1] = in->app_type_cfg.app_type;
825 set_values[2] = (long)effect_config.module_id;
826 set_values[3] = (long)effect_config.instance_id;
827 set_values[4] = (long)effect_config.param_id;
828 set_values[5] = param_value;
829
830 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
831
832 return 0;
833
834}
835
836static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
837 int effect_type, unsigned int *param_value)
838{
839 int ret = 0;
840 struct audio_effect_config other_effect_config;
841 struct audio_usecase *usecase = NULL;
842 struct stream_in *in = adev->active_input;
843
844 usecase = get_usecase_from_list(adev, in->usecase);
845 if (!usecase)
846 return -EINVAL;
847
848 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
849 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
850 if (ret < 0) {
851 ALOGE("%s Failed to get effect params %d", __func__, ret);
852 return ret;
853 }
854
855 if (module_id == other_effect_config.module_id) {
856 //Same module id for AEC/NS. Values need to be combined
857 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
858 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
859 *param_value |= other_effect_config.param_value;
860 }
861 }
862
863 return ret;
864}
865
866static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
867{
868 struct audio_effect_config effect_config;
869 struct audio_usecase *usecase = NULL;
870 int ret = 0;
871 unsigned int param_value = 0;
872 struct stream_in *in = adev->active_input;
873
874 if (!in) {
875 ALOGE("%s: Invalid input stream", __func__);
876 return -EINVAL;
877 }
878
879 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
880
881 usecase = get_usecase_from_list(adev, in->usecase);
882
883 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
884 if (ret < 0) {
885 ALOGE("%s Failed to get module id %d", __func__, ret);
886 return ret;
887 }
888 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
889 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
890
891 if(enable)
892 param_value = effect_config.param_value;
893
894 /*Special handling for AEC & NS effects Param values need to be
895 updated if module ids are same*/
896
897 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
898 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
899 if (ret < 0)
900 return ret;
901 }
902
903 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
904
905 return ret;
906}
907
908static void check_and_enable_effect(struct audio_device *adev)
909{
910
911 if (adev->active_input->enable_aec) {
912 enable_disable_effect(adev, EFFECT_AEC, true);
913 }
914
915 if (adev->active_input->enable_ns &&
916 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
917 enable_disable_effect(adev, EFFECT_NS, true);
918 }
919}
920#else
921#define enable_disable_effect(x, y, z) ENOSYS
922#define check_and_enable_effect(x) ENOSYS
923#endif
924
925
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700926int pcm_ioctl(struct pcm *pcm, int request, ...)
927{
928 va_list ap;
929 void * arg;
930 int pcm_fd = *(int*)pcm;
931
932 va_start(ap, request);
933 arg = va_arg(ap, void *);
934 va_end(ap);
935
936 return ioctl(pcm_fd, request, arg);
937}
938
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700939int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700940 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700943 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530944 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800945
946 if (usecase == NULL)
947 return -EINVAL;
948
949 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
950
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800951 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800953 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800955
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800956#ifdef DS1_DOLBY_DAP_ENABLED
957 audio_extn_dolby_set_dmid(adev);
958 audio_extn_dolby_set_endpoint(adev);
959#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700960 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700961 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530962 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700963 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530964 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530965 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
966 out = usecase->stream.out;
967 if (out && out->compr)
968 audio_extn_utils_compress_set_clk_rec_mode(usecase);
969 }
970
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800971 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700972 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700973 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700974 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975 ALOGV("%s: exit", __func__);
976 return 0;
977}
978
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700979int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700983 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800984
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530985 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800986 return -EINVAL;
987
988 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 if (usecase->type == PCM_CAPTURE)
990 snd_device = usecase->in_snd_device;
991 else
992 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800993 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700994 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700995 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700996 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700997 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530998 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999 ALOGV("%s: exit", __func__);
1000 return 0;
1001}
1002
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001003int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001004 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301006 int i, num_devices = 0;
1007 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001008 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1009
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001010 if (snd_device < SND_DEVICE_MIN ||
1011 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001012 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001013 return -EINVAL;
1014 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015
1016 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001017
1018 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
1019 ALOGE("%s: Invalid sound device returned", __func__);
1020 return -EINVAL;
1021 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -07001023 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001024 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001025 return 0;
1026 }
1027
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301028
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001029 if (audio_extn_spkr_prot_is_enabled())
1030 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001031
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001032 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1033 audio_extn_spkr_prot_is_enabled()) {
1034 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001035 adev->snd_dev_ref_cnt[snd_device]--;
1036 return -EINVAL;
1037 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001038 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001039 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001040 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001041 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001042 return -EINVAL;
1043 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001044 } else if (platform_split_snd_device(adev->platform,
1045 snd_device,
1046 &num_devices,
1047 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301048 for (i = 0; i < num_devices; i++) {
1049 enable_snd_device(adev, new_snd_devices[i]);
1050 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001051 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001052 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301053
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301054
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301055 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1056 (audio_extn_a2dp_start_playback() < 0)) {
1057 ALOGE(" fail to configure A2dp control path ");
1058 return -EINVAL;
1059 }
1060
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001061 /* due to the possibility of calibration overwrite between listen
1062 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001063 audio_extn_sound_trigger_update_device_status(snd_device,
1064 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301065 audio_extn_listen_update_device_status(snd_device,
1066 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001067 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001068 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001069 audio_extn_sound_trigger_update_device_status(snd_device,
1070 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301071 audio_extn_listen_update_device_status(snd_device,
1072 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001073 return -EINVAL;
1074 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001075 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001076 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301077
1078 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1079 !adev->native_playback_enabled &&
1080 audio_is_true_native_stream_active(adev)) {
1081 ALOGD("%s: %d: napb: enabling native mode in hardware",
1082 __func__, __LINE__);
1083 audio_route_apply_and_update_path(adev->audio_route,
1084 "true-native-mode");
1085 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301086 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001087 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1088 (audio_extn_ffv_get_stream() == adev->active_input)) {
1089 ALOGD("%s: init ec ref loopback", __func__);
1090 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1091 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 return 0;
1094}
1095
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001096int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001097 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301099 int i, num_devices = 0;
1100 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001101 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1102
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001103 if (snd_device < SND_DEVICE_MIN ||
1104 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001105 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001106 return -EINVAL;
1107 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1109 ALOGE("%s: device ref cnt is already 0", __func__);
1110 return -EINVAL;
1111 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001112
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001114
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001115 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1116 ALOGE("%s: Invalid sound device returned", __func__);
1117 return -EINVAL;
1118 }
1119
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001121 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301122
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001123 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1124 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001125 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001126
1127 // when speaker device is disabled, reset swap.
1128 // will be renabled on usecase start
1129 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001130 } else if (platform_split_snd_device(adev->platform,
1131 snd_device,
1132 &num_devices,
1133 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301134 for (i = 0; i < num_devices; i++) {
1135 disable_snd_device(adev, new_snd_devices[i]);
1136 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001137 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001138 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001139 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001140
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301141 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1142 audio_extn_a2dp_stop_playback();
1143
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001144 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301145 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301146 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1147 adev->native_playback_enabled) {
1148 ALOGD("%s: %d: napb: disabling native mode in hardware",
1149 __func__, __LINE__);
1150 audio_route_reset_and_update_path(adev->audio_route,
1151 "true-native-mode");
1152 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301153 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1154 adev->asrc_mode_enabled) {
1155 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301156 disable_asrc_mode(adev);
1157 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301158 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001159 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1160 (audio_extn_ffv_get_stream() == adev->active_input)) {
1161 ALOGD("%s: deinit ec ref loopback", __func__);
1162 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1163 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001164 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001165 audio_extn_sound_trigger_update_device_status(snd_device,
1166 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301167 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001168 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171 return 0;
1172}
1173
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001174/*
1175 legend:
1176 uc - existing usecase
1177 new_uc - new usecase
1178 d1, d11, d2 - SND_DEVICE enums
1179 a1, a2 - corresponding ANDROID device enums
1180 B1, B2 - backend strings
1181
1182case 1
1183 uc->dev d1 (a1) B1
1184 new_uc->dev d1 (a1), d2 (a2) B1, B2
1185
1186 resolution: disable and enable uc->dev on d1
1187
1188case 2
1189 uc->dev d1 (a1) B1
1190 new_uc->dev d11 (a1) B1
1191
1192 resolution: need to switch uc since d1 and d11 are related
1193 (e.g. speaker and voice-speaker)
1194 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1195
1196case 3
1197 uc->dev d1 (a1) B1
1198 new_uc->dev d2 (a2) B2
1199
1200 resolution: no need to switch uc
1201
1202case 4
1203 uc->dev d1 (a1) B1
1204 new_uc->dev d2 (a2) B1
1205
1206 resolution: disable enable uc-dev on d2 since backends match
1207 we cannot enable two streams on two different devices if they
1208 share the same backend. e.g. if offload is on speaker device using
1209 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1210 using the same backend, offload must also be switched to voice-handset.
1211
1212case 5
1213 uc->dev d1 (a1) B1
1214 new_uc->dev d1 (a1), d2 (a2) B1
1215
1216 resolution: disable enable uc-dev on d2 since backends match
1217 we cannot enable two streams on two different devices if they
1218 share the same backend.
1219
1220case 6
1221 uc->dev d1 (a1) B1
1222 new_uc->dev d2 (a1) B2
1223
1224 resolution: no need to switch
1225
1226case 7
1227 uc->dev d1 (a1), d2 (a2) B1, B2
1228 new_uc->dev d1 (a1) B1
1229
1230 resolution: no need to switch
1231
1232*/
1233static snd_device_t derive_playback_snd_device(void * platform,
1234 struct audio_usecase *uc,
1235 struct audio_usecase *new_uc,
1236 snd_device_t new_snd_device)
1237{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301238 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001239
1240 snd_device_t d1 = uc->out_snd_device;
1241 snd_device_t d2 = new_snd_device;
1242
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301243 switch (uc->type) {
1244 case TRANSCODE_LOOPBACK :
1245 a1 = uc->stream.inout->out_config.devices;
1246 a2 = new_uc->stream.inout->out_config.devices;
1247 break;
1248 default :
1249 a1 = uc->stream.out->devices;
1250 a2 = new_uc->stream.out->devices;
1251 break;
1252 }
1253
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001254 // Treat as a special case when a1 and a2 are not disjoint
1255 if ((a1 != a2) && (a1 & a2)) {
1256 snd_device_t d3[2];
1257 int num_devices = 0;
1258 int ret = platform_split_snd_device(platform,
1259 popcount(a1) > 1 ? d1 : d2,
1260 &num_devices,
1261 d3);
1262 if (ret < 0) {
1263 if (ret != -ENOSYS) {
1264 ALOGW("%s failed to split snd_device %d",
1265 __func__,
1266 popcount(a1) > 1 ? d1 : d2);
1267 }
1268 goto end;
1269 }
1270
1271 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1272 // But if it does happen, we need to give priority to d2 if
1273 // the combo devices active on the existing usecase share a backend.
1274 // This is because we cannot have a usecase active on a combo device
1275 // and a new usecase requests one device in this combo pair.
1276 if (platform_check_backends_match(d3[0], d3[1])) {
1277 return d2; // case 5
1278 } else {
1279 return d1; // case 1
1280 }
1281 } else {
1282 if (platform_check_backends_match(d1, d2)) {
1283 return d2; // case 2, 4
1284 } else {
1285 return d1; // case 6, 3
1286 }
1287 }
1288
1289end:
1290 return d2; // return whatever was calculated before.
1291}
1292
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301294 struct audio_usecase *uc_info,
1295 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296{
1297 struct listnode *node;
1298 struct audio_usecase *usecase;
1299 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301300 snd_device_t uc_derive_snd_device;
1301 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001303 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301304 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001305 /*
1306 * This function is to make sure that all the usecases that are active on
1307 * the hardware codec backend are always routed to any one device that is
1308 * handled by the hardware codec.
1309 * For example, if low-latency and deep-buffer usecases are currently active
1310 * on speaker and out_set_parameters(headset) is received on low-latency
1311 * output, then we have to make sure deep-buffer is also switched to headset,
1312 * because of the limitation that both the devices cannot be enabled
1313 * at the same time as they share the same backend.
1314 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001315 /*
1316 * This call is to check if we need to force routing for a particular stream
1317 * If there is a backend configuration change for the device when a
1318 * new stream starts, then ADM needs to be closed and re-opened with the new
1319 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001320 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001321 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001322 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1323 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301324 /* For a2dp device reconfigure all active sessions
1325 * with new AFE encoder format based on a2dp state
1326 */
1327 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1328 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1329 audio_extn_a2dp_is_force_device_switch()) {
1330 force_routing = true;
1331 force_restart_session = true;
1332 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301333 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1334
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001335 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001336 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001337 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1339 switch_device[i] = false;
1340
1341 list_for_each(node, &adev->usecase_list) {
1342 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001343
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301344 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1345 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301346 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301347 platform_get_snd_device_name(usecase->out_snd_device),
1348 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301349 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1350 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1351 usecase, uc_info, snd_device);
1352 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1353 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1354 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1355 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1356 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1357 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1358 ((force_restart_session) ||
1359 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301360 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1361 __func__, use_case_table[usecase->id],
1362 platform_get_snd_device_name(usecase->out_snd_device));
1363 disable_audio_route(adev, usecase);
1364 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301365 /* Enable existing usecase on derived playback device */
1366 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301367 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301368 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001369 }
1370 }
1371
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301372 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1373 num_uc_to_switch);
1374
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001375 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001376 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301378 /* Make sure the previous devices to be disabled first and then enable the
1379 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001380 list_for_each(node, &adev->usecase_list) {
1381 usecase = node_to_item(node, struct audio_usecase, list);
1382 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001383 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001384 }
1385 }
1386
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001387 list_for_each(node, &adev->usecase_list) {
1388 usecase = node_to_item(node, struct audio_usecase, list);
1389 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301390 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001391 }
1392 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001394 /* Re-route all the usecases on the shared backend other than the
1395 specified usecase to new snd devices */
1396 list_for_each(node, &adev->usecase_list) {
1397 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301398 /* Update the out_snd_device only before enabling the audio route */
1399 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301400 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301401 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301402 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301403 use_case_table[usecase->id],
1404 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001405 /* Update voc calibration before enabling VoIP route */
1406 if (usecase->type == VOIP_CALL)
1407 status = platform_switch_voice_call_device_post(adev->platform,
1408 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001409 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301410 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301411 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001412 }
1413 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 }
1415}
1416
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301417static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001418 struct audio_usecase *uc_info,
1419 snd_device_t snd_device)
1420{
1421 struct listnode *node;
1422 struct audio_usecase *usecase;
1423 bool switch_device[AUDIO_USECASE_MAX];
1424 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301425 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001426 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001427
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301428 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1429 snd_device);
1430 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301431
1432 /*
1433 * Make sure out devices is checked against out codec backend device and
1434 * also in devices against in codec backend. Checking out device against in
1435 * codec backend or vice versa causes issues.
1436 */
1437 if (uc_info->type == PCM_CAPTURE)
1438 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001439 /*
1440 * This function is to make sure that all the active capture usecases
1441 * are always routed to the same input sound device.
1442 * For example, if audio-record and voice-call usecases are currently
1443 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1444 * is received for voice call then we have to make sure that audio-record
1445 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1446 * because of the limitation that two devices cannot be enabled
1447 * at the same time if they share the same backend.
1448 */
1449 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1450 switch_device[i] = false;
1451
1452 list_for_each(node, &adev->usecase_list) {
1453 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301454 /*
1455 * TODO: Enhance below condition to handle BT sco/USB multi recording
1456 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001457 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001458 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301459 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301460 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301461 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301462 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001463 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001464 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1465 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001466 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001467 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001468 switch_device[usecase->id] = true;
1469 num_uc_to_switch++;
1470 }
1471 }
1472
1473 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001474 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001475
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301476 /* Make sure the previous devices to be disabled first and then enable the
1477 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001478 list_for_each(node, &adev->usecase_list) {
1479 usecase = node_to_item(node, struct audio_usecase, list);
1480 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001481 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001482 }
1483 }
1484
1485 list_for_each(node, &adev->usecase_list) {
1486 usecase = node_to_item(node, struct audio_usecase, list);
1487 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001488 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001489 }
1490 }
1491
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001492 /* Re-route all the usecases on the shared backend other than the
1493 specified usecase to new snd devices */
1494 list_for_each(node, &adev->usecase_list) {
1495 usecase = node_to_item(node, struct audio_usecase, list);
1496 /* Update the in_snd_device only before enabling the audio route */
1497 if (switch_device[usecase->id] ) {
1498 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001499 if (usecase->type != VOICE_CALL) {
1500 /* Update voc calibration before enabling VoIP route */
1501 if (usecase->type == VOIP_CALL)
1502 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001503 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001504 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301505 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001506 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001507 }
1508 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001509 }
1510}
1511
Mingming Yin3a941d42016-02-17 18:08:05 -08001512static void reset_hdmi_sink_caps(struct stream_out *out) {
1513 int i = 0;
1514
1515 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1516 out->supported_channel_masks[i] = 0;
1517 }
1518 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1519 out->supported_formats[i] = 0;
1520 }
1521 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1522 out->supported_sample_rates[i] = 0;
1523 }
1524}
1525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001527static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528{
Mingming Yin3a941d42016-02-17 18:08:05 -08001529 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001530 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531
Mingming Yin3a941d42016-02-17 18:08:05 -08001532 reset_hdmi_sink_caps(out);
1533
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001534 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001535 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001536 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001537 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001538 }
1539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001542 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001543 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001544 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1545 case 6:
1546 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1547 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1548 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1549 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1550 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1551 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 break;
1553 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001554 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001555 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556 break;
1557 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001558
1559 // check channel format caps
1560 i = 0;
1561 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1562 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1563 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1564 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1565 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1566 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1567 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1568 }
1569
Ben Romberger1aaaf862017-04-06 17:49:46 -07001570 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1571 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1572 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1573 }
1574
Mingming Yin3a941d42016-02-17 18:08:05 -08001575 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1576 ALOGV(":%s HDMI supports DTS format", __func__);
1577 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1578 }
1579
1580 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1581 ALOGV(":%s HDMI supports DTS HD format", __func__);
1582 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1583 }
1584
Naresh Tanniru928f0862017-04-07 16:44:23 -07001585 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1586 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1587 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1588 }
1589
Mingming Yin3a941d42016-02-17 18:08:05 -08001590
1591 // check sample rate caps
1592 i = 0;
1593 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1594 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1595 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1596 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1597 }
1598 }
1599
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001600 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601}
1602
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001603static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1604 uint32_t *supported_sample_rates __unused,
1605 uint32_t max_rates __unused)
1606{
1607 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1608 supported_sample_rates,
1609 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301610 ssize_t i = 0;
1611
1612 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001613 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1614 supported_sample_rates[i]);
1615 }
1616 return count;
1617}
1618
1619static inline int read_usb_sup_channel_masks(bool is_playback,
1620 audio_channel_mask_t *supported_channel_masks,
1621 uint32_t max_masks)
1622{
1623 int channels = audio_extn_usb_get_max_channels(is_playback);
1624 int channel_count;
1625 uint32_t num_masks = 0;
1626 if (channels > MAX_HIFI_CHANNEL_COUNT)
1627 channels = MAX_HIFI_CHANNEL_COUNT;
1628
1629 if (is_playback) {
1630 // For playback we never report mono because the framework always outputs stereo
1631 channel_count = DEFAULT_CHANNEL_COUNT;
1632 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1633 // above 2 but we want indexed masks here. So we
1634 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1635 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1636 }
1637 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1638 supported_channel_masks[num_masks++] =
1639 audio_channel_mask_for_index_assignment_from_count(channel_count);
1640 }
1641 } else {
1642 // For capture we report all supported channel masks from 1 channel up.
1643 channel_count = MIN_CHANNEL_COUNT;
1644 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1645 // indexed mask
1646 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1647 supported_channel_masks[num_masks++] =
1648 audio_channel_in_mask_from_count(channel_count);
1649 }
1650 }
1651 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1652 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1653 return num_masks;
1654}
1655
1656static inline int read_usb_sup_formats(bool is_playback __unused,
1657 audio_format_t *supported_formats,
1658 uint32_t max_formats __unused)
1659{
1660 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1661 switch (bitwidth) {
1662 case 24:
1663 // XXX : usb.c returns 24 for s24 and s24_le?
1664 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1665 break;
1666 case 32:
1667 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1668 break;
1669 case 16:
1670 default :
1671 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1672 break;
1673 }
1674 ALOGV("%s: %s supported format %d", __func__,
1675 is_playback ? "P" : "C", bitwidth);
1676 return 1;
1677}
1678
1679static inline int read_usb_sup_params_and_compare(bool is_playback,
1680 audio_format_t *format,
1681 audio_format_t *supported_formats,
1682 uint32_t max_formats,
1683 audio_channel_mask_t *mask,
1684 audio_channel_mask_t *supported_channel_masks,
1685 uint32_t max_masks,
1686 uint32_t *rate,
1687 uint32_t *supported_sample_rates,
1688 uint32_t max_rates) {
1689 int ret = 0;
1690 int num_formats;
1691 int num_masks;
1692 int num_rates;
1693 int i;
1694
1695 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1696 max_formats);
1697 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1698 max_masks);
1699
1700 num_rates = read_usb_sup_sample_rates(is_playback,
1701 supported_sample_rates, max_rates);
1702
1703#define LUT(table, len, what, dflt) \
1704 for (i=0; i<len && (table[i] != what); i++); \
1705 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1706
1707 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1708 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1709 LUT(supported_sample_rates, num_rates, *rate, 0);
1710
1711#undef LUT
1712 return ret < 0 ? -EINVAL : 0; // HACK TBD
1713}
1714
Alexy Josephb1379942016-01-29 15:49:38 -08001715audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001716 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001717{
1718 struct audio_usecase *usecase;
1719 struct listnode *node;
1720
1721 list_for_each(node, &adev->usecase_list) {
1722 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001723 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001724 ALOGV("%s: usecase id %d", __func__, usecase->id);
1725 return usecase->id;
1726 }
1727 }
1728 return USECASE_INVALID;
1729}
1730
Alexy Josephb1379942016-01-29 15:49:38 -08001731struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001732 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001733{
1734 struct audio_usecase *usecase;
1735 struct listnode *node;
1736
1737 list_for_each(node, &adev->usecase_list) {
1738 usecase = node_to_item(node, struct audio_usecase, list);
1739 if (usecase->id == uc_id)
1740 return usecase;
1741 }
1742 return NULL;
1743}
1744
Dhananjay Kumard4833242016-10-06 22:09:12 +05301745struct stream_in *get_next_active_input(const struct audio_device *adev)
1746{
1747 struct audio_usecase *usecase;
1748 struct listnode *node;
1749
1750 list_for_each_reverse(node, &adev->usecase_list) {
1751 usecase = node_to_item(node, struct audio_usecase, list);
1752 if (usecase->type == PCM_CAPTURE)
1753 return usecase->stream.in;
1754 }
1755 return NULL;
1756}
1757
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301758/*
1759 * is a true native playback active
1760 */
1761bool audio_is_true_native_stream_active(struct audio_device *adev)
1762{
1763 bool active = false;
1764 int i = 0;
1765 struct listnode *node;
1766
1767 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1768 ALOGV("%s:napb: not in true mode or non hdphones device",
1769 __func__);
1770 active = false;
1771 goto exit;
1772 }
1773
1774 list_for_each(node, &adev->usecase_list) {
1775 struct audio_usecase *uc;
1776 uc = node_to_item(node, struct audio_usecase, list);
1777 struct stream_out *curr_out =
1778 (struct stream_out*) uc->stream.out;
1779
1780 if (curr_out && PCM_PLAYBACK == uc->type) {
1781 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1782 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1783 uc->id, curr_out->sample_rate,
1784 curr_out->bit_width,
1785 platform_get_snd_device_name(uc->out_snd_device));
1786
1787 if (is_offload_usecase(uc->id) &&
1788 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1789 active = true;
1790 ALOGD("%s:napb:native stream detected", __func__);
1791 }
1792 }
1793 }
1794exit:
1795 return active;
1796}
1797
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001798uint32_t adev_get_dsp_bit_width_enforce_mode()
1799{
1800 if (adev == NULL) {
1801 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1802 return 0;
1803 }
1804 return adev->dsp_bit_width_enforce_mode;
1805}
1806
1807static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1808{
1809 char value[PROPERTY_VALUE_MAX];
1810 int trial;
1811 uint32_t dsp_bit_width_enforce_mode = 0;
1812
1813 if (!mixer) {
1814 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1815 __func__);
1816 return 0;
1817 }
1818
1819 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1820 value, NULL) > 0) {
1821 trial = atoi(value);
1822 switch (trial) {
1823 case 16:
1824 dsp_bit_width_enforce_mode = 16;
1825 break;
1826 case 24:
1827 dsp_bit_width_enforce_mode = 24;
1828 break;
1829 case 32:
1830 dsp_bit_width_enforce_mode = 32;
1831 break;
1832 default:
1833 dsp_bit_width_enforce_mode = 0;
1834 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1835 break;
1836 }
1837 }
1838
1839 return dsp_bit_width_enforce_mode;
1840}
1841
1842static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1843 uint32_t enforce_mode,
1844 bool enable)
1845{
1846 struct mixer_ctl *ctl = NULL;
1847 const char *mixer_ctl_name = "ASM Bit Width";
1848 uint32_t asm_bit_width_mode = 0;
1849
1850 if (enforce_mode == 0) {
1851 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1852 return;
1853 }
1854
1855 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1856 if (!ctl) {
1857 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1858 __func__, mixer_ctl_name);
1859 return;
1860 }
1861
1862 if (enable)
1863 asm_bit_width_mode = enforce_mode;
1864 else
1865 asm_bit_width_mode = 0;
1866
1867 ALOGV("%s DSP bit width feature status is %d width=%d",
1868 __func__, enable, asm_bit_width_mode);
1869 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1870 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1871 asm_bit_width_mode);
1872
1873 return;
1874}
1875
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301876/*
1877 * if native DSD playback active
1878 */
1879bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1880{
1881 bool active = false;
1882 struct listnode *node = NULL;
1883 struct audio_usecase *uc = NULL;
1884 struct stream_out *curr_out = NULL;
1885
1886 list_for_each(node, &adev->usecase_list) {
1887 uc = node_to_item(node, struct audio_usecase, list);
1888 curr_out = (struct stream_out*) uc->stream.out;
1889
1890 if (curr_out && PCM_PLAYBACK == uc->type &&
1891 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1892 active = true;
1893 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301894 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301895 }
1896 }
1897 return active;
1898}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301899
1900static bool force_device_switch(struct audio_usecase *usecase)
1901{
1902 bool ret = false;
1903 bool is_it_true_mode = false;
1904
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001905 if(usecase->stream.out == NULL) {
1906 ALOGE("%s: stream.out is NULL", __func__);
1907 return false;
1908 }
1909
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301910 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001911 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1912 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1913 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301914 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1915 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1916 (!is_it_true_mode && adev->native_playback_enabled)){
1917 ret = true;
1918 ALOGD("napb: time to toggle native mode");
1919 }
1920 }
1921
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301922 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301923 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1924 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07001925 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301926 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301927 ALOGD("Force a2dp device switch to update new encoder config");
1928 ret = true;
1929 }
1930
Manish Dewangan671a4202017-08-18 17:30:46 +05301931 if (usecase->stream.out->stream_config_changed) {
1932 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1933 return true;
1934 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301935 return ret;
1936}
1937
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301938bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1939{
1940 bool ret=false;
1941 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1942 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1943 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1944 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1945 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1946 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1947 ret = true;
1948
1949 return ret;
1950}
1951
1952bool is_a2dp_device(snd_device_t out_snd_device)
1953{
1954 bool ret=false;
1955 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1956 ret = true;
1957
1958 return ret;
1959}
1960
1961bool is_bt_soc_on(struct audio_device *adev)
1962{
1963 struct mixer_ctl *ctl;
1964 char *mixer_ctl_name = "BT SOC status";
1965 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1966 bool bt_soc_status = true;
1967 if (!ctl) {
1968 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1969 __func__, mixer_ctl_name);
1970 /*This is to ensure we dont break targets which dont have the kernel change*/
1971 return true;
1972 }
1973 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1974 ALOGD("BT SOC status: %d",bt_soc_status);
1975 return bt_soc_status;
1976}
1977
1978int out_standby_l(struct audio_stream *stream);
1979
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001980int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001982 snd_device_t out_snd_device = SND_DEVICE_NONE;
1983 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001984 struct audio_usecase *usecase = NULL;
1985 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001986 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001987 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301988 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001989 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001990 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301992 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1993
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001994 usecase = get_usecase_from_list(adev, uc_id);
1995 if (usecase == NULL) {
1996 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1997 return -EINVAL;
1998 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002000 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002001 (usecase->type == VOIP_CALL) ||
2002 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302003 if(usecase->stream.out == NULL) {
2004 ALOGE("%s: stream.out is NULL", __func__);
2005 return -EINVAL;
2006 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002007 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002008 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002009 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002010 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302011 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
2012 if (usecase->stream.inout == NULL) {
2013 ALOGE("%s: stream.inout is NULL", __func__);
2014 return -EINVAL;
2015 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302016 stream_out.devices = usecase->stream.inout->out_config.devices;
2017 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2018 stream_out.format = usecase->stream.inout->out_config.format;
2019 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2020 out_snd_device = platform_get_output_snd_device(adev->platform,
2021 &stream_out);
2022 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302023 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002024 } else {
2025 /*
2026 * If the voice call is active, use the sound devices of voice call usecase
2027 * so that it would not result any device switch. All the usecases will
2028 * be switched to new device when select_devices() is called for voice call
2029 * usecase. This is to avoid switching devices for voice call when
2030 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002031 * choose voice call device only if the use case device is
2032 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002033 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002034 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002035 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002036 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002037 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2038 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302039 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2040 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002041 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002042 in_snd_device = vc_usecase->in_snd_device;
2043 out_snd_device = vc_usecase->out_snd_device;
2044 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002045 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002046 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002047 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002048 if ((voip_usecase != NULL) &&
2049 (usecase->type == PCM_PLAYBACK) &&
2050 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002051 out_snd_device_backend_match = platform_check_backends_match(
2052 voip_usecase->out_snd_device,
2053 platform_get_output_snd_device(
2054 adev->platform,
2055 usecase->stream.out));
2056 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002057 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002058 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2059 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002060 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002061 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002062 in_snd_device = voip_usecase->in_snd_device;
2063 out_snd_device = voip_usecase->out_snd_device;
2064 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002065 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002066 hfp_ucid = audio_extn_hfp_get_usecase();
2067 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002068 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002069 in_snd_device = hfp_usecase->in_snd_device;
2070 out_snd_device = hfp_usecase->out_snd_device;
2071 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002072 }
2073 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302074 if (usecase->stream.out == NULL) {
2075 ALOGE("%s: stream.out is NULL", __func__);
2076 return -EINVAL;
2077 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078 usecase->devices = usecase->stream.out->devices;
2079 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002080 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002081 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002082 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002083 if (usecase->stream.out == adev->primary_output &&
2084 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08002085 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002086 select_devices(adev, adev->active_input->usecase);
2087 }
2088 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002089 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302090 if (usecase->stream.in == NULL) {
2091 ALOGE("%s: stream.in is NULL", __func__);
2092 return -EINVAL;
2093 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094 usecase->devices = usecase->stream.in->device;
2095 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002096 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002097 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002098 if (adev->active_input &&
2099 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302100 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
2101 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
2102 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002103 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002104 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002105 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2106 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002107 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002108 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002110 }
2111 }
2112
2113 if (out_snd_device == usecase->out_snd_device &&
2114 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302115
2116 if (!force_device_switch(usecase))
2117 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 }
2119
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302120 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
2121 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
2122 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2123 return 0;
2124 }
2125
sangwoobc677242013-08-08 16:53:43 +09002126 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07002127 out_snd_device, platform_get_snd_device_name(out_snd_device),
2128 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 /*
2131 * Limitation: While in call, to do a device switch we need to disable
2132 * and enable both RX and TX devices though one of them is same as current
2133 * device.
2134 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002135 if ((usecase->type == VOICE_CALL) &&
2136 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2137 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002138 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002139 }
2140
2141 if (((usecase->type == VOICE_CALL) ||
2142 (usecase->type == VOIP_CALL)) &&
2143 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2144 /* Disable sidetone only if voice/voip call already exists */
2145 if (voice_is_call_state_active(adev) ||
2146 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002147 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002148
2149 /* Disable aanc only if voice call exists */
2150 if (voice_is_call_state_active(adev))
2151 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002152 }
2153
Zhou Songc66eb7e2017-08-08 18:29:07 +08002154 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302155 (!audio_extn_a2dp_is_ready())) {
2156 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002157 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302158 }
2159
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002160 /* Disable current sound devices */
2161 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002162 disable_audio_route(adev, usecase);
2163 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 }
2165
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002166 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002167 disable_audio_route(adev, usecase);
2168 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 }
2170
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002171 /* Applicable only on the targets that has external modem.
2172 * New device information should be sent to modem before enabling
2173 * the devices to reduce in-call device switch time.
2174 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002175 if ((usecase->type == VOICE_CALL) &&
2176 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2177 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002178 status = platform_switch_voice_call_enable_device_config(adev->platform,
2179 out_snd_device,
2180 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002181 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002182
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183 /* Enable new sound devices */
2184 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002185 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302186 if (platform_check_codec_asrc_support(adev->platform))
2187 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002188 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 }
2190
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002191 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302192 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002193 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002194 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002195
Avinash Vaish71a8b972014-07-24 15:36:33 +05302196 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002197 status = platform_switch_voice_call_device_post(adev->platform,
2198 out_snd_device,
2199 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302200 enable_audio_route_for_voice_usecases(adev, usecase);
2201 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002202
sangwoo170731f2013-06-08 15:36:36 +09002203 usecase->in_snd_device = in_snd_device;
2204 usecase->out_snd_device = out_snd_device;
2205
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302206 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2207 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302208 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002209 if ((24 == usecase->stream.out->bit_width) &&
2210 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2211 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2212 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2213 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2214 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2215 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2216 /*
2217 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2218 * configured device sample rate, if not update the COPP rate to be equal to the
2219 * device sample rate, else open COPP at stream sample rate
2220 */
2221 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2222 usecase->stream.out->sample_rate,
2223 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302224 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2225 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002226 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2227 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2228 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2229 }
2230
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002231 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002232 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002233 audio_extn_gef_notify_device_config(
2234 usecase->stream.out->devices,
2235 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002236 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002237 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002238 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302239 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002240 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002241
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002242 /* If input stream is already running then effect needs to be
2243 applied on the new input device that's being enabled here. */
2244 if ((in_snd_device != SND_DEVICE_NONE) && (!adev->active_input->standby))
2245 check_and_enable_effect(adev);
2246
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002247 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002248 /* Enable aanc only if voice call exists */
2249 if (voice_is_call_state_active(adev))
2250 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2251
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002252 /* Enable sidetone only if other voice/voip call already exists */
2253 if (voice_is_call_state_active(adev) ||
2254 voice_extn_compress_voip_is_started(adev))
2255 voice_set_sidetone(adev, out_snd_device, true);
2256 }
2257
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002258 /* Applicable only on the targets that has external modem.
2259 * Enable device command should be sent to modem only after
2260 * enabling voice call mixer controls
2261 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002262 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002263 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2264 out_snd_device,
2265 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302266
2267 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2268
2269 if (usecase->type == VOIP_CALL) {
2270 if (adev->active_input != NULL &&
2271 !adev->active_input->standby) {
2272 if (is_bt_soc_on(adev) == false){
2273 ALOGD("BT SCO MIC disconnected while in connection");
2274 if (adev->active_input->pcm != NULL)
2275 pcm_stop(adev->active_input->pcm);
2276 }
2277 }
2278 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2279 && usecase->stream.out->started) {
2280 if (is_bt_soc_on(adev) == false) {
2281 ALOGD("BT SCO/A2DP disconnected while in connection");
2282 out_standby_l(&usecase->stream.out->stream.common);
2283 }
2284 }
2285 } else if ((usecase->stream.out != NULL) &&
2286 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2287 usecase->stream.out->started) {
2288 if (is_bt_soc_on(adev) == false) {
2289 ALOGD("BT SCO/A2dp disconnected while in connection");
2290 out_standby_l(&usecase->stream.out->stream.common);
2291 }
2292 }
2293 }
2294
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302295 ALOGD("%s: done",__func__);
2296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 return status;
2298}
2299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300static int stop_input_stream(struct stream_in *in)
2301{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302302 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 struct audio_usecase *uc_info;
2304 struct audio_device *adev = in->dev;
2305
Eric Laurent994a6932013-07-17 11:51:42 -07002306 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002308 uc_info = get_usecase_from_list(adev, in->usecase);
2309 if (uc_info == NULL) {
2310 ALOGE("%s: Could not find the usecase (%d) in the list",
2311 __func__, in->usecase);
2312 return -EINVAL;
2313 }
2314
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002315 /* Close in-call recording streams */
2316 voice_check_and_stop_incall_rec_usecase(adev, in);
2317
Eric Laurent150dbfe2013-02-27 14:31:02 -08002318 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002319 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002320
2321 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002322 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002324 list_remove(&uc_info->list);
2325 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002327 adev->active_input = get_next_active_input(adev);
2328
Eric Laurent994a6932013-07-17 11:51:42 -07002329 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 return ret;
2331}
2332
2333int start_input_stream(struct stream_in *in)
2334{
2335 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002336 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337 struct audio_usecase *uc_info;
2338 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002339 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002340 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341
Mingming Yin2664a5b2015-09-03 10:53:11 -07002342 if (get_usecase_from_list(adev, usecase) == NULL)
2343 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302344 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2345 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002346
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302347 if (CARD_STATUS_OFFLINE == in->card_status||
2348 CARD_STATUS_OFFLINE == adev->card_status) {
2349 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302350 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302351 goto error_config;
2352 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302353
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302354 if (audio_is_bluetooth_sco_device(in->device)) {
2355 if (!adev->bt_sco_on) {
2356 ALOGE("%s: SCO profile is not ready, return error", __func__);
2357 ret = -EIO;
2358 goto error_config;
2359 }
2360 }
2361
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002362 /* Check if source matches incall recording usecase criteria */
2363 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2364 if (ret)
2365 goto error_config;
2366 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002367 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2368
2369 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2370 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2371 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002372 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002373 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002374
Eric Laurentb23d5282013-05-14 15:27:20 -07002375 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 if (in->pcm_device_id < 0) {
2377 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2378 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002379 ret = -EINVAL;
2380 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002382
2383 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002385
2386 if (!uc_info) {
2387 ret = -ENOMEM;
2388 goto error_config;
2389 }
2390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 uc_info->id = in->usecase;
2392 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002393 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394 uc_info->devices = in->device;
2395 uc_info->in_snd_device = SND_DEVICE_NONE;
2396 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002398 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302399 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2400 adev->perf_lock_opts,
2401 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002402 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403
Haynes Mathew George16081042017-05-31 17:16:49 -07002404 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302405 ret = audio_extn_cin_start_input_stream(in);
2406 if (ret)
2407 goto error_open;
2408 else
2409 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002410 }
2411
Haynes Mathew George16081042017-05-31 17:16:49 -07002412 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002413 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002414 ALOGE("%s: pcm stream not ready", __func__);
2415 goto error_open;
2416 }
2417 ret = pcm_start(in->pcm);
2418 if (ret < 0) {
2419 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2420 goto error_open;
2421 }
2422 } else {
2423 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2424 unsigned int pcm_open_retry_count = 0;
2425
2426 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2427 flags |= PCM_MMAP | PCM_NOIRQ;
2428 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2429 } else if (in->realtime) {
2430 flags |= PCM_MMAP | PCM_NOIRQ;
2431 }
2432
Garmond Leunge2433c32017-09-28 21:51:22 -07002433 if (audio_extn_ffv_get_stream() == in) {
2434 ALOGD("%s: ffv stream, update pcm config", __func__);
2435 audio_extn_ffv_update_pcm_config(&config);
2436 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002437 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2438 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2439
2440 while (1) {
2441 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002442 flags, &config);
Haynes Mathew George16081042017-05-31 17:16:49 -07002443 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2444 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2445 if (in->pcm != NULL) {
2446 pcm_close(in->pcm);
2447 in->pcm = NULL;
2448 }
2449 if (pcm_open_retry_count-- == 0) {
2450 ret = -EIO;
2451 goto error_open;
2452 }
2453 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2454 continue;
2455 }
2456 break;
2457 }
2458
2459 ALOGV("%s: pcm_prepare", __func__);
2460 ret = pcm_prepare(in->pcm);
2461 if (ret < 0) {
2462 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2463 pcm_close(in->pcm);
2464 in->pcm = NULL;
2465 goto error_open;
2466 }
2467 register_in_stream(in);
2468 if (in->realtime) {
2469 ret = pcm_start(in->pcm);
2470 if (ret < 0) {
2471 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002472 pcm_close(in->pcm);
2473 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002474 goto error_open;
2475 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002476 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002477 }
2478
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002479 check_and_enable_effect(adev);
2480
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302481done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302482 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002483 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002484
Eric Laurentc8400632013-02-14 19:04:54 -08002485 return ret;
2486
2487error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302488 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002490error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302491 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302492 /*
2493 * sleep 50ms to allow sufficient time for kernel
2494 * drivers to recover incases like SSR.
2495 */
2496 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002497 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002498
2499 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500}
2501
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002502void lock_input_stream(struct stream_in *in)
2503{
2504 pthread_mutex_lock(&in->pre_lock);
2505 pthread_mutex_lock(&in->lock);
2506 pthread_mutex_unlock(&in->pre_lock);
2507}
2508
2509void lock_output_stream(struct stream_out *out)
2510{
2511 pthread_mutex_lock(&out->pre_lock);
2512 pthread_mutex_lock(&out->lock);
2513 pthread_mutex_unlock(&out->pre_lock);
2514}
2515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002516/* must be called with out->lock locked */
2517static int send_offload_cmd_l(struct stream_out* out, int command)
2518{
2519 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2520
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002521 if (!cmd) {
2522 ALOGE("failed to allocate mem for command 0x%x", command);
2523 return -ENOMEM;
2524 }
2525
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 ALOGVV("%s %d", __func__, command);
2527
2528 cmd->cmd = command;
2529 list_add_tail(&out->offload_cmd_list, &cmd->node);
2530 pthread_cond_signal(&out->offload_cond);
2531 return 0;
2532}
2533
2534/* must be called iwth out->lock locked */
2535static void stop_compressed_output_l(struct stream_out *out)
2536{
2537 out->offload_state = OFFLOAD_STATE_IDLE;
2538 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002539 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002540 if (out->compr != NULL) {
2541 compress_stop(out->compr);
2542 while (out->offload_thread_blocked) {
2543 pthread_cond_wait(&out->cond, &out->lock);
2544 }
2545 }
2546}
2547
Varun Balaraje49253e2017-07-06 19:48:56 +05302548bool is_interactive_usecase(audio_usecase_t uc_id)
2549{
2550 unsigned int i;
2551 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2552 if (uc_id == interactive_usecases[i])
2553 return true;
2554 }
2555 return false;
2556}
2557
2558static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2559{
2560 audio_usecase_t ret_uc = USECASE_INVALID;
2561 unsigned int intract_uc_index;
2562 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2563
2564 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2565 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2566 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2567 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2568 ret_uc = interactive_usecases[intract_uc_index];
2569 break;
2570 }
2571 }
2572
2573 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2574 return ret_uc;
2575}
2576
2577static void free_interactive_usecase(struct audio_device *adev,
2578 audio_usecase_t uc_id)
2579{
2580 unsigned int interact_uc_index;
2581 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2582
2583 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2584 if (interactive_usecases[interact_uc_index] == uc_id) {
2585 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2586 break;
2587 }
2588 }
2589 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2590}
2591
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002592bool is_offload_usecase(audio_usecase_t uc_id)
2593{
2594 unsigned int i;
2595 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2596 if (uc_id == offload_usecases[i])
2597 return true;
2598 }
2599 return false;
2600}
2601
Dhananjay Kumarac341582017-02-23 23:42:25 +05302602static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002603{
vivek mehta446c3962015-09-14 10:57:35 -07002604 audio_usecase_t ret_uc = USECASE_INVALID;
2605 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002606 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002607 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302608 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002609 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2610 else
2611 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002612
vivek mehta446c3962015-09-14 10:57:35 -07002613 pthread_mutex_lock(&adev->lock);
2614 if (get_usecase_from_list(adev, ret_uc) != NULL)
2615 ret_uc = USECASE_INVALID;
2616 pthread_mutex_unlock(&adev->lock);
2617
2618 return ret_uc;
2619 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002620
2621 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002622 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2623 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2624 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2625 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002626 break;
2627 }
2628 }
vivek mehta446c3962015-09-14 10:57:35 -07002629
2630 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2631 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002632}
2633
2634static void free_offload_usecase(struct audio_device *adev,
2635 audio_usecase_t uc_id)
2636{
vivek mehta446c3962015-09-14 10:57:35 -07002637 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002638 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002639
2640 if (!adev->multi_offload_enable)
2641 return;
2642
2643 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2644 if (offload_usecases[offload_uc_index] == uc_id) {
2645 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002646 break;
2647 }
2648 }
2649 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2650}
2651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652static void *offload_thread_loop(void *context)
2653{
2654 struct stream_out *out = (struct stream_out *) context;
2655 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002656 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2659 set_sched_policy(0, SP_FOREGROUND);
2660 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2661
2662 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002663 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664 for (;;) {
2665 struct offload_cmd *cmd = NULL;
2666 stream_callback_event_t event;
2667 bool send_callback = false;
2668
2669 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2670 __func__, list_empty(&out->offload_cmd_list),
2671 out->offload_state);
2672 if (list_empty(&out->offload_cmd_list)) {
2673 ALOGV("%s SLEEPING", __func__);
2674 pthread_cond_wait(&out->offload_cond, &out->lock);
2675 ALOGV("%s RUNNING", __func__);
2676 continue;
2677 }
2678
2679 item = list_head(&out->offload_cmd_list);
2680 cmd = node_to_item(item, struct offload_cmd, node);
2681 list_remove(item);
2682
2683 ALOGVV("%s STATE %d CMD %d out->compr %p",
2684 __func__, out->offload_state, cmd->cmd, out->compr);
2685
2686 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2687 free(cmd);
2688 break;
2689 }
2690
2691 if (out->compr == NULL) {
2692 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002693 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002694 pthread_cond_signal(&out->cond);
2695 continue;
2696 }
2697 out->offload_thread_blocked = true;
2698 pthread_mutex_unlock(&out->lock);
2699 send_callback = false;
2700 switch(cmd->cmd) {
2701 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002702 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002703 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002704 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002705 send_callback = true;
2706 event = STREAM_CBK_EVENT_WRITE_READY;
2707 break;
2708 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002709 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302710 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002711 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302712 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002713 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302714 if (ret < 0)
2715 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302716 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302717 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002718 compress_drain(out->compr);
2719 else
2720 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302721 if (ret != -ENETRESET) {
2722 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302723 pthread_mutex_lock(&out->lock);
2724 out->send_new_metadata = 1;
2725 out->send_next_track_params = true;
2726 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302727 event = STREAM_CBK_EVENT_DRAIN_READY;
2728 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2729 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302730 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002731 break;
2732 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002733 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002734 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002735 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002736 send_callback = true;
2737 event = STREAM_CBK_EVENT_DRAIN_READY;
2738 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302739 case OFFLOAD_CMD_ERROR:
2740 ALOGD("copl(%p): sending error callback to AF", out);
2741 send_callback = true;
2742 event = STREAM_CBK_EVENT_ERROR;
2743 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 default:
2745 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2746 break;
2747 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002748 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002749 out->offload_thread_blocked = false;
2750 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002751 if (send_callback && out->client_callback) {
2752 ALOGVV("%s: sending client_callback event %d", __func__, event);
2753 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002754 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002755 free(cmd);
2756 }
2757
2758 pthread_cond_signal(&out->cond);
2759 while (!list_empty(&out->offload_cmd_list)) {
2760 item = list_head(&out->offload_cmd_list);
2761 list_remove(item);
2762 free(node_to_item(item, struct offload_cmd, node));
2763 }
2764 pthread_mutex_unlock(&out->lock);
2765
2766 return NULL;
2767}
2768
2769static int create_offload_callback_thread(struct stream_out *out)
2770{
2771 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2772 list_init(&out->offload_cmd_list);
2773 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2774 offload_thread_loop, out);
2775 return 0;
2776}
2777
2778static int destroy_offload_callback_thread(struct stream_out *out)
2779{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002780 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002781 stop_compressed_output_l(out);
2782 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2783
2784 pthread_mutex_unlock(&out->lock);
2785 pthread_join(out->offload_thread, (void **) NULL);
2786 pthread_cond_destroy(&out->offload_cond);
2787
2788 return 0;
2789}
2790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791static int stop_output_stream(struct stream_out *out)
2792{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302793 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 struct audio_usecase *uc_info;
2795 struct audio_device *adev = out->dev;
2796
Eric Laurent994a6932013-07-17 11:51:42 -07002797 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002798 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 uc_info = get_usecase_from_list(adev, out->usecase);
2800 if (uc_info == NULL) {
2801 ALOGE("%s: Could not find the usecase (%d) in the list",
2802 __func__, out->usecase);
2803 return -EINVAL;
2804 }
2805
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002806 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302807 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002808 if (adev->visualizer_stop_output != NULL)
2809 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002810
2811 audio_extn_dts_remove_state_notifier_node(out->usecase);
2812
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002813 if (adev->offload_effects_stop_output != NULL)
2814 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2815 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002816
Eric Laurent150dbfe2013-02-27 14:31:02 -08002817 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002818 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002819
2820 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002821 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002823 if (is_offload_usecase(out->usecase)) {
2824 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2825 adev->dsp_bit_width_enforce_mode,
2826 false);
2827 }
2828
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002829 list_remove(&uc_info->list);
2830 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302831 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002832 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302833 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002834 ALOGV("Disable passthrough , reset mixer to pcm");
2835 /* NO_PASSTHROUGH */
2836 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002837 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002838 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2839 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002840
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302841 /* Must be called after removing the usecase from list */
2842 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302843 audio_extn_keep_alive_start();
2844
Manish Dewangan21a850a2017-08-14 12:03:55 +05302845 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002846 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2847 if (ret < 0)
2848 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2849 }
2850
Eric Laurent994a6932013-07-17 11:51:42 -07002851 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 return ret;
2853}
2854
2855int start_output_stream(struct stream_out *out)
2856{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 struct audio_usecase *uc_info;
2859 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002860 char mixer_ctl_name[128];
2861 struct mixer_ctl *ctl = NULL;
2862 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302863 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002865 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2866 ret = -EINVAL;
2867 goto error_config;
2868 }
2869
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302870 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2871 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2872 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302873
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302874 if (CARD_STATUS_OFFLINE == out->card_status ||
2875 CARD_STATUS_OFFLINE == adev->card_status) {
2876 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302877 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302878 goto error_config;
2879 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302880
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302881 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2882 if (!audio_extn_a2dp_is_ready()) {
2883 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302884 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302885 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302886 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2887 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2888 ret = -EAGAIN;
2889 goto error_config;
2890 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302891 }
2892 }
2893 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302894 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2895 if (!adev->bt_sco_on) {
2896 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2897 //combo usecase just by pass a2dp
2898 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2899 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2900 } else {
2901 ALOGE("%s: SCO profile is not ready, return error", __func__);
2902 ret = -EAGAIN;
2903 goto error_config;
2904 }
2905 }
2906 }
2907
Eric Laurentb23d5282013-05-14 15:27:20 -07002908 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 if (out->pcm_device_id < 0) {
2910 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2911 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002912 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 }
2915
2916 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002917
2918 if (!uc_info) {
2919 ret = -ENOMEM;
2920 goto error_config;
2921 }
2922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 uc_info->id = out->usecase;
2924 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002925 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002926 uc_info->devices = out->devices;
2927 uc_info->in_snd_device = SND_DEVICE_NONE;
2928 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002929 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302931 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2932 adev->perf_lock_opts,
2933 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302934
2935 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2936 audio_extn_keep_alive_stop();
2937 if (audio_extn_passthru_is_enabled() &&
2938 audio_extn_passthru_is_passthrough_stream(out)) {
2939 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302940 }
2941 }
2942
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302943 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2944 (!audio_extn_a2dp_is_ready())) {
2945 if (!a2dp_combo) {
2946 check_a2dp_restore_l(adev, out, false);
2947 } else {
2948 audio_devices_t dev = out->devices;
2949 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2950 select_devices(adev, out->usecase);
2951 out->devices = dev;
2952 }
2953 } else {
2954 select_devices(adev, out->usecase);
2955 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002956
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002957 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2958 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002959
2960 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2961 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2962 ALOGE("%s: pcm stream not ready", __func__);
2963 goto error_open;
2964 }
2965 ret = pcm_start(out->pcm);
2966 if (ret < 0) {
2967 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2968 goto error_open;
2969 }
2970 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002971 unsigned int flags = PCM_OUT;
2972 unsigned int pcm_open_retry_count = 0;
2973 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2974 flags |= PCM_MMAP | PCM_NOIRQ;
2975 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002976 } else if (out->realtime) {
2977 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002978 } else
2979 flags |= PCM_MONOTONIC;
2980
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002981 if ((adev->vr_audio_mode_enabled) &&
2982 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2983 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2984 "PCM_Dev %d Topology", out->pcm_device_id);
2985 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2986 if (!ctl) {
2987 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2988 __func__, mixer_ctl_name);
2989 } else {
2990 //if success use ULLPP
2991 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2992 __func__, mixer_ctl_name, out->pcm_device_id);
2993 //There is a still a possibility that some sessions
2994 // that request for FAST|RAW when 3D audio is active
2995 //can go through ULLPP. Ideally we expects apps to
2996 //listen to audio focus and stop concurrent playback
2997 //Also, we will look for mode flag (voice_in_communication)
2998 //before enabling the realtime flag.
2999 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3000 }
3001 }
3002
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003003 while (1) {
3004 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3005 flags, &out->config);
3006 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3007 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3008 if (out->pcm != NULL) {
3009 pcm_close(out->pcm);
3010 out->pcm = NULL;
3011 }
3012 if (pcm_open_retry_count-- == 0) {
3013 ret = -EIO;
3014 goto error_open;
3015 }
3016 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3017 continue;
3018 }
3019 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003021
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003022 ALOGV("%s: pcm_prepare", __func__);
3023 if (pcm_is_ready(out->pcm)) {
3024 ret = pcm_prepare(out->pcm);
3025 if (ret < 0) {
3026 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3027 pcm_close(out->pcm);
3028 out->pcm = NULL;
3029 goto error_open;
3030 }
3031 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05303032 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303033 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08003034 // apply volume for voip playback after path is set up
3035 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3036 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003038 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303039 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003040 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3041 adev->dsp_bit_width_enforce_mode,
3042 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003044 out->compr = compress_open(adev->snd_card,
3045 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 COMPRESS_IN, &out->compr_config);
3047 if (out->compr && !is_compress_ready(out->compr)) {
3048 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
3049 compress_close(out->compr);
3050 out->compr = NULL;
3051 ret = -EIO;
3052 goto error_open;
3053 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303054 /* compress_open sends params of the track, so reset the flag here */
3055 out->is_compr_metadata_avail = false;
3056
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003057 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003059
Fred Oh3f43e742015-03-04 18:42:34 -08003060 /* Since small bufs uses blocking writes, a write will be blocked
3061 for the default max poll time (20s) in the event of an SSR.
3062 Reduce the poll time to observe and deal with SSR faster.
3063 */
Ashish Jain5106d362016-05-11 19:23:33 +05303064 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003065 compress_set_max_poll_wait(out->compr, 1000);
3066 }
3067
Manish Dewangan69426c82017-01-30 17:35:36 +05303068 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303069 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303070
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003071 audio_extn_dts_create_state_notifier_node(out->usecase);
3072 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3073 popcount(out->channel_mask),
3074 out->playback_started);
3075
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003076#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303077 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003078 audio_extn_dolby_send_ddp_endp_params(adev);
3079#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303080 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3081 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003082 if (adev->visualizer_start_output != NULL)
3083 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3084 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303085 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003086 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003087 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003089
3090 if (ret == 0) {
3091 register_out_stream(out);
3092 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003093 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3094 ALOGE("%s: pcm stream not ready", __func__);
3095 goto error_open;
3096 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003097 ret = pcm_start(out->pcm);
3098 if (ret < 0)
3099 goto error_open;
3100 }
3101 }
3102
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303103 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003104 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003105
Manish Dewangan21a850a2017-08-14 12:03:55 +05303106 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003107 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003108 if (ret < 0)
3109 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3110 }
3111
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003112 // consider a scenario where on pause lower layers are tear down.
3113 // so on resume, swap mixer control need to be sent only when
3114 // backend is active, hence rather than sending from enable device
3115 // sending it from start of streamtream
3116
3117 platform_set_swap_channels(adev, true);
3118
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003119 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303121 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003123error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303124 /*
3125 * sleep 50ms to allow sufficient time for kernel
3126 * drivers to recover incases like SSR.
3127 */
3128 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003129 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130}
3131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132static int check_input_parameters(uint32_t sample_rate,
3133 audio_format_t format,
3134 int channel_count)
3135{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003136 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303138 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3139 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3140 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003141 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003142 !audio_extn_compr_cap_format_supported(format))
3143 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003144
3145 switch (channel_count) {
3146 case 1:
3147 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303148 case 3:
3149 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003150 case 6:
3151 break;
3152 default:
3153 ret = -EINVAL;
3154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155
3156 switch (sample_rate) {
3157 case 8000:
3158 case 11025:
3159 case 12000:
3160 case 16000:
3161 case 22050:
3162 case 24000:
3163 case 32000:
3164 case 44100:
3165 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303166 case 96000:
3167 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 break;
3169 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003170 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 }
3172
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003173 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174}
3175
3176static size_t get_input_buffer_size(uint32_t sample_rate,
3177 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003178 int channel_count,
3179 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
3181 size_t size = 0;
3182
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003183 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3184 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003186 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003187 if (is_low_latency)
3188 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303189
3190 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003192 /* make sure the size is multiple of 32 bytes
3193 * At 48 kHz mono 16-bit PCM:
3194 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3195 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3196 */
3197 size += 0x1f;
3198 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003199
3200 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201}
3202
Ashish Jain058165c2016-09-28 23:18:48 +05303203static size_t get_output_period_size(uint32_t sample_rate,
3204 audio_format_t format,
3205 int channel_count,
3206 int duration /*in millisecs*/)
3207{
3208 size_t size = 0;
3209 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3210
3211 if ((duration == 0) || (sample_rate == 0) ||
3212 (bytes_per_sample == 0) || (channel_count == 0)) {
3213 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3214 bytes_per_sample, channel_count);
3215 return -EINVAL;
3216 }
3217
3218 size = (sample_rate *
3219 duration *
3220 bytes_per_sample *
3221 channel_count) / 1000;
3222 /*
3223 * To have same PCM samples for all channels, the buffer size requires to
3224 * be multiple of (number of channels * bytes per sample)
3225 * For writes to succeed, the buffer must be written at address which is multiple of 32
3226 */
3227 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3228
3229 return (size/(channel_count * bytes_per_sample));
3230}
3231
Ashish Jain5106d362016-05-11 19:23:33 +05303232static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
3233{
3234 uint64_t actual_frames_rendered = 0;
3235 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3236
3237 /* This adjustment accounts for buffering after app processor.
3238 * It is based on estimated DSP latency per use case, rather than exact.
3239 */
3240 int64_t platform_latency = platform_render_latency(out->usecase) *
3241 out->sample_rate / 1000000LL;
3242
3243 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3244 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3245 * hence only estimate.
3246 */
3247 int64_t signed_frames = out->written - kernel_buffer_size;
3248
3249 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3250
3251 if (signed_frames > 0)
3252 actual_frames_rendered = signed_frames;
3253
3254 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3255 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3256 (long long int)out->written, (int)kernel_buffer_size,
3257 audio_bytes_per_sample(out->compr_config.codec->format),
3258 popcount(out->channel_mask));
3259
3260 return actual_frames_rendered;
3261}
3262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3264{
3265 struct stream_out *out = (struct stream_out *)stream;
3266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268}
3269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003270static int out_set_sample_rate(struct audio_stream *stream __unused,
3271 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272{
3273 return -ENOSYS;
3274}
3275
3276static size_t out_get_buffer_size(const struct audio_stream *stream)
3277{
3278 struct stream_out *out = (struct stream_out *)stream;
3279
Varun Balaraje49253e2017-07-06 19:48:56 +05303280 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303281 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303282 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303283 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3284 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3285 else
3286 return out->compr_config.fragment_size;
3287 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003288 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003289 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3290 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 +05303291 else if (is_offload_usecase(out->usecase) &&
3292 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303293 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003295 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003296 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297}
3298
3299static uint32_t out_get_channels(const struct audio_stream *stream)
3300{
3301 struct stream_out *out = (struct stream_out *)stream;
3302
3303 return out->channel_mask;
3304}
3305
3306static audio_format_t out_get_format(const struct audio_stream *stream)
3307{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 struct stream_out *out = (struct stream_out *)stream;
3309
3310 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003313static int out_set_format(struct audio_stream *stream __unused,
3314 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315{
3316 return -ENOSYS;
3317}
3318
3319static int out_standby(struct audio_stream *stream)
3320{
3321 struct stream_out *out = (struct stream_out *)stream;
3322 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003323 struct audio_usecase *uc_info;
3324 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003325 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303327 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3328 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003330 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003332 if (adev->adm_deregister_stream)
3333 adev->adm_deregister_stream(adev->adm_data, out->handle);
3334
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003335 if (is_offload_usecase(out->usecase))
3336 stop_compressed_output_l(out);
3337
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003338 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003340 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3341 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303342 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003343 pthread_mutex_unlock(&adev->lock);
3344 pthread_mutex_unlock(&out->lock);
3345 ALOGD("VOIP output entered standby");
3346 return 0;
3347 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 if (out->pcm) {
3349 pcm_close(out->pcm);
3350 out->pcm = NULL;
3351 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003352 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3353 do_stop = out->playback_started;
3354 out->playback_started = false;
3355 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003357 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303358 out->send_next_track_params = false;
3359 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003360 out->gapless_mdata.encoder_delay = 0;
3361 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 if (out->compr != NULL) {
3363 compress_close(out->compr);
3364 out->compr = NULL;
3365 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003366 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003367 if (do_stop) {
3368 stop_output_stream(out);
3369 }
kunleiza9d11682017-08-04 14:14:09 +08003370 //restore output device for active usecase when current snd device and output device mismatch
3371 list_for_each(node, &adev->usecase_list) {
3372 uc_info = node_to_item(node, struct audio_usecase, list);
3373 if ((uc_info->type == PCM_PLAYBACK) &&
3374 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3375 select_devices(adev, uc_info->id);
3376 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003377 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 }
3379 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303380 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381 return 0;
3382}
3383
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303384static int out_on_error(struct audio_stream *stream)
3385{
3386 struct stream_out *out = (struct stream_out *)stream;
3387 bool do_standby = false;
3388
3389 lock_output_stream(out);
3390 if (!out->standby) {
3391 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3392 stop_compressed_output_l(out);
3393 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3394 } else
3395 do_standby = true;
3396 }
3397 pthread_mutex_unlock(&out->lock);
3398
3399 if (do_standby)
3400 return out_standby(&out->stream.common);
3401
3402 return 0;
3403}
3404
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303405/*
3406 *standby implementation without locks, assumes that the callee already
3407 *has taken adev and out lock.
3408 */
3409int out_standby_l(struct audio_stream *stream)
3410{
3411 struct stream_out *out = (struct stream_out *)stream;
3412 struct audio_device *adev = out->dev;
3413
3414 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3415 stream, out->usecase, use_case_table[out->usecase]);
3416
3417 if (!out->standby) {
3418 if (adev->adm_deregister_stream)
3419 adev->adm_deregister_stream(adev->adm_data, out->handle);
3420
3421 if (is_offload_usecase(out->usecase))
3422 stop_compressed_output_l(out);
3423
3424 out->standby = true;
3425 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3426 voice_extn_compress_voip_close_output_stream(stream);
3427 out->started = 0;
3428 ALOGD("VOIP output entered standby");
3429 return 0;
3430 } else if (!is_offload_usecase(out->usecase)) {
3431 if (out->pcm) {
3432 pcm_close(out->pcm);
3433 out->pcm = NULL;
3434 }
3435 } else {
3436 ALOGD("copl(%p):standby", out);
3437 out->send_next_track_params = false;
3438 out->is_compr_metadata_avail = false;
3439 out->gapless_mdata.encoder_delay = 0;
3440 out->gapless_mdata.encoder_padding = 0;
3441 if (out->compr != NULL) {
3442 compress_close(out->compr);
3443 out->compr = NULL;
3444 }
3445 }
3446 stop_output_stream(out);
3447 }
3448 ALOGD("%s: exit", __func__);
3449 return 0;
3450}
3451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003452static int out_dump(const struct audio_stream *stream __unused,
3453 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454{
3455 return 0;
3456}
3457
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003458static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3459{
3460 int ret = 0;
3461 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003462
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003463 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003464 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003465 return -EINVAL;
3466 }
3467
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303468 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003469
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003470 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3471 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303472 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003473 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003474 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3475 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303476 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003477 }
3478
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003479 ALOGV("%s new encoder delay %u and padding %u", __func__,
3480 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3481
3482 return 0;
3483}
3484
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003485static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3486{
3487 return out == adev->primary_output || out == adev->voice_tx_output;
3488}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003489
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303490// note: this call is safe only if the stream_cb is
3491// removed first in close_output_stream (as is done now).
3492static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3493{
3494 if (!stream || !parms)
3495 return;
3496
3497 struct stream_out *out = (struct stream_out *)stream;
3498 struct audio_device *adev = out->dev;
3499
3500 card_status_t status;
3501 int card;
3502 if (parse_snd_card_status(parms, &card, &status) < 0)
3503 return;
3504
3505 pthread_mutex_lock(&adev->lock);
3506 bool valid_cb = (card == adev->snd_card);
3507 pthread_mutex_unlock(&adev->lock);
3508
3509 if (!valid_cb)
3510 return;
3511
3512 lock_output_stream(out);
3513 if (out->card_status != status)
3514 out->card_status = status;
3515 pthread_mutex_unlock(&out->lock);
3516
3517 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3518 use_case_table[out->usecase],
3519 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3520
3521 if (status == CARD_STATUS_OFFLINE)
3522 out_on_error(stream);
3523
3524 return;
3525}
3526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3528{
3529 struct stream_out *out = (struct stream_out *)stream;
3530 struct audio_device *adev = out->dev;
3531 struct str_parms *parms;
3532 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003533 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303534 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535
sangwoobc677242013-08-08 16:53:43 +09003536 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003537 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303539 if (!parms)
3540 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003541 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3542 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003544 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003547 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003548 * When HDMI cable is unplugged the music playback is paused and
3549 * the policy manager sends routing=0. But the audioflinger continues
3550 * to write data until standby time (3sec). As the HDMI core is
3551 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003552 * Avoid this by routing audio to speaker until standby.
3553 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003554 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3555 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303556 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003557 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3558 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003559 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303560 /*
3561 * When A2DP is disconnected the
3562 * music playback is paused and the policy manager sends routing=0
3563 * But the audioflingercontinues to write data until standby time
3564 * (3sec). As BT is turned off, the write gets blocked.
3565 * Avoid this by routing audio to speaker until standby.
3566 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003567 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303568 (val == AUDIO_DEVICE_NONE)) {
3569 val = AUDIO_DEVICE_OUT_SPEAKER;
3570 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303571 /* To avoid a2dp to sco overlapping / BT device improper state
3572 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303573 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303574 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3575 if (!audio_extn_a2dp_is_ready()) {
3576 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3577 //combo usecase just by pass a2dp
3578 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303579 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303580 } else {
3581 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3582 /* update device to a2dp and don't route as BT returned error
3583 * However it is still possible a2dp routing called because
3584 * of current active device disconnection (like wired headset)
3585 */
3586 out->devices = val;
3587 pthread_mutex_unlock(&out->lock);
3588 pthread_mutex_unlock(&adev->lock);
3589 goto error;
3590 }
3591 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303592 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003593 /*
3594 * select_devices() call below switches all the usecases on the same
3595 * backend to the new device. Refer to check_usecases_codec_backend() in
3596 * the select_devices(). But how do we undo this?
3597 *
3598 * For example, music playback is active on headset (deep-buffer usecase)
3599 * and if we go to ringtones and select a ringtone, low-latency usecase
3600 * will be started on headset+speaker. As we can't enable headset+speaker
3601 * and headset devices at the same time, select_devices() switches the music
3602 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3603 * So when the ringtone playback is completed, how do we undo the same?
3604 *
3605 * We are relying on the out_set_parameters() call on deep-buffer output,
3606 * once the ringtone playback is ended.
3607 * NOTE: We should not check if the current devices are same as new devices.
3608 * Because select_devices() must be called to switch back the music
3609 * playback to headset.
3610 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003611 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003612 audio_devices_t new_dev = val;
3613 bool same_dev = out->devices == new_dev;
3614 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003615
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003616 if (output_drives_call(adev, out)) {
3617 if(!voice_is_in_call(adev)) {
3618 if (adev->mode == AUDIO_MODE_IN_CALL) {
3619 adev->current_call_output = out;
3620 ret = voice_start_call(adev);
3621 }
3622 } else {
3623 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003624 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003625 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003626 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003627
3628 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003629 if (!same_dev) {
3630 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303631 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3632 adev->perf_lock_opts,
3633 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003634 if (adev->adm_on_routing_change)
3635 adev->adm_on_routing_change(adev->adm_data,
3636 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003637 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303638 if (!bypass_a2dp) {
3639 select_devices(adev, out->usecase);
3640 } else {
3641 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3642 select_devices(adev, out->usecase);
3643 out->devices = new_dev;
3644 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003645
3646 if (!same_dev) {
3647 // on device switch force swap, lower functions will make sure
3648 // to check if swap is allowed or not.
3649 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05303650 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003651 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303652 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3653 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003654 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303655 pthread_mutex_lock(&out->compr_mute_lock);
3656 out->a2dp_compress_mute = false;
3657 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3658 pthread_mutex_unlock(&out->compr_mute_lock);
3659 }
3660
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003661 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003662 }
3663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003665 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003667
3668 if (out == adev->primary_output) {
3669 pthread_mutex_lock(&adev->lock);
3670 audio_extn_set_parameters(adev, parms);
3671 pthread_mutex_unlock(&adev->lock);
3672 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003673 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003674 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003675 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003676
3677 audio_extn_dts_create_state_notifier_node(out->usecase);
3678 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3679 popcount(out->channel_mask),
3680 out->playback_started);
3681
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003682 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003683 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003684
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303685 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3686 if (err >= 0) {
3687 strlcpy(out->profile, value, sizeof(out->profile));
3688 ALOGV("updating stream profile with value '%s'", out->profile);
3689 lock_output_stream(out);
3690 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3691 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003692 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303693 out->sample_rate, out->bit_width,
3694 out->channel_mask, out->profile,
3695 &out->app_type_cfg);
3696 pthread_mutex_unlock(&out->lock);
3697 }
3698
Alexy Joseph98988832017-01-13 14:56:59 -08003699 //suspend, resume handling block
3700 if (out->dynamic_pm_qos_enabled) {
3701 //check suspend parameter only for low latency and if the property
3702 //is enabled
3703 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3704 ALOGI("%s: got suspend_playback %s", __func__, value);
3705 lock_output_stream(out);
3706 if (!strncmp(value, "false", 5)) {
3707 //suspend_playback=false is supposed to set QOS value back to 75%
3708 //the mixer control sent with value Enable will achieve that
3709 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3710 } else if (!strncmp (value, "true", 4)) {
3711 //suspend_playback=true is supposed to remove QOS value
3712 //resetting the mixer control will set the default value
3713 //for the mixer control which is Disable and this removes the QOS vote
3714 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3715 } else {
3716 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3717 " got %s", __func__, value);
3718 ret = -1;
3719 }
3720
3721 if (ret != 0) {
3722 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3723 __func__, out->pm_qos_mixer_path, ret);
3724 }
3725
3726 pthread_mutex_unlock(&out->lock);
3727 }
3728 }
3729 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303731error:
Eric Laurent994a6932013-07-17 11:51:42 -07003732 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 return ret;
3734}
3735
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003736static bool stream_get_parameter_channels(struct str_parms *query,
3737 struct str_parms *reply,
3738 audio_channel_mask_t *supported_channel_masks) {
3739 int ret = -1;
3740 char value[512];
3741 bool first = true;
3742 size_t i, j;
3743
3744 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3745 ret = 0;
3746 value[0] = '\0';
3747 i = 0;
3748 while (supported_channel_masks[i] != 0) {
3749 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3750 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
3751 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303752 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003753
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303754 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003755 first = false;
3756 break;
3757 }
3758 }
3759 i++;
3760 }
3761 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3762 }
3763 return ret == 0;
3764}
3765
3766static bool stream_get_parameter_formats(struct str_parms *query,
3767 struct str_parms *reply,
3768 audio_format_t *supported_formats) {
3769 int ret = -1;
3770 char value[256];
3771 size_t i, j;
3772 bool first = true;
3773
3774 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3775 ret = 0;
3776 value[0] = '\0';
3777 i = 0;
3778 while (supported_formats[i] != 0) {
3779 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3780 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
3781 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303782 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003783 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303784 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003785 first = false;
3786 break;
3787 }
3788 }
3789 i++;
3790 }
3791 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
3792 }
3793 return ret == 0;
3794}
3795
3796static bool stream_get_parameter_rates(struct str_parms *query,
3797 struct str_parms *reply,
3798 uint32_t *supported_sample_rates) {
3799
3800 int i;
3801 char value[256];
3802 int ret = -1;
3803 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3804 ret = 0;
3805 value[0] = '\0';
3806 i=0;
3807 int cursor = 0;
3808 while (supported_sample_rates[i]) {
3809 int avail = sizeof(value) - cursor;
3810 ret = snprintf(value + cursor, avail, "%s%d",
3811 cursor > 0 ? "|" : "",
3812 supported_sample_rates[i]);
3813 if (ret < 0 || ret >= avail) {
3814 // if cursor is at the last element of the array
3815 // overwrite with \0 is duplicate work as
3816 // snprintf already put a \0 in place.
3817 // else
3818 // we had space to write the '|' at value[cursor]
3819 // (which will be overwritten) or no space to fill
3820 // the first element (=> cursor == 0)
3821 value[cursor] = '\0';
3822 break;
3823 }
3824 cursor += ret;
3825 ++i;
3826 }
3827 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3828 value);
3829 }
3830 return ret >= 0;
3831}
3832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3834{
3835 struct stream_out *out = (struct stream_out *)stream;
3836 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003837 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 char value[256];
3839 struct str_parms *reply = str_parms_create();
3840 size_t i, j;
3841 int ret;
3842 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003843
3844 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003845 if (reply) {
3846 str_parms_destroy(reply);
3847 }
3848 if (query) {
3849 str_parms_destroy(query);
3850 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003851 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3852 return NULL;
3853 }
3854
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003855 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3857 if (ret >= 0) {
3858 value[0] = '\0';
3859 i = 0;
3860 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003861 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3862 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003864 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003866 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 first = false;
3868 break;
3869 }
3870 }
3871 i++;
3872 }
3873 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3874 str = str_parms_to_str(reply);
3875 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003876 voice_extn_out_get_parameters(out, query, reply);
3877 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003879
Alexy Joseph62142aa2015-11-16 15:10:34 -08003880
3881 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3882 if (ret >= 0) {
3883 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303884 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3885 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003886 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303887 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003888 } else {
3889 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303890 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003891 }
3892 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003893 if (str)
3894 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003895 str = str_parms_to_str(reply);
3896 }
3897
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003898 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3899 if (ret >= 0) {
3900 value[0] = '\0';
3901 i = 0;
3902 first = true;
3903 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003904 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3905 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003906 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003907 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003908 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003909 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003910 first = false;
3911 break;
3912 }
3913 }
3914 i++;
3915 }
3916 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003917 if (str)
3918 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003919 str = str_parms_to_str(reply);
3920 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003921
3922 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3923 if (ret >= 0) {
3924 value[0] = '\0';
3925 i = 0;
3926 first = true;
3927 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003928 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
3929 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003930 if (!first) {
3931 strlcat(value, "|", sizeof(value));
3932 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003933 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08003934 first = false;
3935 break;
3936 }
3937 }
3938 i++;
3939 }
3940 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3941 if (str)
3942 free(str);
3943 str = str_parms_to_str(reply);
3944 }
3945
Alexy Joseph98988832017-01-13 14:56:59 -08003946 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3947 //only low latency track supports suspend_resume
3948 str_parms_add_int(reply, "supports_hw_suspend",
3949 (out->dynamic_pm_qos_enabled));
3950 if (str)
3951 free(str);
3952 str = str_parms_to_str(reply);
3953 }
3954
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 str_parms_destroy(query);
3957 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003958 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 return str;
3960}
3961
3962static uint32_t out_get_latency(const struct audio_stream_out *stream)
3963{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003964 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003965 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003966 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967
Alexy Josephaa54c872014-12-03 02:46:47 -08003968 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303969 lock_output_stream(out);
3970 latency = audio_extn_utils_compress_get_dsp_latency(out);
3971 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003972 } else if ((out->realtime) ||
3973 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003974 // since the buffer won't be filled up faster than realtime,
3975 // return a smaller number
3976 if (out->config.rate)
3977 period_ms = (out->af_period_multiplier * out->config.period_size *
3978 1000) / (out->config.rate);
3979 else
3980 period_ms = 0;
3981 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003982 } else {
3983 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003985 }
3986
yidongh0515e042017-07-06 15:00:34 +08003987 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003988 latency += audio_extn_a2dp_get_encoder_latency();
3989
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303990 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003991 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992}
3993
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303994static float AmpToDb(float amplification)
3995{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303996 float db = DSD_VOLUME_MIN_DB;
3997 if (amplification > 0) {
3998 db = 20 * log10(amplification);
3999 if(db < DSD_VOLUME_MIN_DB)
4000 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304001 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304002 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304003}
4004
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304005static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4006 float right)
4007{
4008 struct stream_out *out = (struct stream_out *)stream;
4009 int volume[2];
4010 char mixer_ctl_name[128];
4011 struct audio_device *adev = out->dev;
4012 struct mixer_ctl *ctl;
4013 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4014 PCM_PLAYBACK);
4015
4016 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4017 "Compress Playback %d Volume", pcm_device_id);
4018 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4019 if (!ctl) {
4020 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4021 __func__, mixer_ctl_name);
4022 return -EINVAL;
4023 }
4024 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4025 __func__, mixer_ctl_name, left, right);
4026 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4027 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4028 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4029
4030 return 0;
4031}
4032
Zhou Song2b8f28f2017-09-11 10:51:38 +08004033static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4034 float right)
4035{
4036 struct stream_out *out = (struct stream_out *)stream;
4037 char mixer_ctl_name[] = "App Type Gain";
4038 struct audio_device *adev = out->dev;
4039 struct mixer_ctl *ctl;
4040 uint32_t set_values[4];
4041
4042 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4043 if (!ctl) {
4044 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4045 __func__, mixer_ctl_name);
4046 return -EINVAL;
4047 }
4048
4049 set_values[0] = 0; //0: Rx Session 1:Tx Session
4050 set_values[1] = out->app_type_cfg.app_type;
4051 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4052 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4053
4054 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4055 return 0;
4056}
4057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058static int out_set_volume(struct audio_stream_out *stream, float left,
4059 float right)
4060{
Eric Laurenta9024de2013-04-04 09:19:12 -07004061 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004062 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304063 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004064
Eric Laurenta9024de2013-04-04 09:19:12 -07004065 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4066 /* only take left channel into account: the API is for stereo anyway */
4067 out->muted = (left == 0.0f);
4068 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004069 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304070 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004071 /*
4072 * Set mute or umute on HDMI passthrough stream.
4073 * Only take left channel into account.
4074 * Mute is 0 and unmute 1
4075 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304076 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304077 } else if (out->format == AUDIO_FORMAT_DSD){
4078 char mixer_ctl_name[128] = "DSD Volume";
4079 struct audio_device *adev = out->dev;
4080 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4081
4082 if (!ctl) {
4083 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4084 __func__, mixer_ctl_name);
4085 return -EINVAL;
4086 }
4087 volume[0] = (int)(AmpToDb(left));
4088 volume[1] = (int)(AmpToDb(right));
4089 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4090 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004091 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304092 pthread_mutex_lock(&out->compr_mute_lock);
4093 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
4094 if (!out->a2dp_compress_mute)
4095 ret = out_set_compr_volume(stream, left, right);
4096 out->volume_l = left;
4097 out->volume_r = right;
4098 pthread_mutex_unlock(&out->compr_mute_lock);
4099 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004100 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004101 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08004102 if (!out->standby)
4103 ret = out_set_voip_volume(stream, left, right);
4104 out->volume_l = left;
4105 out->volume_r = right;
4106 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004107 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109 return -ENOSYS;
4110}
4111
Zhou Songc9672822017-08-16 16:01:39 +08004112static void update_frames_written(struct stream_out *out, size_t bytes)
4113{
4114 size_t bpf = 0;
4115
4116 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4117 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4118 bpf = 1;
4119 else if (!is_offload_usecase(out->usecase))
4120 bpf = audio_bytes_per_sample(out->format) *
4121 audio_channel_count_from_out_mask(out->channel_mask);
4122 if (bpf != 0)
4123 out->written += bytes / bpf;
4124}
4125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4127 size_t bytes)
4128{
4129 struct stream_out *out = (struct stream_out *)stream;
4130 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004131 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304132 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004134 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304135
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304136 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08004137
Dhananjay Kumarac341582017-02-23 23:42:25 +05304138 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304139 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05304140 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
4141 pthread_mutex_unlock(&out->lock);
4142 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05304143 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05304144 ALOGD(" %s: sound card is not active/SSR state", __func__);
4145 ret= -EIO;
4146 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304147 }
4148 }
4149
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304150 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304151 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304152 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304153 goto exit;
4154 }
4155
Haynes Mathew George16081042017-05-31 17:16:49 -07004156 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4157 ret = -EINVAL;
4158 goto exit;
4159 }
4160
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304161 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4162 !out->is_iec61937_info_available) {
4163
4164 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4165 out->is_iec61937_info_available = true;
4166 } else if (audio_extn_passthru_is_enabled()) {
4167 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304168 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304169
4170 if((out->format == AUDIO_FORMAT_DTS) ||
4171 (out->format == AUDIO_FORMAT_DTS_HD)) {
4172 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4173 buffer, bytes);
4174 if (ret) {
4175 if (ret != -ENOSYS) {
4176 out->is_iec61937_info_available = false;
4177 ALOGD("iec61937 transmission info not yet updated retry");
4178 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304179 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304180 /* if stream has started and after that there is
4181 * stream config change (iec transmission config)
4182 * then trigger select_device to update backend configuration.
4183 */
4184 out->stream_config_changed = true;
4185 pthread_mutex_lock(&adev->lock);
4186 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304187 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4188 ret = -EINVAL;
4189 goto exit;
4190 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304191 pthread_mutex_unlock(&adev->lock);
4192 out->stream_config_changed = false;
4193 out->is_iec61937_info_available = true;
4194 }
4195 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304196
Garmond Leung317cbf12017-09-13 16:20:50 -07004197 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304198 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4199 (out->is_iec61937_info_available == true)) {
4200 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4201 ret = -EINVAL;
4202 goto exit;
4203 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304204 }
4205 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304206
4207 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4208 (audio_extn_a2dp_is_suspended())) {
4209 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4210 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304211 ret = -EIO;
4212 goto exit;
4213 }
4214 }
4215 }
4216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004218 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004219 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004220 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4221 ret = voice_extn_compress_voip_start_output_stream(out);
4222 else
4223 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004224 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004225 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004227 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228 goto exit;
4229 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304230 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004231 if (last_known_cal_step != -1) {
4232 ALOGD("%s: retry previous failed cal level set", __func__);
4233 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304234 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004235 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304236
4237 if ((out->is_iec61937_info_available == true) &&
4238 (audio_extn_passthru_is_passthrough_stream(out))&&
4239 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4240 ret = -EINVAL;
4241 goto exit;
4242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244
Ashish Jain81eb2a82015-05-13 10:52:34 +05304245 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004246 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304247 adev->is_channel_status_set = true;
4248 }
4249
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004250 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004251 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004252 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004253 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004254 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4255 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304256 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4257 ALOGD("copl(%p):send next track params in gapless", out);
4258 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4259 out->send_next_track_params = false;
4260 out->is_compr_metadata_avail = false;
4261 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004262 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304263 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304264 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004265
Ashish Jain83a6cc22016-06-28 14:34:17 +05304266 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304267 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304268 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304269 pthread_mutex_unlock(&out->lock);
4270 return -EINVAL;
4271 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304272 audio_format_t dst_format = out->hal_op_format;
4273 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304274
4275 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4276 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4277
Ashish Jain83a6cc22016-06-28 14:34:17 +05304278 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304279 dst_format,
4280 buffer,
4281 src_format,
4282 frames);
4283
Ashish Jain83a6cc22016-06-28 14:34:17 +05304284 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304285 bytes_to_write);
4286
4287 /*Convert written bytes in audio flinger format*/
4288 if (ret > 0)
4289 ret = ((ret * format_to_bitwidth_table[out->format]) /
4290 format_to_bitwidth_table[dst_format]);
4291 }
4292 } else
4293 ret = compress_write(out->compr, buffer, bytes);
4294
Zhou Songc9672822017-08-16 16:01:39 +08004295 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4296 update_frames_written(out, bytes);
4297
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304298 if (ret < 0)
4299 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304300 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304301 /*msg to cb thread only if non blocking write is enabled*/
4302 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304303 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004304 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304305 } else if (-ENETRESET == ret) {
4306 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304307 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304308 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304309 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05304310 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004311 }
Ashish Jain5106d362016-05-11 19:23:33 +05304312
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304313 /* Call compr start only when non-zero bytes of data is there to be rendered */
4314 if (!out->playback_started && ret > 0) {
4315 int status = compress_start(out->compr);
4316 if (status < 0) {
4317 ret = status;
4318 ALOGE("%s: compr start failed with err %d", __func__, errno);
4319 goto exit;
4320 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004321 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004322 out->playback_started = 1;
4323 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004324
4325 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4326 popcount(out->channel_mask),
4327 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004328 }
4329 pthread_mutex_unlock(&out->lock);
4330 return ret;
4331 } else {
4332 if (out->pcm) {
4333 if (out->muted)
4334 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004335
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304336 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004337
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004338 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004339
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004340 if (out->config.rate)
4341 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4342 out->config.rate;
4343
4344 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4345
4346 request_out_focus(out, ns);
4347
4348 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004349 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004350 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304351 out->convert_buffer != NULL) {
4352
4353 memcpy_by_audio_format(out->convert_buffer,
4354 out->hal_op_format,
4355 buffer,
4356 out->hal_ip_format,
4357 out->config.period_size * out->config.channels);
4358
4359 ret = pcm_write(out->pcm, out->convert_buffer,
4360 (out->config.period_size *
4361 out->config.channels *
4362 format_to_bitwidth_table[out->hal_op_format]));
4363 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304364 /*
4365 * To avoid underrun in DSP when the application is not pumping
4366 * data at required rate, check for the no. of bytes and ignore
4367 * pcm_write if it is less than actual buffer size.
4368 * It is a work around to a change in compress VOIP driver.
4369 */
4370 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4371 bytes < (out->config.period_size * out->config.channels *
4372 audio_bytes_per_sample(out->format))) {
4373 size_t voip_buf_size =
4374 out->config.period_size * out->config.channels *
4375 audio_bytes_per_sample(out->format);
4376 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4377 __func__, bytes, voip_buf_size);
4378 usleep(((uint64_t)voip_buf_size - bytes) *
4379 1000000 / audio_stream_out_frame_size(stream) /
4380 out_get_sample_rate(&out->stream.common));
4381 ret = 0;
4382 } else
4383 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304384 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004385
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004386 release_out_focus(out);
4387
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304388 if (ret < 0)
4389 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004390 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304391 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004392 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 }
4394
4395exit:
Zhou Songc9672822017-08-16 16:01:39 +08004396 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304397 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304398 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304399 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 pthread_mutex_unlock(&out->lock);
4401
4402 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004403 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004404 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304405 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304406 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304407 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304408 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304409 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304410 out->standby = true;
4411 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304412 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304413 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4414 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4415 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004416
4417 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07004418 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004419 return ret;
4420 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 }
4422 return bytes;
4423}
4424
4425static int out_get_render_position(const struct audio_stream_out *stream,
4426 uint32_t *dsp_frames)
4427{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004428 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004429
4430 if (dsp_frames == NULL)
4431 return -EINVAL;
4432
4433 *dsp_frames = 0;
4434 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004435 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304436
4437 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4438 * this operation and adev_close_output_stream(where out gets reset).
4439 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304440 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304441 *dsp_frames = get_actual_pcm_frames_rendered(out);
4442 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4443 return 0;
4444 }
4445
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004446 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304447 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304448 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004449 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304450 if (ret < 0)
4451 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004452 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304453 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004454 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304455 if (-ENETRESET == ret) {
4456 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304457 out->card_status = CARD_STATUS_OFFLINE;
4458 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304459 } else if(ret < 0) {
4460 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304461 ret = -EINVAL;
4462 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304463 /*
4464 * Handle corner case where compress session is closed during SSR
4465 * and timestamp is queried
4466 */
4467 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304468 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304469 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304470 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304471 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304472 pthread_mutex_unlock(&out->lock);
4473 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004474 } else if (audio_is_linear_pcm(out->format)) {
4475 *dsp_frames = out->written;
4476 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004477 } else
4478 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479}
4480
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004481static int out_add_audio_effect(const struct audio_stream *stream __unused,
4482 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483{
4484 return 0;
4485}
4486
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004487static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4488 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489{
4490 return 0;
4491}
4492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004493static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4494 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304496 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497}
4498
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004499static int out_get_presentation_position(const struct audio_stream_out *stream,
4500 uint64_t *frames, struct timespec *timestamp)
4501{
4502 struct stream_out *out = (struct stream_out *)stream;
4503 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004504 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004505
Ashish Jain5106d362016-05-11 19:23:33 +05304506 /* below piece of code is not guarded against any lock because audioFliner serializes
4507 * this operation and adev_close_output_stream( where out gets reset).
4508 */
4509 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304510 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304511 *frames = get_actual_pcm_frames_rendered(out);
4512 /* this is the best we can do */
4513 clock_gettime(CLOCK_MONOTONIC, timestamp);
4514 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4515 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4516 return 0;
4517 }
4518
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004519 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004520
Ashish Jain5106d362016-05-11 19:23:33 +05304521 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4522 ret = compress_get_tstamp(out->compr, &dsp_frames,
4523 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004524 // Adjustment accounts for A2dp encoder latency with offload usecases
4525 // Note: Encoder latency is returned in ms.
4526 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4527 unsigned long offset =
4528 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4529 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4530 }
Ashish Jain5106d362016-05-11 19:23:33 +05304531 ALOGVV("%s rendered frames %ld sample_rate %d",
4532 __func__, dsp_frames, out->sample_rate);
4533 *frames = dsp_frames;
4534 if (ret < 0)
4535 ret = -errno;
4536 if (-ENETRESET == ret) {
4537 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304538 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304539 ret = -EINVAL;
4540 } else
4541 ret = 0;
4542 /* this is the best we can do */
4543 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004544 } else {
4545 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004546 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004547 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4548 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004549 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004550 // This adjustment accounts for buffering after app processor.
4551 // It is based on estimated DSP latency per use case, rather than exact.
4552 signed_frames -=
4553 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4554
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004555 // Adjustment accounts for A2dp encoder latency with non offload usecases
4556 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4557 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4558 signed_frames -=
4559 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4560 }
4561
Eric Laurent949a0892013-09-20 09:20:13 -07004562 // It would be unusual for this value to be negative, but check just in case ...
4563 if (signed_frames >= 0) {
4564 *frames = signed_frames;
4565 ret = 0;
4566 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004567 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304568 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304569 *frames = out->written;
4570 clock_gettime(CLOCK_MONOTONIC, timestamp);
4571 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004572 }
4573 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004574 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004575 return ret;
4576}
4577
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004578static int out_set_callback(struct audio_stream_out *stream,
4579 stream_callback_t callback, void *cookie)
4580{
4581 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004582 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004583
4584 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004585 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004586 out->client_callback = callback;
4587 out->client_cookie = cookie;
4588 if (out->adsp_hdlr_stream_handle) {
4589 ret = audio_extn_adsp_hdlr_stream_set_callback(
4590 out->adsp_hdlr_stream_handle,
4591 callback,
4592 cookie);
4593 if (ret)
4594 ALOGW("%s:adsp hdlr callback registration failed %d",
4595 __func__, ret);
4596 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004597 pthread_mutex_unlock(&out->lock);
4598 return 0;
4599}
4600
4601static int out_pause(struct audio_stream_out* stream)
4602{
4603 struct stream_out *out = (struct stream_out *)stream;
4604 int status = -ENOSYS;
4605 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004606 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004607 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004608 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004609 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304610 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304611 status = compress_pause(out->compr);
4612
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004613 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004614
Mingming Yin21854652016-04-13 11:54:02 -07004615 if (audio_extn_passthru_is_active()) {
4616 ALOGV("offload use case, pause passthru");
4617 audio_extn_passthru_on_pause(out);
4618 }
4619
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304620 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004621 audio_extn_dts_notify_playback_state(out->usecase, 0,
4622 out->sample_rate, popcount(out->channel_mask),
4623 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004624 }
4625 pthread_mutex_unlock(&out->lock);
4626 }
4627 return status;
4628}
4629
4630static int out_resume(struct audio_stream_out* stream)
4631{
4632 struct stream_out *out = (struct stream_out *)stream;
4633 int status = -ENOSYS;
4634 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004635 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004636 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004637 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004638 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004639 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304640 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304641 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004642 }
4643 if (!status) {
4644 out->offload_state = OFFLOAD_STATE_PLAYING;
4645 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304646 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004647 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4648 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004649 }
4650 pthread_mutex_unlock(&out->lock);
4651 }
4652 return status;
4653}
4654
4655static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4656{
4657 struct stream_out *out = (struct stream_out *)stream;
4658 int status = -ENOSYS;
4659 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004660 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004661 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004662 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4663 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4664 else
4665 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4666 pthread_mutex_unlock(&out->lock);
4667 }
4668 return status;
4669}
4670
4671static int out_flush(struct audio_stream_out* stream)
4672{
4673 struct stream_out *out = (struct stream_out *)stream;
4674 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004675 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004676 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004677 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004678 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4679 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004680 } else {
4681 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4682 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08004683 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004684 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004685 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004686 return 0;
4687 }
4688 return -ENOSYS;
4689}
4690
Haynes Mathew George16081042017-05-31 17:16:49 -07004691static int out_stop(const struct audio_stream_out* stream)
4692{
4693 struct stream_out *out = (struct stream_out *)stream;
4694 struct audio_device *adev = out->dev;
4695 int ret = -ENOSYS;
4696
4697 ALOGV("%s", __func__);
4698 pthread_mutex_lock(&adev->lock);
4699 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4700 out->playback_started && out->pcm != NULL) {
4701 pcm_stop(out->pcm);
4702 ret = stop_output_stream(out);
4703 out->playback_started = false;
4704 }
4705 pthread_mutex_unlock(&adev->lock);
4706 return ret;
4707}
4708
4709static int out_start(const struct audio_stream_out* stream)
4710{
4711 struct stream_out *out = (struct stream_out *)stream;
4712 struct audio_device *adev = out->dev;
4713 int ret = -ENOSYS;
4714
4715 ALOGV("%s", __func__);
4716 pthread_mutex_lock(&adev->lock);
4717 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4718 !out->playback_started && out->pcm != NULL) {
4719 ret = start_output_stream(out);
4720 if (ret == 0) {
4721 out->playback_started = true;
4722 }
4723 }
4724 pthread_mutex_unlock(&adev->lock);
4725 return ret;
4726}
4727
4728/*
4729 * Modify config->period_count based on min_size_frames
4730 */
4731static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4732{
4733 int periodCountRequested = (min_size_frames + config->period_size - 1)
4734 / config->period_size;
4735 int periodCount = MMAP_PERIOD_COUNT_MIN;
4736
4737 ALOGV("%s original config.period_size = %d config.period_count = %d",
4738 __func__, config->period_size, config->period_count);
4739
4740 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4741 periodCount *= 2;
4742 }
4743 config->period_count = periodCount;
4744
4745 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4746}
4747
4748static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4749 int32_t min_size_frames,
4750 struct audio_mmap_buffer_info *info)
4751{
4752 struct stream_out *out = (struct stream_out *)stream;
4753 struct audio_device *adev = out->dev;
4754 int ret = 0;
4755 unsigned int offset1;
4756 unsigned int frames1;
4757 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004758 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004759
4760 ALOGV("%s", __func__);
4761 pthread_mutex_lock(&adev->lock);
4762
4763 if (info == NULL || min_size_frames == 0) {
4764 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4765 ret = -EINVAL;
4766 goto exit;
4767 }
4768 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4769 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4770 ret = -ENOSYS;
4771 goto exit;
4772 }
4773 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4774 if (out->pcm_device_id < 0) {
4775 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4776 __func__, out->pcm_device_id, out->usecase);
4777 ret = -EINVAL;
4778 goto exit;
4779 }
4780
4781 adjust_mmap_period_count(&out->config, min_size_frames);
4782
4783 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4784 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4785 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4786 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4787 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4788 step = "open";
4789 ret = -ENODEV;
4790 goto exit;
4791 }
4792 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4793 if (ret < 0) {
4794 step = "begin";
4795 goto exit;
4796 }
4797 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4798 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004799 ret = platform_get_mmap_data_fd(adev->platform,
4800 out->pcm_device_id, 0 /*playback*/,
4801 &info->shared_memory_fd,
4802 &mmap_size);
4803 if (ret < 0) {
4804 step = "get_mmap_fd";
4805 goto exit;
4806 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004807 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004808 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004809
4810 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4811 if (ret < 0) {
4812 step = "commit";
4813 goto exit;
4814 }
4815
4816 out->standby = false;
4817 ret = 0;
4818
4819 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4820 __func__, info->shared_memory_address, info->buffer_size_frames);
4821
4822exit:
4823 if (ret != 0) {
4824 if (out->pcm == NULL) {
4825 ALOGE("%s: %s - %d", __func__, step, ret);
4826 } else {
4827 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4828 pcm_close(out->pcm);
4829 out->pcm = NULL;
4830 }
4831 }
4832 pthread_mutex_unlock(&adev->lock);
4833 return ret;
4834}
4835
4836static int out_get_mmap_position(const struct audio_stream_out *stream,
4837 struct audio_mmap_position *position)
4838{
4839 struct stream_out *out = (struct stream_out *)stream;
4840 ALOGVV("%s", __func__);
4841 if (position == NULL) {
4842 return -EINVAL;
4843 }
4844 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4845 return -ENOSYS;
4846 }
4847 if (out->pcm == NULL) {
4848 return -ENOSYS;
4849 }
4850
4851 struct timespec ts = { 0, 0 };
4852 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4853 if (ret < 0) {
4854 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4855 return ret;
4856 }
4857 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4858 return 0;
4859}
4860
4861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862/** audio_stream_in implementation **/
4863static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4864{
4865 struct stream_in *in = (struct stream_in *)stream;
4866
4867 return in->config.rate;
4868}
4869
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004870static int in_set_sample_rate(struct audio_stream *stream __unused,
4871 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872{
4873 return -ENOSYS;
4874}
4875
4876static size_t in_get_buffer_size(const struct audio_stream *stream)
4877{
4878 struct stream_in *in = (struct stream_in *)stream;
4879
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004880 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4881 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004882 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4883 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 -07004884 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4885 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304886 else if(audio_extn_cin_attached_usecase(in->usecase))
4887 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004888
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004889 return in->config.period_size * in->af_period_multiplier *
4890 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891}
4892
4893static uint32_t in_get_channels(const struct audio_stream *stream)
4894{
4895 struct stream_in *in = (struct stream_in *)stream;
4896
4897 return in->channel_mask;
4898}
4899
4900static audio_format_t in_get_format(const struct audio_stream *stream)
4901{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004902 struct stream_in *in = (struct stream_in *)stream;
4903
4904 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004905}
4906
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004907static int in_set_format(struct audio_stream *stream __unused,
4908 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909{
4910 return -ENOSYS;
4911}
4912
4913static int in_standby(struct audio_stream *stream)
4914{
4915 struct stream_in *in = (struct stream_in *)stream;
4916 struct audio_device *adev = in->dev;
4917 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304918 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4919 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004920 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304921
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004922 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004923 if (!in->standby && in->is_st_session) {
4924 ALOGD("%s: sound trigger pcm stop lab", __func__);
4925 audio_extn_sound_trigger_stop_lab(in);
4926 in->standby = 1;
4927 }
4928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004929 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004930 if (adev->adm_deregister_stream)
4931 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4932
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004933 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004934 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004935 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004936 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004937 voice_extn_compress_voip_close_input_stream(stream);
4938 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004939 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4940 do_stop = in->capture_started;
4941 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004942 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304943 if (audio_extn_cin_attached_usecase(in->usecase))
4944 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004945 }
4946
4947 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004948 if (in->pcm) {
4949 pcm_close(in->pcm);
4950 in->pcm = NULL;
4951 }
4952 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004953 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004954 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955 }
4956 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004957 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004958 return status;
4959}
4960
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004961static int in_dump(const struct audio_stream *stream __unused,
4962 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004963{
4964 return 0;
4965}
4966
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304967static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4968{
4969 if (!stream || !parms)
4970 return;
4971
4972 struct stream_in *in = (struct stream_in *)stream;
4973 struct audio_device *adev = in->dev;
4974
4975 card_status_t status;
4976 int card;
4977 if (parse_snd_card_status(parms, &card, &status) < 0)
4978 return;
4979
4980 pthread_mutex_lock(&adev->lock);
4981 bool valid_cb = (card == adev->snd_card);
4982 pthread_mutex_unlock(&adev->lock);
4983
4984 if (!valid_cb)
4985 return;
4986
4987 lock_input_stream(in);
4988 if (in->card_status != status)
4989 in->card_status = status;
4990 pthread_mutex_unlock(&in->lock);
4991
4992 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4993 use_case_table[in->usecase],
4994 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4995
4996 // a better solution would be to report error back to AF and let
4997 // it put the stream to standby
4998 if (status == CARD_STATUS_OFFLINE)
4999 in_standby(&in->stream.common);
5000
5001 return;
5002}
5003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
5005{
5006 struct stream_in *in = (struct stream_in *)stream;
5007 struct audio_device *adev = in->dev;
5008 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005010 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305012 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005013 parms = str_parms_create_str(kvpairs);
5014
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305015 if (!parms)
5016 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005017 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005018 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005019
5020 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
5021 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022 val = atoi(value);
5023 /* no audio source uses val == 0 */
5024 if ((in->source != val) && (val != 0)) {
5025 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005026 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5027 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
5028 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005029 (in->config.rate == 8000 || in->config.rate == 16000 ||
5030 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005031 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005032 err = voice_extn_compress_voip_open_input_stream(in);
5033 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005034 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08005035 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005036 }
5037 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005038 }
5039 }
5040
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005041 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
5042 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005044 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045 in->device = val;
5046 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005047 if (!in->standby && !in->is_st_session) {
5048 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07005049 if (adev->adm_on_routing_change)
5050 adev->adm_on_routing_change(adev->adm_data,
5051 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005052 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005053 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005054 }
5055 }
5056
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305057 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5058 if (err >= 0) {
5059 strlcpy(in->profile, value, sizeof(in->profile));
5060 ALOGV("updating stream profile with value '%s'", in->profile);
5061 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5062 &adev->streams_input_cfg_list,
5063 in->device, in->flags, in->format,
5064 in->sample_rate, in->bit_width,
5065 in->profile, &in->app_type_cfg);
5066 }
5067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005068 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005069 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005070
5071 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305072error:
Eric Laurent994a6932013-07-17 11:51:42 -07005073 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005074 return ret;
5075}
5076
5077static char* in_get_parameters(const struct audio_stream *stream,
5078 const char *keys)
5079{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005080 struct stream_in *in = (struct stream_in *)stream;
5081 struct str_parms *query = str_parms_create_str(keys);
5082 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005083 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005084
5085 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005086 if (reply) {
5087 str_parms_destroy(reply);
5088 }
5089 if (query) {
5090 str_parms_destroy(query);
5091 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005092 ALOGE("in_get_parameters: failed to create query or reply");
5093 return NULL;
5094 }
5095
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005096 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005097
5098 voice_extn_in_get_parameters(in, query, reply);
5099
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005100 stream_get_parameter_channels(query, reply,
5101 &in->supported_channel_masks[0]);
5102 stream_get_parameter_formats(query, reply,
5103 &in->supported_formats[0]);
5104 stream_get_parameter_rates(query, reply,
5105 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005106 str = str_parms_to_str(reply);
5107 str_parms_destroy(query);
5108 str_parms_destroy(reply);
5109
5110 ALOGV("%s: exit: returns - %s", __func__, str);
5111 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112}
5113
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005114static int in_set_gain(struct audio_stream_in *stream __unused,
5115 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005116{
5117 return 0;
5118}
5119
5120static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
5121 size_t bytes)
5122{
5123 struct stream_in *in = (struct stream_in *)stream;
5124 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305125 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305126 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005128 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305129
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005130 if (in->is_st_session) {
5131 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
5132 /* Read from sound trigger HAL */
5133 audio_extn_sound_trigger_read(in, buffer, bytes);
5134 pthread_mutex_unlock(&in->lock);
5135 return bytes;
5136 }
5137
Haynes Mathew George16081042017-05-31 17:16:49 -07005138 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5139 ret = -ENOSYS;
5140 goto exit;
5141 }
5142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005144 pthread_mutex_lock(&adev->lock);
5145 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
5146 ret = voice_extn_compress_voip_start_input_stream(in);
5147 else
5148 ret = start_input_stream(in);
5149 pthread_mutex_unlock(&adev->lock);
5150 if (ret != 0) {
5151 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005152 }
5153 in->standby = 0;
5154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005156 // what's the duration requested by the client?
5157 long ns = 0;
5158
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305159 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005160 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5161 in->config.rate;
5162
5163 request_in_focus(in, ns);
5164 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005165
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305166 if (audio_extn_cin_attached_usecase(in->usecase)) {
5167 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5168 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305169 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005170 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305171 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005172 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005173 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005174 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005175 } else if (audio_extn_ffv_get_stream() == in) {
5176 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305177 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005178 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305179 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5180 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5181 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5182 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305183 ret = -EINVAL;
5184 goto exit;
5185 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305186 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305187 ret = -errno;
5188 }
5189 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305190 /* bytes read is always set to bytes for non compress usecases */
5191 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 }
5193
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005194 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005196 /*
5197 * Instead of writing zeroes here, we could trust the hardware
5198 * to always provide zeroes when muted.
5199 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305200 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5201 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202 memset(buffer, 0, bytes);
5203
5204exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005205 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305206 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207 pthread_mutex_unlock(&in->lock);
5208
5209 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305210 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305211 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305212 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305213 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305214 in->standby = true;
5215 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305216 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5217 bytes_read = bytes;
5218 memset(buffer, 0, bytes);
5219 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005221 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305222 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305223 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005224 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305225 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226}
5227
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005228static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005229{
5230 return 0;
5231}
5232
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005233static int add_remove_audio_effect(const struct audio_stream *stream,
5234 effect_handle_t effect,
5235 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005237 struct stream_in *in = (struct stream_in *)stream;
5238 int status = 0;
5239 effect_descriptor_t desc;
5240
5241 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005242 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
5243
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005244 if (status != 0)
5245 return status;
5246
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005247 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005248 pthread_mutex_lock(&in->dev->lock);
5249 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5250 in->enable_aec != enable &&
5251 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5252 in->enable_aec = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005253 if (!in->standby) {
5254 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
5255 select_devices(in->dev, in->usecase);
5256 }
5257
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005258 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005259 if (in->enable_ns != enable &&
5260 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5261 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07005262 if (!in->standby) {
5263 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
5264 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
5265 select_devices(in->dev, in->usecase);
5266 } else
5267 select_devices(in->dev, in->usecase);
5268 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005269 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005270 pthread_mutex_unlock(&in->dev->lock);
5271 pthread_mutex_unlock(&in->lock);
5272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005273 return 0;
5274}
5275
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005276static int in_add_audio_effect(const struct audio_stream *stream,
5277 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278{
Eric Laurent994a6932013-07-17 11:51:42 -07005279 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005280 return add_remove_audio_effect(stream, effect, true);
5281}
5282
5283static int in_remove_audio_effect(const struct audio_stream *stream,
5284 effect_handle_t effect)
5285{
Eric Laurent994a6932013-07-17 11:51:42 -07005286 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005287 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288}
5289
Haynes Mathew George16081042017-05-31 17:16:49 -07005290static int in_stop(const struct audio_stream_in* stream)
5291{
5292 struct stream_in *in = (struct stream_in *)stream;
5293 struct audio_device *adev = in->dev;
5294
5295 int ret = -ENOSYS;
5296 ALOGV("%s", __func__);
5297 pthread_mutex_lock(&adev->lock);
5298 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5299 in->capture_started && in->pcm != NULL) {
5300 pcm_stop(in->pcm);
5301 ret = stop_input_stream(in);
5302 in->capture_started = false;
5303 }
5304 pthread_mutex_unlock(&adev->lock);
5305 return ret;
5306}
5307
5308static int in_start(const struct audio_stream_in* stream)
5309{
5310 struct stream_in *in = (struct stream_in *)stream;
5311 struct audio_device *adev = in->dev;
5312 int ret = -ENOSYS;
5313
5314 ALOGV("%s in %p", __func__, in);
5315 pthread_mutex_lock(&adev->lock);
5316 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5317 !in->capture_started && in->pcm != NULL) {
5318 if (!in->capture_started) {
5319 ret = start_input_stream(in);
5320 if (ret == 0) {
5321 in->capture_started = true;
5322 }
5323 }
5324 }
5325 pthread_mutex_unlock(&adev->lock);
5326 return ret;
5327}
5328
5329static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5330 int32_t min_size_frames,
5331 struct audio_mmap_buffer_info *info)
5332{
5333 struct stream_in *in = (struct stream_in *)stream;
5334 struct audio_device *adev = in->dev;
5335 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005336 unsigned int offset1 = 0;
5337 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005338 const char *step = "";
5339
5340 pthread_mutex_lock(&adev->lock);
5341 ALOGV("%s in %p", __func__, in);
5342
5343 if (info == NULL || min_size_frames == 0) {
5344 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5345 ret = -EINVAL;
5346 goto exit;
5347 }
5348 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5349 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5350 ALOGV("%s in %p", __func__, in);
5351 ret = -ENOSYS;
5352 goto exit;
5353 }
5354 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5355 if (in->pcm_device_id < 0) {
5356 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5357 __func__, in->pcm_device_id, in->usecase);
5358 ret = -EINVAL;
5359 goto exit;
5360 }
5361
5362 adjust_mmap_period_count(&in->config, min_size_frames);
5363
5364 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5365 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5366 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5367 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5368 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5369 step = "open";
5370 ret = -ENODEV;
5371 goto exit;
5372 }
5373
5374 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5375 if (ret < 0) {
5376 step = "begin";
5377 goto exit;
5378 }
5379 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5380 info->burst_size_frames = in->config.period_size;
5381 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5382
5383 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5384 info->buffer_size_frames));
5385
5386 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5387 if (ret < 0) {
5388 step = "commit";
5389 goto exit;
5390 }
5391
5392 in->standby = false;
5393 ret = 0;
5394
5395 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5396 __func__, info->shared_memory_address, info->buffer_size_frames);
5397
5398exit:
5399 if (ret != 0) {
5400 if (in->pcm == NULL) {
5401 ALOGE("%s: %s - %d", __func__, step, ret);
5402 } else {
5403 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5404 pcm_close(in->pcm);
5405 in->pcm = NULL;
5406 }
5407 }
5408 pthread_mutex_unlock(&adev->lock);
5409 return ret;
5410}
5411
5412static int in_get_mmap_position(const struct audio_stream_in *stream,
5413 struct audio_mmap_position *position)
5414{
5415 struct stream_in *in = (struct stream_in *)stream;
5416 ALOGVV("%s", __func__);
5417 if (position == NULL) {
5418 return -EINVAL;
5419 }
5420 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5421 return -ENOSYS;
5422 }
5423 if (in->pcm == NULL) {
5424 return -ENOSYS;
5425 }
5426 struct timespec ts = { 0, 0 };
5427 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5428 if (ret < 0) {
5429 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5430 return ret;
5431 }
5432 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5433 return 0;
5434}
5435
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305436int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005437 audio_io_handle_t handle,
5438 audio_devices_t devices,
5439 audio_output_flags_t flags,
5440 struct audio_config *config,
5441 struct audio_stream_out **stream_out,
5442 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005443{
5444 struct audio_device *adev = (struct audio_device *)dev;
5445 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305446 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005447 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005448 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305449 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005450 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5451 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5452 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5453 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005455 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005457 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5458
Mingming Yin3a941d42016-02-17 18:08:05 -08005459 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5460 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305461 devices, flags, &out->stream);
5462
5463
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005464 if (!out) {
5465 return -ENOMEM;
5466 }
5467
Haynes Mathew George204045b2015-02-25 20:32:03 -08005468 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005469 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305470 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005471 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 if (devices == AUDIO_DEVICE_NONE)
5474 devices = AUDIO_DEVICE_OUT_SPEAKER;
5475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 out->flags = flags;
5477 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005478 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005479 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005480 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305481 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305482 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5483 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5484 else
5485 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005486 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005487 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005488 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305489 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305490 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305491 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005492 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305494 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005495 (property_get_bool("audio.matrix.limiter.enable", false)))
5496 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5497
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005498 if (audio_is_linear_pcm(out->format) &&
5499 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5500 pthread_mutex_lock(&adev->lock);
5501 if (is_hdmi) {
5502 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5503 ret = read_hdmi_sink_caps(out);
5504 } else if (is_usb_dev) {
5505 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5506 &config->format,
5507 &out->supported_formats[0],
5508 MAX_SUPPORTED_FORMATS,
5509 &config->channel_mask,
5510 &out->supported_channel_masks[0],
5511 MAX_SUPPORTED_CHANNEL_MASKS,
5512 &config->sample_rate,
5513 &out->supported_sample_rates[0],
5514 MAX_SUPPORTED_SAMPLE_RATES);
5515 ALOGV("plugged dev USB ret %d", ret);
5516 } else {
5517 ret = -1;
5518 }
5519 pthread_mutex_unlock(&adev->lock);
5520 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005521 if (ret == -ENOSYS) {
5522 /* ignore and go with default */
5523 ret = 0;
5524 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005525 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005526 goto error_open;
5527 }
5528 }
5529 }
5530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305532#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005533 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5534 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5535 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5536 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5537 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5538 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5539
5540 out->config = default_pcm_config_voip_copp;
5541 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5542 out->config.rate = out->sample_rate;
5543
5544#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305545 } 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 -08005546 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005547 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005548 ret = voice_extn_compress_voip_open_output_stream(out);
5549 if (ret != 0) {
5550 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5551 __func__, ret);
5552 goto error_open;
5553 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005554#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005555 } else if (audio_is_linear_pcm(out->format) &&
5556 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5557 out->channel_mask = config->channel_mask;
5558 out->sample_rate = config->sample_rate;
5559 out->format = config->format;
5560 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5561 // does this change?
5562 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5563 out->config.rate = config->sample_rate;
5564 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5565 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5566 audio_bytes_per_sample(config->format));
5567 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005568 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305569 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305570 pthread_mutex_lock(&adev->lock);
5571 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5572 pthread_mutex_unlock(&adev->lock);
5573
5574 // reject offload during card offline to allow
5575 // fallback to s/w paths
5576 if (offline) {
5577 ret = -ENODEV;
5578 goto error_open;
5579 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005580
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005581 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5582 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5583 ALOGE("%s: Unsupported Offload information", __func__);
5584 ret = -EINVAL;
5585 goto error_open;
5586 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005587
Mingming Yin3a941d42016-02-17 18:08:05 -08005588 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005589 if(config->offload_info.format == 0)
5590 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005591 if (config->offload_info.sample_rate == 0)
5592 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005593 }
5594
Mingming Yin90310102013-11-13 16:57:00 -08005595 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305596 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005597 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005598 ret = -EINVAL;
5599 goto error_open;
5600 }
5601
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005602 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5603 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5604 (audio_extn_passthru_is_passthrough_stream(out)) &&
5605 !((config->sample_rate == 48000) ||
5606 (config->sample_rate == 96000) ||
5607 (config->sample_rate == 192000))) {
5608 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5609 __func__, config->sample_rate, config->offload_info.format);
5610 ret = -EINVAL;
5611 goto error_open;
5612 }
5613
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005614 out->compr_config.codec = (struct snd_codec *)
5615 calloc(1, sizeof(struct snd_codec));
5616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005617 if (!out->compr_config.codec) {
5618 ret = -ENOMEM;
5619 goto error_open;
5620 }
5621
Dhananjay Kumarac341582017-02-23 23:42:25 +05305622 out->stream.pause = out_pause;
5623 out->stream.resume = out_resume;
5624 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05305625 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305626 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005627 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305628 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005629 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305630 } else {
5631 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5632 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005633 }
vivek mehta446c3962015-09-14 10:57:35 -07005634
5635 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005636 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5637 config->format == 0 && config->sample_rate == 0 &&
5638 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005639 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005640 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5641 } else {
5642 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5643 ret = -EEXIST;
5644 goto error_open;
5645 }
vivek mehta446c3962015-09-14 10:57:35 -07005646 }
5647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005648 if (config->offload_info.channel_mask)
5649 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005650 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005651 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005652 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005653 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305654 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005655 ret = -EINVAL;
5656 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005657 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005658
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005659 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005660 out->sample_rate = config->offload_info.sample_rate;
5661
Mingming Yin3ee55c62014-08-04 14:23:35 -07005662 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005663
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305664 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305665 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305666 audio_extn_dolby_send_ddp_endp_params(adev);
5667 audio_extn_dolby_set_dmid(adev);
5668 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005669
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005670 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005671 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005672 out->compr_config.codec->bit_rate =
5673 config->offload_info.bit_rate;
5674 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305675 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005676 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305677 /* Update bit width only for non passthrough usecases.
5678 * For passthrough usecases, the output will always be opened @16 bit
5679 */
5680 if (!audio_extn_passthru_is_passthrough_stream(out))
5681 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305682
5683 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5684 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5685 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5686
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005687 /*TODO: Do we need to change it for passthrough */
5688 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005689
Manish Dewangana6fc5442015-08-24 20:30:31 +05305690 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5691 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305692 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305693 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305694 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5695 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305696
5697 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5698 AUDIO_FORMAT_PCM) {
5699
5700 /*Based on platform support, configure appropriate alsa format for corresponding
5701 *hal input format.
5702 */
5703 out->compr_config.codec->format = hal_format_to_alsa(
5704 config->offload_info.format);
5705
Ashish Jain83a6cc22016-06-28 14:34:17 +05305706 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305707 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305708 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305709
Dhananjay Kumarac341582017-02-23 23:42:25 +05305710 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305711 *hal input format and alsa format might differ based on platform support.
5712 */
5713 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305714 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305715
5716 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5717
5718 /* Check if alsa session is configured with the same format as HAL input format,
5719 * if not then derive correct fragment size needed to accomodate the
5720 * conversion of HAL input format to alsa format.
5721 */
5722 audio_extn_utils_update_direct_pcm_fragment_size(out);
5723
5724 /*if hal input and output fragment size is different this indicates HAL input format is
5725 *not same as the alsa format
5726 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305727 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305728 /*Allocate a buffer to convert input data to the alsa configured format.
5729 *size of convert buffer is equal to the size required to hold one fragment size
5730 *worth of pcm data, this is because flinger does not write more than fragment_size
5731 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305732 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5733 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305734 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5735 ret = -ENOMEM;
5736 goto error_open;
5737 }
5738 }
5739 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5740 out->compr_config.fragment_size =
5741 audio_extn_passthru_get_buffer_size(&config->offload_info);
5742 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5743 } else {
5744 out->compr_config.fragment_size =
5745 platform_get_compress_offload_buffer_size(&config->offload_info);
5746 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5747 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005748
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305749 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5750 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5751 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005752 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305753 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005754
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305755 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5756 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5757 }
5758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005759 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5760 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005761
Manish Dewangan69426c82017-01-30 17:35:36 +05305762 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5763 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5764 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5765 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5766 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5767 } else {
5768 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5769 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005770
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305771 memset(&out->channel_map_param, 0,
5772 sizeof(struct audio_out_channel_map_param));
5773
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005774 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305775 out->send_next_track_params = false;
5776 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005777 out->offload_state = OFFLOAD_STATE_IDLE;
5778 out->playback_started = 0;
5779
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005780 audio_extn_dts_create_state_notifier_node(out->usecase);
5781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005782 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5783 __func__, config->offload_info.version,
5784 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305785
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305786 /* Check if DSD audio format is supported in codec
5787 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305788 */
5789
5790 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305791 (!platform_check_codec_dsd_support(adev->platform) ||
5792 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305793 ret = -EINVAL;
5794 goto error_open;
5795 }
5796
Ashish Jain5106d362016-05-11 19:23:33 +05305797 /* Disable gapless if any of the following is true
5798 * passthrough playback
5799 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305800 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305801 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305802 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305803 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005804 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305805 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305806 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305807 check_and_set_gapless_mode(adev, false);
5808 } else
5809 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005810
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305811 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005812 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5813 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305814 if (config->format == AUDIO_FORMAT_DSD) {
5815 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5816 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5817 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005818
5819 create_offload_callback_thread(out);
5820
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005821 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305822 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005823 if (ret != 0) {
5824 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5825 __func__, ret);
5826 goto error_open;
5827 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005828 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5829 if (config->sample_rate == 0)
5830 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5831 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5832 config->sample_rate != 8000) {
5833 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5834 ret = -EINVAL;
5835 goto error_open;
5836 }
5837 out->sample_rate = config->sample_rate;
5838 out->config.rate = config->sample_rate;
5839 if (config->format == AUDIO_FORMAT_DEFAULT)
5840 config->format = AUDIO_FORMAT_PCM_16_BIT;
5841 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5842 config->format = AUDIO_FORMAT_PCM_16_BIT;
5843 ret = -EINVAL;
5844 goto error_open;
5845 }
5846 out->format = config->format;
5847 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5848 out->config = pcm_config_afe_proxy_playback;
5849 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005850 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305851 unsigned int channels = 0;
5852 /*Update config params to default if not set by the caller*/
5853 if (config->sample_rate == 0)
5854 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5855 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5856 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5857 if (config->format == AUDIO_FORMAT_DEFAULT)
5858 config->format = AUDIO_FORMAT_PCM_16_BIT;
5859
5860 channels = audio_channel_count_from_out_mask(out->channel_mask);
5861
Varun Balaraje49253e2017-07-06 19:48:56 +05305862 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5863 out->usecase = get_interactive_usecase(adev);
5864 out->config = pcm_config_low_latency;
5865 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305866 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005867 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5868 out->flags);
5869 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005870 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5871 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5872 out->config = pcm_config_mmap_playback;
5873 out->stream.start = out_start;
5874 out->stream.stop = out_stop;
5875 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5876 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305877 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5878 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005879 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5880 if (!out->dynamic_pm_qos_enabled) {
5881 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5882 } else {
5883 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5884 //the mixer path will be a string similar to "low-latency-playback resume"
5885 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5886 strlcat(out->pm_qos_mixer_path,
5887 " resume", MAX_MIXER_PATH_LEN);
5888 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5889 out->pm_qos_mixer_path);
5890 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305891 out->config = pcm_config_low_latency;
5892 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5893 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5894 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305895 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5896 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5897 if (out->config.period_size <= 0) {
5898 ALOGE("Invalid configuration period size is not valid");
5899 ret = -EINVAL;
5900 goto error_open;
5901 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305902 } else {
5903 /* primary path is the default path selected if no other outputs are available/suitable */
5904 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5905 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5906 }
5907 out->hal_ip_format = format = out->format;
5908 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5909 out->hal_op_format = pcm_format_to_hal(out->config.format);
5910 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5911 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005912 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305913 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305914 if (out->hal_ip_format != out->hal_op_format) {
5915 uint32_t buffer_size = out->config.period_size *
5916 format_to_bitwidth_table[out->hal_op_format] *
5917 out->config.channels;
5918 out->convert_buffer = calloc(1, buffer_size);
5919 if (out->convert_buffer == NULL){
5920 ALOGE("Allocation failed for convert buffer for size %d",
5921 out->compr_config.fragment_size);
5922 ret = -ENOMEM;
5923 goto error_open;
5924 }
5925 ALOGD("Convert buffer allocated of size %d", buffer_size);
5926 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005927 }
5928
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005929 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5930 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305931
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005932 /* TODO remove this hardcoding and check why width is zero*/
5933 if (out->bit_width == 0)
5934 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305935 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005936 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07005937 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305938 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305939 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005940 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5941 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5942 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005943 if(adev->primary_output == NULL)
5944 adev->primary_output = out;
5945 else {
5946 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005947 ret = -EEXIST;
5948 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005949 }
5950 }
5951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005952 /* Check if this usecase is already existing */
5953 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005954 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5955 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005956 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005957 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005958 ret = -EEXIST;
5959 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005960 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005962 pthread_mutex_unlock(&adev->lock);
5963
5964 out->stream.common.get_sample_rate = out_get_sample_rate;
5965 out->stream.common.set_sample_rate = out_set_sample_rate;
5966 out->stream.common.get_buffer_size = out_get_buffer_size;
5967 out->stream.common.get_channels = out_get_channels;
5968 out->stream.common.get_format = out_get_format;
5969 out->stream.common.set_format = out_set_format;
5970 out->stream.common.standby = out_standby;
5971 out->stream.common.dump = out_dump;
5972 out->stream.common.set_parameters = out_set_parameters;
5973 out->stream.common.get_parameters = out_get_parameters;
5974 out->stream.common.add_audio_effect = out_add_audio_effect;
5975 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5976 out->stream.get_latency = out_get_latency;
5977 out->stream.set_volume = out_set_volume;
5978 out->stream.write = out_write;
5979 out->stream.get_render_position = out_get_render_position;
5980 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005981 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005982
Haynes Mathew George16081042017-05-31 17:16:49 -07005983 if (out->realtime)
5984 out->af_period_multiplier = af_period_multiplier;
5985 else
5986 out->af_period_multiplier = 1;
5987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005988 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005989 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005990 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005991
5992 config->format = out->stream.common.get_format(&out->stream.common);
5993 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5994 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5995
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305996 /*
5997 By locking output stream before registering, we allow the callback
5998 to update stream's state only after stream's initial state is set to
5999 adev state.
6000 */
6001 lock_output_stream(out);
6002 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
6003 pthread_mutex_lock(&adev->lock);
6004 out->card_status = adev->card_status;
6005 pthread_mutex_unlock(&adev->lock);
6006 pthread_mutex_unlock(&out->lock);
6007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006008 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306009 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07006010 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006011
6012 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
6013 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6014 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006015 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05306016 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006017 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07006018 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05306019 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006020 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
6021 out->usecase, PCM_PLAYBACK);
6022 hdlr_stream_cfg.flags = out->flags;
6023 hdlr_stream_cfg.type = PCM_PLAYBACK;
6024 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
6025 &hdlr_stream_cfg);
6026 if (ret) {
6027 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
6028 out->adsp_hdlr_stream_handle = NULL;
6029 }
6030 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05306031 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07006032 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07006033 if (ret < 0) {
6034 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
6035 out->ip_hdlr_handle = NULL;
6036 }
6037 }
Eric Laurent994a6932013-07-17 11:51:42 -07006038 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006039 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006040
6041error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05306042 if (out->convert_buffer)
6043 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006044 free(out);
6045 *stream_out = NULL;
6046 ALOGD("%s: exit: ret %d", __func__, ret);
6047 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006048}
6049
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306050void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006051 struct audio_stream_out *stream)
6052{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006053 struct stream_out *out = (struct stream_out *)stream;
6054 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006055 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006056
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006057 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306058
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306059 // must deregister from sndmonitor first to prevent races
6060 // between the callback and close_stream
6061 audio_extn_snd_mon_unregister_listener(out);
6062
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006063 /* close adsp hdrl session before standby */
6064 if (out->adsp_hdlr_stream_handle) {
6065 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
6066 if (ret)
6067 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
6068 out->adsp_hdlr_stream_handle = NULL;
6069 }
6070
Manish Dewangan21a850a2017-08-14 12:03:55 +05306071 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07006072 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
6073 out->ip_hdlr_handle = NULL;
6074 }
6075
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006076 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306077 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006078 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306079 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306080 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006081 if(ret != 0)
6082 ALOGE("%s: Compress voip output cannot be closed, error:%d",
6083 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006084 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006085 out_standby(&stream->common);
6086
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006087 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006088 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006089 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006090 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006091 if (out->compr_config.codec != NULL)
6092 free(out->compr_config.codec);
6093 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006094
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306095 out->a2dp_compress_mute = false;
6096
Varun Balaraje49253e2017-07-06 19:48:56 +05306097 if (is_interactive_usecase(out->usecase))
6098 free_interactive_usecase(adev, out->usecase);
6099
Ashish Jain83a6cc22016-06-28 14:34:17 +05306100 if (out->convert_buffer != NULL) {
6101 free(out->convert_buffer);
6102 out->convert_buffer = NULL;
6103 }
6104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006105 if (adev->voice_tx_output == out)
6106 adev->voice_tx_output = NULL;
6107
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05306108 if (adev->primary_output == out)
6109 adev->primary_output = NULL;
6110
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006111 pthread_cond_destroy(&out->cond);
6112 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006113 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07006114 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006115}
6116
6117static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
6118{
6119 struct audio_device *adev = (struct audio_device *)dev;
6120 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006121 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006122 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006123 int ret;
6124 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006125
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006126 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006127 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006128
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306129 if (!parms)
6130 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306131
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306132 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
6133 if (ret >= 0) {
6134 /* When set to false, HAL should disable EC and NS */
6135 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6136 adev->bt_sco_on = true;
6137 else
6138 adev->bt_sco_on = false;
6139 }
6140
Naresh Tanniru4c630392014-05-12 01:05:52 +05306141 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006142 status = voice_set_parameters(adev, parms);
6143 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006144 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006145
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006146 status = platform_set_parameters(adev->platform, parms);
6147 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006148 goto done;
6149
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006150 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
6151 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07006152 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6154 adev->bluetooth_nrec = true;
6155 else
6156 adev->bluetooth_nrec = false;
6157 }
6158
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006159 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6160 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006161 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6162 adev->screen_off = false;
6163 else
6164 adev->screen_off = true;
6165 }
6166
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006167 ret = str_parms_get_int(parms, "rotation", &val);
6168 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006169 bool reverse_speakers = false;
6170 switch(val) {
6171 // FIXME: note that the code below assumes that the speakers are in the correct placement
6172 // relative to the user when the device is rotated 90deg from its default rotation. This
6173 // assumption is device-specific, not platform-specific like this code.
6174 case 270:
6175 reverse_speakers = true;
6176 break;
6177 case 0:
6178 case 90:
6179 case 180:
6180 break;
6181 default:
6182 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006183 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006184 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006185 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07006186 // check and set swap
6187 // - check if orientation changed and speaker active
6188 // - set rotation and cache the rotation value
6189 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006190 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006191 }
6192
Mingming Yin514a8bc2014-07-29 15:22:21 -07006193 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6194 if (ret >= 0) {
6195 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6196 adev->bt_wb_speech_enabled = true;
6197 else
6198 adev->bt_wb_speech_enabled = false;
6199 }
6200
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006201 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6202 if (ret >= 0) {
6203 val = atoi(value);
6204 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006205 ALOGV("cache new ext disp type and edid");
6206 ret = platform_get_ext_disp_type(adev->platform);
6207 if (ret < 0) {
6208 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08006209 status = ret;
6210 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006211 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006212 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006213 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08006214 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07006215 /*
6216 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6217 * Per AudioPolicyManager, USB device is higher priority than WFD.
6218 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6219 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6220 * starting voice call on USB
6221 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006222 ret = str_parms_get_str(parms, "card", value, sizeof(value));
6223 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08006224 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
6225 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006226 }
vivek mehta344576a2016-04-12 18:56:03 -07006227 ALOGV("detected USB connect .. disable proxy");
6228 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006229 }
6230 }
6231
6232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6233 if (ret >= 0) {
6234 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07006235 /*
6236 * The HDMI / Displayport disconnect handling has been moved to
6237 * audio extension to ensure that its parameters are not
6238 * invalidated prior to updating sysfs of the disconnect event
6239 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6240 */
6241 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08006242 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006243 ret = str_parms_get_str(parms, "card", value, sizeof(value));
6244 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05306245 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
6246 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006247 }
vivek mehta344576a2016-04-12 18:56:03 -07006248 ALOGV("detected USB disconnect .. enable proxy");
6249 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006250 }
6251 }
6252
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306253 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6254 if (ret >= 0) {
6255 struct audio_usecase *usecase;
6256 struct listnode *node;
6257 list_for_each(node, &adev->usecase_list) {
6258 usecase = node_to_item(node, struct audio_usecase, list);
6259 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006260 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306261 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006262
6263 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306264 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006265 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306266 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306267 //force device switch to re configure encoder
6268 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306269 audio_extn_a2dp_set_handoff_mode(false);
6270 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306271 break;
6272 }
6273 }
6274 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006275
6276 //handle vr audio setparam
6277 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6278 value, sizeof(value));
6279 if (ret >= 0) {
6280 ALOGI("Setting vr mode to be %s", value);
6281 if (!strncmp(value, "true", 4)) {
6282 adev->vr_audio_mode_enabled = true;
6283 ALOGI("Setting vr mode to true");
6284 } else if (!strncmp(value, "false", 5)) {
6285 adev->vr_audio_mode_enabled = false;
6286 ALOGI("Setting vr mode to false");
6287 } else {
6288 ALOGI("wrong vr mode set");
6289 }
6290 }
6291
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306292 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006293done:
6294 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006295 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306296error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006297 ALOGV("%s: exit with code(%d)", __func__, status);
6298 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006299}
6300
6301static char* adev_get_parameters(const struct audio_hw_device *dev,
6302 const char *keys)
6303{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006304 struct audio_device *adev = (struct audio_device *)dev;
6305 struct str_parms *reply = str_parms_create();
6306 struct str_parms *query = str_parms_create_str(keys);
6307 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306308 char value[256] = {0};
6309 int ret = 0;
6310
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006311 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006312 if (reply) {
6313 str_parms_destroy(reply);
6314 }
6315 if (query) {
6316 str_parms_destroy(query);
6317 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006318 ALOGE("adev_get_parameters: failed to create query or reply");
6319 return NULL;
6320 }
6321
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006322 //handle vr audio getparam
6323
6324 ret = str_parms_get_str(query,
6325 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6326 value, sizeof(value));
6327
6328 if (ret >= 0) {
6329 bool vr_audio_enabled = false;
6330 pthread_mutex_lock(&adev->lock);
6331 vr_audio_enabled = adev->vr_audio_mode_enabled;
6332 pthread_mutex_unlock(&adev->lock);
6333
6334 ALOGI("getting vr mode to %d", vr_audio_enabled);
6335
6336 if (vr_audio_enabled) {
6337 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6338 "true");
6339 goto exit;
6340 } else {
6341 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6342 "false");
6343 goto exit;
6344 }
6345 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006346
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006347 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006348 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006349 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006350 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306351 pthread_mutex_unlock(&adev->lock);
6352
Naresh Tannirud7205b62014-06-20 02:54:48 +05306353exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006354 str = str_parms_to_str(reply);
6355 str_parms_destroy(query);
6356 str_parms_destroy(reply);
6357
6358 ALOGV("%s: exit: returns - %s", __func__, str);
6359 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006360}
6361
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006362static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006363{
6364 return 0;
6365}
6366
6367static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6368{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006369 int ret;
6370 struct audio_device *adev = (struct audio_device *)dev;
6371 pthread_mutex_lock(&adev->lock);
6372 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006373 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006374 pthread_mutex_unlock(&adev->lock);
6375 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006376}
6377
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006378static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6379 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006380{
6381 return -ENOSYS;
6382}
6383
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006384static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6385 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006386{
6387 return -ENOSYS;
6388}
6389
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006390static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6391 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392{
6393 return -ENOSYS;
6394}
6395
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006396static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6397 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006398{
6399 return -ENOSYS;
6400}
6401
6402static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6403{
6404 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006406 pthread_mutex_lock(&adev->lock);
6407 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006408 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006409 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006410 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006411 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006412 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006413 adev->current_call_output = NULL;
6414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415 }
6416 pthread_mutex_unlock(&adev->lock);
6417 return 0;
6418}
6419
6420static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6421{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006422 int ret;
6423
6424 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006425 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006426 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6427 pthread_mutex_unlock(&adev->lock);
6428
6429 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006430}
6431
6432static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6433{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006434 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006435 return 0;
6436}
6437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006438static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006439 const struct audio_config *config)
6440{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006441 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006442
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006443 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6444 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006445}
6446
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006447static bool adev_input_allow_hifi_record(struct audio_device *adev,
6448 audio_devices_t devices,
6449 audio_input_flags_t flags,
6450 audio_source_t source) {
6451 const bool allowed = true;
6452
6453 if (!audio_is_usb_in_device(devices))
6454 return !allowed;
6455
6456 switch (flags) {
6457 case AUDIO_INPUT_FLAG_NONE:
6458 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
6459 break;
6460 default:
6461 return !allowed;
6462 }
6463
6464 switch (source) {
6465 case AUDIO_SOURCE_DEFAULT:
6466 case AUDIO_SOURCE_MIC:
6467 case AUDIO_SOURCE_UNPROCESSED:
6468 break;
6469 default:
6470 return !allowed;
6471 }
6472
6473 switch (adev->mode) {
6474 case 0:
6475 break;
6476 default:
6477 return !allowed;
6478 }
6479
6480 return allowed;
6481}
6482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006483static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006484 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006485 audio_devices_t devices,
6486 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006487 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306488 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006489 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006490 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006491{
6492 struct audio_device *adev = (struct audio_device *)dev;
6493 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006494 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006495 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006496 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306497 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006498 bool is_usb_dev = audio_is_usb_in_device(devices);
6499 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6500 devices,
6501 flags,
6502 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006504 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006505
6506 if (!(is_usb_dev && may_use_hifi_record)) {
6507 if (config->sample_rate == 0)
6508 config->sample_rate = 48000;
6509 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6510 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6511 if (config->format == AUDIO_FORMAT_DEFAULT)
6512 config->format = AUDIO_FORMAT_PCM_16_BIT;
6513
6514 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6515
6516 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6517 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006519
6520 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006521
6522 if (!in) {
6523 ALOGE("failed to allocate input stream");
6524 return -ENOMEM;
6525 }
6526
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306527 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306528 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6529 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006530 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006531 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006533 in->stream.common.get_sample_rate = in_get_sample_rate;
6534 in->stream.common.set_sample_rate = in_set_sample_rate;
6535 in->stream.common.get_buffer_size = in_get_buffer_size;
6536 in->stream.common.get_channels = in_get_channels;
6537 in->stream.common.get_format = in_get_format;
6538 in->stream.common.set_format = in_set_format;
6539 in->stream.common.standby = in_standby;
6540 in->stream.common.dump = in_dump;
6541 in->stream.common.set_parameters = in_set_parameters;
6542 in->stream.common.get_parameters = in_get_parameters;
6543 in->stream.common.add_audio_effect = in_add_audio_effect;
6544 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6545 in->stream.set_gain = in_set_gain;
6546 in->stream.read = in_read;
6547 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6548
6549 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006550 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006551 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006552 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006553 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006554 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006555
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306556 /* restrict 24 bit capture for unprocessed source only
6557 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6558 */
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006559 if (is_usb_dev && may_use_hifi_record) {
6560 /* HiFi record selects an appropriate format, channel, rate combo
6561 depending on sink capabilities*/
6562 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
6563 &config->format,
6564 &in->supported_formats[0],
6565 MAX_SUPPORTED_FORMATS,
6566 &config->channel_mask,
6567 &in->supported_channel_masks[0],
6568 MAX_SUPPORTED_CHANNEL_MASKS,
6569 &config->sample_rate,
6570 &in->supported_sample_rates[0],
6571 MAX_SUPPORTED_SAMPLE_RATES);
6572 if (ret != 0) {
6573 ret = -EINVAL;
6574 goto err_open;
6575 }
6576 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6577 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306578 config->format = AUDIO_FORMAT_PCM_16_BIT;
6579 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6580 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6581 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6582 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6583 bool ret_error = false;
6584 in->bit_width = 24;
6585 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6586 from HAL is 24_packed and 8_24
6587 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6588 24_packed return error indicating supported format is 24_packed
6589 *> In case of any other source requesting 24 bit or float return error
6590 indicating format supported is 16 bit only.
6591
6592 on error flinger will retry with supported format passed
6593 */
6594 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6595 (source != AUDIO_SOURCE_CAMCORDER)) {
6596 config->format = AUDIO_FORMAT_PCM_16_BIT;
6597 if (config->sample_rate > 48000)
6598 config->sample_rate = 48000;
6599 ret_error = true;
6600 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6601 in->config.format = PCM_FORMAT_S24_3LE;
6602 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6603 in->config.format = PCM_FORMAT_S24_LE;
6604 } else {
6605 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6606 ret_error = true;
6607 }
6608
6609 if (ret_error) {
6610 ret = -EINVAL;
6611 goto err_open;
6612 }
6613 }
6614
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006615 in->channel_mask = config->channel_mask;
6616 in->format = config->format;
6617
6618 in->usecase = USECASE_AUDIO_RECORD;
6619 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
6620 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
6621 is_low_latency = true;
6622#if LOW_LATENCY_CAPTURE_USE_CASE
6623 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6624#endif
6625 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6626 }
6627
6628 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6629 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6630 in->realtime = 0;
6631 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6632 in->config = pcm_config_mmap_capture;
6633 in->stream.start = in_start;
6634 in->stream.stop = in_stop;
6635 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6636 in->stream.get_mmap_position = in_get_mmap_position;
6637 in->af_period_multiplier = 1;
6638 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6639 } else if (in->realtime) {
6640 in->config = pcm_config_audio_capture_rt;
6641 in->sample_rate = in->config.rate;
6642 in->af_period_multiplier = af_period_multiplier;
6643 } else {
6644 in->config = pcm_config_audio_capture;
6645 in->config.rate = config->sample_rate;
6646 in->sample_rate = config->sample_rate;
6647 in->af_period_multiplier = 1;
6648 }
6649 in->bit_width = 16;
6650
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306651 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306652 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6653 (adev->mode != AUDIO_MODE_IN_CALL)) {
6654 ret = -EINVAL;
6655 goto err_open;
6656 }
6657
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006658 if (is_usb_dev && may_use_hifi_record) {
6659 in->usecase = USECASE_AUDIO_RECORD_HIFI;
6660 in->config = pcm_config_audio_capture;
6661 frame_size = audio_stream_in_frame_size(&in->stream);
6662 buffer_size = get_input_buffer_size(config->sample_rate,
6663 config->format,
6664 channel_count,
6665 false /*is_low_latency*/);
6666 in->config.period_size = buffer_size / frame_size;
6667 in->config.rate = config->sample_rate;
6668 in->af_period_multiplier = 1;
6669 in->config.format = pcm_format_from_audio_format(config->format);
6670 in->config.channels = channel_count;
6671 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306672 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006673 if (config->sample_rate == 0)
6674 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6675 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6676 config->sample_rate != 8000) {
6677 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6678 ret = -EINVAL;
6679 goto err_open;
6680 }
6681 if (config->format == AUDIO_FORMAT_DEFAULT)
6682 config->format = AUDIO_FORMAT_PCM_16_BIT;
6683 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6684 config->format = AUDIO_FORMAT_PCM_16_BIT;
6685 ret = -EINVAL;
6686 goto err_open;
6687 }
6688
6689 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6690 in->config = pcm_config_afe_proxy_record;
6691 in->config.channels = channel_count;
6692 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306693 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306694 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6695 in, config, &channel_mask_updated)) {
6696 if (channel_mask_updated == true) {
6697 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6698 __func__, config->channel_mask);
6699 ret = -EINVAL;
6700 goto err_open;
6701 }
Garmond Leunge2433c32017-09-28 21:51:22 -07006702 ALOGD("%s: created multi-channel session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006703 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006704 audio_extn_compr_cap_format_supported(config->format) &&
6705 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006706 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306707 } else if (audio_extn_cin_applicable_stream(in)) {
6708 ret = audio_extn_cin_configure_input_stream(in);
6709 if (ret)
6710 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006711 } else {
6712 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006713 if (!in->realtime) {
6714 in->format = config->format;
6715 frame_size = audio_stream_in_frame_size(&in->stream);
6716 buffer_size = get_input_buffer_size(config->sample_rate,
6717 config->format,
6718 channel_count,
6719 is_low_latency);
6720 in->config.period_size = buffer_size / frame_size;
6721 }
6722
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006723#ifndef COMPRESS_VOIP_ENABLED
6724 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6725 (in->config.rate == 8000 || in->config.rate == 16000 ||
6726 in->config.rate == 32000 || in->config.rate == 48000) &&
6727 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6728
6729 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6730 in->config = default_pcm_config_voip_copp;
6731 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6732 in->config.rate = in->sample_rate;
6733#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006734 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006735 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6736 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006737 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006738 (in->config.rate == 8000 || in->config.rate == 16000 ||
6739 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006740 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6741 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006742#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006743 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006745
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306746 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6747 &adev->streams_input_cfg_list,
6748 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306749 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306750
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006751 /* This stream could be for sound trigger lab,
6752 get sound trigger pcm if present */
6753 audio_extn_sound_trigger_check_and_get_session(in);
6754
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306755 lock_input_stream(in);
6756 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6757 pthread_mutex_lock(&adev->lock);
6758 in->card_status = adev->card_status;
6759 pthread_mutex_unlock(&adev->lock);
6760 pthread_mutex_unlock(&in->lock);
6761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006762 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006763 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006764 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006765
6766err_open:
6767 free(in);
6768 *stream_in = NULL;
6769 return ret;
6770}
6771
6772static void adev_close_input_stream(struct audio_hw_device *dev,
6773 struct audio_stream_in *stream)
6774{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006775 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006776 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006777 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306778
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306779 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006780
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306781 // must deregister from sndmonitor first to prevent races
6782 // between the callback and close_stream
6783 audio_extn_snd_mon_unregister_listener(stream);
6784
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306785 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006786 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306787
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006788 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306789 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006790 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306791 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006792 if (ret != 0)
6793 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6794 __func__, ret);
6795 } else
6796 in_standby(&stream->common);
6797
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006798 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006799 audio_extn_ssr_deinit();
6800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006801
Garmond Leunge2433c32017-09-28 21:51:22 -07006802 if (audio_extn_ffv_get_stream() == in) {
6803 audio_extn_ffv_stream_deinit();
6804 }
6805
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306806 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006807 audio_extn_compr_cap_format_supported(in->config.format))
6808 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306809
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306810 if (audio_extn_cin_attached_usecase(in->usecase))
6811 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006812
Mingming Yinfd7607b2016-01-22 12:48:44 -08006813 if (in->is_st_session) {
6814 ALOGV("%s: sound trigger pcm stop lab", __func__);
6815 audio_extn_sound_trigger_stop_lab(in);
6816 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006817 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006818 return;
6819}
6820
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306821int adev_create_audio_patch(struct audio_hw_device *dev,
6822 unsigned int num_sources,
6823 const struct audio_port_config *sources,
6824 unsigned int num_sinks,
6825 const struct audio_port_config *sinks,
6826 audio_patch_handle_t *handle)
6827{
6828
6829
6830 return audio_extn_hw_loopback_create_audio_patch(dev,
6831 num_sources,
6832 sources,
6833 num_sinks,
6834 sinks,
6835 handle);
6836
6837}
6838
6839int adev_release_audio_patch(struct audio_hw_device *dev,
6840 audio_patch_handle_t handle)
6841{
6842 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6843}
6844
6845int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6846{
6847 return audio_extn_hw_loopback_get_audio_port(dev, config);
6848}
6849
6850int adev_set_audio_port_config(struct audio_hw_device *dev,
6851 const struct audio_port_config *config)
6852{
6853 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6854}
6855
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006856static int adev_dump(const audio_hw_device_t *device __unused,
6857 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006858{
6859 return 0;
6860}
6861
6862static int adev_close(hw_device_t *device)
6863{
6864 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006865
6866 if (!adev)
6867 return 0;
6868
6869 pthread_mutex_lock(&adev_init_lock);
6870
6871 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306872 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006873 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006874 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306875 audio_extn_utils_release_streams_cfg_lists(
6876 &adev->streams_output_cfg_list,
6877 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306878 if (audio_extn_qaf_is_enabled())
6879 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006880 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006881 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006882 free(adev->snd_dev_ref_cnt);
6883 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006884 if (adev->adm_deinit)
6885 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306886 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006887 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306888 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306889 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006890 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306891 if (adev->device_cfg_params) {
6892 free(adev->device_cfg_params);
6893 adev->device_cfg_params = NULL;
6894 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006895 free(device);
6896 adev = NULL;
6897 }
6898 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006900 return 0;
6901}
6902
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006903/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6904 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6905 * just that it _might_ work.
6906 */
6907static int period_size_is_plausible_for_low_latency(int period_size)
6908{
6909 switch (period_size) {
6910 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006911 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006912 case 240:
6913 case 320:
6914 case 480:
6915 return 1;
6916 default:
6917 return 0;
6918 }
6919}
6920
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306921static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6922{
6923 bool is_snd_card_status = false;
6924 bool is_ext_device_status = false;
6925 char value[32];
6926 int card = -1;
6927 card_status_t status;
6928
6929 if (cookie != adev || !parms)
6930 return;
6931
6932 if (!parse_snd_card_status(parms, &card, &status)) {
6933 is_snd_card_status = true;
6934 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6935 is_ext_device_status = true;
6936 } else {
6937 // not a valid event
6938 return;
6939 }
6940
6941 pthread_mutex_lock(&adev->lock);
6942 if (card == adev->snd_card || is_ext_device_status) {
6943 if (is_snd_card_status && adev->card_status != status) {
6944 adev->card_status = status;
6945 platform_snd_card_update(adev->platform, status);
6946 audio_extn_fm_set_parameters(adev, parms);
6947 } else if (is_ext_device_status) {
6948 platform_set_parameters(adev->platform, parms);
6949 }
6950 }
6951 pthread_mutex_unlock(&adev->lock);
6952 return;
6953}
6954
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306955/* out and adev lock held */
6956static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6957{
6958 struct audio_usecase *uc_info;
6959 float left_p;
6960 float right_p;
6961 audio_devices_t devices;
6962
6963 uc_info = get_usecase_from_list(adev, out->usecase);
6964 if (uc_info == NULL) {
6965 ALOGE("%s: Could not find the usecase (%d) in the list",
6966 __func__, out->usecase);
6967 return -EINVAL;
6968 }
6969
6970 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6971 out->usecase, use_case_table[out->usecase]);
6972
6973 if (restore) {
6974 // restore A2DP device for active usecases and unmute if required
6975 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6976 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6977 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6978 select_devices(adev, uc_info->id);
6979 pthread_mutex_lock(&out->compr_mute_lock);
6980 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6981 (out->a2dp_compress_mute)) {
6982 out->a2dp_compress_mute = false;
6983 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6984 }
6985 pthread_mutex_unlock(&out->compr_mute_lock);
6986 }
6987 } else {
6988 // mute compress stream if suspended
6989 pthread_mutex_lock(&out->compr_mute_lock);
6990 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6991 (!out->a2dp_compress_mute)) {
6992 if (!out->standby) {
6993 ALOGD("%s: selecting speaker and muting stream", __func__);
6994 devices = out->devices;
6995 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6996 left_p = out->volume_l;
6997 right_p = out->volume_r;
6998 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6999 compress_pause(out->compr);
7000 out_set_compr_volume(&out->stream, (float)0, (float)0);
7001 out->a2dp_compress_mute = true;
7002 select_devices(adev, out->usecase);
7003 if (out->offload_state == OFFLOAD_STATE_PLAYING)
7004 compress_resume(out->compr);
7005 out->devices = devices;
7006 out->volume_l = left_p;
7007 out->volume_r = right_p;
7008 }
7009 }
7010 pthread_mutex_unlock(&out->compr_mute_lock);
7011 }
7012 ALOGV("%s: exit", __func__);
7013 return 0;
7014}
7015
7016int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
7017{
7018 int ret = 0;
7019
7020 lock_output_stream(out);
7021 pthread_mutex_lock(&adev->lock);
7022
7023 ret = check_a2dp_restore_l(adev, out, restore);
7024
7025 pthread_mutex_unlock(&adev->lock);
7026 pthread_mutex_unlock(&out->lock);
7027 return ret;
7028}
7029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007030static int adev_open(const hw_module_t *module, const char *name,
7031 hw_device_t **device)
7032{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307033 int ret;
7034
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08007035 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007036 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
7037
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007038 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07007039 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007040 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07007041 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007042 ALOGD("%s: returning existing instance of adev", __func__);
7043 ALOGD("%s: exit", __func__);
7044 pthread_mutex_unlock(&adev_init_lock);
7045 return 0;
7046 }
7047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007048 adev = calloc(1, sizeof(struct audio_device));
7049
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007050 if (!adev) {
7051 pthread_mutex_unlock(&adev_init_lock);
7052 return -ENOMEM;
7053 }
7054
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07007055 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
7056
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05307057#ifdef DYNAMIC_LOG_ENABLED
7058 register_for_dynamic_logging("hal");
7059#endif
7060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061 adev->device.common.tag = HARDWARE_DEVICE_TAG;
7062 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7063 adev->device.common.module = (struct hw_module_t *)module;
7064 adev->device.common.close = adev_close;
7065
7066 adev->device.init_check = adev_init_check;
7067 adev->device.set_voice_volume = adev_set_voice_volume;
7068 adev->device.set_master_volume = adev_set_master_volume;
7069 adev->device.get_master_volume = adev_get_master_volume;
7070 adev->device.set_master_mute = adev_set_master_mute;
7071 adev->device.get_master_mute = adev_get_master_mute;
7072 adev->device.set_mode = adev_set_mode;
7073 adev->device.set_mic_mute = adev_set_mic_mute;
7074 adev->device.get_mic_mute = adev_get_mic_mute;
7075 adev->device.set_parameters = adev_set_parameters;
7076 adev->device.get_parameters = adev_get_parameters;
7077 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
7078 adev->device.open_output_stream = adev_open_output_stream;
7079 adev->device.close_output_stream = adev_close_output_stream;
7080 adev->device.open_input_stream = adev_open_input_stream;
7081 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05307082 adev->device.create_audio_patch = adev_create_audio_patch;
7083 adev->device.release_audio_patch = adev_release_audio_patch;
7084 adev->device.get_audio_port = adev_get_audio_port;
7085 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007086 adev->device.dump = adev_dump;
7087
7088 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08007090 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007091 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007093 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08007094 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07007095 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307096 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07007097 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07007098 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007099 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08007100 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08007101 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007102 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05307103 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307104 adev->perf_lock_opts[0] = 0x101;
7105 adev->perf_lock_opts[1] = 0x20E;
7106 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007107 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007109 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07007110 adev->platform = platform_init(adev);
7111 if (!adev->platform) {
7112 free(adev->snd_dev_ref_cnt);
7113 free(adev);
7114 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7115 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08007116 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307117 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07007118 return -EINVAL;
7119 }
Eric Laurentc4aef752013-09-12 17:45:53 -07007120
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307121 if (audio_extn_qaf_is_enabled()) {
7122 ret = audio_extn_qaf_init(adev);
7123 if (ret < 0) {
7124 free(adev);
7125 ALOGE("%s: Failed to init platform data, aborting.", __func__);
7126 *device = NULL;
7127 pthread_mutex_unlock(&adev_init_lock);
7128 pthread_mutex_destroy(&adev->lock);
7129 return ret;
7130 }
7131
7132 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
7133 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
7134 }
7135
Eric Laurentc4aef752013-09-12 17:45:53 -07007136 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
7137 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
7138 if (adev->visualizer_lib == NULL) {
7139 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
7140 } else {
7141 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
7142 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007143 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007144 "visualizer_hal_start_output");
7145 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007146 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07007147 "visualizer_hal_stop_output");
7148 }
7149 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307150 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007151 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007152 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307153 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007154 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007155
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007156 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7157 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7158 if (adev->offload_effects_lib == NULL) {
7159 ALOGE("%s: DLOPEN failed for %s", __func__,
7160 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7161 } else {
7162 ALOGV("%s: DLOPEN successful for %s", __func__,
7163 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7164 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307165 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007166 "offload_effects_bundle_hal_start_output");
7167 adev->offload_effects_stop_output =
7168 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7169 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007170 adev->offload_effects_set_hpx_state =
7171 (int (*)(bool))dlsym(adev->offload_effects_lib,
7172 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307173 adev->offload_effects_get_parameters =
7174 (void (*)(struct str_parms *, struct str_parms *))
7175 dlsym(adev->offload_effects_lib,
7176 "offload_effects_bundle_get_parameters");
7177 adev->offload_effects_set_parameters =
7178 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7179 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007180 }
7181 }
7182
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007183 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7184 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7185 if (adev->adm_lib == NULL) {
7186 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7187 } else {
7188 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7189 adev->adm_init = (adm_init_t)
7190 dlsym(adev->adm_lib, "adm_init");
7191 adev->adm_deinit = (adm_deinit_t)
7192 dlsym(adev->adm_lib, "adm_deinit");
7193 adev->adm_register_input_stream = (adm_register_input_stream_t)
7194 dlsym(adev->adm_lib, "adm_register_input_stream");
7195 adev->adm_register_output_stream = (adm_register_output_stream_t)
7196 dlsym(adev->adm_lib, "adm_register_output_stream");
7197 adev->adm_deregister_stream = (adm_deregister_stream_t)
7198 dlsym(adev->adm_lib, "adm_deregister_stream");
7199 adev->adm_request_focus = (adm_request_focus_t)
7200 dlsym(adev->adm_lib, "adm_request_focus");
7201 adev->adm_abandon_focus = (adm_abandon_focus_t)
7202 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007203 adev->adm_set_config = (adm_set_config_t)
7204 dlsym(adev->adm_lib, "adm_set_config");
7205 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7206 dlsym(adev->adm_lib, "adm_request_focus_v2");
7207 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7208 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7209 adev->adm_on_routing_change = (adm_on_routing_change_t)
7210 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007211 }
7212 }
7213
Mingming Yin514a8bc2014-07-29 15:22:21 -07007214 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007215 //initialize this to false for now,
7216 //this will be set to true through set param
7217 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007218
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007219 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007220 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007221 adev->dsp_bit_width_enforce_mode =
7222 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007223
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307224 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7225 &adev->streams_output_cfg_list,
7226 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007227
Kiran Kandi910e1862013-10-29 13:29:42 -07007228 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007229
7230 char value[PROPERTY_VALUE_MAX];
7231 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007232 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007233 trial = atoi(value);
7234 if (period_size_is_plausible_for_low_latency(trial)) {
7235 pcm_config_low_latency.period_size = trial;
7236 pcm_config_low_latency.start_threshold = trial / 4;
7237 pcm_config_low_latency.avail_min = trial / 4;
7238 configured_low_latency_capture_period_size = trial;
7239 }
7240 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007241 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007242 trial = atoi(value);
7243 if (period_size_is_plausible_for_low_latency(trial)) {
7244 configured_low_latency_capture_period_size = trial;
7245 }
7246 }
7247
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007248 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007249 af_period_multiplier = atoi(value);
7250 if (af_period_multiplier < 0)
7251 af_period_multiplier = 2;
7252 else if (af_period_multiplier > 4)
7253 af_period_multiplier = 4;
7254
7255 ALOGV("new period_multiplier = %d", af_period_multiplier);
7256 }
7257
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007258 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007259 pthread_mutex_unlock(&adev_init_lock);
7260
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007261 if (adev->adm_init)
7262 adev->adm_data = adev->adm_init();
7263
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307264 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307265 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007266 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307267
7268 audio_extn_snd_mon_init();
7269 pthread_mutex_lock(&adev->lock);
7270 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7271 adev->card_status = CARD_STATUS_ONLINE;
7272 pthread_mutex_unlock(&adev->lock);
7273 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307274 /* Allocate memory for Device config params */
7275 adev->device_cfg_params = (struct audio_device_config_param*)
7276 calloc(platform_get_max_codec_backend(),
7277 sizeof(struct audio_device_config_param));
7278 if (adev->device_cfg_params == NULL)
7279 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307280
Eric Laurent994a6932013-07-17 11:51:42 -07007281 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007282 return 0;
7283}
7284
7285static struct hw_module_methods_t hal_module_methods = {
7286 .open = adev_open,
7287};
7288
7289struct audio_module HAL_MODULE_INFO_SYM = {
7290 .common = {
7291 .tag = HARDWARE_MODULE_TAG,
7292 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7293 .hal_api_version = HARDWARE_HAL_API_VERSION,
7294 .id = AUDIO_HARDWARE_MODULE_ID,
7295 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007296 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007297 .methods = &hal_module_methods,
7298 },
7299};