blob: b24973b40b7dc0a5f6a14dc5cdb4545c988a83a0 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070066#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070068#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070078#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080079#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080080
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053081#ifdef DYNAMIC_LOG_ENABLED
82#include <log_xml_parser.h>
83#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
84#include <log_utils.h>
85#endif
86
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070087#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053088/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
89#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070091#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053092#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070093
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070094#define PROXY_OPEN_RETRY_COUNT 100
95#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080096
Mingming Yin08c7e312015-03-16 18:10:58 -070097#ifdef USE_LL_AS_PRIMARY_OUTPUT
98#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
99#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
100#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800101#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700102#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
103#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800104
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700105#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700106#define DEFAULT_VOIP_BUF_DURATION_MS 20
107#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
108#define DEFAULT_VOIP_SAMP_RATE 48000
109
110#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
111
112struct pcm_config default_pcm_config_voip_copp = {
113 .channels = 1,
114 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
115 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
116 .period_count = 2,
117 .format = PCM_FORMAT_S16_LE,
118};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700119
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700120#define MIN_CHANNEL_COUNT 1
121#define DEFAULT_CHANNEL_COUNT 2
122#define MAX_HIFI_CHANNEL_COUNT 8
123
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700124static unsigned int configured_low_latency_capture_period_size =
125 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
126
Haynes Mathew George16081042017-05-31 17:16:49 -0700127#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
128#define MMAP_PERIOD_COUNT_MIN 32
129#define MMAP_PERIOD_COUNT_MAX 512
130#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
131
Eric Laurentb23d5282013-05-14 15:27:20 -0700132struct pcm_config pcm_config_deep_buffer = {
133 .channels = 2,
134 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
135 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
136 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
137 .format = PCM_FORMAT_S16_LE,
138 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
139 .stop_threshold = INT_MAX,
140 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
141};
142
143struct pcm_config pcm_config_low_latency = {
144 .channels = 2,
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
146 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
147 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
150 .stop_threshold = INT_MAX,
151 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
152};
153
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700154static int af_period_multiplier = 4;
155struct pcm_config pcm_config_rt = {
156 .channels = 2,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = ULL_PERIOD_SIZE, //1 ms
159 .period_count = 512, //=> buffer size is 512ms
160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
162 .stop_threshold = INT_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = ULL_PERIOD_SIZE, //1 ms
166};
167
Eric Laurentb23d5282013-05-14 15:27:20 -0700168struct pcm_config pcm_config_hdmi_multi = {
169 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = HDMI_MULTI_PERIOD_SIZE,
172 .period_count = HDMI_MULTI_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Haynes Mathew George16081042017-05-31 17:16:49 -0700179struct pcm_config pcm_config_mmap_playback = {
180 .channels = 2,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = MMAP_PERIOD_SIZE,
183 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = MMAP_PERIOD_SIZE*8,
186 .stop_threshold = INT32_MAX,
187 .silence_threshold = 0,
188 .silence_size = 0,
189 .avail_min = MMAP_PERIOD_SIZE, //1 ms
190};
191
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700192struct pcm_config pcm_config_hifi = {
193 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
195 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
196 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S24_3LE,
198 .start_threshold = 0,
199 .stop_threshold = INT_MAX,
200 .avail_min = 0,
201};
202
Eric Laurentb23d5282013-05-14 15:27:20 -0700203struct pcm_config pcm_config_audio_capture = {
204 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700205 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
206 .format = PCM_FORMAT_S16_LE,
207};
208
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700209struct pcm_config pcm_config_audio_capture_rt = {
210 .channels = 2,
211 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
212 .period_size = ULL_PERIOD_SIZE,
213 .period_count = 512,
214 .format = PCM_FORMAT_S16_LE,
215 .start_threshold = 0,
216 .stop_threshold = INT_MAX,
217 .silence_threshold = 0,
218 .silence_size = 0,
219 .avail_min = ULL_PERIOD_SIZE, //1 ms
220};
221
Haynes Mathew George16081042017-05-31 17:16:49 -0700222struct pcm_config pcm_config_mmap_capture = {
223 .channels = 2,
224 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
225 .period_size = MMAP_PERIOD_SIZE,
226 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
227 .format = PCM_FORMAT_S16_LE,
228 .start_threshold = 0,
229 .stop_threshold = INT_MAX,
230 .silence_threshold = 0,
231 .silence_size = 0,
232 .avail_min = MMAP_PERIOD_SIZE, //1 ms
233};
234
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700235#define AFE_PROXY_CHANNEL_COUNT 2
236#define AFE_PROXY_SAMPLING_RATE 48000
237
238#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
239#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
240
241struct pcm_config pcm_config_afe_proxy_playback = {
242 .channels = AFE_PROXY_CHANNEL_COUNT,
243 .rate = AFE_PROXY_SAMPLING_RATE,
244 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
245 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
248 .stop_threshold = INT_MAX,
249 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
250};
251
252#define AFE_PROXY_RECORD_PERIOD_SIZE 768
253#define AFE_PROXY_RECORD_PERIOD_COUNT 4
254
255struct pcm_config pcm_config_afe_proxy_record = {
256 .channels = AFE_PROXY_CHANNEL_COUNT,
257 .rate = AFE_PROXY_SAMPLING_RATE,
258 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
259 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
260 .format = PCM_FORMAT_S16_LE,
261 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
262 .stop_threshold = INT_MAX,
263 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
264};
265
Ashish Jainf1eaa582016-05-23 20:54:24 +0530266#define AUDIO_MAX_PCM_FORMATS 7
267
268const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
269 [AUDIO_FORMAT_DEFAULT] = 0,
270 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
271 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
272 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
273 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
274 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
275 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
276};
277
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800278const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700279 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
280 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700281 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
282 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700283 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700284 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700285 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
286 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
287 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
288 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
289 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
290 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
291 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
292 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700293 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
294 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700295 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700296
Eric Laurentb23d5282013-05-14 15:27:20 -0700297 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700298 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530299 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
300 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
301 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700302 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700303 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700304 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700305 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700306
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800307 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800308 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700309 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700310
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700311 [USECASE_VOICE2_CALL] = "voice2-call",
312 [USECASE_VOLTE_CALL] = "volte-call",
313 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800314 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800315 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
316 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800317 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700318 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
319 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
320 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800321 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
322 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
323 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
324
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700325 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
326 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700327 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
328 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700329
330 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
331 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700332 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700333
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530334 /* Transcode loopback cases */
335 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700336
337 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
338 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530339 /* For Interactive Audio Streams */
340 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
341 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
342 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
343 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
344 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
345 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
346 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
347 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700348
349 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture"
Eric Laurentb23d5282013-05-14 15:27:20 -0700350};
351
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700352static const audio_usecase_t offload_usecases[] = {
353 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700354 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
355 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
356 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
357 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
358 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
359 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
360 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
361 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700362};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800363
Varun Balaraje49253e2017-07-06 19:48:56 +0530364static const audio_usecase_t interactive_usecases[] = {
365 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
366 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
367 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
368 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
369 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
370 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
371 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
372 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
373};
374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800375#define STRING_TO_ENUM(string) { #string, string }
376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800377struct string_to_enum {
378 const char *name;
379 uint32_t value;
380};
381
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700382static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800383 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800384 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
385 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
386 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700387 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800388 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
389 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800390 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700391 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
392 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
393 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
394 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
395 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
396 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
397 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
398 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
399 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
400 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
401 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800402};
403
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700404static const struct string_to_enum formats_name_to_enum_table[] = {
405 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
406 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
407 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700408 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
409 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
410 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700411 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800412 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
413 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700414 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800415};
416
417//list of all supported sample rates by HDMI specification.
418static const int out_hdmi_sample_rates[] = {
419 32000, 44100, 48000, 88200, 96000, 176400, 192000,
420};
421
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700422static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800423 STRING_TO_ENUM(32000),
424 STRING_TO_ENUM(44100),
425 STRING_TO_ENUM(48000),
426 STRING_TO_ENUM(88200),
427 STRING_TO_ENUM(96000),
428 STRING_TO_ENUM(176400),
429 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700430};
431
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432static struct audio_device *adev = NULL;
433static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700434static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700435//cache last MBDRC cal step level
436static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700437
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530438static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
439static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800440static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530441
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700442static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
443 int flags __unused)
444{
445 int dir = 0;
446 switch (uc_id) {
447 case USECASE_AUDIO_RECORD_LOW_LATENCY:
448 dir = 1;
449 case USECASE_AUDIO_PLAYBACK_ULL:
450 break;
451 default:
452 return false;
453 }
454
455 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
456 PCM_PLAYBACK : PCM_CAPTURE);
457 if (adev->adm_is_noirq_avail)
458 return adev->adm_is_noirq_avail(adev->adm_data,
459 adev->snd_card, dev_id, dir);
460 return false;
461}
462
463static void register_out_stream(struct stream_out *out)
464{
465 struct audio_device *adev = out->dev;
466 if (is_offload_usecase(out->usecase) ||
467 !adev->adm_register_output_stream)
468 return;
469
470 // register stream first for backward compatibility
471 adev->adm_register_output_stream(adev->adm_data,
472 out->handle,
473 out->flags);
474
475 if (!adev->adm_set_config)
476 return;
477
478 if (out->realtime)
479 adev->adm_set_config(adev->adm_data,
480 out->handle,
481 out->pcm, &out->config);
482}
483
484static void register_in_stream(struct stream_in *in)
485{
486 struct audio_device *adev = in->dev;
487 if (!adev->adm_register_input_stream)
488 return;
489
490 adev->adm_register_input_stream(adev->adm_data,
491 in->capture_handle,
492 in->flags);
493
494 if (!adev->adm_set_config)
495 return;
496
497 if (in->realtime)
498 adev->adm_set_config(adev->adm_data,
499 in->capture_handle,
500 in->pcm,
501 &in->config);
502}
503
504static void request_out_focus(struct stream_out *out, long ns)
505{
506 struct audio_device *adev = out->dev;
507
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700508 if (adev->adm_request_focus_v2)
509 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
510 else if (adev->adm_request_focus)
511 adev->adm_request_focus(adev->adm_data, out->handle);
512}
513
514static void request_in_focus(struct stream_in *in, long ns)
515{
516 struct audio_device *adev = in->dev;
517
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700518 if (adev->adm_request_focus_v2)
519 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
520 else if (adev->adm_request_focus)
521 adev->adm_request_focus(adev->adm_data, in->capture_handle);
522}
523
524static void release_out_focus(struct stream_out *out)
525{
526 struct audio_device *adev = out->dev;
527
528 if (adev->adm_abandon_focus)
529 adev->adm_abandon_focus(adev->adm_data, out->handle);
530}
531
532static void release_in_focus(struct stream_in *in)
533{
534 struct audio_device *adev = in->dev;
535 if (adev->adm_abandon_focus)
536 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
537}
538
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530539static int parse_snd_card_status(struct str_parms *parms, int *card,
540 card_status_t *status)
541{
542 char value[32]={0};
543 char state[32]={0};
544
545 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
546 if (ret < 0)
547 return -1;
548
549 // sscanf should be okay as value is of max length 32.
550 // same as sizeof state.
551 if (sscanf(value, "%d,%s", card, state) < 2)
552 return -1;
553
554 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
555 CARD_STATUS_OFFLINE;
556 return 0;
557}
558
vivek mehtaa76401a2015-04-24 14:12:15 -0700559__attribute__ ((visibility ("default")))
560bool audio_hw_send_gain_dep_calibration(int level) {
561 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700562 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700563
564 pthread_mutex_lock(&adev_init_lock);
565
566 if (adev != NULL && adev->platform != NULL) {
567 pthread_mutex_lock(&adev->lock);
568 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700569
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530570 // cache level info for any of the use case which
571 // was not started.
572 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700573
vivek mehtaa76401a2015-04-24 14:12:15 -0700574 pthread_mutex_unlock(&adev->lock);
575 } else {
576 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
577 }
578
579 pthread_mutex_unlock(&adev_init_lock);
580
581 return ret_val;
582}
583
Ashish Jain5106d362016-05-11 19:23:33 +0530584static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
585{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800586 bool gapless_enabled = false;
587 const char *mixer_ctl_name = "Compress Gapless Playback";
588 struct mixer_ctl *ctl;
589
590 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700591 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530592
593 /*Disable gapless if its AV playback*/
594 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800595
596 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
597 if (!ctl) {
598 ALOGE("%s: Could not get ctl for mixer cmd - %s",
599 __func__, mixer_ctl_name);
600 return -EINVAL;
601 }
602
603 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
604 ALOGE("%s: Could not set gapless mode %d",
605 __func__, gapless_enabled);
606 return -EINVAL;
607 }
608 return 0;
609}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700610
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700611__attribute__ ((visibility ("default")))
612int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
613 int table_size) {
614 int ret_val = 0;
615 ALOGV("%s: enter ... ", __func__);
616
617 pthread_mutex_lock(&adev_init_lock);
618 if (adev == NULL) {
619 ALOGW("%s: adev is NULL .... ", __func__);
620 goto done;
621 }
622
623 pthread_mutex_lock(&adev->lock);
624 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
625 pthread_mutex_unlock(&adev->lock);
626done:
627 pthread_mutex_unlock(&adev_init_lock);
628 ALOGV("%s: exit ... ", __func__);
629 return ret_val;
630}
631
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700632static bool is_supported_format(audio_format_t format)
633{
Eric Laurent86e17132013-09-12 17:49:30 -0700634 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530635 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530636 format == AUDIO_FORMAT_AAC_LC ||
637 format == AUDIO_FORMAT_AAC_HE_V1 ||
638 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530639 format == AUDIO_FORMAT_AAC_ADTS_LC ||
640 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
641 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530642 format == AUDIO_FORMAT_AAC_LATM_LC ||
643 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
644 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530645 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
646 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530647 format == AUDIO_FORMAT_PCM_FLOAT ||
648 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700649 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530650 format == AUDIO_FORMAT_AC3 ||
651 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700652 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530653 format == AUDIO_FORMAT_DTS ||
654 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800655 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530656 format == AUDIO_FORMAT_ALAC ||
657 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530658 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530659 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800660 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530661 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700662 format == AUDIO_FORMAT_APTX ||
663 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800664 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700665
666 return false;
667}
668
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700669static inline bool is_mmap_usecase(audio_usecase_t uc_id)
670{
671 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
672 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
673}
674
Avinash Vaish71a8b972014-07-24 15:36:33 +0530675static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
676 struct audio_usecase *uc_info)
677{
678 struct listnode *node;
679 struct audio_usecase *usecase;
680
681 if (uc_info == NULL)
682 return -EINVAL;
683
684 /* Re-route all voice usecases on the shared backend other than the
685 specified usecase to new snd devices */
686 list_for_each(node, &adev->usecase_list) {
687 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800688 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530689 enable_audio_route(adev, usecase);
690 }
691 return 0;
692}
693
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530694static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530695{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530696 ALOGV("%s", __func__);
697 audio_route_apply_and_update_path(adev->audio_route,
698 "asrc-mode");
699 adev->asrc_mode_enabled = true;
700}
701
702static void disable_asrc_mode(struct audio_device *adev)
703{
704 ALOGV("%s", __func__);
705 audio_route_reset_and_update_path(adev->audio_route,
706 "asrc-mode");
707 adev->asrc_mode_enabled = false;
708}
709
710/*
711 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
712 * 44.1 or Native DSD backends are enabled for any of current use case.
713 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
714 * - Disable current mix path use case(Headphone backend) and re-enable it with
715 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
716 * e.g. Naitve DSD or Headphone 44.1 -> + 48
717 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530718static void check_and_set_asrc_mode(struct audio_device *adev,
719 struct audio_usecase *uc_info,
720 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530721{
722 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530723 int i, num_new_devices = 0;
724 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
725 /*
726 *Split snd device for new combo use case
727 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
728 */
729 if (platform_split_snd_device(adev->platform,
730 snd_device,
731 &num_new_devices,
732 split_new_snd_devices) == 0) {
733 for (i = 0; i < num_new_devices; i++)
734 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
735 } else {
736 int new_backend_idx = platform_get_backend_index(snd_device);
737 if (((new_backend_idx == HEADPHONE_BACKEND) ||
738 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
739 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
740 !adev->asrc_mode_enabled) {
741 struct listnode *node = NULL;
742 struct audio_usecase *uc = NULL;
743 struct stream_out *curr_out = NULL;
744 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
745 int i, num_devices, ret = 0;
746 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530747
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530748 list_for_each(node, &adev->usecase_list) {
749 uc = node_to_item(node, struct audio_usecase, list);
750 curr_out = (struct stream_out*) uc->stream.out;
751 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
752 /*
753 *Split snd device for existing combo use case
754 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
755 */
756 ret = platform_split_snd_device(adev->platform,
757 uc->out_snd_device,
758 &num_devices,
759 split_snd_devices);
760 if (ret < 0 || num_devices == 0) {
761 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
762 split_snd_devices[0] = uc->out_snd_device;
763 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800764 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530765 for (i = 0; i < num_devices; i++) {
766 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
767 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
768 if((new_backend_idx == HEADPHONE_BACKEND) &&
769 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
770 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
771 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
772 __func__);
773 enable_asrc_mode(adev);
774 break;
775 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
776 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
777 (usecase_backend_idx == HEADPHONE_BACKEND)) {
778 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
779 __func__);
780 disable_audio_route(adev, uc);
781 disable_snd_device(adev, uc->out_snd_device);
782 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
783 if (new_backend_idx == DSD_NATIVE_BACKEND)
784 audio_route_apply_and_update_path(adev->audio_route,
785 "hph-true-highquality-mode");
786 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
787 (curr_out->bit_width >= 24))
788 audio_route_apply_and_update_path(adev->audio_route,
789 "hph-highquality-mode");
790 enable_asrc_mode(adev);
791 enable_snd_device(adev, uc->out_snd_device);
792 enable_audio_route(adev, uc);
793 break;
794 }
795 }
796 // reset split devices count
797 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800798 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530799 if (adev->asrc_mode_enabled)
800 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530801 }
802 }
803 }
804}
805
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700806int pcm_ioctl(struct pcm *pcm, int request, ...)
807{
808 va_list ap;
809 void * arg;
810 int pcm_fd = *(int*)pcm;
811
812 va_start(ap, request);
813 arg = va_arg(ap, void *);
814 va_end(ap);
815
816 return ioctl(pcm_fd, request, arg);
817}
818
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700819int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700820 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800821{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700823 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530824 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800825
826 if (usecase == NULL)
827 return -EINVAL;
828
829 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
830
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800831 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800833 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800835
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800836#ifdef DS1_DOLBY_DAP_ENABLED
837 audio_extn_dolby_set_dmid(adev);
838 audio_extn_dolby_set_endpoint(adev);
839#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700840 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700841 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530842 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700843 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530844 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530845 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
846 out = usecase->stream.out;
847 if (out && out->compr)
848 audio_extn_utils_compress_set_clk_rec_mode(usecase);
849 }
850
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800851 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700852 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700853 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700854 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855 ALOGV("%s: exit", __func__);
856 return 0;
857}
858
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700859int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700860 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800861{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700863 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800864
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530865 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800866 return -EINVAL;
867
868 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 if (usecase->type == PCM_CAPTURE)
870 snd_device = usecase->in_snd_device;
871 else
872 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800873 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700874 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700875 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700876 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700877 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530878 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800879 ALOGV("%s: exit", __func__);
880 return 0;
881}
882
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700883int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700884 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800885{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530886 int i, num_devices = 0;
887 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700888 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
889
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800890 if (snd_device < SND_DEVICE_MIN ||
891 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800892 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800893 return -EINVAL;
894 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895
896 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700897
898 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
899 ALOGE("%s: Invalid sound device returned", __func__);
900 return -EINVAL;
901 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700902 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700903 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700904 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 return 0;
906 }
907
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530908
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700909 if (audio_extn_spkr_prot_is_enabled())
910 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700911
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800912 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
913 audio_extn_spkr_prot_is_enabled()) {
914 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700915 adev->snd_dev_ref_cnt[snd_device]--;
916 return -EINVAL;
917 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200918 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800919 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800920 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200921 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800922 return -EINVAL;
923 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700924 } else if (platform_split_snd_device(adev->platform,
925 snd_device,
926 &num_devices,
927 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530928 for (i = 0; i < num_devices; i++) {
929 enable_snd_device(adev, new_snd_devices[i]);
930 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800931 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700932 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530933
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530934
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530935 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
936 (audio_extn_a2dp_start_playback() < 0)) {
937 ALOGE(" fail to configure A2dp control path ");
938 return -EINVAL;
939 }
940
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700941 /* due to the possibility of calibration overwrite between listen
942 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700943 audio_extn_sound_trigger_update_device_status(snd_device,
944 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530945 audio_extn_listen_update_device_status(snd_device,
946 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700947 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700948 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700949 audio_extn_sound_trigger_update_device_status(snd_device,
950 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530951 audio_extn_listen_update_device_status(snd_device,
952 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700953 return -EINVAL;
954 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300955 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700956 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530957
958 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
959 !adev->native_playback_enabled &&
960 audio_is_true_native_stream_active(adev)) {
961 ALOGD("%s: %d: napb: enabling native mode in hardware",
962 __func__, __LINE__);
963 audio_route_apply_and_update_path(adev->audio_route,
964 "true-native-mode");
965 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530966 }
Garmond Leunge2433c32017-09-28 21:51:22 -0700967 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
968 (audio_extn_ffv_get_stream() == adev->active_input)) {
969 ALOGD("%s: init ec ref loopback", __func__);
970 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 return 0;
974}
975
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700976int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700977 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530979 int i, num_devices = 0;
980 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700981 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
982
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800983 if (snd_device < SND_DEVICE_MIN ||
984 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800985 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800986 return -EINVAL;
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
989 ALOGE("%s: device ref cnt is already 0", __func__);
990 return -EINVAL;
991 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700992
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700994
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700995 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
996 ALOGE("%s: Invalid sound device returned", __func__);
997 return -EINVAL;
998 }
999
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001001 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301002
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001003 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1004 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001005 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001006 } else if (platform_split_snd_device(adev->platform,
1007 snd_device,
1008 &num_devices,
1009 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301010 for (i = 0; i < num_devices; i++) {
1011 disable_snd_device(adev, new_snd_devices[i]);
1012 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001013 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001014 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001015 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001016
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301017 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
1018 audio_extn_a2dp_stop_playback();
1019
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001020 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +05301021 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301022 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1023 adev->native_playback_enabled) {
1024 ALOGD("%s: %d: napb: disabling native mode in hardware",
1025 __func__, __LINE__);
1026 audio_route_reset_and_update_path(adev->audio_route,
1027 "true-native-mode");
1028 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301029 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1030 adev->asrc_mode_enabled) {
1031 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301032 disable_asrc_mode(adev);
1033 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301034 }
Garmond Leunge2433c32017-09-28 21:51:22 -07001035 if ((snd_device == SND_DEVICE_IN_HANDSET_6MIC) &&
1036 (audio_extn_ffv_get_stream() == adev->active_input)) {
1037 ALOGD("%s: deinit ec ref loopback", __func__);
1038 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1039 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001040 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001041 audio_extn_sound_trigger_update_device_status(snd_device,
1042 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301043 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001044 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001045 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 return 0;
1048}
1049
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001050/*
1051 legend:
1052 uc - existing usecase
1053 new_uc - new usecase
1054 d1, d11, d2 - SND_DEVICE enums
1055 a1, a2 - corresponding ANDROID device enums
1056 B1, B2 - backend strings
1057
1058case 1
1059 uc->dev d1 (a1) B1
1060 new_uc->dev d1 (a1), d2 (a2) B1, B2
1061
1062 resolution: disable and enable uc->dev on d1
1063
1064case 2
1065 uc->dev d1 (a1) B1
1066 new_uc->dev d11 (a1) B1
1067
1068 resolution: need to switch uc since d1 and d11 are related
1069 (e.g. speaker and voice-speaker)
1070 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1071
1072case 3
1073 uc->dev d1 (a1) B1
1074 new_uc->dev d2 (a2) B2
1075
1076 resolution: no need to switch uc
1077
1078case 4
1079 uc->dev d1 (a1) B1
1080 new_uc->dev d2 (a2) B1
1081
1082 resolution: disable enable uc-dev on d2 since backends match
1083 we cannot enable two streams on two different devices if they
1084 share the same backend. e.g. if offload is on speaker device using
1085 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1086 using the same backend, offload must also be switched to voice-handset.
1087
1088case 5
1089 uc->dev d1 (a1) B1
1090 new_uc->dev d1 (a1), d2 (a2) B1
1091
1092 resolution: disable enable uc-dev on d2 since backends match
1093 we cannot enable two streams on two different devices if they
1094 share the same backend.
1095
1096case 6
1097 uc->dev d1 (a1) B1
1098 new_uc->dev d2 (a1) B2
1099
1100 resolution: no need to switch
1101
1102case 7
1103 uc->dev d1 (a1), d2 (a2) B1, B2
1104 new_uc->dev d1 (a1) B1
1105
1106 resolution: no need to switch
1107
1108*/
1109static snd_device_t derive_playback_snd_device(void * platform,
1110 struct audio_usecase *uc,
1111 struct audio_usecase *new_uc,
1112 snd_device_t new_snd_device)
1113{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301114 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001115
1116 snd_device_t d1 = uc->out_snd_device;
1117 snd_device_t d2 = new_snd_device;
1118
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301119 switch (uc->type) {
1120 case TRANSCODE_LOOPBACK :
1121 a1 = uc->stream.inout->out_config.devices;
1122 a2 = new_uc->stream.inout->out_config.devices;
1123 break;
1124 default :
1125 a1 = uc->stream.out->devices;
1126 a2 = new_uc->stream.out->devices;
1127 break;
1128 }
1129
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001130 // Treat as a special case when a1 and a2 are not disjoint
1131 if ((a1 != a2) && (a1 & a2)) {
1132 snd_device_t d3[2];
1133 int num_devices = 0;
1134 int ret = platform_split_snd_device(platform,
1135 popcount(a1) > 1 ? d1 : d2,
1136 &num_devices,
1137 d3);
1138 if (ret < 0) {
1139 if (ret != -ENOSYS) {
1140 ALOGW("%s failed to split snd_device %d",
1141 __func__,
1142 popcount(a1) > 1 ? d1 : d2);
1143 }
1144 goto end;
1145 }
1146
1147 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1148 // But if it does happen, we need to give priority to d2 if
1149 // the combo devices active on the existing usecase share a backend.
1150 // This is because we cannot have a usecase active on a combo device
1151 // and a new usecase requests one device in this combo pair.
1152 if (platform_check_backends_match(d3[0], d3[1])) {
1153 return d2; // case 5
1154 } else {
1155 return d1; // case 1
1156 }
1157 } else {
1158 if (platform_check_backends_match(d1, d2)) {
1159 return d2; // case 2, 4
1160 } else {
1161 return d1; // case 6, 3
1162 }
1163 }
1164
1165end:
1166 return d2; // return whatever was calculated before.
1167}
1168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301170 struct audio_usecase *uc_info,
1171 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001172{
1173 struct listnode *node;
1174 struct audio_usecase *usecase;
1175 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301176 snd_device_t uc_derive_snd_device;
1177 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001179 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301180 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 /*
1182 * This function is to make sure that all the usecases that are active on
1183 * the hardware codec backend are always routed to any one device that is
1184 * handled by the hardware codec.
1185 * For example, if low-latency and deep-buffer usecases are currently active
1186 * on speaker and out_set_parameters(headset) is received on low-latency
1187 * output, then we have to make sure deep-buffer is also switched to headset,
1188 * because of the limitation that both the devices cannot be enabled
1189 * at the same time as they share the same backend.
1190 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001191 /*
1192 * This call is to check if we need to force routing for a particular stream
1193 * If there is a backend configuration change for the device when a
1194 * new stream starts, then ADM needs to be closed and re-opened with the new
1195 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001196 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001197 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001198 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1199 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301200 /* For a2dp device reconfigure all active sessions
1201 * with new AFE encoder format based on a2dp state
1202 */
1203 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1204 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1205 audio_extn_a2dp_is_force_device_switch()) {
1206 force_routing = true;
1207 force_restart_session = true;
1208 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301209 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1210
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001212 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001213 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001214 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1215 switch_device[i] = false;
1216
1217 list_for_each(node, &adev->usecase_list) {
1218 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001219
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301220 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1221 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301222 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301223 platform_get_snd_device_name(usecase->out_snd_device),
1224 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301225 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1226 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1227 usecase, uc_info, snd_device);
1228 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1229 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1230 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1231 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1232 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1233 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1234 ((force_restart_session) ||
1235 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301236 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1237 __func__, use_case_table[usecase->id],
1238 platform_get_snd_device_name(usecase->out_snd_device));
1239 disable_audio_route(adev, usecase);
1240 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301241 /* Enable existing usecase on derived playback device */
1242 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301243 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301244 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001245 }
1246 }
1247
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301248 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1249 num_uc_to_switch);
1250
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001251 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001252 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001253
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301254 /* Make sure the previous devices to be disabled first and then enable the
1255 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 list_for_each(node, &adev->usecase_list) {
1257 usecase = node_to_item(node, struct audio_usecase, list);
1258 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001259 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001260 }
1261 }
1262
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001263 list_for_each(node, &adev->usecase_list) {
1264 usecase = node_to_item(node, struct audio_usecase, list);
1265 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301266 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001267 }
1268 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001270 /* Re-route all the usecases on the shared backend other than the
1271 specified usecase to new snd devices */
1272 list_for_each(node, &adev->usecase_list) {
1273 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301274 /* Update the out_snd_device only before enabling the audio route */
1275 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301276 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301277 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301278 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301279 use_case_table[usecase->id],
1280 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001281 /* Update voc calibration before enabling VoIP route */
1282 if (usecase->type == VOIP_CALL)
1283 status = platform_switch_voice_call_device_post(adev->platform,
1284 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001285 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301286 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301287 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 }
1289 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001290 }
1291}
1292
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301293static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001294 struct audio_usecase *uc_info,
1295 snd_device_t snd_device)
1296{
1297 struct listnode *node;
1298 struct audio_usecase *usecase;
1299 bool switch_device[AUDIO_USECASE_MAX];
1300 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301301 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001302 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001303
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301304 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1305 snd_device);
1306 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301307
1308 /*
1309 * Make sure out devices is checked against out codec backend device and
1310 * also in devices against in codec backend. Checking out device against in
1311 * codec backend or vice versa causes issues.
1312 */
1313 if (uc_info->type == PCM_CAPTURE)
1314 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001315 /*
1316 * This function is to make sure that all the active capture usecases
1317 * are always routed to the same input sound device.
1318 * For example, if audio-record and voice-call usecases are currently
1319 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1320 * is received for voice call then we have to make sure that audio-record
1321 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1322 * because of the limitation that two devices cannot be enabled
1323 * at the same time if they share the same backend.
1324 */
1325 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1326 switch_device[i] = false;
1327
1328 list_for_each(node, &adev->usecase_list) {
1329 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301330 /*
1331 * TODO: Enhance below condition to handle BT sco/USB multi recording
1332 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001333 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001334 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301335 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301336 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301337 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301338 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001339 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001340 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1341 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001342 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001343 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001344 switch_device[usecase->id] = true;
1345 num_uc_to_switch++;
1346 }
1347 }
1348
1349 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001350 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001351
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301352 /* Make sure the previous devices to be disabled first and then enable the
1353 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001354 list_for_each(node, &adev->usecase_list) {
1355 usecase = node_to_item(node, struct audio_usecase, list);
1356 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001358 }
1359 }
1360
1361 list_for_each(node, &adev->usecase_list) {
1362 usecase = node_to_item(node, struct audio_usecase, list);
1363 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001364 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001365 }
1366 }
1367
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001368 /* Re-route all the usecases on the shared backend other than the
1369 specified usecase to new snd devices */
1370 list_for_each(node, &adev->usecase_list) {
1371 usecase = node_to_item(node, struct audio_usecase, list);
1372 /* Update the in_snd_device only before enabling the audio route */
1373 if (switch_device[usecase->id] ) {
1374 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001375 if (usecase->type != VOICE_CALL) {
1376 /* Update voc calibration before enabling VoIP route */
1377 if (usecase->type == VOIP_CALL)
1378 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001379 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001380 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301381 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001382 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001383 }
1384 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001385 }
1386}
1387
Mingming Yin3a941d42016-02-17 18:08:05 -08001388static void reset_hdmi_sink_caps(struct stream_out *out) {
1389 int i = 0;
1390
1391 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1392 out->supported_channel_masks[i] = 0;
1393 }
1394 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1395 out->supported_formats[i] = 0;
1396 }
1397 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1398 out->supported_sample_rates[i] = 0;
1399 }
1400}
1401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001403static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404{
Mingming Yin3a941d42016-02-17 18:08:05 -08001405 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001406 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407
Mingming Yin3a941d42016-02-17 18:08:05 -08001408 reset_hdmi_sink_caps(out);
1409
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001410 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001411 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001412 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001413 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001414 }
1415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001416 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001418 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001419 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001420 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1421 case 6:
1422 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1423 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1424 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1425 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1426 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1427 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 break;
1429 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001430 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001431 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 break;
1433 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001434
1435 // check channel format caps
1436 i = 0;
1437 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1438 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1439 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1440 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1441 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1442 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1443 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1444 }
1445
Ben Romberger1aaaf862017-04-06 17:49:46 -07001446 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1447 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1448 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1449 }
1450
Mingming Yin3a941d42016-02-17 18:08:05 -08001451 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1452 ALOGV(":%s HDMI supports DTS format", __func__);
1453 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1454 }
1455
1456 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1457 ALOGV(":%s HDMI supports DTS HD format", __func__);
1458 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1459 }
1460
Naresh Tanniru928f0862017-04-07 16:44:23 -07001461 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1462 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1463 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1464 }
1465
Mingming Yin3a941d42016-02-17 18:08:05 -08001466
1467 // check sample rate caps
1468 i = 0;
1469 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1470 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1471 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1472 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1473 }
1474 }
1475
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001476 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477}
1478
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001479static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1480 uint32_t *supported_sample_rates __unused,
1481 uint32_t max_rates __unused)
1482{
1483 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1484 supported_sample_rates,
1485 max_rates);
1486 for (ssize_t i=0; i<count; i++) {
1487 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1488 supported_sample_rates[i]);
1489 }
1490 return count;
1491}
1492
1493static inline int read_usb_sup_channel_masks(bool is_playback,
1494 audio_channel_mask_t *supported_channel_masks,
1495 uint32_t max_masks)
1496{
1497 int channels = audio_extn_usb_get_max_channels(is_playback);
1498 int channel_count;
1499 uint32_t num_masks = 0;
1500 if (channels > MAX_HIFI_CHANNEL_COUNT)
1501 channels = MAX_HIFI_CHANNEL_COUNT;
1502
1503 if (is_playback) {
1504 // For playback we never report mono because the framework always outputs stereo
1505 channel_count = DEFAULT_CHANNEL_COUNT;
1506 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1507 // above 2 but we want indexed masks here. So we
1508 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1509 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1510 }
1511 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1512 supported_channel_masks[num_masks++] =
1513 audio_channel_mask_for_index_assignment_from_count(channel_count);
1514 }
1515 } else {
1516 // For capture we report all supported channel masks from 1 channel up.
1517 channel_count = MIN_CHANNEL_COUNT;
1518 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1519 // indexed mask
1520 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1521 supported_channel_masks[num_masks++] =
1522 audio_channel_in_mask_from_count(channel_count);
1523 }
1524 }
1525 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1526 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1527 return num_masks;
1528}
1529
1530static inline int read_usb_sup_formats(bool is_playback __unused,
1531 audio_format_t *supported_formats,
1532 uint32_t max_formats __unused)
1533{
1534 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1535 switch (bitwidth) {
1536 case 24:
1537 // XXX : usb.c returns 24 for s24 and s24_le?
1538 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1539 break;
1540 case 32:
1541 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1542 break;
1543 case 16:
1544 default :
1545 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1546 break;
1547 }
1548 ALOGV("%s: %s supported format %d", __func__,
1549 is_playback ? "P" : "C", bitwidth);
1550 return 1;
1551}
1552
1553static inline int read_usb_sup_params_and_compare(bool is_playback,
1554 audio_format_t *format,
1555 audio_format_t *supported_formats,
1556 uint32_t max_formats,
1557 audio_channel_mask_t *mask,
1558 audio_channel_mask_t *supported_channel_masks,
1559 uint32_t max_masks,
1560 uint32_t *rate,
1561 uint32_t *supported_sample_rates,
1562 uint32_t max_rates) {
1563 int ret = 0;
1564 int num_formats;
1565 int num_masks;
1566 int num_rates;
1567 int i;
1568
1569 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1570 max_formats);
1571 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1572 max_masks);
1573
1574 num_rates = read_usb_sup_sample_rates(is_playback,
1575 supported_sample_rates, max_rates);
1576
1577#define LUT(table, len, what, dflt) \
1578 for (i=0; i<len && (table[i] != what); i++); \
1579 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1580
1581 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1582 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1583 LUT(supported_sample_rates, num_rates, *rate, 0);
1584
1585#undef LUT
1586 return ret < 0 ? -EINVAL : 0; // HACK TBD
1587}
1588
Alexy Josephb1379942016-01-29 15:49:38 -08001589audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001590 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001591{
1592 struct audio_usecase *usecase;
1593 struct listnode *node;
1594
1595 list_for_each(node, &adev->usecase_list) {
1596 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001597 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001598 ALOGV("%s: usecase id %d", __func__, usecase->id);
1599 return usecase->id;
1600 }
1601 }
1602 return USECASE_INVALID;
1603}
1604
Alexy Josephb1379942016-01-29 15:49:38 -08001605struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001606 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001607{
1608 struct audio_usecase *usecase;
1609 struct listnode *node;
1610
1611 list_for_each(node, &adev->usecase_list) {
1612 usecase = node_to_item(node, struct audio_usecase, list);
1613 if (usecase->id == uc_id)
1614 return usecase;
1615 }
1616 return NULL;
1617}
1618
Dhananjay Kumard4833242016-10-06 22:09:12 +05301619struct stream_in *get_next_active_input(const struct audio_device *adev)
1620{
1621 struct audio_usecase *usecase;
1622 struct listnode *node;
1623
1624 list_for_each_reverse(node, &adev->usecase_list) {
1625 usecase = node_to_item(node, struct audio_usecase, list);
1626 if (usecase->type == PCM_CAPTURE)
1627 return usecase->stream.in;
1628 }
1629 return NULL;
1630}
1631
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301632/*
1633 * is a true native playback active
1634 */
1635bool audio_is_true_native_stream_active(struct audio_device *adev)
1636{
1637 bool active = false;
1638 int i = 0;
1639 struct listnode *node;
1640
1641 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1642 ALOGV("%s:napb: not in true mode or non hdphones device",
1643 __func__);
1644 active = false;
1645 goto exit;
1646 }
1647
1648 list_for_each(node, &adev->usecase_list) {
1649 struct audio_usecase *uc;
1650 uc = node_to_item(node, struct audio_usecase, list);
1651 struct stream_out *curr_out =
1652 (struct stream_out*) uc->stream.out;
1653
1654 if (curr_out && PCM_PLAYBACK == uc->type) {
1655 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1656 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1657 uc->id, curr_out->sample_rate,
1658 curr_out->bit_width,
1659 platform_get_snd_device_name(uc->out_snd_device));
1660
1661 if (is_offload_usecase(uc->id) &&
1662 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1663 active = true;
1664 ALOGD("%s:napb:native stream detected", __func__);
1665 }
1666 }
1667 }
1668exit:
1669 return active;
1670}
1671
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001672uint32_t adev_get_dsp_bit_width_enforce_mode()
1673{
1674 if (adev == NULL) {
1675 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1676 return 0;
1677 }
1678 return adev->dsp_bit_width_enforce_mode;
1679}
1680
1681static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1682{
1683 char value[PROPERTY_VALUE_MAX];
1684 int trial;
1685 uint32_t dsp_bit_width_enforce_mode = 0;
1686
1687 if (!mixer) {
1688 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1689 __func__);
1690 return 0;
1691 }
1692
1693 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1694 value, NULL) > 0) {
1695 trial = atoi(value);
1696 switch (trial) {
1697 case 16:
1698 dsp_bit_width_enforce_mode = 16;
1699 break;
1700 case 24:
1701 dsp_bit_width_enforce_mode = 24;
1702 break;
1703 case 32:
1704 dsp_bit_width_enforce_mode = 32;
1705 break;
1706 default:
1707 dsp_bit_width_enforce_mode = 0;
1708 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1709 break;
1710 }
1711 }
1712
1713 return dsp_bit_width_enforce_mode;
1714}
1715
1716static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1717 uint32_t enforce_mode,
1718 bool enable)
1719{
1720 struct mixer_ctl *ctl = NULL;
1721 const char *mixer_ctl_name = "ASM Bit Width";
1722 uint32_t asm_bit_width_mode = 0;
1723
1724 if (enforce_mode == 0) {
1725 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1726 return;
1727 }
1728
1729 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1730 if (!ctl) {
1731 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1732 __func__, mixer_ctl_name);
1733 return;
1734 }
1735
1736 if (enable)
1737 asm_bit_width_mode = enforce_mode;
1738 else
1739 asm_bit_width_mode = 0;
1740
1741 ALOGV("%s DSP bit width feature status is %d width=%d",
1742 __func__, enable, asm_bit_width_mode);
1743 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1744 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1745 asm_bit_width_mode);
1746
1747 return;
1748}
1749
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301750/*
1751 * if native DSD playback active
1752 */
1753bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1754{
1755 bool active = false;
1756 struct listnode *node = NULL;
1757 struct audio_usecase *uc = NULL;
1758 struct stream_out *curr_out = NULL;
1759
1760 list_for_each(node, &adev->usecase_list) {
1761 uc = node_to_item(node, struct audio_usecase, list);
1762 curr_out = (struct stream_out*) uc->stream.out;
1763
1764 if (curr_out && PCM_PLAYBACK == uc->type &&
1765 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1766 active = true;
1767 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301768 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301769 }
1770 }
1771 return active;
1772}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301773
1774static bool force_device_switch(struct audio_usecase *usecase)
1775{
1776 bool ret = false;
1777 bool is_it_true_mode = false;
1778
1779 if (is_offload_usecase(usecase->id) &&
1780 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001781 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1782 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1783 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301784 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1785 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1786 (!is_it_true_mode && adev->native_playback_enabled)){
1787 ret = true;
1788 ALOGD("napb: time to toggle native mode");
1789 }
1790 }
1791
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301792 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301793 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1794 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301795 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001796 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301797 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301798 ALOGD("Force a2dp device switch to update new encoder config");
1799 ret = true;
1800 }
1801
Manish Dewangan671a4202017-08-18 17:30:46 +05301802 if (usecase->stream.out->stream_config_changed) {
1803 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1804 return true;
1805 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301806 return ret;
1807}
1808
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301809bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1810{
1811 bool ret=false;
1812 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1813 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1814 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1815 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1816 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1817 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1818 ret = true;
1819
1820 return ret;
1821}
1822
1823bool is_a2dp_device(snd_device_t out_snd_device)
1824{
1825 bool ret=false;
1826 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1827 ret = true;
1828
1829 return ret;
1830}
1831
1832bool is_bt_soc_on(struct audio_device *adev)
1833{
1834 struct mixer_ctl *ctl;
1835 char *mixer_ctl_name = "BT SOC status";
1836 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1837 bool bt_soc_status = true;
1838 if (!ctl) {
1839 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1840 __func__, mixer_ctl_name);
1841 /*This is to ensure we dont break targets which dont have the kernel change*/
1842 return true;
1843 }
1844 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1845 ALOGD("BT SOC status: %d",bt_soc_status);
1846 return bt_soc_status;
1847}
1848
1849int out_standby_l(struct audio_stream *stream);
1850
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001851int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001853 snd_device_t out_snd_device = SND_DEVICE_NONE;
1854 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855 struct audio_usecase *usecase = NULL;
1856 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001857 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001858 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301859 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001860 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301863 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1864
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001865 usecase = get_usecase_from_list(adev, uc_id);
1866 if (usecase == NULL) {
1867 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1868 return -EINVAL;
1869 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001871 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001872 (usecase->type == VOIP_CALL) ||
1873 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301874 if(usecase->stream.out == NULL) {
1875 ALOGE("%s: stream.out is NULL", __func__);
1876 return -EINVAL;
1877 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001878 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001879 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001880 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301882 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1883 if (usecase->stream.inout == NULL) {
1884 ALOGE("%s: stream.inout is NULL", __func__);
1885 return -EINVAL;
1886 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301887 stream_out.devices = usecase->stream.inout->out_config.devices;
1888 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1889 stream_out.format = usecase->stream.inout->out_config.format;
1890 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1891 out_snd_device = platform_get_output_snd_device(adev->platform,
1892 &stream_out);
1893 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301894 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 } else {
1896 /*
1897 * If the voice call is active, use the sound devices of voice call usecase
1898 * so that it would not result any device switch. All the usecases will
1899 * be switched to new device when select_devices() is called for voice call
1900 * usecase. This is to avoid switching devices for voice call when
1901 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001902 * choose voice call device only if the use case device is
1903 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001904 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001905 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001906 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001907 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001908 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1909 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301910 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1911 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001912 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001913 in_snd_device = vc_usecase->in_snd_device;
1914 out_snd_device = vc_usecase->out_snd_device;
1915 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001916 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001917 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001918 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001919 if ((voip_usecase != NULL) &&
1920 (usecase->type == PCM_PLAYBACK) &&
1921 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001922 out_snd_device_backend_match = platform_check_backends_match(
1923 voip_usecase->out_snd_device,
1924 platform_get_output_snd_device(
1925 adev->platform,
1926 usecase->stream.out));
1927 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001928 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001929 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1930 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001931 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001932 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001933 in_snd_device = voip_usecase->in_snd_device;
1934 out_snd_device = voip_usecase->out_snd_device;
1935 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001936 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001937 hfp_ucid = audio_extn_hfp_get_usecase();
1938 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001939 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001940 in_snd_device = hfp_usecase->in_snd_device;
1941 out_snd_device = hfp_usecase->out_snd_device;
1942 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943 }
1944 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301945 if (usecase->stream.out == NULL) {
1946 ALOGE("%s: stream.out is NULL", __func__);
1947 return -EINVAL;
1948 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949 usecase->devices = usecase->stream.out->devices;
1950 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001951 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001952 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001953 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001954 if (usecase->stream.out == adev->primary_output &&
1955 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001956 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001957 select_devices(adev, adev->active_input->usecase);
1958 }
1959 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001960 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301961 if (usecase->stream.in == NULL) {
1962 ALOGE("%s: stream.in is NULL", __func__);
1963 return -EINVAL;
1964 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001965 usecase->devices = usecase->stream.in->device;
1966 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001967 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001968 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001969 if (adev->active_input &&
1970 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301971 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1972 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1973 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001974 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001975 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001976 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1977 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001978 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001979 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001980 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 }
1982 }
1983
1984 if (out_snd_device == usecase->out_snd_device &&
1985 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301986
1987 if (!force_device_switch(usecase))
1988 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 }
1990
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301991 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1992 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1993 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1994 return 0;
1995 }
1996
sangwoobc677242013-08-08 16:53:43 +09001997 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001998 out_snd_device, platform_get_snd_device_name(out_snd_device),
1999 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 /*
2002 * Limitation: While in call, to do a device switch we need to disable
2003 * and enable both RX and TX devices though one of them is same as current
2004 * device.
2005 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002006 if ((usecase->type == VOICE_CALL) &&
2007 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2008 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002009 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002010 }
2011
2012 if (((usecase->type == VOICE_CALL) ||
2013 (usecase->type == VOIP_CALL)) &&
2014 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2015 /* Disable sidetone only if voice/voip call already exists */
2016 if (voice_is_call_state_active(adev) ||
2017 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002018 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002019
2020 /* Disable aanc only if voice call exists */
2021 if (voice_is_call_state_active(adev))
2022 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002023 }
2024
Zhou Songc66eb7e2017-08-08 18:29:07 +08002025 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302026 (!audio_extn_a2dp_is_ready())) {
2027 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08002028 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302029 }
2030
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002031 /* Disable current sound devices */
2032 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002033 disable_audio_route(adev, usecase);
2034 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 }
2036
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002037 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002038 disable_audio_route(adev, usecase);
2039 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 }
2041
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002042 /* Applicable only on the targets that has external modem.
2043 * New device information should be sent to modem before enabling
2044 * the devices to reduce in-call device switch time.
2045 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002046 if ((usecase->type == VOICE_CALL) &&
2047 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2048 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002049 status = platform_switch_voice_call_enable_device_config(adev->platform,
2050 out_snd_device,
2051 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002052 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002053
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054 /* Enable new sound devices */
2055 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002056 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302057 if (platform_check_codec_asrc_support(adev->platform))
2058 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002059 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 }
2061
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002062 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302063 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002064 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002065 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002066
Avinash Vaish71a8b972014-07-24 15:36:33 +05302067 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002068 status = platform_switch_voice_call_device_post(adev->platform,
2069 out_snd_device,
2070 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302071 enable_audio_route_for_voice_usecases(adev, usecase);
2072 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002073
sangwoo170731f2013-06-08 15:36:36 +09002074 usecase->in_snd_device = in_snd_device;
2075 usecase->out_snd_device = out_snd_device;
2076
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302077 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2078 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302079 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002080 if ((24 == usecase->stream.out->bit_width) &&
2081 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2082 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2083 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2084 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2085 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2086 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2087 /*
2088 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2089 * configured device sample rate, if not update the COPP rate to be equal to the
2090 * device sample rate, else open COPP at stream sample rate
2091 */
2092 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2093 usecase->stream.out->sample_rate,
2094 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302095 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2096 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002097 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2098 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2099 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2100 }
2101
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002102 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002103 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002104 audio_extn_gef_notify_device_config(
2105 usecase->stream.out->devices,
2106 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002107 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08002108 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002109 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302110 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002111 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002112
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002113 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002114 /* Enable aanc only if voice call exists */
2115 if (voice_is_call_state_active(adev))
2116 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2117
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002118 /* Enable sidetone only if other voice/voip call already exists */
2119 if (voice_is_call_state_active(adev) ||
2120 voice_extn_compress_voip_is_started(adev))
2121 voice_set_sidetone(adev, out_snd_device, true);
2122 }
2123
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002124 /* Applicable only on the targets that has external modem.
2125 * Enable device command should be sent to modem only after
2126 * enabling voice call mixer controls
2127 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002128 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002129 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2130 out_snd_device,
2131 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302132
2133 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2134
2135 if (usecase->type == VOIP_CALL) {
2136 if (adev->active_input != NULL &&
2137 !adev->active_input->standby) {
2138 if (is_bt_soc_on(adev) == false){
2139 ALOGD("BT SCO MIC disconnected while in connection");
2140 if (adev->active_input->pcm != NULL)
2141 pcm_stop(adev->active_input->pcm);
2142 }
2143 }
2144 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2145 && usecase->stream.out->started) {
2146 if (is_bt_soc_on(adev) == false) {
2147 ALOGD("BT SCO/A2DP disconnected while in connection");
2148 out_standby_l(&usecase->stream.out->stream.common);
2149 }
2150 }
2151 } else if ((usecase->stream.out != NULL) &&
2152 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2153 usecase->stream.out->started) {
2154 if (is_bt_soc_on(adev) == false) {
2155 ALOGD("BT SCO/A2dp disconnected while in connection");
2156 out_standby_l(&usecase->stream.out->stream.common);
2157 }
2158 }
2159 }
2160
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302161 ALOGD("%s: done",__func__);
2162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 return status;
2164}
2165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166static int stop_input_stream(struct stream_in *in)
2167{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302168 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 struct audio_usecase *uc_info;
2170 struct audio_device *adev = in->dev;
2171
Eric Laurent994a6932013-07-17 11:51:42 -07002172 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002173 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 uc_info = get_usecase_from_list(adev, in->usecase);
2175 if (uc_info == NULL) {
2176 ALOGE("%s: Could not find the usecase (%d) in the list",
2177 __func__, in->usecase);
2178 return -EINVAL;
2179 }
2180
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002181 /* Close in-call recording streams */
2182 voice_check_and_stop_incall_rec_usecase(adev, in);
2183
Eric Laurent150dbfe2013-02-27 14:31:02 -08002184 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002185 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002186
2187 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002188 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002190 list_remove(&uc_info->list);
2191 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002193 adev->active_input = get_next_active_input(adev);
2194
Eric Laurent994a6932013-07-17 11:51:42 -07002195 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 return ret;
2197}
2198
2199int start_input_stream(struct stream_in *in)
2200{
2201 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002202 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 struct audio_usecase *uc_info;
2204 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002205 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002206 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
Mingming Yin2664a5b2015-09-03 10:53:11 -07002208 if (get_usecase_from_list(adev, usecase) == NULL)
2209 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302210 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2211 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002212
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302213 if (CARD_STATUS_OFFLINE == in->card_status||
2214 CARD_STATUS_OFFLINE == adev->card_status) {
2215 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302216 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302217 goto error_config;
2218 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302219
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302220 if (audio_is_bluetooth_sco_device(in->device)) {
2221 if (!adev->bt_sco_on) {
2222 ALOGE("%s: SCO profile is not ready, return error", __func__);
2223 ret = -EIO;
2224 goto error_config;
2225 }
2226 }
2227
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002228 /* Check if source matches incall recording usecase criteria */
2229 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2230 if (ret)
2231 goto error_config;
2232 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002233 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2234
2235 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2236 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2237 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002238 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002239 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002240
Eric Laurentb23d5282013-05-14 15:27:20 -07002241 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 if (in->pcm_device_id < 0) {
2243 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2244 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002245 ret = -EINVAL;
2246 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002248
2249 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002251
2252 if (!uc_info) {
2253 ret = -ENOMEM;
2254 goto error_config;
2255 }
2256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 uc_info->id = in->usecase;
2258 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002259 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002260 uc_info->devices = in->device;
2261 uc_info->in_snd_device = SND_DEVICE_NONE;
2262 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002264 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302265 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2266 adev->perf_lock_opts,
2267 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002268 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269
Haynes Mathew George16081042017-05-31 17:16:49 -07002270 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302271 ret = audio_extn_cin_start_input_stream(in);
2272 if (ret)
2273 goto error_open;
2274 else
2275 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002276 }
2277
Haynes Mathew George16081042017-05-31 17:16:49 -07002278 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002279 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002280 ALOGE("%s: pcm stream not ready", __func__);
2281 goto error_open;
2282 }
2283 ret = pcm_start(in->pcm);
2284 if (ret < 0) {
2285 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2286 goto error_open;
2287 }
2288 } else {
2289 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2290 unsigned int pcm_open_retry_count = 0;
2291
2292 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2293 flags |= PCM_MMAP | PCM_NOIRQ;
2294 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2295 } else if (in->realtime) {
2296 flags |= PCM_MMAP | PCM_NOIRQ;
2297 }
2298
Garmond Leunge2433c32017-09-28 21:51:22 -07002299 if (audio_extn_ffv_get_stream() == in) {
2300 ALOGD("%s: ffv stream, update pcm config", __func__);
2301 audio_extn_ffv_update_pcm_config(&config);
2302 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002303 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2304 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2305
2306 while (1) {
2307 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002308 flags, &config);
Haynes Mathew George16081042017-05-31 17:16:49 -07002309 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2310 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2311 if (in->pcm != NULL) {
2312 pcm_close(in->pcm);
2313 in->pcm = NULL;
2314 }
2315 if (pcm_open_retry_count-- == 0) {
2316 ret = -EIO;
2317 goto error_open;
2318 }
2319 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2320 continue;
2321 }
2322 break;
2323 }
2324
2325 ALOGV("%s: pcm_prepare", __func__);
2326 ret = pcm_prepare(in->pcm);
2327 if (ret < 0) {
2328 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2329 pcm_close(in->pcm);
2330 in->pcm = NULL;
2331 goto error_open;
2332 }
2333 register_in_stream(in);
2334 if (in->realtime) {
2335 ret = pcm_start(in->pcm);
2336 if (ret < 0) {
2337 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002338 pcm_close(in->pcm);
2339 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002340 goto error_open;
2341 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002342 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002343 }
2344
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302345done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302346 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002347 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002348
Eric Laurentc8400632013-02-14 19:04:54 -08002349 return ret;
2350
2351error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302352 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002354error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302355 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302356 /*
2357 * sleep 50ms to allow sufficient time for kernel
2358 * drivers to recover incases like SSR.
2359 */
2360 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002361 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002362
2363 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364}
2365
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002366void lock_input_stream(struct stream_in *in)
2367{
2368 pthread_mutex_lock(&in->pre_lock);
2369 pthread_mutex_lock(&in->lock);
2370 pthread_mutex_unlock(&in->pre_lock);
2371}
2372
2373void lock_output_stream(struct stream_out *out)
2374{
2375 pthread_mutex_lock(&out->pre_lock);
2376 pthread_mutex_lock(&out->lock);
2377 pthread_mutex_unlock(&out->pre_lock);
2378}
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380/* must be called with out->lock locked */
2381static int send_offload_cmd_l(struct stream_out* out, int command)
2382{
2383 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2384
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002385 if (!cmd) {
2386 ALOGE("failed to allocate mem for command 0x%x", command);
2387 return -ENOMEM;
2388 }
2389
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 ALOGVV("%s %d", __func__, command);
2391
2392 cmd->cmd = command;
2393 list_add_tail(&out->offload_cmd_list, &cmd->node);
2394 pthread_cond_signal(&out->offload_cond);
2395 return 0;
2396}
2397
2398/* must be called iwth out->lock locked */
2399static void stop_compressed_output_l(struct stream_out *out)
2400{
2401 out->offload_state = OFFLOAD_STATE_IDLE;
2402 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002403 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 if (out->compr != NULL) {
2405 compress_stop(out->compr);
2406 while (out->offload_thread_blocked) {
2407 pthread_cond_wait(&out->cond, &out->lock);
2408 }
2409 }
2410}
2411
Varun Balaraje49253e2017-07-06 19:48:56 +05302412bool is_interactive_usecase(audio_usecase_t uc_id)
2413{
2414 unsigned int i;
2415 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2416 if (uc_id == interactive_usecases[i])
2417 return true;
2418 }
2419 return false;
2420}
2421
2422static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2423{
2424 audio_usecase_t ret_uc = USECASE_INVALID;
2425 unsigned int intract_uc_index;
2426 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2427
2428 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2429 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2430 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2431 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2432 ret_uc = interactive_usecases[intract_uc_index];
2433 break;
2434 }
2435 }
2436
2437 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2438 return ret_uc;
2439}
2440
2441static void free_interactive_usecase(struct audio_device *adev,
2442 audio_usecase_t uc_id)
2443{
2444 unsigned int interact_uc_index;
2445 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2446
2447 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2448 if (interactive_usecases[interact_uc_index] == uc_id) {
2449 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2450 break;
2451 }
2452 }
2453 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2454}
2455
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002456bool is_offload_usecase(audio_usecase_t uc_id)
2457{
2458 unsigned int i;
2459 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2460 if (uc_id == offload_usecases[i])
2461 return true;
2462 }
2463 return false;
2464}
2465
Dhananjay Kumarac341582017-02-23 23:42:25 +05302466static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002467{
vivek mehta446c3962015-09-14 10:57:35 -07002468 audio_usecase_t ret_uc = USECASE_INVALID;
2469 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002470 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002471 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302472 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002473 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2474 else
2475 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002476
vivek mehta446c3962015-09-14 10:57:35 -07002477 pthread_mutex_lock(&adev->lock);
2478 if (get_usecase_from_list(adev, ret_uc) != NULL)
2479 ret_uc = USECASE_INVALID;
2480 pthread_mutex_unlock(&adev->lock);
2481
2482 return ret_uc;
2483 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002484
2485 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002486 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2487 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2488 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2489 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002490 break;
2491 }
2492 }
vivek mehta446c3962015-09-14 10:57:35 -07002493
2494 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2495 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002496}
2497
2498static void free_offload_usecase(struct audio_device *adev,
2499 audio_usecase_t uc_id)
2500{
vivek mehta446c3962015-09-14 10:57:35 -07002501 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002502 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002503
2504 if (!adev->multi_offload_enable)
2505 return;
2506
2507 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2508 if (offload_usecases[offload_uc_index] == uc_id) {
2509 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002510 break;
2511 }
2512 }
2513 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2514}
2515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002516static void *offload_thread_loop(void *context)
2517{
2518 struct stream_out *out = (struct stream_out *) context;
2519 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002520 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002521
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002522 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2523 set_sched_policy(0, SP_FOREGROUND);
2524 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2525
2526 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002527 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002528 for (;;) {
2529 struct offload_cmd *cmd = NULL;
2530 stream_callback_event_t event;
2531 bool send_callback = false;
2532
2533 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2534 __func__, list_empty(&out->offload_cmd_list),
2535 out->offload_state);
2536 if (list_empty(&out->offload_cmd_list)) {
2537 ALOGV("%s SLEEPING", __func__);
2538 pthread_cond_wait(&out->offload_cond, &out->lock);
2539 ALOGV("%s RUNNING", __func__);
2540 continue;
2541 }
2542
2543 item = list_head(&out->offload_cmd_list);
2544 cmd = node_to_item(item, struct offload_cmd, node);
2545 list_remove(item);
2546
2547 ALOGVV("%s STATE %d CMD %d out->compr %p",
2548 __func__, out->offload_state, cmd->cmd, out->compr);
2549
2550 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2551 free(cmd);
2552 break;
2553 }
2554
2555 if (out->compr == NULL) {
2556 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002557 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002558 pthread_cond_signal(&out->cond);
2559 continue;
2560 }
2561 out->offload_thread_blocked = true;
2562 pthread_mutex_unlock(&out->lock);
2563 send_callback = false;
2564 switch(cmd->cmd) {
2565 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002566 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002568 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002569 send_callback = true;
2570 event = STREAM_CBK_EVENT_WRITE_READY;
2571 break;
2572 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002573 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302574 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002575 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302576 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002577 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302578 if (ret < 0)
2579 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302580 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302581 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002582 compress_drain(out->compr);
2583 else
2584 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302585 if (ret != -ENETRESET) {
2586 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302587 pthread_mutex_lock(&out->lock);
2588 out->send_new_metadata = 1;
2589 out->send_next_track_params = true;
2590 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302591 event = STREAM_CBK_EVENT_DRAIN_READY;
2592 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2593 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302594 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 break;
2596 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002597 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002599 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002600 send_callback = true;
2601 event = STREAM_CBK_EVENT_DRAIN_READY;
2602 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302603 case OFFLOAD_CMD_ERROR:
2604 ALOGD("copl(%p): sending error callback to AF", out);
2605 send_callback = true;
2606 event = STREAM_CBK_EVENT_ERROR;
2607 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 default:
2609 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2610 break;
2611 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002612 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002613 out->offload_thread_blocked = false;
2614 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002615 if (send_callback && out->client_callback) {
2616 ALOGVV("%s: sending client_callback event %d", __func__, event);
2617 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002618 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002619 free(cmd);
2620 }
2621
2622 pthread_cond_signal(&out->cond);
2623 while (!list_empty(&out->offload_cmd_list)) {
2624 item = list_head(&out->offload_cmd_list);
2625 list_remove(item);
2626 free(node_to_item(item, struct offload_cmd, node));
2627 }
2628 pthread_mutex_unlock(&out->lock);
2629
2630 return NULL;
2631}
2632
2633static int create_offload_callback_thread(struct stream_out *out)
2634{
2635 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2636 list_init(&out->offload_cmd_list);
2637 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2638 offload_thread_loop, out);
2639 return 0;
2640}
2641
2642static int destroy_offload_callback_thread(struct stream_out *out)
2643{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002644 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 stop_compressed_output_l(out);
2646 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2647
2648 pthread_mutex_unlock(&out->lock);
2649 pthread_join(out->offload_thread, (void **) NULL);
2650 pthread_cond_destroy(&out->offload_cond);
2651
2652 return 0;
2653}
2654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655static int stop_output_stream(struct stream_out *out)
2656{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302657 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 struct audio_usecase *uc_info;
2659 struct audio_device *adev = out->dev;
2660
Eric Laurent994a6932013-07-17 11:51:42 -07002661 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 uc_info = get_usecase_from_list(adev, out->usecase);
2664 if (uc_info == NULL) {
2665 ALOGE("%s: Could not find the usecase (%d) in the list",
2666 __func__, out->usecase);
2667 return -EINVAL;
2668 }
2669
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002670 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302671 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002672 if (adev->visualizer_stop_output != NULL)
2673 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002674
2675 audio_extn_dts_remove_state_notifier_node(out->usecase);
2676
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002677 if (adev->offload_effects_stop_output != NULL)
2678 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2679 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002680
Eric Laurent150dbfe2013-02-27 14:31:02 -08002681 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002682 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683
2684 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002685 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002687 if (is_offload_usecase(out->usecase)) {
2688 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2689 adev->dsp_bit_width_enforce_mode,
2690 false);
2691 }
2692
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002693 list_remove(&uc_info->list);
2694 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302695 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002696 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302697 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002698 ALOGV("Disable passthrough , reset mixer to pcm");
2699 /* NO_PASSTHROUGH */
2700 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002701 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002702 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2703 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002704
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302705 /* Must be called after removing the usecase from list */
2706 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302707 audio_extn_keep_alive_start();
2708
Manish Dewangan21a850a2017-08-14 12:03:55 +05302709 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002710 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2711 if (ret < 0)
2712 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2713 }
2714
Eric Laurent994a6932013-07-17 11:51:42 -07002715 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 return ret;
2717}
2718
2719int start_output_stream(struct stream_out *out)
2720{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 struct audio_usecase *uc_info;
2723 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002724 char mixer_ctl_name[128];
2725 struct mixer_ctl *ctl = NULL;
2726 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302727 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002729 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2730 ret = -EINVAL;
2731 goto error_config;
2732 }
2733
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302734 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2735 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2736 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302737
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302738 if (CARD_STATUS_OFFLINE == out->card_status ||
2739 CARD_STATUS_OFFLINE == adev->card_status) {
2740 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302741 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302742 goto error_config;
2743 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302744
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302745 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2746 if (!audio_extn_a2dp_is_ready()) {
2747 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302748 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302749 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302750 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2751 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2752 ret = -EAGAIN;
2753 goto error_config;
2754 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302755 }
2756 }
2757 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302758 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2759 if (!adev->bt_sco_on) {
2760 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2761 //combo usecase just by pass a2dp
2762 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2763 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2764 } else {
2765 ALOGE("%s: SCO profile is not ready, return error", __func__);
2766 ret = -EAGAIN;
2767 goto error_config;
2768 }
2769 }
2770 }
2771
Eric Laurentb23d5282013-05-14 15:27:20 -07002772 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 if (out->pcm_device_id < 0) {
2774 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2775 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002776 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002777 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 }
2779
2780 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002781
2782 if (!uc_info) {
2783 ret = -ENOMEM;
2784 goto error_config;
2785 }
2786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 uc_info->id = out->usecase;
2788 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002789 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002790 uc_info->devices = out->devices;
2791 uc_info->in_snd_device = SND_DEVICE_NONE;
2792 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002793 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302795 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2796 adev->perf_lock_opts,
2797 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302798
2799 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2800 audio_extn_keep_alive_stop();
2801 if (audio_extn_passthru_is_enabled() &&
2802 audio_extn_passthru_is_passthrough_stream(out)) {
2803 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302804 }
2805 }
2806
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302807 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2808 (!audio_extn_a2dp_is_ready())) {
2809 if (!a2dp_combo) {
2810 check_a2dp_restore_l(adev, out, false);
2811 } else {
2812 audio_devices_t dev = out->devices;
2813 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2814 select_devices(adev, out->usecase);
2815 out->devices = dev;
2816 }
2817 } else {
2818 select_devices(adev, out->usecase);
2819 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002820
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002821 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2822 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002823
2824 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2825 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2826 ALOGE("%s: pcm stream not ready", __func__);
2827 goto error_open;
2828 }
2829 ret = pcm_start(out->pcm);
2830 if (ret < 0) {
2831 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2832 goto error_open;
2833 }
2834 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002835 unsigned int flags = PCM_OUT;
2836 unsigned int pcm_open_retry_count = 0;
2837 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2838 flags |= PCM_MMAP | PCM_NOIRQ;
2839 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002840 } else if (out->realtime) {
2841 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002842 } else
2843 flags |= PCM_MONOTONIC;
2844
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002845 if ((adev->vr_audio_mode_enabled) &&
2846 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2847 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2848 "PCM_Dev %d Topology", out->pcm_device_id);
2849 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2850 if (!ctl) {
2851 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2852 __func__, mixer_ctl_name);
2853 } else {
2854 //if success use ULLPP
2855 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2856 __func__, mixer_ctl_name, out->pcm_device_id);
2857 //There is a still a possibility that some sessions
2858 // that request for FAST|RAW when 3D audio is active
2859 //can go through ULLPP. Ideally we expects apps to
2860 //listen to audio focus and stop concurrent playback
2861 //Also, we will look for mode flag (voice_in_communication)
2862 //before enabling the realtime flag.
2863 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2864 }
2865 }
2866
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002867 while (1) {
2868 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2869 flags, &out->config);
2870 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2871 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2872 if (out->pcm != NULL) {
2873 pcm_close(out->pcm);
2874 out->pcm = NULL;
2875 }
2876 if (pcm_open_retry_count-- == 0) {
2877 ret = -EIO;
2878 goto error_open;
2879 }
2880 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2881 continue;
2882 }
2883 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002885
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002886 ALOGV("%s: pcm_prepare", __func__);
2887 if (pcm_is_ready(out->pcm)) {
2888 ret = pcm_prepare(out->pcm);
2889 if (ret < 0) {
2890 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2891 pcm_close(out->pcm);
2892 out->pcm = NULL;
2893 goto error_open;
2894 }
2895 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302896 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302897 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08002898 // apply volume for voip playback after path is set up
2899 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2900 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002902 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302903 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002904 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2905 adev->dsp_bit_width_enforce_mode,
2906 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002908 out->compr = compress_open(adev->snd_card,
2909 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 COMPRESS_IN, &out->compr_config);
2911 if (out->compr && !is_compress_ready(out->compr)) {
2912 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2913 compress_close(out->compr);
2914 out->compr = NULL;
2915 ret = -EIO;
2916 goto error_open;
2917 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302918 /* compress_open sends params of the track, so reset the flag here */
2919 out->is_compr_metadata_avail = false;
2920
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002921 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002923
Fred Oh3f43e742015-03-04 18:42:34 -08002924 /* Since small bufs uses blocking writes, a write will be blocked
2925 for the default max poll time (20s) in the event of an SSR.
2926 Reduce the poll time to observe and deal with SSR faster.
2927 */
Ashish Jain5106d362016-05-11 19:23:33 +05302928 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002929 compress_set_max_poll_wait(out->compr, 1000);
2930 }
2931
Manish Dewangan69426c82017-01-30 17:35:36 +05302932 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302933 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302934
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002935 audio_extn_dts_create_state_notifier_node(out->usecase);
2936 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2937 popcount(out->channel_mask),
2938 out->playback_started);
2939
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002940#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05302941 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002942 audio_extn_dolby_send_ddp_endp_params(adev);
2943#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302944 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2945 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002946 if (adev->visualizer_start_output != NULL)
2947 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2948 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302949 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002950 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002951 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002953
2954 if (ret == 0) {
2955 register_out_stream(out);
2956 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07002957 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2958 ALOGE("%s: pcm stream not ready", __func__);
2959 goto error_open;
2960 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002961 ret = pcm_start(out->pcm);
2962 if (ret < 0)
2963 goto error_open;
2964 }
2965 }
2966
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302967 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002968 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002969
Manish Dewangan21a850a2017-08-14 12:03:55 +05302970 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002971 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002972 if (ret < 0)
2973 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2974 }
2975
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002976 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302978 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002980error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302981 /*
2982 * sleep 50ms to allow sufficient time for kernel
2983 * drivers to recover incases like SSR.
2984 */
2985 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002986 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987}
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989static int check_input_parameters(uint32_t sample_rate,
2990 audio_format_t format,
2991 int channel_count)
2992{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002993 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302995 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2996 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2997 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002998 !voice_extn_compress_voip_is_format_supported(format) &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002999 !audio_extn_compr_cap_format_supported(format))
3000 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003001
3002 switch (channel_count) {
3003 case 1:
3004 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303005 case 3:
3006 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003007 case 6:
3008 break;
3009 default:
3010 ret = -EINVAL;
3011 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012
3013 switch (sample_rate) {
3014 case 8000:
3015 case 11025:
3016 case 12000:
3017 case 16000:
3018 case 22050:
3019 case 24000:
3020 case 32000:
3021 case 44100:
3022 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303023 case 96000:
3024 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 break;
3026 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003027 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 }
3029
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003030 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031}
3032
3033static size_t get_input_buffer_size(uint32_t sample_rate,
3034 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003035 int channel_count,
3036 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037{
3038 size_t size = 0;
3039
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003040 if (check_input_parameters(sample_rate, format, channel_count) != 0)
3041 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003043 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003044 if (is_low_latency)
3045 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303046
3047 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003049 /* make sure the size is multiple of 32 bytes
3050 * At 48 kHz mono 16-bit PCM:
3051 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3052 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
3053 */
3054 size += 0x1f;
3055 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003056
3057 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058}
3059
Ashish Jain058165c2016-09-28 23:18:48 +05303060static size_t get_output_period_size(uint32_t sample_rate,
3061 audio_format_t format,
3062 int channel_count,
3063 int duration /*in millisecs*/)
3064{
3065 size_t size = 0;
3066 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3067
3068 if ((duration == 0) || (sample_rate == 0) ||
3069 (bytes_per_sample == 0) || (channel_count == 0)) {
3070 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3071 bytes_per_sample, channel_count);
3072 return -EINVAL;
3073 }
3074
3075 size = (sample_rate *
3076 duration *
3077 bytes_per_sample *
3078 channel_count) / 1000;
3079 /*
3080 * To have same PCM samples for all channels, the buffer size requires to
3081 * be multiple of (number of channels * bytes per sample)
3082 * For writes to succeed, the buffer must be written at address which is multiple of 32
3083 */
3084 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3085
3086 return (size/(channel_count * bytes_per_sample));
3087}
3088
Ashish Jain5106d362016-05-11 19:23:33 +05303089static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
3090{
3091 uint64_t actual_frames_rendered = 0;
3092 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3093
3094 /* This adjustment accounts for buffering after app processor.
3095 * It is based on estimated DSP latency per use case, rather than exact.
3096 */
3097 int64_t platform_latency = platform_render_latency(out->usecase) *
3098 out->sample_rate / 1000000LL;
3099
3100 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3101 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3102 * hence only estimate.
3103 */
3104 int64_t signed_frames = out->written - kernel_buffer_size;
3105
3106 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3107
3108 if (signed_frames > 0)
3109 actual_frames_rendered = signed_frames;
3110
3111 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3112 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3113 (long long int)out->written, (int)kernel_buffer_size,
3114 audio_bytes_per_sample(out->compr_config.codec->format),
3115 popcount(out->channel_mask));
3116
3117 return actual_frames_rendered;
3118}
3119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3121{
3122 struct stream_out *out = (struct stream_out *)stream;
3123
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125}
3126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003127static int out_set_sample_rate(struct audio_stream *stream __unused,
3128 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129{
3130 return -ENOSYS;
3131}
3132
3133static size_t out_get_buffer_size(const struct audio_stream *stream)
3134{
3135 struct stream_out *out = (struct stream_out *)stream;
3136
Varun Balaraje49253e2017-07-06 19:48:56 +05303137 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303138 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303139 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303140 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3141 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3142 else
3143 return out->compr_config.fragment_size;
3144 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003145 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003146 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3147 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 +05303148 else if (is_offload_usecase(out->usecase) &&
3149 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303150 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003152 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003153 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154}
3155
3156static uint32_t out_get_channels(const struct audio_stream *stream)
3157{
3158 struct stream_out *out = (struct stream_out *)stream;
3159
3160 return out->channel_mask;
3161}
3162
3163static audio_format_t out_get_format(const struct audio_stream *stream)
3164{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003165 struct stream_out *out = (struct stream_out *)stream;
3166
3167 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168}
3169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003170static int out_set_format(struct audio_stream *stream __unused,
3171 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172{
3173 return -ENOSYS;
3174}
3175
3176static int out_standby(struct audio_stream *stream)
3177{
3178 struct stream_out *out = (struct stream_out *)stream;
3179 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003180 struct audio_usecase *uc_info;
3181 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003182 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003183
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303184 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3185 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003187 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003189 if (adev->adm_deregister_stream)
3190 adev->adm_deregister_stream(adev->adm_data, out->handle);
3191
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003192 if (is_offload_usecase(out->usecase))
3193 stop_compressed_output_l(out);
3194
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003195 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003197 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3198 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303199 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003200 pthread_mutex_unlock(&adev->lock);
3201 pthread_mutex_unlock(&out->lock);
3202 ALOGD("VOIP output entered standby");
3203 return 0;
3204 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 if (out->pcm) {
3206 pcm_close(out->pcm);
3207 out->pcm = NULL;
3208 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003209 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3210 do_stop = out->playback_started;
3211 out->playback_started = false;
3212 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003214 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303215 out->send_next_track_params = false;
3216 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003217 out->gapless_mdata.encoder_delay = 0;
3218 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219 if (out->compr != NULL) {
3220 compress_close(out->compr);
3221 out->compr = NULL;
3222 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003223 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003224 if (do_stop) {
3225 stop_output_stream(out);
3226 }
kunleiza9d11682017-08-04 14:14:09 +08003227 //restore output device for active usecase when current snd device and output device mismatch
3228 list_for_each(node, &adev->usecase_list) {
3229 uc_info = node_to_item(node, struct audio_usecase, list);
3230 if ((uc_info->type == PCM_PLAYBACK) &&
3231 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3232 select_devices(adev, uc_info->id);
3233 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003234 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 }
3236 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303237 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 return 0;
3239}
3240
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303241static int out_on_error(struct audio_stream *stream)
3242{
3243 struct stream_out *out = (struct stream_out *)stream;
3244 bool do_standby = false;
3245
3246 lock_output_stream(out);
3247 if (!out->standby) {
3248 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3249 stop_compressed_output_l(out);
3250 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3251 } else
3252 do_standby = true;
3253 }
3254 pthread_mutex_unlock(&out->lock);
3255
3256 if (do_standby)
3257 return out_standby(&out->stream.common);
3258
3259 return 0;
3260}
3261
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303262/*
3263 *standby implementation without locks, assumes that the callee already
3264 *has taken adev and out lock.
3265 */
3266int out_standby_l(struct audio_stream *stream)
3267{
3268 struct stream_out *out = (struct stream_out *)stream;
3269 struct audio_device *adev = out->dev;
3270
3271 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3272 stream, out->usecase, use_case_table[out->usecase]);
3273
3274 if (!out->standby) {
3275 if (adev->adm_deregister_stream)
3276 adev->adm_deregister_stream(adev->adm_data, out->handle);
3277
3278 if (is_offload_usecase(out->usecase))
3279 stop_compressed_output_l(out);
3280
3281 out->standby = true;
3282 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3283 voice_extn_compress_voip_close_output_stream(stream);
3284 out->started = 0;
3285 ALOGD("VOIP output entered standby");
3286 return 0;
3287 } else if (!is_offload_usecase(out->usecase)) {
3288 if (out->pcm) {
3289 pcm_close(out->pcm);
3290 out->pcm = NULL;
3291 }
3292 } else {
3293 ALOGD("copl(%p):standby", out);
3294 out->send_next_track_params = false;
3295 out->is_compr_metadata_avail = false;
3296 out->gapless_mdata.encoder_delay = 0;
3297 out->gapless_mdata.encoder_padding = 0;
3298 if (out->compr != NULL) {
3299 compress_close(out->compr);
3300 out->compr = NULL;
3301 }
3302 }
3303 stop_output_stream(out);
3304 }
3305 ALOGD("%s: exit", __func__);
3306 return 0;
3307}
3308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003309static int out_dump(const struct audio_stream *stream __unused,
3310 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311{
3312 return 0;
3313}
3314
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003315static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3316{
3317 int ret = 0;
3318 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003319
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003320 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003321 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003322 return -EINVAL;
3323 }
3324
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303325 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003326
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003327 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3328 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303329 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003330 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003331 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3332 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303333 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003334 }
3335
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003336 ALOGV("%s new encoder delay %u and padding %u", __func__,
3337 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3338
3339 return 0;
3340}
3341
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003342static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3343{
3344 return out == adev->primary_output || out == adev->voice_tx_output;
3345}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003346
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303347// note: this call is safe only if the stream_cb is
3348// removed first in close_output_stream (as is done now).
3349static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3350{
3351 if (!stream || !parms)
3352 return;
3353
3354 struct stream_out *out = (struct stream_out *)stream;
3355 struct audio_device *adev = out->dev;
3356
3357 card_status_t status;
3358 int card;
3359 if (parse_snd_card_status(parms, &card, &status) < 0)
3360 return;
3361
3362 pthread_mutex_lock(&adev->lock);
3363 bool valid_cb = (card == adev->snd_card);
3364 pthread_mutex_unlock(&adev->lock);
3365
3366 if (!valid_cb)
3367 return;
3368
3369 lock_output_stream(out);
3370 if (out->card_status != status)
3371 out->card_status = status;
3372 pthread_mutex_unlock(&out->lock);
3373
3374 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3375 use_case_table[out->usecase],
3376 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3377
3378 if (status == CARD_STATUS_OFFLINE)
3379 out_on_error(stream);
3380
3381 return;
3382}
3383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3385{
3386 struct stream_out *out = (struct stream_out *)stream;
3387 struct audio_device *adev = out->dev;
3388 struct str_parms *parms;
3389 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003390 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303391 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392
sangwoobc677242013-08-08 16:53:43 +09003393 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003394 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303396 if (!parms)
3397 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003398 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3399 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003401 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003402 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003404 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003405 * When HDMI cable is unplugged the music playback is paused and
3406 * the policy manager sends routing=0. But the audioflinger continues
3407 * to write data until standby time (3sec). As the HDMI core is
3408 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003409 * Avoid this by routing audio to speaker until standby.
3410 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003411 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3412 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303413 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003414 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3415 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003416 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303417 /*
3418 * When A2DP is disconnected the
3419 * music playback is paused and the policy manager sends routing=0
3420 * But the audioflingercontinues to write data until standby time
3421 * (3sec). As BT is turned off, the write gets blocked.
3422 * Avoid this by routing audio to speaker until standby.
3423 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003424 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303425 (val == AUDIO_DEVICE_NONE)) {
3426 val = AUDIO_DEVICE_OUT_SPEAKER;
3427 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303428 /* To avoid a2dp to sco overlapping / BT device improper state
3429 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303430 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303431 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3432 if (!audio_extn_a2dp_is_ready()) {
3433 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3434 //combo usecase just by pass a2dp
3435 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303436 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303437 } else {
3438 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3439 /* update device to a2dp and don't route as BT returned error
3440 * However it is still possible a2dp routing called because
3441 * of current active device disconnection (like wired headset)
3442 */
3443 out->devices = val;
3444 pthread_mutex_unlock(&out->lock);
3445 pthread_mutex_unlock(&adev->lock);
3446 goto error;
3447 }
3448 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303449 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003450 /*
3451 * select_devices() call below switches all the usecases on the same
3452 * backend to the new device. Refer to check_usecases_codec_backend() in
3453 * the select_devices(). But how do we undo this?
3454 *
3455 * For example, music playback is active on headset (deep-buffer usecase)
3456 * and if we go to ringtones and select a ringtone, low-latency usecase
3457 * will be started on headset+speaker. As we can't enable headset+speaker
3458 * and headset devices at the same time, select_devices() switches the music
3459 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3460 * So when the ringtone playback is completed, how do we undo the same?
3461 *
3462 * We are relying on the out_set_parameters() call on deep-buffer output,
3463 * once the ringtone playback is ended.
3464 * NOTE: We should not check if the current devices are same as new devices.
3465 * Because select_devices() must be called to switch back the music
3466 * playback to headset.
3467 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003468 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003469 audio_devices_t new_dev = val;
3470 bool same_dev = out->devices == new_dev;
3471 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003472
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003473 if (output_drives_call(adev, out)) {
3474 if(!voice_is_in_call(adev)) {
3475 if (adev->mode == AUDIO_MODE_IN_CALL) {
3476 adev->current_call_output = out;
3477 ret = voice_start_call(adev);
3478 }
3479 } else {
3480 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003481 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003482 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003483 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003484
3485 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003486 if (!same_dev) {
3487 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303488 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3489 adev->perf_lock_opts,
3490 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003491 if (adev->adm_on_routing_change)
3492 adev->adm_on_routing_change(adev->adm_data,
3493 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003494 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303495 if (!bypass_a2dp) {
3496 select_devices(adev, out->usecase);
3497 } else {
3498 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3499 select_devices(adev, out->usecase);
3500 out->devices = new_dev;
3501 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303502 if (!same_dev)
3503 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303504 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3505 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003506 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303507 pthread_mutex_lock(&out->compr_mute_lock);
3508 out->a2dp_compress_mute = false;
3509 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3510 pthread_mutex_unlock(&out->compr_mute_lock);
3511 }
3512
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003513 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003514 }
3515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003517 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003519
3520 if (out == adev->primary_output) {
3521 pthread_mutex_lock(&adev->lock);
3522 audio_extn_set_parameters(adev, parms);
3523 pthread_mutex_unlock(&adev->lock);
3524 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003525 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003526 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003527 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003528
3529 audio_extn_dts_create_state_notifier_node(out->usecase);
3530 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3531 popcount(out->channel_mask),
3532 out->playback_started);
3533
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003534 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003535 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003536
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303537 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3538 if (err >= 0) {
3539 strlcpy(out->profile, value, sizeof(out->profile));
3540 ALOGV("updating stream profile with value '%s'", out->profile);
3541 lock_output_stream(out);
3542 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3543 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07003544 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303545 out->sample_rate, out->bit_width,
3546 out->channel_mask, out->profile,
3547 &out->app_type_cfg);
3548 pthread_mutex_unlock(&out->lock);
3549 }
3550
Alexy Joseph98988832017-01-13 14:56:59 -08003551 //suspend, resume handling block
3552 if (out->dynamic_pm_qos_enabled) {
3553 //check suspend parameter only for low latency and if the property
3554 //is enabled
3555 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3556 ALOGI("%s: got suspend_playback %s", __func__, value);
3557 lock_output_stream(out);
3558 if (!strncmp(value, "false", 5)) {
3559 //suspend_playback=false is supposed to set QOS value back to 75%
3560 //the mixer control sent with value Enable will achieve that
3561 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3562 } else if (!strncmp (value, "true", 4)) {
3563 //suspend_playback=true is supposed to remove QOS value
3564 //resetting the mixer control will set the default value
3565 //for the mixer control which is Disable and this removes the QOS vote
3566 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3567 } else {
3568 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3569 " got %s", __func__, value);
3570 ret = -1;
3571 }
3572
3573 if (ret != 0) {
3574 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3575 __func__, out->pm_qos_mixer_path, ret);
3576 }
3577
3578 pthread_mutex_unlock(&out->lock);
3579 }
3580 }
3581 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303583error:
Eric Laurent994a6932013-07-17 11:51:42 -07003584 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 return ret;
3586}
3587
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003588static bool stream_get_parameter_channels(struct str_parms *query,
3589 struct str_parms *reply,
3590 audio_channel_mask_t *supported_channel_masks) {
3591 int ret = -1;
3592 char value[512];
3593 bool first = true;
3594 size_t i, j;
3595
3596 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3597 ret = 0;
3598 value[0] = '\0';
3599 i = 0;
3600 while (supported_channel_masks[i] != 0) {
3601 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3602 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
3603 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303604 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003605
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303606 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003607 first = false;
3608 break;
3609 }
3610 }
3611 i++;
3612 }
3613 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3614 }
3615 return ret == 0;
3616}
3617
3618static bool stream_get_parameter_formats(struct str_parms *query,
3619 struct str_parms *reply,
3620 audio_format_t *supported_formats) {
3621 int ret = -1;
3622 char value[256];
3623 size_t i, j;
3624 bool first = true;
3625
3626 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3627 ret = 0;
3628 value[0] = '\0';
3629 i = 0;
3630 while (supported_formats[i] != 0) {
3631 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3632 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
3633 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303634 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003635 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05303636 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003637 first = false;
3638 break;
3639 }
3640 }
3641 i++;
3642 }
3643 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
3644 }
3645 return ret == 0;
3646}
3647
3648static bool stream_get_parameter_rates(struct str_parms *query,
3649 struct str_parms *reply,
3650 uint32_t *supported_sample_rates) {
3651
3652 int i;
3653 char value[256];
3654 int ret = -1;
3655 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3656 ret = 0;
3657 value[0] = '\0';
3658 i=0;
3659 int cursor = 0;
3660 while (supported_sample_rates[i]) {
3661 int avail = sizeof(value) - cursor;
3662 ret = snprintf(value + cursor, avail, "%s%d",
3663 cursor > 0 ? "|" : "",
3664 supported_sample_rates[i]);
3665 if (ret < 0 || ret >= avail) {
3666 // if cursor is at the last element of the array
3667 // overwrite with \0 is duplicate work as
3668 // snprintf already put a \0 in place.
3669 // else
3670 // we had space to write the '|' at value[cursor]
3671 // (which will be overwritten) or no space to fill
3672 // the first element (=> cursor == 0)
3673 value[cursor] = '\0';
3674 break;
3675 }
3676 cursor += ret;
3677 ++i;
3678 }
3679 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3680 value);
3681 }
3682 return ret >= 0;
3683}
3684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3686{
3687 struct stream_out *out = (struct stream_out *)stream;
3688 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003689 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 char value[256];
3691 struct str_parms *reply = str_parms_create();
3692 size_t i, j;
3693 int ret;
3694 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003695
3696 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003697 if (reply) {
3698 str_parms_destroy(reply);
3699 }
3700 if (query) {
3701 str_parms_destroy(query);
3702 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003703 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3704 return NULL;
3705 }
3706
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003707 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3709 if (ret >= 0) {
3710 value[0] = '\0';
3711 i = 0;
3712 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003713 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3714 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003716 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003718 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 first = false;
3720 break;
3721 }
3722 }
3723 i++;
3724 }
3725 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3726 str = str_parms_to_str(reply);
3727 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003728 voice_extn_out_get_parameters(out, query, reply);
3729 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003731
Alexy Joseph62142aa2015-11-16 15:10:34 -08003732
3733 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3734 if (ret >= 0) {
3735 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303736 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3737 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003738 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303739 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003740 } else {
3741 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303742 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003743 }
3744 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003745 if (str)
3746 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003747 str = str_parms_to_str(reply);
3748 }
3749
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003750 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3751 if (ret >= 0) {
3752 value[0] = '\0';
3753 i = 0;
3754 first = true;
3755 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003756 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
3757 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003758 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003759 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003760 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003761 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003762 first = false;
3763 break;
3764 }
3765 }
3766 i++;
3767 }
3768 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003769 if (str)
3770 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003771 str = str_parms_to_str(reply);
3772 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003773
3774 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3775 if (ret >= 0) {
3776 value[0] = '\0';
3777 i = 0;
3778 first = true;
3779 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003780 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
3781 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003782 if (!first) {
3783 strlcat(value, "|", sizeof(value));
3784 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003785 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08003786 first = false;
3787 break;
3788 }
3789 }
3790 i++;
3791 }
3792 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3793 if (str)
3794 free(str);
3795 str = str_parms_to_str(reply);
3796 }
3797
Alexy Joseph98988832017-01-13 14:56:59 -08003798 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3799 //only low latency track supports suspend_resume
3800 str_parms_add_int(reply, "supports_hw_suspend",
3801 (out->dynamic_pm_qos_enabled));
3802 if (str)
3803 free(str);
3804 str = str_parms_to_str(reply);
3805 }
3806
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 str_parms_destroy(query);
3809 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003810 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 return str;
3812}
3813
3814static uint32_t out_get_latency(const struct audio_stream_out *stream)
3815{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003816 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003818 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819
Alexy Josephaa54c872014-12-03 02:46:47 -08003820 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303821 lock_output_stream(out);
3822 latency = audio_extn_utils_compress_get_dsp_latency(out);
3823 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003824 } else if ((out->realtime) ||
3825 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003826 // since the buffer won't be filled up faster than realtime,
3827 // return a smaller number
3828 if (out->config.rate)
3829 period_ms = (out->af_period_multiplier * out->config.period_size *
3830 1000) / (out->config.rate);
3831 else
3832 period_ms = 0;
3833 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003834 } else {
3835 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003837 }
3838
yidongh0515e042017-07-06 15:00:34 +08003839 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003840 latency += audio_extn_a2dp_get_encoder_latency();
3841
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303842 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003843 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844}
3845
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303846static float AmpToDb(float amplification)
3847{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303848 float db = DSD_VOLUME_MIN_DB;
3849 if (amplification > 0) {
3850 db = 20 * log10(amplification);
3851 if(db < DSD_VOLUME_MIN_DB)
3852 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303853 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303854 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303855}
3856
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303857static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3858 float right)
3859{
3860 struct stream_out *out = (struct stream_out *)stream;
3861 int volume[2];
3862 char mixer_ctl_name[128];
3863 struct audio_device *adev = out->dev;
3864 struct mixer_ctl *ctl;
3865 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3866 PCM_PLAYBACK);
3867
3868 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3869 "Compress Playback %d Volume", pcm_device_id);
3870 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3871 if (!ctl) {
3872 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3873 __func__, mixer_ctl_name);
3874 return -EINVAL;
3875 }
3876 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3877 __func__, mixer_ctl_name, left, right);
3878 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3879 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3880 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3881
3882 return 0;
3883}
3884
Zhou Song2b8f28f2017-09-11 10:51:38 +08003885static int out_set_voip_volume(struct audio_stream_out *stream, float left,
3886 float right)
3887{
3888 struct stream_out *out = (struct stream_out *)stream;
3889 char mixer_ctl_name[] = "App Type Gain";
3890 struct audio_device *adev = out->dev;
3891 struct mixer_ctl *ctl;
3892 uint32_t set_values[4];
3893
3894 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3895 if (!ctl) {
3896 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3897 __func__, mixer_ctl_name);
3898 return -EINVAL;
3899 }
3900
3901 set_values[0] = 0; //0: Rx Session 1:Tx Session
3902 set_values[1] = out->app_type_cfg.app_type;
3903 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3904 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3905
3906 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3907 return 0;
3908}
3909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910static int out_set_volume(struct audio_stream_out *stream, float left,
3911 float right)
3912{
Eric Laurenta9024de2013-04-04 09:19:12 -07003913 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003914 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303915 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003916
Eric Laurenta9024de2013-04-04 09:19:12 -07003917 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3918 /* only take left channel into account: the API is for stereo anyway */
3919 out->muted = (left == 0.0f);
3920 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003921 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303922 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003923 /*
3924 * Set mute or umute on HDMI passthrough stream.
3925 * Only take left channel into account.
3926 * Mute is 0 and unmute 1
3927 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303928 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303929 } else if (out->format == AUDIO_FORMAT_DSD){
3930 char mixer_ctl_name[128] = "DSD Volume";
3931 struct audio_device *adev = out->dev;
3932 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3933
3934 if (!ctl) {
3935 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3936 __func__, mixer_ctl_name);
3937 return -EINVAL;
3938 }
3939 volume[0] = (int)(AmpToDb(left));
3940 volume[1] = (int)(AmpToDb(right));
3941 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3942 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003943 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303944 pthread_mutex_lock(&out->compr_mute_lock);
3945 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3946 if (!out->a2dp_compress_mute)
3947 ret = out_set_compr_volume(stream, left, right);
3948 out->volume_l = left;
3949 out->volume_r = right;
3950 pthread_mutex_unlock(&out->compr_mute_lock);
3951 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003952 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003953 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Zhou Song2b8f28f2017-09-11 10:51:38 +08003954 if (!out->standby)
3955 ret = out_set_voip_volume(stream, left, right);
3956 out->volume_l = left;
3957 out->volume_r = right;
3958 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07003959 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 return -ENOSYS;
3962}
3963
Zhou Songc9672822017-08-16 16:01:39 +08003964static void update_frames_written(struct stream_out *out, size_t bytes)
3965{
3966 size_t bpf = 0;
3967
3968 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3969 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3970 bpf = 1;
3971 else if (!is_offload_usecase(out->usecase))
3972 bpf = audio_bytes_per_sample(out->format) *
3973 audio_channel_count_from_out_mask(out->channel_mask);
3974 if (bpf != 0)
3975 out->written += bytes / bpf;
3976}
3977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3979 size_t bytes)
3980{
3981 struct stream_out *out = (struct stream_out *)stream;
3982 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003983 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303984 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003986 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303987
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303988 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003989
Dhananjay Kumarac341582017-02-23 23:42:25 +05303990 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303991 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303992 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3993 pthread_mutex_unlock(&out->lock);
3994 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303995 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303996 ALOGD(" %s: sound card is not active/SSR state", __func__);
3997 ret= -EIO;
3998 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303999 }
4000 }
4001
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304002 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304003 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05304004 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304005 goto exit;
4006 }
4007
Haynes Mathew George16081042017-05-31 17:16:49 -07004008 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4009 ret = -EINVAL;
4010 goto exit;
4011 }
4012
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304013 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4014 !out->is_iec61937_info_available) {
4015
4016 if (!audio_extn_passthru_is_passthrough_stream(out)) {
4017 out->is_iec61937_info_available = true;
4018 } else if (audio_extn_passthru_is_enabled()) {
4019 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05304020 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05304021
4022 if((out->format == AUDIO_FORMAT_DTS) ||
4023 (out->format == AUDIO_FORMAT_DTS_HD)) {
4024 ret = audio_extn_passthru_update_dts_stream_configuration(out,
4025 buffer, bytes);
4026 if (ret) {
4027 if (ret != -ENOSYS) {
4028 out->is_iec61937_info_available = false;
4029 ALOGD("iec61937 transmission info not yet updated retry");
4030 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304031 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05304032 /* if stream has started and after that there is
4033 * stream config change (iec transmission config)
4034 * then trigger select_device to update backend configuration.
4035 */
4036 out->stream_config_changed = true;
4037 pthread_mutex_lock(&adev->lock);
4038 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304039 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
4040 ret = -EINVAL;
4041 goto exit;
4042 }
Manish Dewangan671a4202017-08-18 17:30:46 +05304043 pthread_mutex_unlock(&adev->lock);
4044 out->stream_config_changed = false;
4045 out->is_iec61937_info_available = true;
4046 }
4047 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304048
Garmond Leung317cbf12017-09-13 16:20:50 -07004049 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304050 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
4051 (out->is_iec61937_info_available == true)) {
4052 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
4053 ret = -EINVAL;
4054 goto exit;
4055 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05304056 }
4057 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304058
4059 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
4060 (audio_extn_a2dp_is_suspended())) {
4061 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
4062 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304063 ret = -EIO;
4064 goto exit;
4065 }
4066 }
4067 }
4068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004070 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08004071 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004072 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
4073 ret = voice_extn_compress_voip_start_output_stream(out);
4074 else
4075 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004076 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07004079 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080 goto exit;
4081 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304082 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004083 if (last_known_cal_step != -1) {
4084 ALOGD("%s: retry previous failed cal level set", __func__);
4085 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05304086 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07004087 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304088
4089 if ((out->is_iec61937_info_available == true) &&
4090 (audio_extn_passthru_is_passthrough_stream(out))&&
4091 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
4092 ret = -EINVAL;
4093 goto exit;
4094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096
Ashish Jain81eb2a82015-05-13 10:52:34 +05304097 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08004098 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05304099 adev->is_channel_status_set = true;
4100 }
4101
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004102 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08004103 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004104 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004105 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004106 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
4107 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304108 if (out->send_next_track_params && out->is_compr_metadata_avail) {
4109 ALOGD("copl(%p):send next track params in gapless", out);
4110 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
4111 out->send_next_track_params = false;
4112 out->is_compr_metadata_avail = false;
4113 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004114 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05304115 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304116 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004117
Ashish Jain83a6cc22016-06-28 14:34:17 +05304118 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304119 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05304120 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05304121 pthread_mutex_unlock(&out->lock);
4122 return -EINVAL;
4123 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05304124 audio_format_t dst_format = out->hal_op_format;
4125 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304126
4127 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
4128 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
4129
Ashish Jain83a6cc22016-06-28 14:34:17 +05304130 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304131 dst_format,
4132 buffer,
4133 src_format,
4134 frames);
4135
Ashish Jain83a6cc22016-06-28 14:34:17 +05304136 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05304137 bytes_to_write);
4138
4139 /*Convert written bytes in audio flinger format*/
4140 if (ret > 0)
4141 ret = ((ret * format_to_bitwidth_table[out->format]) /
4142 format_to_bitwidth_table[dst_format]);
4143 }
4144 } else
4145 ret = compress_write(out->compr, buffer, bytes);
4146
Zhou Songc9672822017-08-16 16:01:39 +08004147 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
4148 update_frames_written(out, bytes);
4149
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304150 if (ret < 0)
4151 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304152 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05304153 /*msg to cb thread only if non blocking write is enabled*/
4154 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05304155 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004156 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05304157 } else if (-ENETRESET == ret) {
4158 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304159 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05304160 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05304161 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05304162 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004163 }
Ashish Jain5106d362016-05-11 19:23:33 +05304164
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304165 /* Call compr start only when non-zero bytes of data is there to be rendered */
4166 if (!out->playback_started && ret > 0) {
4167 int status = compress_start(out->compr);
4168 if (status < 0) {
4169 ret = status;
4170 ALOGE("%s: compr start failed with err %d", __func__, errno);
4171 goto exit;
4172 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07004173 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004174 out->playback_started = 1;
4175 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004176
4177 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4178 popcount(out->channel_mask),
4179 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004180 }
4181 pthread_mutex_unlock(&out->lock);
4182 return ret;
4183 } else {
4184 if (out->pcm) {
4185 if (out->muted)
4186 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004187
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304188 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004189
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004190 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004191
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004192 if (out->config.rate)
4193 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
4194 out->config.rate;
4195
4196 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
4197
4198 request_out_focus(out, ns);
4199
4200 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004201 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004202 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05304203 out->convert_buffer != NULL) {
4204
4205 memcpy_by_audio_format(out->convert_buffer,
4206 out->hal_op_format,
4207 buffer,
4208 out->hal_ip_format,
4209 out->config.period_size * out->config.channels);
4210
4211 ret = pcm_write(out->pcm, out->convert_buffer,
4212 (out->config.period_size *
4213 out->config.channels *
4214 format_to_bitwidth_table[out->hal_op_format]));
4215 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05304216 /*
4217 * To avoid underrun in DSP when the application is not pumping
4218 * data at required rate, check for the no. of bytes and ignore
4219 * pcm_write if it is less than actual buffer size.
4220 * It is a work around to a change in compress VOIP driver.
4221 */
4222 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4223 bytes < (out->config.period_size * out->config.channels *
4224 audio_bytes_per_sample(out->format))) {
4225 size_t voip_buf_size =
4226 out->config.period_size * out->config.channels *
4227 audio_bytes_per_sample(out->format);
4228 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
4229 __func__, bytes, voip_buf_size);
4230 usleep(((uint64_t)voip_buf_size - bytes) *
4231 1000000 / audio_stream_out_frame_size(stream) /
4232 out_get_sample_rate(&out->stream.common));
4233 ret = 0;
4234 } else
4235 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304236 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004237
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004238 release_out_focus(out);
4239
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304240 if (ret < 0)
4241 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08004242 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304243 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 }
4246
4247exit:
Zhou Songc9672822017-08-16 16:01:39 +08004248 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304249 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304250 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252 pthread_mutex_unlock(&out->lock);
4253
4254 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004255 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08004256 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304257 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304258 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304259 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304260 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304261 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304262 out->standby = true;
4263 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304264 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05304265 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4266 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
4267 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004268
4269 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07004270 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07004271 return ret;
4272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 }
4274 return bytes;
4275}
4276
4277static int out_get_render_position(const struct audio_stream_out *stream,
4278 uint32_t *dsp_frames)
4279{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004280 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004281
4282 if (dsp_frames == NULL)
4283 return -EINVAL;
4284
4285 *dsp_frames = 0;
4286 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004287 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304288
4289 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4290 * this operation and adev_close_output_stream(where out gets reset).
4291 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304292 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304293 *dsp_frames = get_actual_pcm_frames_rendered(out);
4294 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4295 return 0;
4296 }
4297
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004298 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304299 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304300 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004301 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304302 if (ret < 0)
4303 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004304 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304305 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004306 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304307 if (-ENETRESET == ret) {
4308 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304309 out->card_status = CARD_STATUS_OFFLINE;
4310 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304311 } else if(ret < 0) {
4312 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304313 ret = -EINVAL;
4314 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304315 /*
4316 * Handle corner case where compress session is closed during SSR
4317 * and timestamp is queried
4318 */
4319 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304320 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304321 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304322 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304323 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304324 pthread_mutex_unlock(&out->lock);
4325 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004326 } else if (audio_is_linear_pcm(out->format)) {
4327 *dsp_frames = out->written;
4328 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004329 } else
4330 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331}
4332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004333static int out_add_audio_effect(const struct audio_stream *stream __unused,
4334 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335{
4336 return 0;
4337}
4338
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004339static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4340 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341{
4342 return 0;
4343}
4344
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004345static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4346 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304348 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349}
4350
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004351static int out_get_presentation_position(const struct audio_stream_out *stream,
4352 uint64_t *frames, struct timespec *timestamp)
4353{
4354 struct stream_out *out = (struct stream_out *)stream;
4355 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004356 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004357
Ashish Jain5106d362016-05-11 19:23:33 +05304358 /* below piece of code is not guarded against any lock because audioFliner serializes
4359 * this operation and adev_close_output_stream( where out gets reset).
4360 */
4361 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304362 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304363 *frames = get_actual_pcm_frames_rendered(out);
4364 /* this is the best we can do */
4365 clock_gettime(CLOCK_MONOTONIC, timestamp);
4366 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4367 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4368 return 0;
4369 }
4370
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004371 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004372
Ashish Jain5106d362016-05-11 19:23:33 +05304373 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4374 ret = compress_get_tstamp(out->compr, &dsp_frames,
4375 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004376 // Adjustment accounts for A2dp encoder latency with offload usecases
4377 // Note: Encoder latency is returned in ms.
4378 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4379 unsigned long offset =
4380 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4381 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4382 }
Ashish Jain5106d362016-05-11 19:23:33 +05304383 ALOGVV("%s rendered frames %ld sample_rate %d",
4384 __func__, dsp_frames, out->sample_rate);
4385 *frames = dsp_frames;
4386 if (ret < 0)
4387 ret = -errno;
4388 if (-ENETRESET == ret) {
4389 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304390 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304391 ret = -EINVAL;
4392 } else
4393 ret = 0;
4394 /* this is the best we can do */
4395 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004396 } else {
4397 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004398 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004399 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4400 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004401 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004402 // This adjustment accounts for buffering after app processor.
4403 // It is based on estimated DSP latency per use case, rather than exact.
4404 signed_frames -=
4405 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4406
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004407 // Adjustment accounts for A2dp encoder latency with non offload usecases
4408 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4409 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4410 signed_frames -=
4411 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4412 }
4413
Eric Laurent949a0892013-09-20 09:20:13 -07004414 // It would be unusual for this value to be negative, but check just in case ...
4415 if (signed_frames >= 0) {
4416 *frames = signed_frames;
4417 ret = 0;
4418 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004419 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304420 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304421 *frames = out->written;
4422 clock_gettime(CLOCK_MONOTONIC, timestamp);
4423 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004424 }
4425 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004426 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004427 return ret;
4428}
4429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004430static int out_set_callback(struct audio_stream_out *stream,
4431 stream_callback_t callback, void *cookie)
4432{
4433 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004434 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004435
4436 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004437 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004438 out->client_callback = callback;
4439 out->client_cookie = cookie;
4440 if (out->adsp_hdlr_stream_handle) {
4441 ret = audio_extn_adsp_hdlr_stream_set_callback(
4442 out->adsp_hdlr_stream_handle,
4443 callback,
4444 cookie);
4445 if (ret)
4446 ALOGW("%s:adsp hdlr callback registration failed %d",
4447 __func__, ret);
4448 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004449 pthread_mutex_unlock(&out->lock);
4450 return 0;
4451}
4452
4453static int out_pause(struct audio_stream_out* stream)
4454{
4455 struct stream_out *out = (struct stream_out *)stream;
4456 int status = -ENOSYS;
4457 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004458 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004459 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004461 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304462 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304463 status = compress_pause(out->compr);
4464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004465 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004466
Mingming Yin21854652016-04-13 11:54:02 -07004467 if (audio_extn_passthru_is_active()) {
4468 ALOGV("offload use case, pause passthru");
4469 audio_extn_passthru_on_pause(out);
4470 }
4471
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304472 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004473 audio_extn_dts_notify_playback_state(out->usecase, 0,
4474 out->sample_rate, popcount(out->channel_mask),
4475 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004476 }
4477 pthread_mutex_unlock(&out->lock);
4478 }
4479 return status;
4480}
4481
4482static int out_resume(struct audio_stream_out* stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
4485 int status = -ENOSYS;
4486 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004487 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004488 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004489 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004490 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004491 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304492 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304493 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004494 }
4495 if (!status) {
4496 out->offload_state = OFFLOAD_STATE_PLAYING;
4497 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304498 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004499 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4500 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004501 }
4502 pthread_mutex_unlock(&out->lock);
4503 }
4504 return status;
4505}
4506
4507static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4508{
4509 struct stream_out *out = (struct stream_out *)stream;
4510 int status = -ENOSYS;
4511 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004512 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004513 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004514 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4515 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4516 else
4517 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4518 pthread_mutex_unlock(&out->lock);
4519 }
4520 return status;
4521}
4522
4523static int out_flush(struct audio_stream_out* stream)
4524{
4525 struct stream_out *out = (struct stream_out *)stream;
4526 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004527 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004528 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004529 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004530 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4531 stop_compressed_output_l(out);
4532 out->written = 0;
4533 } else {
4534 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4535 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004536 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004537 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004538 return 0;
4539 }
4540 return -ENOSYS;
4541}
4542
Haynes Mathew George16081042017-05-31 17:16:49 -07004543static int out_stop(const struct audio_stream_out* stream)
4544{
4545 struct stream_out *out = (struct stream_out *)stream;
4546 struct audio_device *adev = out->dev;
4547 int ret = -ENOSYS;
4548
4549 ALOGV("%s", __func__);
4550 pthread_mutex_lock(&adev->lock);
4551 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4552 out->playback_started && out->pcm != NULL) {
4553 pcm_stop(out->pcm);
4554 ret = stop_output_stream(out);
4555 out->playback_started = false;
4556 }
4557 pthread_mutex_unlock(&adev->lock);
4558 return ret;
4559}
4560
4561static int out_start(const struct audio_stream_out* stream)
4562{
4563 struct stream_out *out = (struct stream_out *)stream;
4564 struct audio_device *adev = out->dev;
4565 int ret = -ENOSYS;
4566
4567 ALOGV("%s", __func__);
4568 pthread_mutex_lock(&adev->lock);
4569 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4570 !out->playback_started && out->pcm != NULL) {
4571 ret = start_output_stream(out);
4572 if (ret == 0) {
4573 out->playback_started = true;
4574 }
4575 }
4576 pthread_mutex_unlock(&adev->lock);
4577 return ret;
4578}
4579
4580/*
4581 * Modify config->period_count based on min_size_frames
4582 */
4583static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4584{
4585 int periodCountRequested = (min_size_frames + config->period_size - 1)
4586 / config->period_size;
4587 int periodCount = MMAP_PERIOD_COUNT_MIN;
4588
4589 ALOGV("%s original config.period_size = %d config.period_count = %d",
4590 __func__, config->period_size, config->period_count);
4591
4592 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4593 periodCount *= 2;
4594 }
4595 config->period_count = periodCount;
4596
4597 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4598}
4599
4600static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4601 int32_t min_size_frames,
4602 struct audio_mmap_buffer_info *info)
4603{
4604 struct stream_out *out = (struct stream_out *)stream;
4605 struct audio_device *adev = out->dev;
4606 int ret = 0;
4607 unsigned int offset1;
4608 unsigned int frames1;
4609 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004610 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004611
4612 ALOGV("%s", __func__);
4613 pthread_mutex_lock(&adev->lock);
4614
4615 if (info == NULL || min_size_frames == 0) {
4616 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4617 ret = -EINVAL;
4618 goto exit;
4619 }
4620 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4621 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4622 ret = -ENOSYS;
4623 goto exit;
4624 }
4625 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4626 if (out->pcm_device_id < 0) {
4627 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4628 __func__, out->pcm_device_id, out->usecase);
4629 ret = -EINVAL;
4630 goto exit;
4631 }
4632
4633 adjust_mmap_period_count(&out->config, min_size_frames);
4634
4635 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4636 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4637 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4638 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4639 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4640 step = "open";
4641 ret = -ENODEV;
4642 goto exit;
4643 }
4644 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4645 if (ret < 0) {
4646 step = "begin";
4647 goto exit;
4648 }
4649 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4650 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004651 ret = platform_get_mmap_data_fd(adev->platform,
4652 out->pcm_device_id, 0 /*playback*/,
4653 &info->shared_memory_fd,
4654 &mmap_size);
4655 if (ret < 0) {
4656 step = "get_mmap_fd";
4657 goto exit;
4658 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004659 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004660 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004661
4662 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4663 if (ret < 0) {
4664 step = "commit";
4665 goto exit;
4666 }
4667
4668 out->standby = false;
4669 ret = 0;
4670
4671 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4672 __func__, info->shared_memory_address, info->buffer_size_frames);
4673
4674exit:
4675 if (ret != 0) {
4676 if (out->pcm == NULL) {
4677 ALOGE("%s: %s - %d", __func__, step, ret);
4678 } else {
4679 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4680 pcm_close(out->pcm);
4681 out->pcm = NULL;
4682 }
4683 }
4684 pthread_mutex_unlock(&adev->lock);
4685 return ret;
4686}
4687
4688static int out_get_mmap_position(const struct audio_stream_out *stream,
4689 struct audio_mmap_position *position)
4690{
4691 struct stream_out *out = (struct stream_out *)stream;
4692 ALOGVV("%s", __func__);
4693 if (position == NULL) {
4694 return -EINVAL;
4695 }
4696 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4697 return -ENOSYS;
4698 }
4699 if (out->pcm == NULL) {
4700 return -ENOSYS;
4701 }
4702
4703 struct timespec ts = { 0, 0 };
4704 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4705 if (ret < 0) {
4706 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4707 return ret;
4708 }
4709 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4710 return 0;
4711}
4712
4713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714/** audio_stream_in implementation **/
4715static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4716{
4717 struct stream_in *in = (struct stream_in *)stream;
4718
4719 return in->config.rate;
4720}
4721
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004722static int in_set_sample_rate(struct audio_stream *stream __unused,
4723 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724{
4725 return -ENOSYS;
4726}
4727
4728static size_t in_get_buffer_size(const struct audio_stream *stream)
4729{
4730 struct stream_in *in = (struct stream_in *)stream;
4731
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004732 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4733 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004734 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4735 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 -07004736 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4737 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304738 else if(audio_extn_cin_attached_usecase(in->usecase))
4739 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004740
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004741 return in->config.period_size * in->af_period_multiplier *
4742 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743}
4744
4745static uint32_t in_get_channels(const struct audio_stream *stream)
4746{
4747 struct stream_in *in = (struct stream_in *)stream;
4748
4749 return in->channel_mask;
4750}
4751
4752static audio_format_t in_get_format(const struct audio_stream *stream)
4753{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004754 struct stream_in *in = (struct stream_in *)stream;
4755
4756 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757}
4758
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004759static int in_set_format(struct audio_stream *stream __unused,
4760 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761{
4762 return -ENOSYS;
4763}
4764
4765static int in_standby(struct audio_stream *stream)
4766{
4767 struct stream_in *in = (struct stream_in *)stream;
4768 struct audio_device *adev = in->dev;
4769 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304770 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4771 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004772 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304773
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004774 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004775 if (!in->standby && in->is_st_session) {
4776 ALOGD("%s: sound trigger pcm stop lab", __func__);
4777 audio_extn_sound_trigger_stop_lab(in);
4778 in->standby = 1;
4779 }
4780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004782 if (adev->adm_deregister_stream)
4783 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4784
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004785 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004787 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004788 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004789 voice_extn_compress_voip_close_input_stream(stream);
4790 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004791 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4792 do_stop = in->capture_started;
4793 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004794 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304795 if (audio_extn_cin_attached_usecase(in->usecase))
4796 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004797 }
4798
4799 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004800 if (in->pcm) {
4801 pcm_close(in->pcm);
4802 in->pcm = NULL;
4803 }
4804 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004805 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004806 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807 }
4808 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004809 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004810 return status;
4811}
4812
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004813static int in_dump(const struct audio_stream *stream __unused,
4814 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815{
4816 return 0;
4817}
4818
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304819static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4820{
4821 if (!stream || !parms)
4822 return;
4823
4824 struct stream_in *in = (struct stream_in *)stream;
4825 struct audio_device *adev = in->dev;
4826
4827 card_status_t status;
4828 int card;
4829 if (parse_snd_card_status(parms, &card, &status) < 0)
4830 return;
4831
4832 pthread_mutex_lock(&adev->lock);
4833 bool valid_cb = (card == adev->snd_card);
4834 pthread_mutex_unlock(&adev->lock);
4835
4836 if (!valid_cb)
4837 return;
4838
4839 lock_input_stream(in);
4840 if (in->card_status != status)
4841 in->card_status = status;
4842 pthread_mutex_unlock(&in->lock);
4843
4844 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4845 use_case_table[in->usecase],
4846 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4847
4848 // a better solution would be to report error back to AF and let
4849 // it put the stream to standby
4850 if (status == CARD_STATUS_OFFLINE)
4851 in_standby(&in->stream.common);
4852
4853 return;
4854}
4855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4857{
4858 struct stream_in *in = (struct stream_in *)stream;
4859 struct audio_device *adev = in->dev;
4860 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004862 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304864 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 parms = str_parms_create_str(kvpairs);
4866
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304867 if (!parms)
4868 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004869 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004870 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004871
4872 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4873 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874 val = atoi(value);
4875 /* no audio source uses val == 0 */
4876 if ((in->source != val) && (val != 0)) {
4877 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004878 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4879 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4880 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004881 (in->config.rate == 8000 || in->config.rate == 16000 ||
4882 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004883 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004884 err = voice_extn_compress_voip_open_input_stream(in);
4885 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004886 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004887 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004888 }
4889 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890 }
4891 }
4892
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004893 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4894 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004896 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 in->device = val;
4898 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004899 if (!in->standby && !in->is_st_session) {
4900 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004901 if (adev->adm_on_routing_change)
4902 adev->adm_on_routing_change(adev->adm_data,
4903 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004904 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004905 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906 }
4907 }
4908
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304909 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4910 if (err >= 0) {
4911 strlcpy(in->profile, value, sizeof(in->profile));
4912 ALOGV("updating stream profile with value '%s'", in->profile);
4913 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4914 &adev->streams_input_cfg_list,
4915 in->device, in->flags, in->format,
4916 in->sample_rate, in->bit_width,
4917 in->profile, &in->app_type_cfg);
4918 }
4919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004921 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922
4923 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304924error:
Eric Laurent994a6932013-07-17 11:51:42 -07004925 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004926 return ret;
4927}
4928
4929static char* in_get_parameters(const struct audio_stream *stream,
4930 const char *keys)
4931{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004932 struct stream_in *in = (struct stream_in *)stream;
4933 struct str_parms *query = str_parms_create_str(keys);
4934 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004935 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004936
4937 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004938 if (reply) {
4939 str_parms_destroy(reply);
4940 }
4941 if (query) {
4942 str_parms_destroy(query);
4943 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004944 ALOGE("in_get_parameters: failed to create query or reply");
4945 return NULL;
4946 }
4947
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004948 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004949
4950 voice_extn_in_get_parameters(in, query, reply);
4951
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004952 stream_get_parameter_channels(query, reply,
4953 &in->supported_channel_masks[0]);
4954 stream_get_parameter_formats(query, reply,
4955 &in->supported_formats[0]);
4956 stream_get_parameter_rates(query, reply,
4957 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004958 str = str_parms_to_str(reply);
4959 str_parms_destroy(query);
4960 str_parms_destroy(reply);
4961
4962 ALOGV("%s: exit: returns - %s", __func__, str);
4963 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004964}
4965
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004966static int in_set_gain(struct audio_stream_in *stream __unused,
4967 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968{
4969 return 0;
4970}
4971
4972static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4973 size_t bytes)
4974{
4975 struct stream_in *in = (struct stream_in *)stream;
4976 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304977 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304978 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004980 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304981
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004982 if (in->is_st_session) {
4983 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4984 /* Read from sound trigger HAL */
4985 audio_extn_sound_trigger_read(in, buffer, bytes);
4986 pthread_mutex_unlock(&in->lock);
4987 return bytes;
4988 }
4989
Haynes Mathew George16081042017-05-31 17:16:49 -07004990 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4991 ret = -ENOSYS;
4992 goto exit;
4993 }
4994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004995 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004996 pthread_mutex_lock(&adev->lock);
4997 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4998 ret = voice_extn_compress_voip_start_input_stream(in);
4999 else
5000 ret = start_input_stream(in);
5001 pthread_mutex_unlock(&adev->lock);
5002 if (ret != 0) {
5003 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004 }
5005 in->standby = 0;
5006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005008 // what's the duration requested by the client?
5009 long ns = 0;
5010
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305011 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005012 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
5013 in->config.rate;
5014
5015 request_in_focus(in, ns);
5016 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005017
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305018 if (audio_extn_cin_attached_usecase(in->usecase)) {
5019 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
5020 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305021 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005022 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305023 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07005024 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005025 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005026 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07005027 } else if (audio_extn_ffv_get_stream() == in) {
5028 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305029 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005030 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305031 /* data from DSP comes in 24_8 format, convert it to 8_24 */
5032 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5033 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
5034 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305035 ret = -EINVAL;
5036 goto exit;
5037 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305038 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305039 ret = -errno;
5040 }
5041 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305042 /* bytes read is always set to bytes for non compress usecases */
5043 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 }
5045
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005046 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005048 /*
5049 * Instead of writing zeroes here, we could trust the hardware
5050 * to always provide zeroes when muted.
5051 */
Pavan Chikkala63964842014-12-04 10:48:28 +05305052 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
5053 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005054 memset(buffer, 0, bytes);
5055
5056exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005057 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305058 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059 pthread_mutex_unlock(&in->lock);
5060
5061 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305062 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305063 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305064 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305065 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305066 in->standby = true;
5067 }
Sharad Sangled17c9122017-03-20 15:58:52 +05305068 if (!audio_extn_cin_attached_usecase(in->usecase)) {
5069 bytes_read = bytes;
5070 memset(buffer, 0, bytes);
5071 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005072 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005073 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05305074 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05305075 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005076 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305077 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005078}
5079
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005080static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081{
5082 return 0;
5083}
5084
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005085static int add_remove_audio_effect(const struct audio_stream *stream,
5086 effect_handle_t effect,
5087 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005089 struct stream_in *in = (struct stream_in *)stream;
5090 int status = 0;
5091 effect_descriptor_t desc;
5092
5093 status = (*effect)->get_descriptor(effect, &desc);
5094 if (status != 0)
5095 return status;
5096
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005097 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005098 pthread_mutex_lock(&in->dev->lock);
5099 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
5100 in->enable_aec != enable &&
5101 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
5102 in->enable_aec = enable;
5103 if (!in->standby)
5104 select_devices(in->dev, in->usecase);
5105 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08005106 if (in->enable_ns != enable &&
5107 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
5108 in->enable_ns = enable;
5109 if (!in->standby)
5110 select_devices(in->dev, in->usecase);
5111 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005112 pthread_mutex_unlock(&in->dev->lock);
5113 pthread_mutex_unlock(&in->lock);
5114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 return 0;
5116}
5117
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005118static int in_add_audio_effect(const struct audio_stream *stream,
5119 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005120{
Eric Laurent994a6932013-07-17 11:51:42 -07005121 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005122 return add_remove_audio_effect(stream, effect, true);
5123}
5124
5125static int in_remove_audio_effect(const struct audio_stream *stream,
5126 effect_handle_t effect)
5127{
Eric Laurent994a6932013-07-17 11:51:42 -07005128 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07005129 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130}
5131
Haynes Mathew George16081042017-05-31 17:16:49 -07005132static int in_stop(const struct audio_stream_in* stream)
5133{
5134 struct stream_in *in = (struct stream_in *)stream;
5135 struct audio_device *adev = in->dev;
5136
5137 int ret = -ENOSYS;
5138 ALOGV("%s", __func__);
5139 pthread_mutex_lock(&adev->lock);
5140 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5141 in->capture_started && in->pcm != NULL) {
5142 pcm_stop(in->pcm);
5143 ret = stop_input_stream(in);
5144 in->capture_started = false;
5145 }
5146 pthread_mutex_unlock(&adev->lock);
5147 return ret;
5148}
5149
5150static int in_start(const struct audio_stream_in* stream)
5151{
5152 struct stream_in *in = (struct stream_in *)stream;
5153 struct audio_device *adev = in->dev;
5154 int ret = -ENOSYS;
5155
5156 ALOGV("%s in %p", __func__, in);
5157 pthread_mutex_lock(&adev->lock);
5158 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
5159 !in->capture_started && in->pcm != NULL) {
5160 if (!in->capture_started) {
5161 ret = start_input_stream(in);
5162 if (ret == 0) {
5163 in->capture_started = true;
5164 }
5165 }
5166 }
5167 pthread_mutex_unlock(&adev->lock);
5168 return ret;
5169}
5170
5171static int in_create_mmap_buffer(const struct audio_stream_in *stream,
5172 int32_t min_size_frames,
5173 struct audio_mmap_buffer_info *info)
5174{
5175 struct stream_in *in = (struct stream_in *)stream;
5176 struct audio_device *adev = in->dev;
5177 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07005178 unsigned int offset1 = 0;
5179 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005180 const char *step = "";
5181
5182 pthread_mutex_lock(&adev->lock);
5183 ALOGV("%s in %p", __func__, in);
5184
5185 if (info == NULL || min_size_frames == 0) {
5186 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
5187 ret = -EINVAL;
5188 goto exit;
5189 }
5190 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
5191 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
5192 ALOGV("%s in %p", __func__, in);
5193 ret = -ENOSYS;
5194 goto exit;
5195 }
5196 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
5197 if (in->pcm_device_id < 0) {
5198 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5199 __func__, in->pcm_device_id, in->usecase);
5200 ret = -EINVAL;
5201 goto exit;
5202 }
5203
5204 adjust_mmap_period_count(&in->config, min_size_frames);
5205
5206 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
5207 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
5208 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
5209 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
5210 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
5211 step = "open";
5212 ret = -ENODEV;
5213 goto exit;
5214 }
5215
5216 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
5217 if (ret < 0) {
5218 step = "begin";
5219 goto exit;
5220 }
5221 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
5222 info->burst_size_frames = in->config.period_size;
5223 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
5224
5225 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
5226 info->buffer_size_frames));
5227
5228 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
5229 if (ret < 0) {
5230 step = "commit";
5231 goto exit;
5232 }
5233
5234 in->standby = false;
5235 ret = 0;
5236
5237 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
5238 __func__, info->shared_memory_address, info->buffer_size_frames);
5239
5240exit:
5241 if (ret != 0) {
5242 if (in->pcm == NULL) {
5243 ALOGE("%s: %s - %d", __func__, step, ret);
5244 } else {
5245 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
5246 pcm_close(in->pcm);
5247 in->pcm = NULL;
5248 }
5249 }
5250 pthread_mutex_unlock(&adev->lock);
5251 return ret;
5252}
5253
5254static int in_get_mmap_position(const struct audio_stream_in *stream,
5255 struct audio_mmap_position *position)
5256{
5257 struct stream_in *in = (struct stream_in *)stream;
5258 ALOGVV("%s", __func__);
5259 if (position == NULL) {
5260 return -EINVAL;
5261 }
5262 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
5263 return -ENOSYS;
5264 }
5265 if (in->pcm == NULL) {
5266 return -ENOSYS;
5267 }
5268 struct timespec ts = { 0, 0 };
5269 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
5270 if (ret < 0) {
5271 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
5272 return ret;
5273 }
5274 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
5275 return 0;
5276}
5277
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305278int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07005279 audio_io_handle_t handle,
5280 audio_devices_t devices,
5281 audio_output_flags_t flags,
5282 struct audio_config *config,
5283 struct audio_stream_out **stream_out,
5284 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005285{
5286 struct audio_device *adev = (struct audio_device *)dev;
5287 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305288 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005289 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005290 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305291 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005292 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
5293 bool is_usb_dev = audio_is_usb_out_device(devices) &&
5294 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
5295 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5300
Mingming Yin3a941d42016-02-17 18:08:05 -08005301 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5302 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305303 devices, flags, &out->stream);
5304
5305
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005306 if (!out) {
5307 return -ENOMEM;
5308 }
5309
Haynes Mathew George204045b2015-02-25 20:32:03 -08005310 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005311 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305312 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005313 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315 if (devices == AUDIO_DEVICE_NONE)
5316 devices = AUDIO_DEVICE_OUT_SPEAKER;
5317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005318 out->flags = flags;
5319 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005320 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07005321 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005322 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305323 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305324 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5325 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5326 else
5327 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005328 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005329 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005330 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305331 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305332 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305333 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005334 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005335
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305336 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005337 (property_get_bool("audio.matrix.limiter.enable", false)))
5338 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5339
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005340 if (audio_is_linear_pcm(out->format) &&
5341 out->flags == AUDIO_OUTPUT_FLAG_NONE && direct_dev) {
5342 pthread_mutex_lock(&adev->lock);
5343 if (is_hdmi) {
5344 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5345 ret = read_hdmi_sink_caps(out);
5346 } else if (is_usb_dev) {
5347 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
5348 &config->format,
5349 &out->supported_formats[0],
5350 MAX_SUPPORTED_FORMATS,
5351 &config->channel_mask,
5352 &out->supported_channel_masks[0],
5353 MAX_SUPPORTED_CHANNEL_MASKS,
5354 &config->sample_rate,
5355 &out->supported_sample_rates[0],
5356 MAX_SUPPORTED_SAMPLE_RATES);
5357 ALOGV("plugged dev USB ret %d", ret);
5358 } else {
5359 ret = -1;
5360 }
5361 pthread_mutex_unlock(&adev->lock);
5362 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005363 if (ret == -ENOSYS) {
5364 /* ignore and go with default */
5365 ret = 0;
5366 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005367 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08005368 goto error_open;
5369 }
5370 }
5371 }
5372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005373 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305374#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005375 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5376 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5377 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5378 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5379 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5380 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5381
5382 out->config = default_pcm_config_voip_copp;
5383 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5384 out->config.rate = out->sample_rate;
5385
5386#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305387 } 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 -08005388 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005389 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005390 ret = voice_extn_compress_voip_open_output_stream(out);
5391 if (ret != 0) {
5392 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5393 __func__, ret);
5394 goto error_open;
5395 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005396#endif
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005397 } else if (audio_is_linear_pcm(out->format) &&
5398 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
5399 out->channel_mask = config->channel_mask;
5400 out->sample_rate = config->sample_rate;
5401 out->format = config->format;
5402 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
5403 // does this change?
5404 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
5405 out->config.rate = config->sample_rate;
5406 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
5407 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5408 audio_bytes_per_sample(config->format));
5409 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07005410 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305411 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305412 pthread_mutex_lock(&adev->lock);
5413 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5414 pthread_mutex_unlock(&adev->lock);
5415
5416 // reject offload during card offline to allow
5417 // fallback to s/w paths
5418 if (offline) {
5419 ret = -ENODEV;
5420 goto error_open;
5421 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005422
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005423 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5424 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5425 ALOGE("%s: Unsupported Offload information", __func__);
5426 ret = -EINVAL;
5427 goto error_open;
5428 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005429
Mingming Yin3a941d42016-02-17 18:08:05 -08005430 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005431 if(config->offload_info.format == 0)
5432 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005433 if (config->offload_info.sample_rate == 0)
5434 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005435 }
5436
Mingming Yin90310102013-11-13 16:57:00 -08005437 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305438 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005439 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005440 ret = -EINVAL;
5441 goto error_open;
5442 }
5443
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005444 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5445 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5446 (audio_extn_passthru_is_passthrough_stream(out)) &&
5447 !((config->sample_rate == 48000) ||
5448 (config->sample_rate == 96000) ||
5449 (config->sample_rate == 192000))) {
5450 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5451 __func__, config->sample_rate, config->offload_info.format);
5452 ret = -EINVAL;
5453 goto error_open;
5454 }
5455
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005456 out->compr_config.codec = (struct snd_codec *)
5457 calloc(1, sizeof(struct snd_codec));
5458
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005459 if (!out->compr_config.codec) {
5460 ret = -ENOMEM;
5461 goto error_open;
5462 }
5463
Dhananjay Kumarac341582017-02-23 23:42:25 +05305464 out->stream.pause = out_pause;
5465 out->stream.resume = out_resume;
5466 out->stream.flush = out_flush;
5467 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005468 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005469 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305470 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005471 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305472 } else {
5473 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5474 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005475 }
vivek mehta446c3962015-09-14 10:57:35 -07005476
5477 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005478 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5479 config->format == 0 && config->sample_rate == 0 &&
5480 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005481 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005482 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5483 } else {
5484 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5485 ret = -EEXIST;
5486 goto error_open;
5487 }
vivek mehta446c3962015-09-14 10:57:35 -07005488 }
5489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005490 if (config->offload_info.channel_mask)
5491 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005492 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005493 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005494 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005495 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305496 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005497 ret = -EINVAL;
5498 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005499 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005500
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005501 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005502 out->sample_rate = config->offload_info.sample_rate;
5503
Mingming Yin3ee55c62014-08-04 14:23:35 -07005504 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005505
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305506 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305507 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305508 audio_extn_dolby_send_ddp_endp_params(adev);
5509 audio_extn_dolby_set_dmid(adev);
5510 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005511
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005512 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005513 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005514 out->compr_config.codec->bit_rate =
5515 config->offload_info.bit_rate;
5516 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305517 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005518 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305519 /* Update bit width only for non passthrough usecases.
5520 * For passthrough usecases, the output will always be opened @16 bit
5521 */
5522 if (!audio_extn_passthru_is_passthrough_stream(out))
5523 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305524
5525 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5526 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5527 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5528
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005529 /*TODO: Do we need to change it for passthrough */
5530 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005531
Manish Dewangana6fc5442015-08-24 20:30:31 +05305532 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5533 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305534 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305535 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305536 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5537 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305538
5539 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5540 AUDIO_FORMAT_PCM) {
5541
5542 /*Based on platform support, configure appropriate alsa format for corresponding
5543 *hal input format.
5544 */
5545 out->compr_config.codec->format = hal_format_to_alsa(
5546 config->offload_info.format);
5547
Ashish Jain83a6cc22016-06-28 14:34:17 +05305548 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305549 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305550 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305551
Dhananjay Kumarac341582017-02-23 23:42:25 +05305552 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305553 *hal input format and alsa format might differ based on platform support.
5554 */
5555 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305556 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305557
5558 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5559
5560 /* Check if alsa session is configured with the same format as HAL input format,
5561 * if not then derive correct fragment size needed to accomodate the
5562 * conversion of HAL input format to alsa format.
5563 */
5564 audio_extn_utils_update_direct_pcm_fragment_size(out);
5565
5566 /*if hal input and output fragment size is different this indicates HAL input format is
5567 *not same as the alsa format
5568 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305569 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305570 /*Allocate a buffer to convert input data to the alsa configured format.
5571 *size of convert buffer is equal to the size required to hold one fragment size
5572 *worth of pcm data, this is because flinger does not write more than fragment_size
5573 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305574 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5575 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305576 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5577 ret = -ENOMEM;
5578 goto error_open;
5579 }
5580 }
5581 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5582 out->compr_config.fragment_size =
5583 audio_extn_passthru_get_buffer_size(&config->offload_info);
5584 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5585 } else {
5586 out->compr_config.fragment_size =
5587 platform_get_compress_offload_buffer_size(&config->offload_info);
5588 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5589 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005590
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305591 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5592 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5593 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005594 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305595 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005596
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305597 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5598 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5599 }
5600
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005601 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5602 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005603
Manish Dewangan69426c82017-01-30 17:35:36 +05305604 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5605 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5606 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5607 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5608 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5609 } else {
5610 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5611 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005612
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305613 memset(&out->channel_map_param, 0,
5614 sizeof(struct audio_out_channel_map_param));
5615
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005616 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305617 out->send_next_track_params = false;
5618 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005619 out->offload_state = OFFLOAD_STATE_IDLE;
5620 out->playback_started = 0;
5621
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005622 audio_extn_dts_create_state_notifier_node(out->usecase);
5623
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005624 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5625 __func__, config->offload_info.version,
5626 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305627
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305628 /* Check if DSD audio format is supported in codec
5629 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305630 */
5631
5632 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305633 (!platform_check_codec_dsd_support(adev->platform) ||
5634 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305635 ret = -EINVAL;
5636 goto error_open;
5637 }
5638
Ashish Jain5106d362016-05-11 19:23:33 +05305639 /* Disable gapless if any of the following is true
5640 * passthrough playback
5641 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305642 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305643 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305644 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305645 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005646 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305647 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305648 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305649 check_and_set_gapless_mode(adev, false);
5650 } else
5651 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005652
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305653 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005654 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5655 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305656 if (config->format == AUDIO_FORMAT_DSD) {
5657 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5658 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5659 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005660
5661 create_offload_callback_thread(out);
5662
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005663 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305664 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005665 if (ret != 0) {
5666 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5667 __func__, ret);
5668 goto error_open;
5669 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005670 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5671 if (config->sample_rate == 0)
5672 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5673 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5674 config->sample_rate != 8000) {
5675 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5676 ret = -EINVAL;
5677 goto error_open;
5678 }
5679 out->sample_rate = config->sample_rate;
5680 out->config.rate = config->sample_rate;
5681 if (config->format == AUDIO_FORMAT_DEFAULT)
5682 config->format = AUDIO_FORMAT_PCM_16_BIT;
5683 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5684 config->format = AUDIO_FORMAT_PCM_16_BIT;
5685 ret = -EINVAL;
5686 goto error_open;
5687 }
5688 out->format = config->format;
5689 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5690 out->config = pcm_config_afe_proxy_playback;
5691 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005692 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305693 unsigned int channels = 0;
5694 /*Update config params to default if not set by the caller*/
5695 if (config->sample_rate == 0)
5696 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5697 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5698 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5699 if (config->format == AUDIO_FORMAT_DEFAULT)
5700 config->format = AUDIO_FORMAT_PCM_16_BIT;
5701
5702 channels = audio_channel_count_from_out_mask(out->channel_mask);
5703
Varun Balaraje49253e2017-07-06 19:48:56 +05305704 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5705 out->usecase = get_interactive_usecase(adev);
5706 out->config = pcm_config_low_latency;
5707 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305708 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005709 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5710 out->flags);
5711 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005712 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5713 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5714 out->config = pcm_config_mmap_playback;
5715 out->stream.start = out_start;
5716 out->stream.stop = out_stop;
5717 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5718 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305719 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5720 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005721 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5722 if (!out->dynamic_pm_qos_enabled) {
5723 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5724 } else {
5725 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5726 //the mixer path will be a string similar to "low-latency-playback resume"
5727 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5728 strlcat(out->pm_qos_mixer_path,
5729 " resume", MAX_MIXER_PATH_LEN);
5730 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5731 out->pm_qos_mixer_path);
5732 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305733 out->config = pcm_config_low_latency;
5734 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5735 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5736 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305737 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5738 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5739 if (out->config.period_size <= 0) {
5740 ALOGE("Invalid configuration period size is not valid");
5741 ret = -EINVAL;
5742 goto error_open;
5743 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305744 } else {
5745 /* primary path is the default path selected if no other outputs are available/suitable */
5746 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5747 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5748 }
5749 out->hal_ip_format = format = out->format;
5750 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5751 out->hal_op_format = pcm_format_to_hal(out->config.format);
5752 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5753 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005754 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305755 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305756 if (out->hal_ip_format != out->hal_op_format) {
5757 uint32_t buffer_size = out->config.period_size *
5758 format_to_bitwidth_table[out->hal_op_format] *
5759 out->config.channels;
5760 out->convert_buffer = calloc(1, buffer_size);
5761 if (out->convert_buffer == NULL){
5762 ALOGE("Allocation failed for convert buffer for size %d",
5763 out->compr_config.fragment_size);
5764 ret = -ENOMEM;
5765 goto error_open;
5766 }
5767 ALOGD("Convert buffer allocated of size %d", buffer_size);
5768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005769 }
5770
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005771 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5772 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305773
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005774 /* TODO remove this hardcoding and check why width is zero*/
5775 if (out->bit_width == 0)
5776 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305777 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005778 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07005779 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305780 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305781 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005782 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5783 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5784 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005785 if(adev->primary_output == NULL)
5786 adev->primary_output = out;
5787 else {
5788 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005789 ret = -EEXIST;
5790 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005791 }
5792 }
5793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005794 /* Check if this usecase is already existing */
5795 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005796 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5797 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005798 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005799 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005800 ret = -EEXIST;
5801 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005802 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804 pthread_mutex_unlock(&adev->lock);
5805
5806 out->stream.common.get_sample_rate = out_get_sample_rate;
5807 out->stream.common.set_sample_rate = out_set_sample_rate;
5808 out->stream.common.get_buffer_size = out_get_buffer_size;
5809 out->stream.common.get_channels = out_get_channels;
5810 out->stream.common.get_format = out_get_format;
5811 out->stream.common.set_format = out_set_format;
5812 out->stream.common.standby = out_standby;
5813 out->stream.common.dump = out_dump;
5814 out->stream.common.set_parameters = out_set_parameters;
5815 out->stream.common.get_parameters = out_get_parameters;
5816 out->stream.common.add_audio_effect = out_add_audio_effect;
5817 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5818 out->stream.get_latency = out_get_latency;
5819 out->stream.set_volume = out_set_volume;
5820 out->stream.write = out_write;
5821 out->stream.get_render_position = out_get_render_position;
5822 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005823 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005824
Haynes Mathew George16081042017-05-31 17:16:49 -07005825 if (out->realtime)
5826 out->af_period_multiplier = af_period_multiplier;
5827 else
5828 out->af_period_multiplier = 1;
5829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005830 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005831 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005832 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005833
5834 config->format = out->stream.common.get_format(&out->stream.common);
5835 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5836 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5837
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305838 /*
5839 By locking output stream before registering, we allow the callback
5840 to update stream's state only after stream's initial state is set to
5841 adev state.
5842 */
5843 lock_output_stream(out);
5844 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5845 pthread_mutex_lock(&adev->lock);
5846 out->card_status = adev->card_status;
5847 pthread_mutex_unlock(&adev->lock);
5848 pthread_mutex_unlock(&out->lock);
5849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005850 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305851 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005852 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005853
5854 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5855 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5856 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005857 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305858 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005859 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005860 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305861 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005862 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5863 out->usecase, PCM_PLAYBACK);
5864 hdlr_stream_cfg.flags = out->flags;
5865 hdlr_stream_cfg.type = PCM_PLAYBACK;
5866 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5867 &hdlr_stream_cfg);
5868 if (ret) {
5869 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5870 out->adsp_hdlr_stream_handle = NULL;
5871 }
5872 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305873 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005874 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005875 if (ret < 0) {
5876 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5877 out->ip_hdlr_handle = NULL;
5878 }
5879 }
Eric Laurent994a6932013-07-17 11:51:42 -07005880 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005881 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005882
5883error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305884 if (out->convert_buffer)
5885 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005886 free(out);
5887 *stream_out = NULL;
5888 ALOGD("%s: exit: ret %d", __func__, ret);
5889 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005890}
5891
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305892void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005893 struct audio_stream_out *stream)
5894{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005895 struct stream_out *out = (struct stream_out *)stream;
5896 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005897 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005898
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005899 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305900
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305901 // must deregister from sndmonitor first to prevent races
5902 // between the callback and close_stream
5903 audio_extn_snd_mon_unregister_listener(out);
5904
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005905 /* close adsp hdrl session before standby */
5906 if (out->adsp_hdlr_stream_handle) {
5907 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5908 if (ret)
5909 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5910 out->adsp_hdlr_stream_handle = NULL;
5911 }
5912
Manish Dewangan21a850a2017-08-14 12:03:55 +05305913 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005914 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5915 out->ip_hdlr_handle = NULL;
5916 }
5917
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005918 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305919 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005920 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305921 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305922 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005923 if(ret != 0)
5924 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5925 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005926 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005927 out_standby(&stream->common);
5928
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005929 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005930 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005931 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005932 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005933 if (out->compr_config.codec != NULL)
5934 free(out->compr_config.codec);
5935 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005936
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305937 out->a2dp_compress_mute = false;
5938
Varun Balaraje49253e2017-07-06 19:48:56 +05305939 if (is_interactive_usecase(out->usecase))
5940 free_interactive_usecase(adev, out->usecase);
5941
Ashish Jain83a6cc22016-06-28 14:34:17 +05305942 if (out->convert_buffer != NULL) {
5943 free(out->convert_buffer);
5944 out->convert_buffer = NULL;
5945 }
5946
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005947 if (adev->voice_tx_output == out)
5948 adev->voice_tx_output = NULL;
5949
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305950 if (adev->primary_output == out)
5951 adev->primary_output = NULL;
5952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005953 pthread_cond_destroy(&out->cond);
5954 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005955 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005956 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005957}
5958
5959static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5960{
5961 struct audio_device *adev = (struct audio_device *)dev;
5962 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005963 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005964 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005965 int ret;
5966 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005967
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005968 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005969 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005970
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305971 if (!parms)
5972 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305973
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305974 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5975 if (ret >= 0) {
5976 /* When set to false, HAL should disable EC and NS */
5977 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5978 adev->bt_sco_on = true;
5979 else
5980 adev->bt_sco_on = false;
5981 }
5982
Naresh Tanniru4c630392014-05-12 01:05:52 +05305983 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005984 status = voice_set_parameters(adev, parms);
5985 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005986 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005987
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005988 status = platform_set_parameters(adev->platform, parms);
5989 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005990 goto done;
5991
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005992 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5993 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005994 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005995 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5996 adev->bluetooth_nrec = true;
5997 else
5998 adev->bluetooth_nrec = false;
5999 }
6000
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006001 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
6002 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006003 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6004 adev->screen_off = false;
6005 else
6006 adev->screen_off = true;
6007 }
6008
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006009 ret = str_parms_get_int(parms, "rotation", &val);
6010 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006011 bool reverse_speakers = false;
6012 switch(val) {
6013 // FIXME: note that the code below assumes that the speakers are in the correct placement
6014 // relative to the user when the device is rotated 90deg from its default rotation. This
6015 // assumption is device-specific, not platform-specific like this code.
6016 case 270:
6017 reverse_speakers = true;
6018 break;
6019 case 0:
6020 case 90:
6021 case 180:
6022 break;
6023 default:
6024 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006025 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006026 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006027 if (status == 0) {
6028 if (adev->speaker_lr_swap != reverse_speakers) {
6029 adev->speaker_lr_swap = reverse_speakers;
6030 // only update the selected device if there is active pcm playback
6031 struct audio_usecase *usecase;
6032 struct listnode *node;
6033 list_for_each(node, &adev->usecase_list) {
6034 usecase = node_to_item(node, struct audio_usecase, list);
6035 if (usecase->type == PCM_PLAYBACK) {
6036 select_devices(adev, usecase->id);
6037 break;
6038 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006039 }
6040 }
6041 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07006042 }
6043
Mingming Yin514a8bc2014-07-29 15:22:21 -07006044 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
6045 if (ret >= 0) {
6046 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
6047 adev->bt_wb_speech_enabled = true;
6048 else
6049 adev->bt_wb_speech_enabled = false;
6050 }
6051
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006052 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
6053 if (ret >= 0) {
6054 val = atoi(value);
6055 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006056 ALOGV("cache new ext disp type and edid");
6057 ret = platform_get_ext_disp_type(adev->platform);
6058 if (ret < 0) {
6059 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08006060 status = ret;
6061 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07006062 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006063 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006064 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08006065 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07006066 /*
6067 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
6068 * Per AudioPolicyManager, USB device is higher priority than WFD.
6069 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
6070 * If WFD use case occupies AFE proxy, it may result unintended behavior while
6071 * starting voice call on USB
6072 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006073 ret = str_parms_get_str(parms, "card", value, sizeof(value));
6074 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08006075 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
6076 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006077 }
vivek mehta344576a2016-04-12 18:56:03 -07006078 ALOGV("detected USB connect .. disable proxy");
6079 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006080 }
6081 }
6082
6083 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
6084 if (ret >= 0) {
6085 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07006086 /*
6087 * The HDMI / Displayport disconnect handling has been moved to
6088 * audio extension to ensure that its parameters are not
6089 * invalidated prior to updating sysfs of the disconnect event
6090 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
6091 */
6092 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08006093 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006094 ret = str_parms_get_str(parms, "card", value, sizeof(value));
6095 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05306096 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
6097 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08006098 }
vivek mehta344576a2016-04-12 18:56:03 -07006099 ALOGV("detected USB disconnect .. enable proxy");
6100 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07006101 }
6102 }
6103
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306104 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
6105 if (ret >= 0) {
6106 struct audio_usecase *usecase;
6107 struct listnode *node;
6108 list_for_each(node, &adev->usecase_list) {
6109 usecase = node_to_item(node, struct audio_usecase, list);
6110 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07006111 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306112 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08006113
6114 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306115 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08006116 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306117 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306118 //force device switch to re configure encoder
6119 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306120 audio_extn_a2dp_set_handoff_mode(false);
6121 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05306122 break;
6123 }
6124 }
6125 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006126
6127 //handle vr audio setparam
6128 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6129 value, sizeof(value));
6130 if (ret >= 0) {
6131 ALOGI("Setting vr mode to be %s", value);
6132 if (!strncmp(value, "true", 4)) {
6133 adev->vr_audio_mode_enabled = true;
6134 ALOGI("Setting vr mode to true");
6135 } else if (!strncmp(value, "false", 5)) {
6136 adev->vr_audio_mode_enabled = false;
6137 ALOGI("Setting vr mode to false");
6138 } else {
6139 ALOGI("wrong vr mode set");
6140 }
6141 }
6142
Naresh Tannirucd2353e2016-08-19 00:37:25 +05306143 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006144done:
6145 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006146 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306147error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006148 ALOGV("%s: exit with code(%d)", __func__, status);
6149 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150}
6151
6152static char* adev_get_parameters(const struct audio_hw_device *dev,
6153 const char *keys)
6154{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006155 struct audio_device *adev = (struct audio_device *)dev;
6156 struct str_parms *reply = str_parms_create();
6157 struct str_parms *query = str_parms_create_str(keys);
6158 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05306159 char value[256] = {0};
6160 int ret = 0;
6161
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006162 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006163 if (reply) {
6164 str_parms_destroy(reply);
6165 }
6166 if (query) {
6167 str_parms_destroy(query);
6168 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006169 ALOGE("adev_get_parameters: failed to create query or reply");
6170 return NULL;
6171 }
6172
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006173 //handle vr audio getparam
6174
6175 ret = str_parms_get_str(query,
6176 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6177 value, sizeof(value));
6178
6179 if (ret >= 0) {
6180 bool vr_audio_enabled = false;
6181 pthread_mutex_lock(&adev->lock);
6182 vr_audio_enabled = adev->vr_audio_mode_enabled;
6183 pthread_mutex_unlock(&adev->lock);
6184
6185 ALOGI("getting vr mode to %d", vr_audio_enabled);
6186
6187 if (vr_audio_enabled) {
6188 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6189 "true");
6190 goto exit;
6191 } else {
6192 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
6193 "false");
6194 goto exit;
6195 }
6196 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006197
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006198 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006199 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08006200 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006201 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05306202 pthread_mutex_unlock(&adev->lock);
6203
Naresh Tannirud7205b62014-06-20 02:54:48 +05306204exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006205 str = str_parms_to_str(reply);
6206 str_parms_destroy(query);
6207 str_parms_destroy(reply);
6208
6209 ALOGV("%s: exit: returns - %s", __func__, str);
6210 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211}
6212
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006213static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214{
6215 return 0;
6216}
6217
6218static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
6219{
Haynes Mathew George5191a852013-09-11 14:19:36 -07006220 int ret;
6221 struct audio_device *adev = (struct audio_device *)dev;
6222 pthread_mutex_lock(&adev->lock);
6223 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07006224 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07006225 pthread_mutex_unlock(&adev->lock);
6226 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227}
6228
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006229static int adev_set_master_volume(struct audio_hw_device *dev __unused,
6230 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006231{
6232 return -ENOSYS;
6233}
6234
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006235static int adev_get_master_volume(struct audio_hw_device *dev __unused,
6236 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006237{
6238 return -ENOSYS;
6239}
6240
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006241static int adev_set_master_mute(struct audio_hw_device *dev __unused,
6242 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006243{
6244 return -ENOSYS;
6245}
6246
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006247static int adev_get_master_mute(struct audio_hw_device *dev __unused,
6248 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006249{
6250 return -ENOSYS;
6251}
6252
6253static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
6254{
6255 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006257 pthread_mutex_lock(&adev->lock);
6258 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006259 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006260 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08006261 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006262 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07006263 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006264 adev->current_call_output = NULL;
6265 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006266 }
6267 pthread_mutex_unlock(&adev->lock);
6268 return 0;
6269}
6270
6271static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
6272{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006273 int ret;
6274
6275 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08006276 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08006277 ret = voice_set_mic_mute((struct audio_device *)dev, state);
6278 pthread_mutex_unlock(&adev->lock);
6279
6280 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006281}
6282
6283static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
6284{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006285 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006286 return 0;
6287}
6288
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006289static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290 const struct audio_config *config)
6291{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006292 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006293
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006294 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
6295 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006296}
6297
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006298static bool adev_input_allow_hifi_record(struct audio_device *adev,
6299 audio_devices_t devices,
6300 audio_input_flags_t flags,
6301 audio_source_t source) {
6302 const bool allowed = true;
6303
6304 if (!audio_is_usb_in_device(devices))
6305 return !allowed;
6306
6307 switch (flags) {
6308 case AUDIO_INPUT_FLAG_NONE:
6309 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
6310 break;
6311 default:
6312 return !allowed;
6313 }
6314
6315 switch (source) {
6316 case AUDIO_SOURCE_DEFAULT:
6317 case AUDIO_SOURCE_MIC:
6318 case AUDIO_SOURCE_UNPROCESSED:
6319 break;
6320 default:
6321 return !allowed;
6322 }
6323
6324 switch (adev->mode) {
6325 case 0:
6326 break;
6327 default:
6328 return !allowed;
6329 }
6330
6331 return allowed;
6332}
6333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006334static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006335 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006336 audio_devices_t devices,
6337 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006338 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306339 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006340 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006341 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342{
6343 struct audio_device *adev = (struct audio_device *)dev;
6344 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006345 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006346 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006347 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306348 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006349 bool is_usb_dev = audio_is_usb_in_device(devices);
6350 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
6351 devices,
6352 flags,
6353 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006355 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006356
6357 if (!(is_usb_dev && may_use_hifi_record)) {
6358 if (config->sample_rate == 0)
6359 config->sample_rate = 48000;
6360 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6361 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
6362 if (config->format == AUDIO_FORMAT_DEFAULT)
6363 config->format = AUDIO_FORMAT_PCM_16_BIT;
6364
6365 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6366
6367 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
6368 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05306369 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006370
6371 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006372
6373 if (!in) {
6374 ALOGE("failed to allocate input stream");
6375 return -ENOMEM;
6376 }
6377
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306378 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306379 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6380 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006381 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006382 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006384 in->stream.common.get_sample_rate = in_get_sample_rate;
6385 in->stream.common.set_sample_rate = in_set_sample_rate;
6386 in->stream.common.get_buffer_size = in_get_buffer_size;
6387 in->stream.common.get_channels = in_get_channels;
6388 in->stream.common.get_format = in_get_format;
6389 in->stream.common.set_format = in_set_format;
6390 in->stream.common.standby = in_standby;
6391 in->stream.common.dump = in_dump;
6392 in->stream.common.set_parameters = in_set_parameters;
6393 in->stream.common.get_parameters = in_get_parameters;
6394 in->stream.common.add_audio_effect = in_add_audio_effect;
6395 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6396 in->stream.set_gain = in_set_gain;
6397 in->stream.read = in_read;
6398 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6399
6400 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006401 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006403 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006404 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006405 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006406
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306407 /* restrict 24 bit capture for unprocessed source only
6408 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6409 */
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006410 if (is_usb_dev && may_use_hifi_record) {
6411 /* HiFi record selects an appropriate format, channel, rate combo
6412 depending on sink capabilities*/
6413 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
6414 &config->format,
6415 &in->supported_formats[0],
6416 MAX_SUPPORTED_FORMATS,
6417 &config->channel_mask,
6418 &in->supported_channel_masks[0],
6419 MAX_SUPPORTED_CHANNEL_MASKS,
6420 &config->sample_rate,
6421 &in->supported_sample_rates[0],
6422 MAX_SUPPORTED_SAMPLE_RATES);
6423 if (ret != 0) {
6424 ret = -EINVAL;
6425 goto err_open;
6426 }
6427 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
6428 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306429 config->format = AUDIO_FORMAT_PCM_16_BIT;
6430 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6431 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6432 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6433 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6434 bool ret_error = false;
6435 in->bit_width = 24;
6436 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6437 from HAL is 24_packed and 8_24
6438 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6439 24_packed return error indicating supported format is 24_packed
6440 *> In case of any other source requesting 24 bit or float return error
6441 indicating format supported is 16 bit only.
6442
6443 on error flinger will retry with supported format passed
6444 */
6445 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6446 (source != AUDIO_SOURCE_CAMCORDER)) {
6447 config->format = AUDIO_FORMAT_PCM_16_BIT;
6448 if (config->sample_rate > 48000)
6449 config->sample_rate = 48000;
6450 ret_error = true;
6451 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6452 in->config.format = PCM_FORMAT_S24_3LE;
6453 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6454 in->config.format = PCM_FORMAT_S24_LE;
6455 } else {
6456 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6457 ret_error = true;
6458 }
6459
6460 if (ret_error) {
6461 ret = -EINVAL;
6462 goto err_open;
6463 }
6464 }
6465
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006466 in->channel_mask = config->channel_mask;
6467 in->format = config->format;
6468
6469 in->usecase = USECASE_AUDIO_RECORD;
6470 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
6471 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
6472 is_low_latency = true;
6473#if LOW_LATENCY_CAPTURE_USE_CASE
6474 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6475#endif
6476 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6477 }
6478
6479 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6480 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6481 in->realtime = 0;
6482 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6483 in->config = pcm_config_mmap_capture;
6484 in->stream.start = in_start;
6485 in->stream.stop = in_stop;
6486 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6487 in->stream.get_mmap_position = in_get_mmap_position;
6488 in->af_period_multiplier = 1;
6489 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6490 } else if (in->realtime) {
6491 in->config = pcm_config_audio_capture_rt;
6492 in->sample_rate = in->config.rate;
6493 in->af_period_multiplier = af_period_multiplier;
6494 } else {
6495 in->config = pcm_config_audio_capture;
6496 in->config.rate = config->sample_rate;
6497 in->sample_rate = config->sample_rate;
6498 in->af_period_multiplier = 1;
6499 }
6500 in->bit_width = 16;
6501
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306502 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306503 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6504 (adev->mode != AUDIO_MODE_IN_CALL)) {
6505 ret = -EINVAL;
6506 goto err_open;
6507 }
6508
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006509 if (is_usb_dev && may_use_hifi_record) {
6510 in->usecase = USECASE_AUDIO_RECORD_HIFI;
6511 in->config = pcm_config_audio_capture;
6512 frame_size = audio_stream_in_frame_size(&in->stream);
6513 buffer_size = get_input_buffer_size(config->sample_rate,
6514 config->format,
6515 channel_count,
6516 false /*is_low_latency*/);
6517 in->config.period_size = buffer_size / frame_size;
6518 in->config.rate = config->sample_rate;
6519 in->af_period_multiplier = 1;
6520 in->config.format = pcm_format_from_audio_format(config->format);
6521 in->config.channels = channel_count;
6522 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306523 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006524 if (config->sample_rate == 0)
6525 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6526 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6527 config->sample_rate != 8000) {
6528 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6529 ret = -EINVAL;
6530 goto err_open;
6531 }
6532 if (config->format == AUDIO_FORMAT_DEFAULT)
6533 config->format = AUDIO_FORMAT_PCM_16_BIT;
6534 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6535 config->format = AUDIO_FORMAT_PCM_16_BIT;
6536 ret = -EINVAL;
6537 goto err_open;
6538 }
6539
6540 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6541 in->config = pcm_config_afe_proxy_record;
6542 in->config.channels = channel_count;
6543 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306544 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306545 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6546 in, config, &channel_mask_updated)) {
6547 if (channel_mask_updated == true) {
6548 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6549 __func__, config->channel_mask);
6550 ret = -EINVAL;
6551 goto err_open;
6552 }
Garmond Leunge2433c32017-09-28 21:51:22 -07006553 ALOGD("%s: created multi-channel session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006554 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006555 audio_extn_compr_cap_format_supported(config->format) &&
6556 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006557 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306558 } else if (audio_extn_cin_applicable_stream(in)) {
6559 ret = audio_extn_cin_configure_input_stream(in);
6560 if (ret)
6561 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006562 } else {
6563 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006564 if (!in->realtime) {
6565 in->format = config->format;
6566 frame_size = audio_stream_in_frame_size(&in->stream);
6567 buffer_size = get_input_buffer_size(config->sample_rate,
6568 config->format,
6569 channel_count,
6570 is_low_latency);
6571 in->config.period_size = buffer_size / frame_size;
6572 }
6573
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006574#ifndef COMPRESS_VOIP_ENABLED
6575 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6576 (in->config.rate == 8000 || in->config.rate == 16000 ||
6577 in->config.rate == 32000 || in->config.rate == 48000) &&
6578 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6579
6580 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6581 in->config = default_pcm_config_voip_copp;
6582 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6583 in->config.rate = in->sample_rate;
6584#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006585 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006586 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6587 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006588 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006589 (in->config.rate == 8000 || in->config.rate == 16000 ||
6590 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006591 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6592 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006593#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006594 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006595 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006596
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306597 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6598 &adev->streams_input_cfg_list,
6599 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306600 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306601
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006602 /* This stream could be for sound trigger lab,
6603 get sound trigger pcm if present */
6604 audio_extn_sound_trigger_check_and_get_session(in);
6605
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306606 lock_input_stream(in);
6607 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6608 pthread_mutex_lock(&adev->lock);
6609 in->card_status = adev->card_status;
6610 pthread_mutex_unlock(&adev->lock);
6611 pthread_mutex_unlock(&in->lock);
6612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006613 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006614 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006615 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006616
6617err_open:
6618 free(in);
6619 *stream_in = NULL;
6620 return ret;
6621}
6622
6623static void adev_close_input_stream(struct audio_hw_device *dev,
6624 struct audio_stream_in *stream)
6625{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006626 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006627 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006628 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306629
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306630 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006631
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306632 // must deregister from sndmonitor first to prevent races
6633 // between the callback and close_stream
6634 audio_extn_snd_mon_unregister_listener(stream);
6635
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306636 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006637 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306638
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006639 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306640 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006641 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306642 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006643 if (ret != 0)
6644 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6645 __func__, ret);
6646 } else
6647 in_standby(&stream->common);
6648
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006649 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006650 audio_extn_ssr_deinit();
6651 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006652
Garmond Leunge2433c32017-09-28 21:51:22 -07006653 if (audio_extn_ffv_get_stream() == in) {
6654 audio_extn_ffv_stream_deinit();
6655 }
6656
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306657 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006658 audio_extn_compr_cap_format_supported(in->config.format))
6659 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306660
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306661 if (audio_extn_cin_attached_usecase(in->usecase))
6662 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006663
Mingming Yinfd7607b2016-01-22 12:48:44 -08006664 if (in->is_st_session) {
6665 ALOGV("%s: sound trigger pcm stop lab", __func__);
6666 audio_extn_sound_trigger_stop_lab(in);
6667 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006668 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006669 return;
6670}
6671
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306672int adev_create_audio_patch(struct audio_hw_device *dev,
6673 unsigned int num_sources,
6674 const struct audio_port_config *sources,
6675 unsigned int num_sinks,
6676 const struct audio_port_config *sinks,
6677 audio_patch_handle_t *handle)
6678{
6679
6680
6681 return audio_extn_hw_loopback_create_audio_patch(dev,
6682 num_sources,
6683 sources,
6684 num_sinks,
6685 sinks,
6686 handle);
6687
6688}
6689
6690int adev_release_audio_patch(struct audio_hw_device *dev,
6691 audio_patch_handle_t handle)
6692{
6693 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6694}
6695
6696int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6697{
6698 return audio_extn_hw_loopback_get_audio_port(dev, config);
6699}
6700
6701int adev_set_audio_port_config(struct audio_hw_device *dev,
6702 const struct audio_port_config *config)
6703{
6704 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6705}
6706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006707static int adev_dump(const audio_hw_device_t *device __unused,
6708 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709{
6710 return 0;
6711}
6712
6713static int adev_close(hw_device_t *device)
6714{
6715 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006716
6717 if (!adev)
6718 return 0;
6719
6720 pthread_mutex_lock(&adev_init_lock);
6721
6722 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306723 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006724 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006725 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306726 audio_extn_utils_release_streams_cfg_lists(
6727 &adev->streams_output_cfg_list,
6728 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306729 if (audio_extn_qaf_is_enabled())
6730 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006731 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006732 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006733 free(adev->snd_dev_ref_cnt);
6734 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006735 if (adev->adm_deinit)
6736 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306737 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006738 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306739 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306740 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07006741 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306742 if (adev->device_cfg_params) {
6743 free(adev->device_cfg_params);
6744 adev->device_cfg_params = NULL;
6745 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006746 free(device);
6747 adev = NULL;
6748 }
6749 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006751 return 0;
6752}
6753
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006754/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6755 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6756 * just that it _might_ work.
6757 */
6758static int period_size_is_plausible_for_low_latency(int period_size)
6759{
6760 switch (period_size) {
6761 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006762 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006763 case 240:
6764 case 320:
6765 case 480:
6766 return 1;
6767 default:
6768 return 0;
6769 }
6770}
6771
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306772static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6773{
6774 bool is_snd_card_status = false;
6775 bool is_ext_device_status = false;
6776 char value[32];
6777 int card = -1;
6778 card_status_t status;
6779
6780 if (cookie != adev || !parms)
6781 return;
6782
6783 if (!parse_snd_card_status(parms, &card, &status)) {
6784 is_snd_card_status = true;
6785 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6786 is_ext_device_status = true;
6787 } else {
6788 // not a valid event
6789 return;
6790 }
6791
6792 pthread_mutex_lock(&adev->lock);
6793 if (card == adev->snd_card || is_ext_device_status) {
6794 if (is_snd_card_status && adev->card_status != status) {
6795 adev->card_status = status;
6796 platform_snd_card_update(adev->platform, status);
6797 audio_extn_fm_set_parameters(adev, parms);
6798 } else if (is_ext_device_status) {
6799 platform_set_parameters(adev->platform, parms);
6800 }
6801 }
6802 pthread_mutex_unlock(&adev->lock);
6803 return;
6804}
6805
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306806/* out and adev lock held */
6807static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6808{
6809 struct audio_usecase *uc_info;
6810 float left_p;
6811 float right_p;
6812 audio_devices_t devices;
6813
6814 uc_info = get_usecase_from_list(adev, out->usecase);
6815 if (uc_info == NULL) {
6816 ALOGE("%s: Could not find the usecase (%d) in the list",
6817 __func__, out->usecase);
6818 return -EINVAL;
6819 }
6820
6821 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6822 out->usecase, use_case_table[out->usecase]);
6823
6824 if (restore) {
6825 // restore A2DP device for active usecases and unmute if required
6826 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6827 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6828 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6829 select_devices(adev, uc_info->id);
6830 pthread_mutex_lock(&out->compr_mute_lock);
6831 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6832 (out->a2dp_compress_mute)) {
6833 out->a2dp_compress_mute = false;
6834 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6835 }
6836 pthread_mutex_unlock(&out->compr_mute_lock);
6837 }
6838 } else {
6839 // mute compress stream if suspended
6840 pthread_mutex_lock(&out->compr_mute_lock);
6841 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6842 (!out->a2dp_compress_mute)) {
6843 if (!out->standby) {
6844 ALOGD("%s: selecting speaker and muting stream", __func__);
6845 devices = out->devices;
6846 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6847 left_p = out->volume_l;
6848 right_p = out->volume_r;
6849 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6850 compress_pause(out->compr);
6851 out_set_compr_volume(&out->stream, (float)0, (float)0);
6852 out->a2dp_compress_mute = true;
6853 select_devices(adev, out->usecase);
6854 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6855 compress_resume(out->compr);
6856 out->devices = devices;
6857 out->volume_l = left_p;
6858 out->volume_r = right_p;
6859 }
6860 }
6861 pthread_mutex_unlock(&out->compr_mute_lock);
6862 }
6863 ALOGV("%s: exit", __func__);
6864 return 0;
6865}
6866
6867int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6868{
6869 int ret = 0;
6870
6871 lock_output_stream(out);
6872 pthread_mutex_lock(&adev->lock);
6873
6874 ret = check_a2dp_restore_l(adev, out, restore);
6875
6876 pthread_mutex_unlock(&adev->lock);
6877 pthread_mutex_unlock(&out->lock);
6878 return ret;
6879}
6880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006881static int adev_open(const hw_module_t *module, const char *name,
6882 hw_device_t **device)
6883{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306884 int ret;
6885
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006886 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006887 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6888
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006889 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006890 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006891 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006892 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006893 ALOGD("%s: returning existing instance of adev", __func__);
6894 ALOGD("%s: exit", __func__);
6895 pthread_mutex_unlock(&adev_init_lock);
6896 return 0;
6897 }
6898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006899 adev = calloc(1, sizeof(struct audio_device));
6900
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006901 if (!adev) {
6902 pthread_mutex_unlock(&adev_init_lock);
6903 return -ENOMEM;
6904 }
6905
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006906 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6907
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306908#ifdef DYNAMIC_LOG_ENABLED
6909 register_for_dynamic_logging("hal");
6910#endif
6911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006912 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6913 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6914 adev->device.common.module = (struct hw_module_t *)module;
6915 adev->device.common.close = adev_close;
6916
6917 adev->device.init_check = adev_init_check;
6918 adev->device.set_voice_volume = adev_set_voice_volume;
6919 adev->device.set_master_volume = adev_set_master_volume;
6920 adev->device.get_master_volume = adev_get_master_volume;
6921 adev->device.set_master_mute = adev_set_master_mute;
6922 adev->device.get_master_mute = adev_get_master_mute;
6923 adev->device.set_mode = adev_set_mode;
6924 adev->device.set_mic_mute = adev_set_mic_mute;
6925 adev->device.get_mic_mute = adev_get_mic_mute;
6926 adev->device.set_parameters = adev_set_parameters;
6927 adev->device.get_parameters = adev_get_parameters;
6928 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6929 adev->device.open_output_stream = adev_open_output_stream;
6930 adev->device.close_output_stream = adev_close_output_stream;
6931 adev->device.open_input_stream = adev_open_input_stream;
6932 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306933 adev->device.create_audio_patch = adev_create_audio_patch;
6934 adev->device.release_audio_patch = adev_release_audio_patch;
6935 adev->device.get_audio_port = adev_get_audio_port;
6936 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006937 adev->device.dump = adev_dump;
6938
6939 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006940 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006941 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006942 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006944 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006945 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006946 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306947 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006948 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006949 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006950 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006951 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006952 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006953 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306954 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306955 adev->perf_lock_opts[0] = 0x101;
6956 adev->perf_lock_opts[1] = 0x20E;
6957 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006958 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006960 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006961 adev->platform = platform_init(adev);
6962 if (!adev->platform) {
6963 free(adev->snd_dev_ref_cnt);
6964 free(adev);
6965 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6966 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006967 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306968 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006969 return -EINVAL;
6970 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006971
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306972 if (audio_extn_qaf_is_enabled()) {
6973 ret = audio_extn_qaf_init(adev);
6974 if (ret < 0) {
6975 free(adev);
6976 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6977 *device = NULL;
6978 pthread_mutex_unlock(&adev_init_lock);
6979 pthread_mutex_destroy(&adev->lock);
6980 return ret;
6981 }
6982
6983 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6984 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6985 }
6986
Eric Laurentc4aef752013-09-12 17:45:53 -07006987 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6988 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6989 if (adev->visualizer_lib == NULL) {
6990 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6991 } else {
6992 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6993 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006994 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006995 "visualizer_hal_start_output");
6996 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006997 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006998 "visualizer_hal_stop_output");
6999 }
7000 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05307001 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08007002 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08007003 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05307004 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07007005 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07007006
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007007 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
7008 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
7009 if (adev->offload_effects_lib == NULL) {
7010 ALOGE("%s: DLOPEN failed for %s", __func__,
7011 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7012 } else {
7013 ALOGV("%s: DLOPEN successful for %s", __func__,
7014 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
7015 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05307016 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007017 "offload_effects_bundle_hal_start_output");
7018 adev->offload_effects_stop_output =
7019 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
7020 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007021 adev->offload_effects_set_hpx_state =
7022 (int (*)(bool))dlsym(adev->offload_effects_lib,
7023 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05307024 adev->offload_effects_get_parameters =
7025 (void (*)(struct str_parms *, struct str_parms *))
7026 dlsym(adev->offload_effects_lib,
7027 "offload_effects_bundle_get_parameters");
7028 adev->offload_effects_set_parameters =
7029 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
7030 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08007031 }
7032 }
7033
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007034 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
7035 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
7036 if (adev->adm_lib == NULL) {
7037 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
7038 } else {
7039 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
7040 adev->adm_init = (adm_init_t)
7041 dlsym(adev->adm_lib, "adm_init");
7042 adev->adm_deinit = (adm_deinit_t)
7043 dlsym(adev->adm_lib, "adm_deinit");
7044 adev->adm_register_input_stream = (adm_register_input_stream_t)
7045 dlsym(adev->adm_lib, "adm_register_input_stream");
7046 adev->adm_register_output_stream = (adm_register_output_stream_t)
7047 dlsym(adev->adm_lib, "adm_register_output_stream");
7048 adev->adm_deregister_stream = (adm_deregister_stream_t)
7049 dlsym(adev->adm_lib, "adm_deregister_stream");
7050 adev->adm_request_focus = (adm_request_focus_t)
7051 dlsym(adev->adm_lib, "adm_request_focus");
7052 adev->adm_abandon_focus = (adm_abandon_focus_t)
7053 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007054 adev->adm_set_config = (adm_set_config_t)
7055 dlsym(adev->adm_lib, "adm_set_config");
7056 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
7057 dlsym(adev->adm_lib, "adm_request_focus_v2");
7058 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
7059 dlsym(adev->adm_lib, "adm_is_noirq_avail");
7060 adev->adm_on_routing_change = (adm_on_routing_change_t)
7061 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007062 }
7063 }
7064
Mingming Yin514a8bc2014-07-29 15:22:21 -07007065 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007066 //initialize this to false for now,
7067 //this will be set to true through set param
7068 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07007069
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07007070 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007071 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08007072 adev->dsp_bit_width_enforce_mode =
7073 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007074
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307075 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
7076 &adev->streams_output_cfg_list,
7077 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007078
Kiran Kandi910e1862013-10-29 13:29:42 -07007079 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007080
7081 char value[PROPERTY_VALUE_MAX];
7082 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007083 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007084 trial = atoi(value);
7085 if (period_size_is_plausible_for_low_latency(trial)) {
7086 pcm_config_low_latency.period_size = trial;
7087 pcm_config_low_latency.start_threshold = trial / 4;
7088 pcm_config_low_latency.avail_min = trial / 4;
7089 configured_low_latency_capture_period_size = trial;
7090 }
7091 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007092 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007093 trial = atoi(value);
7094 if (period_size_is_plausible_for_low_latency(trial)) {
7095 configured_low_latency_capture_period_size = trial;
7096 }
7097 }
7098
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007099 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007100 af_period_multiplier = atoi(value);
7101 if (af_period_multiplier < 0)
7102 af_period_multiplier = 2;
7103 else if (af_period_multiplier > 4)
7104 af_period_multiplier = 4;
7105
7106 ALOGV("new period_multiplier = %d", af_period_multiplier);
7107 }
7108
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07007109 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07007110 pthread_mutex_unlock(&adev_init_lock);
7111
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007112 if (adev->adm_init)
7113 adev->adm_data = adev->adm_init();
7114
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307115 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05307116 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007117 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307118
7119 audio_extn_snd_mon_init();
7120 pthread_mutex_lock(&adev->lock);
7121 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
7122 adev->card_status = CARD_STATUS_ONLINE;
7123 pthread_mutex_unlock(&adev->lock);
7124 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05307125 /* Allocate memory for Device config params */
7126 adev->device_cfg_params = (struct audio_device_config_param*)
7127 calloc(platform_get_max_codec_backend(),
7128 sizeof(struct audio_device_config_param));
7129 if (adev->device_cfg_params == NULL)
7130 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307131
Eric Laurent994a6932013-07-17 11:51:42 -07007132 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133 return 0;
7134}
7135
7136static struct hw_module_methods_t hal_module_methods = {
7137 .open = adev_open,
7138};
7139
7140struct audio_module HAL_MODULE_INFO_SYM = {
7141 .common = {
7142 .tag = HARDWARE_MODULE_TAG,
7143 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
7144 .hal_api_version = HARDWARE_HAL_API_VERSION,
7145 .id = AUDIO_HARDWARE_MODULE_ID,
7146 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08007147 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007148 .methods = &hal_module_methods,
7149 },
7150};