blob: a59e1eaf54d9783910156b55f8be92f16fc777aa [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>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080078#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080079
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053080#ifdef DYNAMIC_LOG_ENABLED
81#include <log_xml_parser.h>
82#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
83#include <log_utils.h>
84#endif
85
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053087/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
88#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070090#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053091#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070093#define PROXY_OPEN_RETRY_COUNT 100
94#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080095
Mingming Yin08c7e312015-03-16 18:10:58 -070096#ifdef USE_LL_AS_PRIMARY_OUTPUT
97#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
98#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
99#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800100#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -0700101#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
102#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800103
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700104#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700105#define DEFAULT_VOIP_BUF_DURATION_MS 20
106#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
107#define DEFAULT_VOIP_SAMP_RATE 48000
108
109#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
110
111struct pcm_config default_pcm_config_voip_copp = {
112 .channels = 1,
113 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
114 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
115 .period_count = 2,
116 .format = PCM_FORMAT_S16_LE,
117};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700118
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700119static unsigned int configured_low_latency_capture_period_size =
120 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
121
Haynes Mathew George16081042017-05-31 17:16:49 -0700122#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
123#define MMAP_PERIOD_COUNT_MIN 32
124#define MMAP_PERIOD_COUNT_MAX 512
125#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
126
Eric Laurentb23d5282013-05-14 15:27:20 -0700127struct pcm_config pcm_config_deep_buffer = {
128 .channels = 2,
129 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
130 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
131 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
134 .stop_threshold = INT_MAX,
135 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
136};
137
138struct pcm_config pcm_config_low_latency = {
139 .channels = 2,
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
141 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
142 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
145 .stop_threshold = INT_MAX,
146 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
147};
148
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700149static int af_period_multiplier = 4;
150struct pcm_config pcm_config_rt = {
151 .channels = 2,
152 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
153 .period_size = ULL_PERIOD_SIZE, //1 ms
154 .period_count = 512, //=> buffer size is 512ms
155 .format = PCM_FORMAT_S16_LE,
156 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
157 .stop_threshold = INT_MAX,
158 .silence_threshold = 0,
159 .silence_size = 0,
160 .avail_min = ULL_PERIOD_SIZE, //1 ms
161};
162
Eric Laurentb23d5282013-05-14 15:27:20 -0700163struct pcm_config pcm_config_hdmi_multi = {
164 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
165 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
166 .period_size = HDMI_MULTI_PERIOD_SIZE,
167 .period_count = HDMI_MULTI_PERIOD_COUNT,
168 .format = PCM_FORMAT_S16_LE,
169 .start_threshold = 0,
170 .stop_threshold = INT_MAX,
171 .avail_min = 0,
172};
173
Haynes Mathew George16081042017-05-31 17:16:49 -0700174struct pcm_config pcm_config_mmap_playback = {
175 .channels = 2,
176 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
177 .period_size = MMAP_PERIOD_SIZE,
178 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = MMAP_PERIOD_SIZE*8,
181 .stop_threshold = INT32_MAX,
182 .silence_threshold = 0,
183 .silence_size = 0,
184 .avail_min = MMAP_PERIOD_SIZE, //1 ms
185};
186
Eric Laurentb23d5282013-05-14 15:27:20 -0700187struct pcm_config pcm_config_audio_capture = {
188 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
190 .format = PCM_FORMAT_S16_LE,
191};
192
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700193struct pcm_config pcm_config_audio_capture_rt = {
194 .channels = 2,
195 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
196 .period_size = ULL_PERIOD_SIZE,
197 .period_count = 512,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = 0,
200 .stop_threshold = INT_MAX,
201 .silence_threshold = 0,
202 .silence_size = 0,
203 .avail_min = ULL_PERIOD_SIZE, //1 ms
204};
205
Haynes Mathew George16081042017-05-31 17:16:49 -0700206struct pcm_config pcm_config_mmap_capture = {
207 .channels = 2,
208 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
209 .period_size = MMAP_PERIOD_SIZE,
210 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
211 .format = PCM_FORMAT_S16_LE,
212 .start_threshold = 0,
213 .stop_threshold = INT_MAX,
214 .silence_threshold = 0,
215 .silence_size = 0,
216 .avail_min = MMAP_PERIOD_SIZE, //1 ms
217};
218
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700219#define AFE_PROXY_CHANNEL_COUNT 2
220#define AFE_PROXY_SAMPLING_RATE 48000
221
222#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
223#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
224
225struct pcm_config pcm_config_afe_proxy_playback = {
226 .channels = AFE_PROXY_CHANNEL_COUNT,
227 .rate = AFE_PROXY_SAMPLING_RATE,
228 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
229 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
232 .stop_threshold = INT_MAX,
233 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234};
235
236#define AFE_PROXY_RECORD_PERIOD_SIZE 768
237#define AFE_PROXY_RECORD_PERIOD_COUNT 4
238
239struct pcm_config pcm_config_afe_proxy_record = {
240 .channels = AFE_PROXY_CHANNEL_COUNT,
241 .rate = AFE_PROXY_SAMPLING_RATE,
242 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
243 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
244 .format = PCM_FORMAT_S16_LE,
245 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
246 .stop_threshold = INT_MAX,
247 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
248};
249
Ashish Jainf1eaa582016-05-23 20:54:24 +0530250#define AUDIO_MAX_PCM_FORMATS 7
251
252const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
253 [AUDIO_FORMAT_DEFAULT] = 0,
254 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
255 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
256 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
257 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
258 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
259 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
260};
261
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800262const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700263 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
264 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700265 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
266 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700267 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700268 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700269 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
270 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
271 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
272 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
273 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
274 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
275 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
276 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700277 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
278 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700279
Eric Laurentb23d5282013-05-14 15:27:20 -0700280 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700281 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530282 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
283 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
284 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700285 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700286 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700287 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
288
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800289 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800290 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700291 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700292
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700293 [USECASE_VOICE2_CALL] = "voice2-call",
294 [USECASE_VOLTE_CALL] = "volte-call",
295 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800296 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800297 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
298 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800299 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700300 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
301 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
302 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800303 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
304 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
305 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
306
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700307 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
308 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700309 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
310 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700311
312 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
313 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700314 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700315
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530316 /* Transcode loopback cases */
317 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700318
319 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
320 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530321 /* For Interactive Audio Streams */
322 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
323 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
324 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
325 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
326 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
327 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
328 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
329 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Eric Laurentb23d5282013-05-14 15:27:20 -0700330};
331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332static const audio_usecase_t offload_usecases[] = {
333 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
335 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
336 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
337 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
338 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
339 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
340 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
341 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700342};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800343
Varun Balaraje49253e2017-07-06 19:48:56 +0530344static const audio_usecase_t interactive_usecases[] = {
345 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
346 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
347 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
348 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
349 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
350 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
351 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
352 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
353};
354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800355#define STRING_TO_ENUM(string) { #string, string }
356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800357struct string_to_enum {
358 const char *name;
359 uint32_t value;
360};
361
362static const struct string_to_enum out_channels_name_to_enum_table[] = {
363 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800364 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
365 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
366 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700367 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800368 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
369 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800370 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
371};
372
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700373static const struct string_to_enum out_formats_name_to_enum_table[] = {
374 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
375 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
376 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700377 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800378 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
379 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700380 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800381};
382
383//list of all supported sample rates by HDMI specification.
384static const int out_hdmi_sample_rates[] = {
385 32000, 44100, 48000, 88200, 96000, 176400, 192000,
386};
387
388static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
389 STRING_TO_ENUM(32000),
390 STRING_TO_ENUM(44100),
391 STRING_TO_ENUM(48000),
392 STRING_TO_ENUM(88200),
393 STRING_TO_ENUM(96000),
394 STRING_TO_ENUM(176400),
395 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700396};
397
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700398static struct audio_device *adev = NULL;
399static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700400static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700401//cache last MBDRC cal step level
402static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700403
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530404static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
405static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
406
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700407static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
408 int flags __unused)
409{
410 int dir = 0;
411 switch (uc_id) {
412 case USECASE_AUDIO_RECORD_LOW_LATENCY:
413 dir = 1;
414 case USECASE_AUDIO_PLAYBACK_ULL:
415 break;
416 default:
417 return false;
418 }
419
420 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
421 PCM_PLAYBACK : PCM_CAPTURE);
422 if (adev->adm_is_noirq_avail)
423 return adev->adm_is_noirq_avail(adev->adm_data,
424 adev->snd_card, dev_id, dir);
425 return false;
426}
427
428static void register_out_stream(struct stream_out *out)
429{
430 struct audio_device *adev = out->dev;
431 if (is_offload_usecase(out->usecase) ||
432 !adev->adm_register_output_stream)
433 return;
434
435 // register stream first for backward compatibility
436 adev->adm_register_output_stream(adev->adm_data,
437 out->handle,
438 out->flags);
439
440 if (!adev->adm_set_config)
441 return;
442
443 if (out->realtime)
444 adev->adm_set_config(adev->adm_data,
445 out->handle,
446 out->pcm, &out->config);
447}
448
449static void register_in_stream(struct stream_in *in)
450{
451 struct audio_device *adev = in->dev;
452 if (!adev->adm_register_input_stream)
453 return;
454
455 adev->adm_register_input_stream(adev->adm_data,
456 in->capture_handle,
457 in->flags);
458
459 if (!adev->adm_set_config)
460 return;
461
462 if (in->realtime)
463 adev->adm_set_config(adev->adm_data,
464 in->capture_handle,
465 in->pcm,
466 &in->config);
467}
468
469static void request_out_focus(struct stream_out *out, long ns)
470{
471 struct audio_device *adev = out->dev;
472
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700473 if (adev->adm_request_focus_v2)
474 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
475 else if (adev->adm_request_focus)
476 adev->adm_request_focus(adev->adm_data, out->handle);
477}
478
479static void request_in_focus(struct stream_in *in, long ns)
480{
481 struct audio_device *adev = in->dev;
482
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700483 if (adev->adm_request_focus_v2)
484 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
485 else if (adev->adm_request_focus)
486 adev->adm_request_focus(adev->adm_data, in->capture_handle);
487}
488
489static void release_out_focus(struct stream_out *out)
490{
491 struct audio_device *adev = out->dev;
492
493 if (adev->adm_abandon_focus)
494 adev->adm_abandon_focus(adev->adm_data, out->handle);
495}
496
497static void release_in_focus(struct stream_in *in)
498{
499 struct audio_device *adev = in->dev;
500 if (adev->adm_abandon_focus)
501 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
502}
503
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530504static int parse_snd_card_status(struct str_parms *parms, int *card,
505 card_status_t *status)
506{
507 char value[32]={0};
508 char state[32]={0};
509
510 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
511 if (ret < 0)
512 return -1;
513
514 // sscanf should be okay as value is of max length 32.
515 // same as sizeof state.
516 if (sscanf(value, "%d,%s", card, state) < 2)
517 return -1;
518
519 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
520 CARD_STATUS_OFFLINE;
521 return 0;
522}
523
vivek mehtaa76401a2015-04-24 14:12:15 -0700524__attribute__ ((visibility ("default")))
525bool audio_hw_send_gain_dep_calibration(int level) {
526 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700527 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700528
529 pthread_mutex_lock(&adev_init_lock);
530
531 if (adev != NULL && adev->platform != NULL) {
532 pthread_mutex_lock(&adev->lock);
533 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700534
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530535 // cache level info for any of the use case which
536 // was not started.
537 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700538
vivek mehtaa76401a2015-04-24 14:12:15 -0700539 pthread_mutex_unlock(&adev->lock);
540 } else {
541 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
542 }
543
544 pthread_mutex_unlock(&adev_init_lock);
545
546 return ret_val;
547}
548
Ashish Jain5106d362016-05-11 19:23:33 +0530549static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
550{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800551 bool gapless_enabled = false;
552 const char *mixer_ctl_name = "Compress Gapless Playback";
553 struct mixer_ctl *ctl;
554
555 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700556 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530557
558 /*Disable gapless if its AV playback*/
559 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800560
561 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
562 if (!ctl) {
563 ALOGE("%s: Could not get ctl for mixer cmd - %s",
564 __func__, mixer_ctl_name);
565 return -EINVAL;
566 }
567
568 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
569 ALOGE("%s: Could not set gapless mode %d",
570 __func__, gapless_enabled);
571 return -EINVAL;
572 }
573 return 0;
574}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700575
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700576__attribute__ ((visibility ("default")))
577int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
578 int table_size) {
579 int ret_val = 0;
580 ALOGV("%s: enter ... ", __func__);
581
582 pthread_mutex_lock(&adev_init_lock);
583 if (adev == NULL) {
584 ALOGW("%s: adev is NULL .... ", __func__);
585 goto done;
586 }
587
588 pthread_mutex_lock(&adev->lock);
589 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
590 pthread_mutex_unlock(&adev->lock);
591done:
592 pthread_mutex_unlock(&adev_init_lock);
593 ALOGV("%s: exit ... ", __func__);
594 return ret_val;
595}
596
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700597static bool is_supported_format(audio_format_t format)
598{
Eric Laurent86e17132013-09-12 17:49:30 -0700599 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530600 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530601 format == AUDIO_FORMAT_AAC_LC ||
602 format == AUDIO_FORMAT_AAC_HE_V1 ||
603 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530604 format == AUDIO_FORMAT_AAC_ADTS_LC ||
605 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
606 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530607 format == AUDIO_FORMAT_AAC_LATM_LC ||
608 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
609 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530610 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
611 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530612 format == AUDIO_FORMAT_PCM_FLOAT ||
613 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700614 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530615 format == AUDIO_FORMAT_AC3 ||
616 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700617 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530618 format == AUDIO_FORMAT_DTS ||
619 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800620 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530621 format == AUDIO_FORMAT_ALAC ||
622 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530623 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530624 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800625 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530626 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700627 format == AUDIO_FORMAT_APTX ||
628 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800629 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700630
631 return false;
632}
633
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700634static inline bool is_mmap_usecase(audio_usecase_t uc_id)
635{
636 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
637 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
638}
639
Avinash Vaish71a8b972014-07-24 15:36:33 +0530640static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
641 struct audio_usecase *uc_info)
642{
643 struct listnode *node;
644 struct audio_usecase *usecase;
645
646 if (uc_info == NULL)
647 return -EINVAL;
648
649 /* Re-route all voice usecases on the shared backend other than the
650 specified usecase to new snd devices */
651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800653 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530654 enable_audio_route(adev, usecase);
655 }
656 return 0;
657}
658
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530659static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530660{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530661 ALOGV("%s", __func__);
662 audio_route_apply_and_update_path(adev->audio_route,
663 "asrc-mode");
664 adev->asrc_mode_enabled = true;
665}
666
667static void disable_asrc_mode(struct audio_device *adev)
668{
669 ALOGV("%s", __func__);
670 audio_route_reset_and_update_path(adev->audio_route,
671 "asrc-mode");
672 adev->asrc_mode_enabled = false;
673}
674
675/*
676 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
677 * 44.1 or Native DSD backends are enabled for any of current use case.
678 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
679 * - Disable current mix path use case(Headphone backend) and re-enable it with
680 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
681 * e.g. Naitve DSD or Headphone 44.1 -> + 48
682 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530683static void check_and_set_asrc_mode(struct audio_device *adev,
684 struct audio_usecase *uc_info,
685 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530686{
687 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530688 int i, num_new_devices = 0;
689 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
690 /*
691 *Split snd device for new combo use case
692 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
693 */
694 if (platform_split_snd_device(adev->platform,
695 snd_device,
696 &num_new_devices,
697 split_new_snd_devices) == 0) {
698 for (i = 0; i < num_new_devices; i++)
699 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
700 } else {
701 int new_backend_idx = platform_get_backend_index(snd_device);
702 if (((new_backend_idx == HEADPHONE_BACKEND) ||
703 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
704 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
705 !adev->asrc_mode_enabled) {
706 struct listnode *node = NULL;
707 struct audio_usecase *uc = NULL;
708 struct stream_out *curr_out = NULL;
709 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
710 int i, num_devices, ret = 0;
711 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530712
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530713 list_for_each(node, &adev->usecase_list) {
714 uc = node_to_item(node, struct audio_usecase, list);
715 curr_out = (struct stream_out*) uc->stream.out;
716 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
717 /*
718 *Split snd device for existing combo use case
719 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
720 */
721 ret = platform_split_snd_device(adev->platform,
722 uc->out_snd_device,
723 &num_devices,
724 split_snd_devices);
725 if (ret < 0 || num_devices == 0) {
726 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
727 split_snd_devices[0] = uc->out_snd_device;
728 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800729 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530730 for (i = 0; i < num_devices; i++) {
731 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
732 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
733 if((new_backend_idx == HEADPHONE_BACKEND) &&
734 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
735 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
736 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
737 __func__);
738 enable_asrc_mode(adev);
739 break;
740 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
741 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
742 (usecase_backend_idx == HEADPHONE_BACKEND)) {
743 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
744 __func__);
745 disable_audio_route(adev, uc);
746 disable_snd_device(adev, uc->out_snd_device);
747 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
748 if (new_backend_idx == DSD_NATIVE_BACKEND)
749 audio_route_apply_and_update_path(adev->audio_route,
750 "hph-true-highquality-mode");
751 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
752 (curr_out->bit_width >= 24))
753 audio_route_apply_and_update_path(adev->audio_route,
754 "hph-highquality-mode");
755 enable_asrc_mode(adev);
756 enable_snd_device(adev, uc->out_snd_device);
757 enable_audio_route(adev, uc);
758 break;
759 }
760 }
761 // reset split devices count
762 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800763 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530764 if (adev->asrc_mode_enabled)
765 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530766 }
767 }
768 }
769}
770
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700771int pcm_ioctl(struct pcm *pcm, int request, ...)
772{
773 va_list ap;
774 void * arg;
775 int pcm_fd = *(int*)pcm;
776
777 va_start(ap, request);
778 arg = va_arg(ap, void *);
779 va_end(ap);
780
781 return ioctl(pcm_fd, request, arg);
782}
783
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700784int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700785 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700788 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530789 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800790
791 if (usecase == NULL)
792 return -EINVAL;
793
794 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
795
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800796 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700797 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800798 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800800
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800801#ifdef DS1_DOLBY_DAP_ENABLED
802 audio_extn_dolby_set_dmid(adev);
803 audio_extn_dolby_set_endpoint(adev);
804#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700805 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700806 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530807 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700808 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530809 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530810 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
811 out = usecase->stream.out;
812 if (out && out->compr)
813 audio_extn_utils_compress_set_clk_rec_mode(usecase);
814 }
815
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800816 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700817 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700818 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700819 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 ALOGV("%s: exit", __func__);
821 return 0;
822}
823
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700824int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700825 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700828 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800829
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530830 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800831 return -EINVAL;
832
833 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 if (usecase->type == PCM_CAPTURE)
835 snd_device = usecase->in_snd_device;
836 else
837 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800838 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700839 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700840 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700841 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700842 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530843 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844 ALOGV("%s: exit", __func__);
845 return 0;
846}
847
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700848int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700849 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530851 int i, num_devices = 0;
852 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700853 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
854
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800855 if (snd_device < SND_DEVICE_MIN ||
856 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800857 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800858 return -EINVAL;
859 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860
861 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700862
863 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
864 ALOGE("%s: Invalid sound device returned", __func__);
865 return -EINVAL;
866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700868 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700869 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 return 0;
871 }
872
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530873
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700874 if (audio_extn_spkr_prot_is_enabled())
875 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700876
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800877 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
878 audio_extn_spkr_prot_is_enabled()) {
879 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700880 adev->snd_dev_ref_cnt[snd_device]--;
881 return -EINVAL;
882 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200883 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800884 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800885 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200886 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800887 return -EINVAL;
888 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700889 } else if (platform_split_snd_device(adev->platform,
890 snd_device,
891 &num_devices,
892 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530893 for (i = 0; i < num_devices; i++) {
894 enable_snd_device(adev, new_snd_devices[i]);
895 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800896 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700897 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530898
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530899
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530900 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
901 (audio_extn_a2dp_start_playback() < 0)) {
902 ALOGE(" fail to configure A2dp control path ");
903 return -EINVAL;
904 }
905
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700906 /* due to the possibility of calibration overwrite between listen
907 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700908 audio_extn_sound_trigger_update_device_status(snd_device,
909 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530910 audio_extn_listen_update_device_status(snd_device,
911 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700912 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700913 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700914 audio_extn_sound_trigger_update_device_status(snd_device,
915 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530916 audio_extn_listen_update_device_status(snd_device,
917 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700918 return -EINVAL;
919 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300920 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700921 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530922
923 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
924 !adev->native_playback_enabled &&
925 audio_is_true_native_stream_active(adev)) {
926 ALOGD("%s: %d: napb: enabling native mode in hardware",
927 __func__, __LINE__);
928 audio_route_apply_and_update_path(adev->audio_route,
929 "true-native-mode");
930 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530931 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 return 0;
934}
935
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700936int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700937 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800938{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530939 int i, num_devices = 0;
940 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700941 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
942
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800943 if (snd_device < SND_DEVICE_MIN ||
944 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800945 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800946 return -EINVAL;
947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
949 ALOGE("%s: device ref cnt is already 0", __func__);
950 return -EINVAL;
951 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700954
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700955 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
956 ALOGE("%s: Invalid sound device returned", __func__);
957 return -EINVAL;
958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700961 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530962
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800963 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
964 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700965 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700966 } else if (platform_split_snd_device(adev->platform,
967 snd_device,
968 &num_devices,
969 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530970 for (i = 0; i < num_devices; i++) {
971 disable_snd_device(adev, new_snd_devices[i]);
972 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300973 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700974 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300975 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700976
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530977 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
978 audio_extn_a2dp_stop_playback();
979
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700980 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530981 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530982 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
983 adev->native_playback_enabled) {
984 ALOGD("%s: %d: napb: disabling native mode in hardware",
985 __func__, __LINE__);
986 audio_route_reset_and_update_path(adev->audio_route,
987 "true-native-mode");
988 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530989 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
990 adev->asrc_mode_enabled) {
991 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530992 disable_asrc_mode(adev);
993 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530994 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530995
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200996 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700997 audio_extn_sound_trigger_update_device_status(snd_device,
998 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530999 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -08001000 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003 return 0;
1004}
1005
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001006/*
1007 legend:
1008 uc - existing usecase
1009 new_uc - new usecase
1010 d1, d11, d2 - SND_DEVICE enums
1011 a1, a2 - corresponding ANDROID device enums
1012 B1, B2 - backend strings
1013
1014case 1
1015 uc->dev d1 (a1) B1
1016 new_uc->dev d1 (a1), d2 (a2) B1, B2
1017
1018 resolution: disable and enable uc->dev on d1
1019
1020case 2
1021 uc->dev d1 (a1) B1
1022 new_uc->dev d11 (a1) B1
1023
1024 resolution: need to switch uc since d1 and d11 are related
1025 (e.g. speaker and voice-speaker)
1026 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1027
1028case 3
1029 uc->dev d1 (a1) B1
1030 new_uc->dev d2 (a2) B2
1031
1032 resolution: no need to switch uc
1033
1034case 4
1035 uc->dev d1 (a1) B1
1036 new_uc->dev d2 (a2) B1
1037
1038 resolution: disable enable uc-dev on d2 since backends match
1039 we cannot enable two streams on two different devices if they
1040 share the same backend. e.g. if offload is on speaker device using
1041 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1042 using the same backend, offload must also be switched to voice-handset.
1043
1044case 5
1045 uc->dev d1 (a1) B1
1046 new_uc->dev d1 (a1), d2 (a2) B1
1047
1048 resolution: disable enable uc-dev on d2 since backends match
1049 we cannot enable two streams on two different devices if they
1050 share the same backend.
1051
1052case 6
1053 uc->dev d1 (a1) B1
1054 new_uc->dev d2 (a1) B2
1055
1056 resolution: no need to switch
1057
1058case 7
1059 uc->dev d1 (a1), d2 (a2) B1, B2
1060 new_uc->dev d1 (a1) B1
1061
1062 resolution: no need to switch
1063
1064*/
1065static snd_device_t derive_playback_snd_device(void * platform,
1066 struct audio_usecase *uc,
1067 struct audio_usecase *new_uc,
1068 snd_device_t new_snd_device)
1069{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301070 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001071
1072 snd_device_t d1 = uc->out_snd_device;
1073 snd_device_t d2 = new_snd_device;
1074
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301075 switch (uc->type) {
1076 case TRANSCODE_LOOPBACK :
1077 a1 = uc->stream.inout->out_config.devices;
1078 a2 = new_uc->stream.inout->out_config.devices;
1079 break;
1080 default :
1081 a1 = uc->stream.out->devices;
1082 a2 = new_uc->stream.out->devices;
1083 break;
1084 }
1085
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001086 // Treat as a special case when a1 and a2 are not disjoint
1087 if ((a1 != a2) && (a1 & a2)) {
1088 snd_device_t d3[2];
1089 int num_devices = 0;
1090 int ret = platform_split_snd_device(platform,
1091 popcount(a1) > 1 ? d1 : d2,
1092 &num_devices,
1093 d3);
1094 if (ret < 0) {
1095 if (ret != -ENOSYS) {
1096 ALOGW("%s failed to split snd_device %d",
1097 __func__,
1098 popcount(a1) > 1 ? d1 : d2);
1099 }
1100 goto end;
1101 }
1102
1103 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1104 // But if it does happen, we need to give priority to d2 if
1105 // the combo devices active on the existing usecase share a backend.
1106 // This is because we cannot have a usecase active on a combo device
1107 // and a new usecase requests one device in this combo pair.
1108 if (platform_check_backends_match(d3[0], d3[1])) {
1109 return d2; // case 5
1110 } else {
1111 return d1; // case 1
1112 }
1113 } else {
1114 if (platform_check_backends_match(d1, d2)) {
1115 return d2; // case 2, 4
1116 } else {
1117 return d1; // case 6, 3
1118 }
1119 }
1120
1121end:
1122 return d2; // return whatever was calculated before.
1123}
1124
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301126 struct audio_usecase *uc_info,
1127 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128{
1129 struct listnode *node;
1130 struct audio_usecase *usecase;
1131 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301132 snd_device_t uc_derive_snd_device;
1133 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001135 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301136 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 /*
1138 * This function is to make sure that all the usecases that are active on
1139 * the hardware codec backend are always routed to any one device that is
1140 * handled by the hardware codec.
1141 * For example, if low-latency and deep-buffer usecases are currently active
1142 * on speaker and out_set_parameters(headset) is received on low-latency
1143 * output, then we have to make sure deep-buffer is also switched to headset,
1144 * because of the limitation that both the devices cannot be enabled
1145 * at the same time as they share the same backend.
1146 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001147 /*
1148 * This call is to check if we need to force routing for a particular stream
1149 * If there is a backend configuration change for the device when a
1150 * new stream starts, then ADM needs to be closed and re-opened with the new
1151 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001152 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001153 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001154 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1155 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301156 /* For a2dp device reconfigure all active sessions
1157 * with new AFE encoder format based on a2dp state
1158 */
1159 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1160 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1161 audio_extn_a2dp_is_force_device_switch()) {
1162 force_routing = true;
1163 force_restart_session = true;
1164 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301165 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1166
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001168 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001169 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1171 switch_device[i] = false;
1172
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001175
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301176 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1177 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301178 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301179 platform_get_snd_device_name(usecase->out_snd_device),
1180 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301181 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1182 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1183 usecase, uc_info, snd_device);
1184 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1185 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1186 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1187 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1188 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1189 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1190 ((force_restart_session) ||
1191 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301192 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1193 __func__, use_case_table[usecase->id],
1194 platform_get_snd_device_name(usecase->out_snd_device));
1195 disable_audio_route(adev, usecase);
1196 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301197 /* Enable existing usecase on derived playback device */
1198 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301199 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301200 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 }
1202 }
1203
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301204 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1205 num_uc_to_switch);
1206
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001207 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001208 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301210 /* Make sure the previous devices to be disabled first and then enable the
1211 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 list_for_each(node, &adev->usecase_list) {
1213 usecase = node_to_item(node, struct audio_usecase, list);
1214 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001215 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 }
1217 }
1218
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001219 list_for_each(node, &adev->usecase_list) {
1220 usecase = node_to_item(node, struct audio_usecase, list);
1221 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301222 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001223 }
1224 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 /* Re-route all the usecases on the shared backend other than the
1227 specified usecase to new snd devices */
1228 list_for_each(node, &adev->usecase_list) {
1229 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301230 /* Update the out_snd_device only before enabling the audio route */
1231 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301232 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301233 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301234 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301235 use_case_table[usecase->id],
1236 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001237 /* Update voc calibration before enabling VoIP route */
1238 if (usecase->type == VOIP_CALL)
1239 status = platform_switch_voice_call_device_post(adev->platform,
1240 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001241 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301242 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301243 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244 }
1245 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001246 }
1247}
1248
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301249static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001250 struct audio_usecase *uc_info,
1251 snd_device_t snd_device)
1252{
1253 struct listnode *node;
1254 struct audio_usecase *usecase;
1255 bool switch_device[AUDIO_USECASE_MAX];
1256 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301257 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001258 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001259
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301260 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1261 snd_device);
1262 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301263
1264 /*
1265 * Make sure out devices is checked against out codec backend device and
1266 * also in devices against in codec backend. Checking out device against in
1267 * codec backend or vice versa causes issues.
1268 */
1269 if (uc_info->type == PCM_CAPTURE)
1270 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001271 /*
1272 * This function is to make sure that all the active capture usecases
1273 * are always routed to the same input sound device.
1274 * For example, if audio-record and voice-call usecases are currently
1275 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1276 * is received for voice call then we have to make sure that audio-record
1277 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1278 * because of the limitation that two devices cannot be enabled
1279 * at the same time if they share the same backend.
1280 */
1281 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1282 switch_device[i] = false;
1283
1284 list_for_each(node, &adev->usecase_list) {
1285 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301286 /*
1287 * TODO: Enhance below condition to handle BT sco/USB multi recording
1288 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001289 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001290 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301291 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301292 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301293 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301294 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001295 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001296 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1297 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001298 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001299 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001300 switch_device[usecase->id] = true;
1301 num_uc_to_switch++;
1302 }
1303 }
1304
1305 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001306 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001307
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301308 /* Make sure the previous devices to be disabled first and then enable the
1309 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001310 list_for_each(node, &adev->usecase_list) {
1311 usecase = node_to_item(node, struct audio_usecase, list);
1312 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001313 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001314 }
1315 }
1316
1317 list_for_each(node, &adev->usecase_list) {
1318 usecase = node_to_item(node, struct audio_usecase, list);
1319 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001320 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001321 }
1322 }
1323
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001324 /* Re-route all the usecases on the shared backend other than the
1325 specified usecase to new snd devices */
1326 list_for_each(node, &adev->usecase_list) {
1327 usecase = node_to_item(node, struct audio_usecase, list);
1328 /* Update the in_snd_device only before enabling the audio route */
1329 if (switch_device[usecase->id] ) {
1330 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001331 if (usecase->type != VOICE_CALL) {
1332 /* Update voc calibration before enabling VoIP route */
1333 if (usecase->type == VOIP_CALL)
1334 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001335 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001336 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301337 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001338 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001339 }
1340 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001341 }
1342}
1343
Mingming Yin3a941d42016-02-17 18:08:05 -08001344static void reset_hdmi_sink_caps(struct stream_out *out) {
1345 int i = 0;
1346
1347 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1348 out->supported_channel_masks[i] = 0;
1349 }
1350 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1351 out->supported_formats[i] = 0;
1352 }
1353 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1354 out->supported_sample_rates[i] = 0;
1355 }
1356}
1357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001359static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001360{
Mingming Yin3a941d42016-02-17 18:08:05 -08001361 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001362 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363
Mingming Yin3a941d42016-02-17 18:08:05 -08001364 reset_hdmi_sink_caps(out);
1365
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001366 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001367 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001368 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001369 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001370 }
1371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001374 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001375 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001376 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1377 case 6:
1378 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1379 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1380 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1381 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1382 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1383 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 break;
1385 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001386 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001387 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 break;
1389 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001390
1391 // check channel format caps
1392 i = 0;
1393 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1394 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1395 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1396 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1397 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1398 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1399 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1400 }
1401
Ben Romberger1aaaf862017-04-06 17:49:46 -07001402 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1403 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1404 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1405 }
1406
Mingming Yin3a941d42016-02-17 18:08:05 -08001407 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1408 ALOGV(":%s HDMI supports DTS format", __func__);
1409 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1410 }
1411
1412 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1413 ALOGV(":%s HDMI supports DTS HD format", __func__);
1414 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1415 }
1416
Naresh Tanniru928f0862017-04-07 16:44:23 -07001417 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1418 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1419 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1420 }
1421
Mingming Yin3a941d42016-02-17 18:08:05 -08001422
1423 // check sample rate caps
1424 i = 0;
1425 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1426 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1427 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1428 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1429 }
1430 }
1431
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001432 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433}
1434
Alexy Josephb1379942016-01-29 15:49:38 -08001435audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001436 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001437{
1438 struct audio_usecase *usecase;
1439 struct listnode *node;
1440
1441 list_for_each(node, &adev->usecase_list) {
1442 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001443 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001444 ALOGV("%s: usecase id %d", __func__, usecase->id);
1445 return usecase->id;
1446 }
1447 }
1448 return USECASE_INVALID;
1449}
1450
Alexy Josephb1379942016-01-29 15:49:38 -08001451struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001452 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001453{
1454 struct audio_usecase *usecase;
1455 struct listnode *node;
1456
1457 list_for_each(node, &adev->usecase_list) {
1458 usecase = node_to_item(node, struct audio_usecase, list);
1459 if (usecase->id == uc_id)
1460 return usecase;
1461 }
1462 return NULL;
1463}
1464
Dhananjay Kumard4833242016-10-06 22:09:12 +05301465struct stream_in *get_next_active_input(const struct audio_device *adev)
1466{
1467 struct audio_usecase *usecase;
1468 struct listnode *node;
1469
1470 list_for_each_reverse(node, &adev->usecase_list) {
1471 usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_CAPTURE)
1473 return usecase->stream.in;
1474 }
1475 return NULL;
1476}
1477
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301478/*
1479 * is a true native playback active
1480 */
1481bool audio_is_true_native_stream_active(struct audio_device *adev)
1482{
1483 bool active = false;
1484 int i = 0;
1485 struct listnode *node;
1486
1487 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1488 ALOGV("%s:napb: not in true mode or non hdphones device",
1489 __func__);
1490 active = false;
1491 goto exit;
1492 }
1493
1494 list_for_each(node, &adev->usecase_list) {
1495 struct audio_usecase *uc;
1496 uc = node_to_item(node, struct audio_usecase, list);
1497 struct stream_out *curr_out =
1498 (struct stream_out*) uc->stream.out;
1499
1500 if (curr_out && PCM_PLAYBACK == uc->type) {
1501 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1502 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1503 uc->id, curr_out->sample_rate,
1504 curr_out->bit_width,
1505 platform_get_snd_device_name(uc->out_snd_device));
1506
1507 if (is_offload_usecase(uc->id) &&
1508 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1509 active = true;
1510 ALOGD("%s:napb:native stream detected", __func__);
1511 }
1512 }
1513 }
1514exit:
1515 return active;
1516}
1517
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301518/*
1519 * if native DSD playback active
1520 */
1521bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1522{
1523 bool active = false;
1524 struct listnode *node = NULL;
1525 struct audio_usecase *uc = NULL;
1526 struct stream_out *curr_out = NULL;
1527
1528 list_for_each(node, &adev->usecase_list) {
1529 uc = node_to_item(node, struct audio_usecase, list);
1530 curr_out = (struct stream_out*) uc->stream.out;
1531
1532 if (curr_out && PCM_PLAYBACK == uc->type &&
1533 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1534 active = true;
1535 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301536 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301537 }
1538 }
1539 return active;
1540}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301541
1542static bool force_device_switch(struct audio_usecase *usecase)
1543{
1544 bool ret = false;
1545 bool is_it_true_mode = false;
1546
1547 if (is_offload_usecase(usecase->id) &&
1548 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001549 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1550 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1551 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301552 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1553 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1554 (!is_it_true_mode && adev->native_playback_enabled)){
1555 ret = true;
1556 ALOGD("napb: time to toggle native mode");
1557 }
1558 }
1559
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301560 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301561 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1562 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301563 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001564 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301565 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301566 ALOGD("Force a2dp device switch to update new encoder config");
1567 ret = true;
1568 }
1569
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301570 return ret;
1571}
1572
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301573bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1574{
1575 bool ret=false;
1576 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1577 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1578 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1579 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1580 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1581 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1582 ret = true;
1583
1584 return ret;
1585}
1586
1587bool is_a2dp_device(snd_device_t out_snd_device)
1588{
1589 bool ret=false;
1590 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1591 ret = true;
1592
1593 return ret;
1594}
1595
1596bool is_bt_soc_on(struct audio_device *adev)
1597{
1598 struct mixer_ctl *ctl;
1599 char *mixer_ctl_name = "BT SOC status";
1600 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1601 bool bt_soc_status = true;
1602 if (!ctl) {
1603 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1604 __func__, mixer_ctl_name);
1605 /*This is to ensure we dont break targets which dont have the kernel change*/
1606 return true;
1607 }
1608 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1609 ALOGD("BT SOC status: %d",bt_soc_status);
1610 return bt_soc_status;
1611}
1612
1613int out_standby_l(struct audio_stream *stream);
1614
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001615int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001617 snd_device_t out_snd_device = SND_DEVICE_NONE;
1618 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 struct audio_usecase *usecase = NULL;
1620 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001621 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001622 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301623 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001624 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301627 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1628
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 usecase = get_usecase_from_list(adev, uc_id);
1630 if (usecase == NULL) {
1631 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1632 return -EINVAL;
1633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001635 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001636 (usecase->type == VOIP_CALL) ||
1637 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301638 if(usecase->stream.out == NULL) {
1639 ALOGE("%s: stream.out is NULL", __func__);
1640 return -EINVAL;
1641 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001642 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001643 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001644 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001645 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301646 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1647 if (usecase->stream.inout == NULL) {
1648 ALOGE("%s: stream.inout is NULL", __func__);
1649 return -EINVAL;
1650 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301651 stream_out.devices = usecase->stream.inout->out_config.devices;
1652 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1653 stream_out.format = usecase->stream.inout->out_config.format;
1654 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1655 out_snd_device = platform_get_output_snd_device(adev->platform,
1656 &stream_out);
1657 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659 } else {
1660 /*
1661 * If the voice call is active, use the sound devices of voice call usecase
1662 * so that it would not result any device switch. All the usecases will
1663 * be switched to new device when select_devices() is called for voice call
1664 * usecase. This is to avoid switching devices for voice call when
1665 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001666 * choose voice call device only if the use case device is
1667 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001669 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001670 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001671 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001672 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1673 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301674 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1675 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001676 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 in_snd_device = vc_usecase->in_snd_device;
1678 out_snd_device = vc_usecase->out_snd_device;
1679 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001680 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001681 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001682 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001683 if ((voip_usecase != NULL) &&
1684 (usecase->type == PCM_PLAYBACK) &&
1685 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001686 out_snd_device_backend_match = platform_check_backends_match(
1687 voip_usecase->out_snd_device,
1688 platform_get_output_snd_device(
1689 adev->platform,
1690 usecase->stream.out));
1691 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001692 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001693 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1694 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001695 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001696 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001697 in_snd_device = voip_usecase->in_snd_device;
1698 out_snd_device = voip_usecase->out_snd_device;
1699 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001700 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001701 hfp_ucid = audio_extn_hfp_get_usecase();
1702 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001703 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001704 in_snd_device = hfp_usecase->in_snd_device;
1705 out_snd_device = hfp_usecase->out_snd_device;
1706 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 }
1708 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301709 if (usecase->stream.out == NULL) {
1710 ALOGE("%s: stream.out is NULL", __func__);
1711 return -EINVAL;
1712 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 usecase->devices = usecase->stream.out->devices;
1714 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001715 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001716 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001717 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001718 if (usecase->stream.out == adev->primary_output &&
1719 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001720 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001721 select_devices(adev, adev->active_input->usecase);
1722 }
1723 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001724 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301725 if (usecase->stream.in == NULL) {
1726 ALOGE("%s: stream.in is NULL", __func__);
1727 return -EINVAL;
1728 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001729 usecase->devices = usecase->stream.in->device;
1730 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001731 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001732 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001733 if (adev->active_input &&
1734 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301735 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1736 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1737 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001738 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001739 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001740 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1741 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001742 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001743 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 }
1746 }
1747
1748 if (out_snd_device == usecase->out_snd_device &&
1749 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301750
1751 if (!force_device_switch(usecase))
1752 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 }
1754
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301755 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1756 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1757 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1758 return 0;
1759 }
1760
sangwoobc677242013-08-08 16:53:43 +09001761 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001762 out_snd_device, platform_get_snd_device_name(out_snd_device),
1763 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 /*
1766 * Limitation: While in call, to do a device switch we need to disable
1767 * and enable both RX and TX devices though one of them is same as current
1768 * device.
1769 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001770 if ((usecase->type == VOICE_CALL) &&
1771 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1772 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001773 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001774 }
1775
1776 if (((usecase->type == VOICE_CALL) ||
1777 (usecase->type == VOIP_CALL)) &&
1778 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1779 /* Disable sidetone only if voice/voip call already exists */
1780 if (voice_is_call_state_active(adev) ||
1781 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001782 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001783
1784 /* Disable aanc only if voice call exists */
1785 if (voice_is_call_state_active(adev))
1786 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001787 }
1788
Zhou Songc66eb7e2017-08-08 18:29:07 +08001789 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301790 (!audio_extn_a2dp_is_ready())) {
1791 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001792 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301793 }
1794
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 /* Disable current sound devices */
1796 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001797 disable_audio_route(adev, usecase);
1798 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 }
1800
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001802 disable_audio_route(adev, usecase);
1803 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 }
1805
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001806 /* Applicable only on the targets that has external modem.
1807 * New device information should be sent to modem before enabling
1808 * the devices to reduce in-call device switch time.
1809 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001810 if ((usecase->type == VOICE_CALL) &&
1811 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1812 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001813 status = platform_switch_voice_call_enable_device_config(adev->platform,
1814 out_snd_device,
1815 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001816 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001817
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001818 /* Enable new sound devices */
1819 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001820 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301821 if (platform_check_codec_asrc_support(adev->platform))
1822 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001823 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 }
1825
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001826 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301827 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001828 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830
Avinash Vaish71a8b972014-07-24 15:36:33 +05301831 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001832 status = platform_switch_voice_call_device_post(adev->platform,
1833 out_snd_device,
1834 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301835 enable_audio_route_for_voice_usecases(adev, usecase);
1836 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001837
sangwoo170731f2013-06-08 15:36:36 +09001838 usecase->in_snd_device = in_snd_device;
1839 usecase->out_snd_device = out_snd_device;
1840
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301841 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1842 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301843 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001844 if ((24 == usecase->stream.out->bit_width) &&
1845 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1846 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1847 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1848 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1849 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1850 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1851 /*
1852 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1853 * configured device sample rate, if not update the COPP rate to be equal to the
1854 * device sample rate, else open COPP at stream sample rate
1855 */
1856 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1857 usecase->stream.out->sample_rate,
1858 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301859 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1860 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001861 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1862 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1863 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1864 }
1865
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001866 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001867 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001868 audio_extn_gef_notify_device_config(
1869 usecase->stream.out->devices,
1870 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001871 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001872 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001873 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301874 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001875 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001876
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001877 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001878 /* Enable aanc only if voice call exists */
1879 if (voice_is_call_state_active(adev))
1880 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1881
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001882 /* Enable sidetone only if other voice/voip call already exists */
1883 if (voice_is_call_state_active(adev) ||
1884 voice_extn_compress_voip_is_started(adev))
1885 voice_set_sidetone(adev, out_snd_device, true);
1886 }
1887
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001888 /* Applicable only on the targets that has external modem.
1889 * Enable device command should be sent to modem only after
1890 * enabling voice call mixer controls
1891 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001892 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001893 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1894 out_snd_device,
1895 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301896
1897 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1898
1899 if (usecase->type == VOIP_CALL) {
1900 if (adev->active_input != NULL &&
1901 !adev->active_input->standby) {
1902 if (is_bt_soc_on(adev) == false){
1903 ALOGD("BT SCO MIC disconnected while in connection");
1904 if (adev->active_input->pcm != NULL)
1905 pcm_stop(adev->active_input->pcm);
1906 }
1907 }
1908 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1909 && usecase->stream.out->started) {
1910 if (is_bt_soc_on(adev) == false) {
1911 ALOGD("BT SCO/A2DP disconnected while in connection");
1912 out_standby_l(&usecase->stream.out->stream.common);
1913 }
1914 }
1915 } else if ((usecase->stream.out != NULL) &&
1916 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1917 usecase->stream.out->started) {
1918 if (is_bt_soc_on(adev) == false) {
1919 ALOGD("BT SCO/A2dp disconnected while in connection");
1920 out_standby_l(&usecase->stream.out->stream.common);
1921 }
1922 }
1923 }
1924
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301925 ALOGD("%s: done",__func__);
1926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 return status;
1928}
1929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930static int stop_input_stream(struct stream_in *in)
1931{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301932 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 struct audio_usecase *uc_info;
1934 struct audio_device *adev = in->dev;
1935
Eric Laurent994a6932013-07-17 11:51:42 -07001936 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001937 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938 uc_info = get_usecase_from_list(adev, in->usecase);
1939 if (uc_info == NULL) {
1940 ALOGE("%s: Could not find the usecase (%d) in the list",
1941 __func__, in->usecase);
1942 return -EINVAL;
1943 }
1944
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001945 /* Close in-call recording streams */
1946 voice_check_and_stop_incall_rec_usecase(adev, in);
1947
Eric Laurent150dbfe2013-02-27 14:31:02 -08001948 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001949 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001950
1951 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001952 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001954 list_remove(&uc_info->list);
1955 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001957 adev->active_input = get_next_active_input(adev);
1958
Eric Laurent994a6932013-07-17 11:51:42 -07001959 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 return ret;
1961}
1962
1963int start_input_stream(struct stream_in *in)
1964{
1965 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001966 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 struct audio_usecase *uc_info;
1968 struct audio_device *adev = in->dev;
1969
Mingming Yin2664a5b2015-09-03 10:53:11 -07001970 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1971 if (get_usecase_from_list(adev, usecase) == NULL)
1972 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301973 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1974 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001975
Naresh Tanniru80659832014-06-04 18:17:56 +05301976
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301977 if (CARD_STATUS_OFFLINE == in->card_status||
1978 CARD_STATUS_OFFLINE == adev->card_status) {
1979 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301980 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301981 goto error_config;
1982 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301983
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301984 if (audio_is_bluetooth_sco_device(in->device)) {
1985 if (!adev->bt_sco_on) {
1986 ALOGE("%s: SCO profile is not ready, return error", __func__);
1987 ret = -EIO;
1988 goto error_config;
1989 }
1990 }
1991
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001992 /* Check if source matches incall recording usecase criteria */
1993 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1994 if (ret)
1995 goto error_config;
1996 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001997 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1998
1999 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2000 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2001 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002002 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002003 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002004
Eric Laurentb23d5282013-05-14 15:27:20 -07002005 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 if (in->pcm_device_id < 0) {
2007 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2008 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002009 ret = -EINVAL;
2010 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002012
2013 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002015
2016 if (!uc_info) {
2017 ret = -ENOMEM;
2018 goto error_config;
2019 }
2020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021 uc_info->id = in->usecase;
2022 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002023 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002024 uc_info->devices = in->device;
2025 uc_info->in_snd_device = SND_DEVICE_NONE;
2026 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002028 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302029 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2030 adev->perf_lock_opts,
2031 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002032 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Haynes Mathew George16081042017-05-31 17:16:49 -07002034 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302035 ret = audio_extn_cin_start_input_stream(in);
2036 if (ret)
2037 goto error_open;
2038 else
2039 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002040 }
2041
Haynes Mathew George16081042017-05-31 17:16:49 -07002042 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002043 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002044 ALOGE("%s: pcm stream not ready", __func__);
2045 goto error_open;
2046 }
2047 ret = pcm_start(in->pcm);
2048 if (ret < 0) {
2049 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2050 goto error_open;
2051 }
2052 } else {
2053 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2054 unsigned int pcm_open_retry_count = 0;
2055
2056 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2057 flags |= PCM_MMAP | PCM_NOIRQ;
2058 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2059 } else if (in->realtime) {
2060 flags |= PCM_MMAP | PCM_NOIRQ;
2061 }
2062
2063 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2064 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2065
2066 while (1) {
2067 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2068 flags, &in->config);
2069 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2070 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2071 if (in->pcm != NULL) {
2072 pcm_close(in->pcm);
2073 in->pcm = NULL;
2074 }
2075 if (pcm_open_retry_count-- == 0) {
2076 ret = -EIO;
2077 goto error_open;
2078 }
2079 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2080 continue;
2081 }
2082 break;
2083 }
2084
2085 ALOGV("%s: pcm_prepare", __func__);
2086 ret = pcm_prepare(in->pcm);
2087 if (ret < 0) {
2088 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2089 pcm_close(in->pcm);
2090 in->pcm = NULL;
2091 goto error_open;
2092 }
2093 register_in_stream(in);
2094 if (in->realtime) {
2095 ret = pcm_start(in->pcm);
2096 if (ret < 0) {
2097 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002098 pcm_close(in->pcm);
2099 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002100 goto error_open;
2101 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002102 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002103 }
2104
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302105done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302106 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002107 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002108
Eric Laurentc8400632013-02-14 19:04:54 -08002109 return ret;
2110
2111error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302112 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002114error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302115 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302116 /*
2117 * sleep 50ms to allow sufficient time for kernel
2118 * drivers to recover incases like SSR.
2119 */
2120 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002121 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002122
2123 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124}
2125
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002126void lock_input_stream(struct stream_in *in)
2127{
2128 pthread_mutex_lock(&in->pre_lock);
2129 pthread_mutex_lock(&in->lock);
2130 pthread_mutex_unlock(&in->pre_lock);
2131}
2132
2133void lock_output_stream(struct stream_out *out)
2134{
2135 pthread_mutex_lock(&out->pre_lock);
2136 pthread_mutex_lock(&out->lock);
2137 pthread_mutex_unlock(&out->pre_lock);
2138}
2139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140/* must be called with out->lock locked */
2141static int send_offload_cmd_l(struct stream_out* out, int command)
2142{
2143 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2144
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002145 if (!cmd) {
2146 ALOGE("failed to allocate mem for command 0x%x", command);
2147 return -ENOMEM;
2148 }
2149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002150 ALOGVV("%s %d", __func__, command);
2151
2152 cmd->cmd = command;
2153 list_add_tail(&out->offload_cmd_list, &cmd->node);
2154 pthread_cond_signal(&out->offload_cond);
2155 return 0;
2156}
2157
2158/* must be called iwth out->lock locked */
2159static void stop_compressed_output_l(struct stream_out *out)
2160{
2161 out->offload_state = OFFLOAD_STATE_IDLE;
2162 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002163 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 if (out->compr != NULL) {
2165 compress_stop(out->compr);
2166 while (out->offload_thread_blocked) {
2167 pthread_cond_wait(&out->cond, &out->lock);
2168 }
2169 }
2170}
2171
Varun Balaraje49253e2017-07-06 19:48:56 +05302172bool is_interactive_usecase(audio_usecase_t uc_id)
2173{
2174 unsigned int i;
2175 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2176 if (uc_id == interactive_usecases[i])
2177 return true;
2178 }
2179 return false;
2180}
2181
2182static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2183{
2184 audio_usecase_t ret_uc = USECASE_INVALID;
2185 unsigned int intract_uc_index;
2186 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2187
2188 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2189 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2190 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2191 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2192 ret_uc = interactive_usecases[intract_uc_index];
2193 break;
2194 }
2195 }
2196
2197 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2198 return ret_uc;
2199}
2200
2201static void free_interactive_usecase(struct audio_device *adev,
2202 audio_usecase_t uc_id)
2203{
2204 unsigned int interact_uc_index;
2205 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2206
2207 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2208 if (interactive_usecases[interact_uc_index] == uc_id) {
2209 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2210 break;
2211 }
2212 }
2213 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2214}
2215
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002216bool is_offload_usecase(audio_usecase_t uc_id)
2217{
2218 unsigned int i;
2219 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2220 if (uc_id == offload_usecases[i])
2221 return true;
2222 }
2223 return false;
2224}
2225
Dhananjay Kumarac341582017-02-23 23:42:25 +05302226static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002227{
vivek mehta446c3962015-09-14 10:57:35 -07002228 audio_usecase_t ret_uc = USECASE_INVALID;
2229 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002230 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002231 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302232 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002233 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2234 else
2235 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002236
vivek mehta446c3962015-09-14 10:57:35 -07002237 pthread_mutex_lock(&adev->lock);
2238 if (get_usecase_from_list(adev, ret_uc) != NULL)
2239 ret_uc = USECASE_INVALID;
2240 pthread_mutex_unlock(&adev->lock);
2241
2242 return ret_uc;
2243 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002244
2245 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002246 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2247 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2248 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2249 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002250 break;
2251 }
2252 }
vivek mehta446c3962015-09-14 10:57:35 -07002253
2254 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2255 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002256}
2257
2258static void free_offload_usecase(struct audio_device *adev,
2259 audio_usecase_t uc_id)
2260{
vivek mehta446c3962015-09-14 10:57:35 -07002261 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002262 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002263
2264 if (!adev->multi_offload_enable)
2265 return;
2266
2267 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2268 if (offload_usecases[offload_uc_index] == uc_id) {
2269 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002270 break;
2271 }
2272 }
2273 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2274}
2275
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276static void *offload_thread_loop(void *context)
2277{
2278 struct stream_out *out = (struct stream_out *) context;
2279 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002280 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2283 set_sched_policy(0, SP_FOREGROUND);
2284 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2285
2286 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002287 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 for (;;) {
2289 struct offload_cmd *cmd = NULL;
2290 stream_callback_event_t event;
2291 bool send_callback = false;
2292
2293 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2294 __func__, list_empty(&out->offload_cmd_list),
2295 out->offload_state);
2296 if (list_empty(&out->offload_cmd_list)) {
2297 ALOGV("%s SLEEPING", __func__);
2298 pthread_cond_wait(&out->offload_cond, &out->lock);
2299 ALOGV("%s RUNNING", __func__);
2300 continue;
2301 }
2302
2303 item = list_head(&out->offload_cmd_list);
2304 cmd = node_to_item(item, struct offload_cmd, node);
2305 list_remove(item);
2306
2307 ALOGVV("%s STATE %d CMD %d out->compr %p",
2308 __func__, out->offload_state, cmd->cmd, out->compr);
2309
2310 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2311 free(cmd);
2312 break;
2313 }
2314
2315 if (out->compr == NULL) {
2316 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002317 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002318 pthread_cond_signal(&out->cond);
2319 continue;
2320 }
2321 out->offload_thread_blocked = true;
2322 pthread_mutex_unlock(&out->lock);
2323 send_callback = false;
2324 switch(cmd->cmd) {
2325 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002326 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002328 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 send_callback = true;
2330 event = STREAM_CBK_EVENT_WRITE_READY;
2331 break;
2332 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002333 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302334 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002335 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302336 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002337 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302338 if (ret < 0)
2339 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302340 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302341 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002342 compress_drain(out->compr);
2343 else
2344 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302345 if (ret != -ENETRESET) {
2346 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302347 pthread_mutex_lock(&out->lock);
2348 out->send_new_metadata = 1;
2349 out->send_next_track_params = true;
2350 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302351 event = STREAM_CBK_EVENT_DRAIN_READY;
2352 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2353 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302354 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 break;
2356 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002357 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002359 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 send_callback = true;
2361 event = STREAM_CBK_EVENT_DRAIN_READY;
2362 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302363 case OFFLOAD_CMD_ERROR:
2364 ALOGD("copl(%p): sending error callback to AF", out);
2365 send_callback = true;
2366 event = STREAM_CBK_EVENT_ERROR;
2367 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 default:
2369 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2370 break;
2371 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002372 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 out->offload_thread_blocked = false;
2374 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002375 if (send_callback && out->client_callback) {
2376 ALOGVV("%s: sending client_callback event %d", __func__, event);
2377 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002378 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 free(cmd);
2380 }
2381
2382 pthread_cond_signal(&out->cond);
2383 while (!list_empty(&out->offload_cmd_list)) {
2384 item = list_head(&out->offload_cmd_list);
2385 list_remove(item);
2386 free(node_to_item(item, struct offload_cmd, node));
2387 }
2388 pthread_mutex_unlock(&out->lock);
2389
2390 return NULL;
2391}
2392
2393static int create_offload_callback_thread(struct stream_out *out)
2394{
2395 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2396 list_init(&out->offload_cmd_list);
2397 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2398 offload_thread_loop, out);
2399 return 0;
2400}
2401
2402static int destroy_offload_callback_thread(struct stream_out *out)
2403{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002404 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 stop_compressed_output_l(out);
2406 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2407
2408 pthread_mutex_unlock(&out->lock);
2409 pthread_join(out->offload_thread, (void **) NULL);
2410 pthread_cond_destroy(&out->offload_cond);
2411
2412 return 0;
2413}
2414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415static int stop_output_stream(struct stream_out *out)
2416{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302417 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418 struct audio_usecase *uc_info;
2419 struct audio_device *adev = out->dev;
2420
Eric Laurent994a6932013-07-17 11:51:42 -07002421 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002422 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 uc_info = get_usecase_from_list(adev, out->usecase);
2424 if (uc_info == NULL) {
2425 ALOGE("%s: Could not find the usecase (%d) in the list",
2426 __func__, out->usecase);
2427 return -EINVAL;
2428 }
2429
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002430 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302431 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002432 if (adev->visualizer_stop_output != NULL)
2433 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002434
2435 audio_extn_dts_remove_state_notifier_node(out->usecase);
2436
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002437 if (adev->offload_effects_stop_output != NULL)
2438 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2439 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002440
Eric Laurent150dbfe2013-02-27 14:31:02 -08002441 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002442 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002443
2444 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002445 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002447 list_remove(&uc_info->list);
2448 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302449 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002450 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302451 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002452 ALOGV("Disable passthrough , reset mixer to pcm");
2453 /* NO_PASSTHROUGH */
2454 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002455 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002456 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2457 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002458
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302459 /* Must be called after removing the usecase from list */
2460 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302461 audio_extn_keep_alive_start();
2462
Naresh Tanniru85819452017-05-04 18:55:45 -07002463 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2464 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2465 if (ret < 0)
2466 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2467 }
2468
Eric Laurent994a6932013-07-17 11:51:42 -07002469 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 return ret;
2471}
2472
2473int start_output_stream(struct stream_out *out)
2474{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 struct audio_usecase *uc_info;
2477 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002478 char mixer_ctl_name[128];
2479 struct mixer_ctl *ctl = NULL;
2480 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302481 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002483 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2484 ret = -EINVAL;
2485 goto error_config;
2486 }
2487
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302488 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2489 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2490 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302491
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302492 if (CARD_STATUS_OFFLINE == out->card_status ||
2493 CARD_STATUS_OFFLINE == adev->card_status) {
2494 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302495 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302496 goto error_config;
2497 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302498
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302499 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2500 if (!audio_extn_a2dp_is_ready()) {
2501 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302502 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302503 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302504 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2505 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2506 ret = -EAGAIN;
2507 goto error_config;
2508 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302509 }
2510 }
2511 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302512 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2513 if (!adev->bt_sco_on) {
2514 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2515 //combo usecase just by pass a2dp
2516 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2517 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2518 } else {
2519 ALOGE("%s: SCO profile is not ready, return error", __func__);
2520 ret = -EAGAIN;
2521 goto error_config;
2522 }
2523 }
2524 }
2525
Eric Laurentb23d5282013-05-14 15:27:20 -07002526 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 if (out->pcm_device_id < 0) {
2528 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2529 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002530 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002531 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 }
2533
2534 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002535
2536 if (!uc_info) {
2537 ret = -ENOMEM;
2538 goto error_config;
2539 }
2540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 uc_info->id = out->usecase;
2542 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002543 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002544 uc_info->devices = out->devices;
2545 uc_info->in_snd_device = SND_DEVICE_NONE;
2546 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002547 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302549 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2550 adev->perf_lock_opts,
2551 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302552
2553 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2554 audio_extn_keep_alive_stop();
2555 if (audio_extn_passthru_is_enabled() &&
2556 audio_extn_passthru_is_passthrough_stream(out)) {
2557 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302558 }
2559 }
2560
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302561 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2562 (!audio_extn_a2dp_is_ready())) {
2563 if (!a2dp_combo) {
2564 check_a2dp_restore_l(adev, out, false);
2565 } else {
2566 audio_devices_t dev = out->devices;
2567 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2568 select_devices(adev, out->usecase);
2569 out->devices = dev;
2570 }
2571 } else {
2572 select_devices(adev, out->usecase);
2573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002575 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2576 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002577
2578 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2579 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2580 ALOGE("%s: pcm stream not ready", __func__);
2581 goto error_open;
2582 }
2583 ret = pcm_start(out->pcm);
2584 if (ret < 0) {
2585 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2586 goto error_open;
2587 }
2588 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002589 unsigned int flags = PCM_OUT;
2590 unsigned int pcm_open_retry_count = 0;
2591 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2592 flags |= PCM_MMAP | PCM_NOIRQ;
2593 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002594 } else if (out->realtime) {
2595 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002596 } else
2597 flags |= PCM_MONOTONIC;
2598
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002599 if ((adev->vr_audio_mode_enabled) &&
2600 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2601 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2602 "PCM_Dev %d Topology", out->pcm_device_id);
2603 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2604 if (!ctl) {
2605 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2606 __func__, mixer_ctl_name);
2607 } else {
2608 //if success use ULLPP
2609 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2610 __func__, mixer_ctl_name, out->pcm_device_id);
2611 //There is a still a possibility that some sessions
2612 // that request for FAST|RAW when 3D audio is active
2613 //can go through ULLPP. Ideally we expects apps to
2614 //listen to audio focus and stop concurrent playback
2615 //Also, we will look for mode flag (voice_in_communication)
2616 //before enabling the realtime flag.
2617 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2618 }
2619 }
2620
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002621 while (1) {
2622 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2623 flags, &out->config);
2624 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2625 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2626 if (out->pcm != NULL) {
2627 pcm_close(out->pcm);
2628 out->pcm = NULL;
2629 }
2630 if (pcm_open_retry_count-- == 0) {
2631 ret = -EIO;
2632 goto error_open;
2633 }
2634 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2635 continue;
2636 }
2637 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002638 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002639
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002640 ALOGV("%s: pcm_prepare", __func__);
2641 if (pcm_is_ready(out->pcm)) {
2642 ret = pcm_prepare(out->pcm);
2643 if (ret < 0) {
2644 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2645 pcm_close(out->pcm);
2646 out->pcm = NULL;
2647 goto error_open;
2648 }
2649 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302650 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302651 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002653 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002654 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302655 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002657 out->compr = compress_open(adev->snd_card,
2658 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 COMPRESS_IN, &out->compr_config);
2660 if (out->compr && !is_compress_ready(out->compr)) {
2661 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2662 compress_close(out->compr);
2663 out->compr = NULL;
2664 ret = -EIO;
2665 goto error_open;
2666 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302667 /* compress_open sends params of the track, so reset the flag here */
2668 out->is_compr_metadata_avail = false;
2669
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002670 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002672
Fred Oh3f43e742015-03-04 18:42:34 -08002673 /* Since small bufs uses blocking writes, a write will be blocked
2674 for the default max poll time (20s) in the event of an SSR.
2675 Reduce the poll time to observe and deal with SSR faster.
2676 */
Ashish Jain5106d362016-05-11 19:23:33 +05302677 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002678 compress_set_max_poll_wait(out->compr, 1000);
2679 }
2680
Manish Dewangan69426c82017-01-30 17:35:36 +05302681 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302682 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302683
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002684 audio_extn_dts_create_state_notifier_node(out->usecase);
2685 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2686 popcount(out->channel_mask),
2687 out->playback_started);
2688
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002689#ifdef DS1_DOLBY_DDP_ENABLED
2690 if (audio_extn_is_dolby_format(out->format))
2691 audio_extn_dolby_send_ddp_endp_params(adev);
2692#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302693 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2694 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002695 if (adev->visualizer_start_output != NULL)
2696 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2697 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302698 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002699 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002702
2703 if (ret == 0) {
2704 register_out_stream(out);
2705 if (out->realtime) {
2706 ret = pcm_start(out->pcm);
2707 if (ret < 0)
2708 goto error_open;
2709 }
2710 }
2711
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302712 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002713 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002714
Naresh Tanniru85819452017-05-04 18:55:45 -07002715 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002716 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002717 if (ret < 0)
2718 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2719 }
2720
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002721 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002722error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302723 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002725error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302726 /*
2727 * sleep 50ms to allow sufficient time for kernel
2728 * drivers to recover incases like SSR.
2729 */
2730 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002731 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732}
2733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734static int check_input_parameters(uint32_t sample_rate,
2735 audio_format_t format,
2736 int channel_count)
2737{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002738 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302740 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2741 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2742 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002743 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302744 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002745
2746 switch (channel_count) {
2747 case 1:
2748 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302749 case 3:
2750 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002751 case 6:
2752 break;
2753 default:
2754 ret = -EINVAL;
2755 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756
2757 switch (sample_rate) {
2758 case 8000:
2759 case 11025:
2760 case 12000:
2761 case 16000:
2762 case 22050:
2763 case 24000:
2764 case 32000:
2765 case 44100:
2766 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302767 case 96000:
2768 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 break;
2770 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002771 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 }
2773
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002774 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775}
2776
2777static size_t get_input_buffer_size(uint32_t sample_rate,
2778 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002779 int channel_count,
2780 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781{
2782 size_t size = 0;
2783
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002784 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2785 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002787 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002788 if (is_low_latency)
2789 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302790
2791 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002793 /* make sure the size is multiple of 32 bytes
2794 * At 48 kHz mono 16-bit PCM:
2795 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2796 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2797 */
2798 size += 0x1f;
2799 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002800
2801 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802}
2803
Ashish Jain058165c2016-09-28 23:18:48 +05302804static size_t get_output_period_size(uint32_t sample_rate,
2805 audio_format_t format,
2806 int channel_count,
2807 int duration /*in millisecs*/)
2808{
2809 size_t size = 0;
2810 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2811
2812 if ((duration == 0) || (sample_rate == 0) ||
2813 (bytes_per_sample == 0) || (channel_count == 0)) {
2814 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2815 bytes_per_sample, channel_count);
2816 return -EINVAL;
2817 }
2818
2819 size = (sample_rate *
2820 duration *
2821 bytes_per_sample *
2822 channel_count) / 1000;
2823 /*
2824 * To have same PCM samples for all channels, the buffer size requires to
2825 * be multiple of (number of channels * bytes per sample)
2826 * For writes to succeed, the buffer must be written at address which is multiple of 32
2827 */
2828 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2829
2830 return (size/(channel_count * bytes_per_sample));
2831}
2832
Ashish Jain5106d362016-05-11 19:23:33 +05302833static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2834{
2835 uint64_t actual_frames_rendered = 0;
2836 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2837
2838 /* This adjustment accounts for buffering after app processor.
2839 * It is based on estimated DSP latency per use case, rather than exact.
2840 */
2841 int64_t platform_latency = platform_render_latency(out->usecase) *
2842 out->sample_rate / 1000000LL;
2843
2844 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2845 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2846 * hence only estimate.
2847 */
2848 int64_t signed_frames = out->written - kernel_buffer_size;
2849
2850 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2851
2852 if (signed_frames > 0)
2853 actual_frames_rendered = signed_frames;
2854
2855 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2856 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2857 (long long int)out->written, (int)kernel_buffer_size,
2858 audio_bytes_per_sample(out->compr_config.codec->format),
2859 popcount(out->channel_mask));
2860
2861 return actual_frames_rendered;
2862}
2863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2865{
2866 struct stream_out *out = (struct stream_out *)stream;
2867
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869}
2870
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002871static int out_set_sample_rate(struct audio_stream *stream __unused,
2872 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873{
2874 return -ENOSYS;
2875}
2876
2877static size_t out_get_buffer_size(const struct audio_stream *stream)
2878{
2879 struct stream_out *out = (struct stream_out *)stream;
2880
Varun Balaraje49253e2017-07-06 19:48:56 +05302881 if (is_interactive_usecase(out->usecase)) {
2882 return out->config.period_size;
2883 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302884 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2885 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2886 else
2887 return out->compr_config.fragment_size;
2888 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002889 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002890 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2891 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 +05302892 else if (is_offload_usecase(out->usecase) &&
2893 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302894 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002896 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002897 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898}
2899
2900static uint32_t out_get_channels(const struct audio_stream *stream)
2901{
2902 struct stream_out *out = (struct stream_out *)stream;
2903
2904 return out->channel_mask;
2905}
2906
2907static audio_format_t out_get_format(const struct audio_stream *stream)
2908{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909 struct stream_out *out = (struct stream_out *)stream;
2910
2911 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912}
2913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002914static int out_set_format(struct audio_stream *stream __unused,
2915 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916{
2917 return -ENOSYS;
2918}
2919
2920static int out_standby(struct audio_stream *stream)
2921{
2922 struct stream_out *out = (struct stream_out *)stream;
2923 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08002924 struct audio_usecase *uc_info;
2925 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07002926 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302928 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2929 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002931 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002933 if (adev->adm_deregister_stream)
2934 adev->adm_deregister_stream(adev->adm_data, out->handle);
2935
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002936 if (is_offload_usecase(out->usecase))
2937 stop_compressed_output_l(out);
2938
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002939 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002941 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2942 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302943 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002944 pthread_mutex_unlock(&adev->lock);
2945 pthread_mutex_unlock(&out->lock);
2946 ALOGD("VOIP output entered standby");
2947 return 0;
2948 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949 if (out->pcm) {
2950 pcm_close(out->pcm);
2951 out->pcm = NULL;
2952 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002953 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2954 do_stop = out->playback_started;
2955 out->playback_started = false;
2956 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002958 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302959 out->send_next_track_params = false;
2960 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002961 out->gapless_mdata.encoder_delay = 0;
2962 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 if (out->compr != NULL) {
2964 compress_close(out->compr);
2965 out->compr = NULL;
2966 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002967 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002968 if (do_stop) {
2969 stop_output_stream(out);
2970 }
kunleiza9d11682017-08-04 14:14:09 +08002971 //restore output device for active usecase when current snd device and output device mismatch
2972 list_for_each(node, &adev->usecase_list) {
2973 uc_info = node_to_item(node, struct audio_usecase, list);
2974 if ((uc_info->type == PCM_PLAYBACK) &&
2975 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
2976 select_devices(adev, uc_info->id);
2977 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002978 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 }
2980 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302981 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 return 0;
2983}
2984
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302985static int out_on_error(struct audio_stream *stream)
2986{
2987 struct stream_out *out = (struct stream_out *)stream;
2988 bool do_standby = false;
2989
2990 lock_output_stream(out);
2991 if (!out->standby) {
2992 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2993 stop_compressed_output_l(out);
2994 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2995 } else
2996 do_standby = true;
2997 }
2998 pthread_mutex_unlock(&out->lock);
2999
3000 if (do_standby)
3001 return out_standby(&out->stream.common);
3002
3003 return 0;
3004}
3005
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303006/*
3007 *standby implementation without locks, assumes that the callee already
3008 *has taken adev and out lock.
3009 */
3010int out_standby_l(struct audio_stream *stream)
3011{
3012 struct stream_out *out = (struct stream_out *)stream;
3013 struct audio_device *adev = out->dev;
3014
3015 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3016 stream, out->usecase, use_case_table[out->usecase]);
3017
3018 if (!out->standby) {
3019 if (adev->adm_deregister_stream)
3020 adev->adm_deregister_stream(adev->adm_data, out->handle);
3021
3022 if (is_offload_usecase(out->usecase))
3023 stop_compressed_output_l(out);
3024
3025 out->standby = true;
3026 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3027 voice_extn_compress_voip_close_output_stream(stream);
3028 out->started = 0;
3029 ALOGD("VOIP output entered standby");
3030 return 0;
3031 } else if (!is_offload_usecase(out->usecase)) {
3032 if (out->pcm) {
3033 pcm_close(out->pcm);
3034 out->pcm = NULL;
3035 }
3036 } else {
3037 ALOGD("copl(%p):standby", out);
3038 out->send_next_track_params = false;
3039 out->is_compr_metadata_avail = false;
3040 out->gapless_mdata.encoder_delay = 0;
3041 out->gapless_mdata.encoder_padding = 0;
3042 if (out->compr != NULL) {
3043 compress_close(out->compr);
3044 out->compr = NULL;
3045 }
3046 }
3047 stop_output_stream(out);
3048 }
3049 ALOGD("%s: exit", __func__);
3050 return 0;
3051}
3052
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003053static int out_dump(const struct audio_stream *stream __unused,
3054 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055{
3056 return 0;
3057}
3058
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003059static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3060{
3061 int ret = 0;
3062 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003063
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003064 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003065 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003066 return -EINVAL;
3067 }
3068
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303069 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003070
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003071 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3072 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303073 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003074 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003075 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3076 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303077 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003078 }
3079
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003080 ALOGV("%s new encoder delay %u and padding %u", __func__,
3081 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3082
3083 return 0;
3084}
3085
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003086static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3087{
3088 return out == adev->primary_output || out == adev->voice_tx_output;
3089}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003090
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303091// note: this call is safe only if the stream_cb is
3092// removed first in close_output_stream (as is done now).
3093static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3094{
3095 if (!stream || !parms)
3096 return;
3097
3098 struct stream_out *out = (struct stream_out *)stream;
3099 struct audio_device *adev = out->dev;
3100
3101 card_status_t status;
3102 int card;
3103 if (parse_snd_card_status(parms, &card, &status) < 0)
3104 return;
3105
3106 pthread_mutex_lock(&adev->lock);
3107 bool valid_cb = (card == adev->snd_card);
3108 pthread_mutex_unlock(&adev->lock);
3109
3110 if (!valid_cb)
3111 return;
3112
3113 lock_output_stream(out);
3114 if (out->card_status != status)
3115 out->card_status = status;
3116 pthread_mutex_unlock(&out->lock);
3117
3118 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3119 use_case_table[out->usecase],
3120 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3121
3122 if (status == CARD_STATUS_OFFLINE)
3123 out_on_error(stream);
3124
3125 return;
3126}
3127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3129{
3130 struct stream_out *out = (struct stream_out *)stream;
3131 struct audio_device *adev = out->dev;
3132 struct str_parms *parms;
3133 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003134 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303135 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136
sangwoobc677242013-08-08 16:53:43 +09003137 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003138 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303140 if (!parms)
3141 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003142 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3143 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003145 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003146 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003148 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003149 * When HDMI cable is unplugged the music playback is paused and
3150 * the policy manager sends routing=0. But the audioflinger continues
3151 * to write data until standby time (3sec). As the HDMI core is
3152 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003153 * Avoid this by routing audio to speaker until standby.
3154 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003155 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3156 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303157 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003158 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3159 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003160 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303161 /*
3162 * When A2DP is disconnected the
3163 * music playback is paused and the policy manager sends routing=0
3164 * But the audioflingercontinues to write data until standby time
3165 * (3sec). As BT is turned off, the write gets blocked.
3166 * Avoid this by routing audio to speaker until standby.
3167 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003168 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303169 (val == AUDIO_DEVICE_NONE)) {
3170 val = AUDIO_DEVICE_OUT_SPEAKER;
3171 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303172 /* To avoid a2dp to sco overlapping / BT device improper state
3173 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303174 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303175 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3176 if (!audio_extn_a2dp_is_ready()) {
3177 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3178 //combo usecase just by pass a2dp
3179 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303180 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303181 } else {
3182 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3183 /* update device to a2dp and don't route as BT returned error
3184 * However it is still possible a2dp routing called because
3185 * of current active device disconnection (like wired headset)
3186 */
3187 out->devices = val;
3188 pthread_mutex_unlock(&out->lock);
3189 pthread_mutex_unlock(&adev->lock);
3190 goto error;
3191 }
3192 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303193 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003194 /*
3195 * select_devices() call below switches all the usecases on the same
3196 * backend to the new device. Refer to check_usecases_codec_backend() in
3197 * the select_devices(). But how do we undo this?
3198 *
3199 * For example, music playback is active on headset (deep-buffer usecase)
3200 * and if we go to ringtones and select a ringtone, low-latency usecase
3201 * will be started on headset+speaker. As we can't enable headset+speaker
3202 * and headset devices at the same time, select_devices() switches the music
3203 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3204 * So when the ringtone playback is completed, how do we undo the same?
3205 *
3206 * We are relying on the out_set_parameters() call on deep-buffer output,
3207 * once the ringtone playback is ended.
3208 * NOTE: We should not check if the current devices are same as new devices.
3209 * Because select_devices() must be called to switch back the music
3210 * playback to headset.
3211 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003212 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003213 audio_devices_t new_dev = val;
3214 bool same_dev = out->devices == new_dev;
3215 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003216
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003217 if (output_drives_call(adev, out)) {
3218 if(!voice_is_in_call(adev)) {
3219 if (adev->mode == AUDIO_MODE_IN_CALL) {
3220 adev->current_call_output = out;
3221 ret = voice_start_call(adev);
3222 }
3223 } else {
3224 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003226 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003227 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003228
3229 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003230 if (!same_dev) {
3231 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303232 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3233 adev->perf_lock_opts,
3234 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003235 if (adev->adm_on_routing_change)
3236 adev->adm_on_routing_change(adev->adm_data,
3237 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003238 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303239 if (!bypass_a2dp) {
3240 select_devices(adev, out->usecase);
3241 } else {
3242 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3243 select_devices(adev, out->usecase);
3244 out->devices = new_dev;
3245 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303246 if (!same_dev)
3247 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303248 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3249 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003250 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303251 pthread_mutex_lock(&out->compr_mute_lock);
3252 out->a2dp_compress_mute = false;
3253 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3254 pthread_mutex_unlock(&out->compr_mute_lock);
3255 }
3256
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003257 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003258 }
3259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003261 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003263
3264 if (out == adev->primary_output) {
3265 pthread_mutex_lock(&adev->lock);
3266 audio_extn_set_parameters(adev, parms);
3267 pthread_mutex_unlock(&adev->lock);
3268 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003269 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003270 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003271 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003272
3273 audio_extn_dts_create_state_notifier_node(out->usecase);
3274 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3275 popcount(out->channel_mask),
3276 out->playback_started);
3277
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003278 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003279 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003280
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303281 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3282 if (err >= 0) {
3283 strlcpy(out->profile, value, sizeof(out->profile));
3284 ALOGV("updating stream profile with value '%s'", out->profile);
3285 lock_output_stream(out);
3286 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3287 &adev->streams_output_cfg_list,
3288 out->devices, out->flags, out->format,
3289 out->sample_rate, out->bit_width,
3290 out->channel_mask, out->profile,
3291 &out->app_type_cfg);
3292 pthread_mutex_unlock(&out->lock);
3293 }
3294
Alexy Joseph98988832017-01-13 14:56:59 -08003295 //suspend, resume handling block
3296 if (out->dynamic_pm_qos_enabled) {
3297 //check suspend parameter only for low latency and if the property
3298 //is enabled
3299 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3300 ALOGI("%s: got suspend_playback %s", __func__, value);
3301 lock_output_stream(out);
3302 if (!strncmp(value, "false", 5)) {
3303 //suspend_playback=false is supposed to set QOS value back to 75%
3304 //the mixer control sent with value Enable will achieve that
3305 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3306 } else if (!strncmp (value, "true", 4)) {
3307 //suspend_playback=true is supposed to remove QOS value
3308 //resetting the mixer control will set the default value
3309 //for the mixer control which is Disable and this removes the QOS vote
3310 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3311 } else {
3312 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3313 " got %s", __func__, value);
3314 ret = -1;
3315 }
3316
3317 if (ret != 0) {
3318 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3319 __func__, out->pm_qos_mixer_path, ret);
3320 }
3321
3322 pthread_mutex_unlock(&out->lock);
3323 }
3324 }
3325 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303327error:
Eric Laurent994a6932013-07-17 11:51:42 -07003328 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 return ret;
3330}
3331
3332static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3333{
3334 struct stream_out *out = (struct stream_out *)stream;
3335 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003336 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 char value[256];
3338 struct str_parms *reply = str_parms_create();
3339 size_t i, j;
3340 int ret;
3341 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003342
3343 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003344 if (reply) {
3345 str_parms_destroy(reply);
3346 }
3347 if (query) {
3348 str_parms_destroy(query);
3349 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003350 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3351 return NULL;
3352 }
3353
Eric Laurent994a6932013-07-17 11:51:42 -07003354 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3356 if (ret >= 0) {
3357 value[0] = '\0';
3358 i = 0;
3359 while (out->supported_channel_masks[i] != 0) {
3360 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3361 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3362 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003363 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003365 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 first = false;
3367 break;
3368 }
3369 }
3370 i++;
3371 }
3372 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3373 str = str_parms_to_str(reply);
3374 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003375 voice_extn_out_get_parameters(out, query, reply);
3376 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003378
Alexy Joseph62142aa2015-11-16 15:10:34 -08003379
3380 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3381 if (ret >= 0) {
3382 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303383 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3384 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003385 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303386 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003387 } else {
3388 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303389 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003390 }
3391 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003392 if (str)
3393 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003394 str = str_parms_to_str(reply);
3395 }
3396
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003397 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3398 if (ret >= 0) {
3399 value[0] = '\0';
3400 i = 0;
3401 first = true;
3402 while (out->supported_formats[i] != 0) {
3403 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3404 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3405 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003406 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003407 }
3408 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3409 first = false;
3410 break;
3411 }
3412 }
3413 i++;
3414 }
3415 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003416 if (str)
3417 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003418 str = str_parms_to_str(reply);
3419 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003420
3421 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3422 if (ret >= 0) {
3423 value[0] = '\0';
3424 i = 0;
3425 first = true;
3426 while (out->supported_sample_rates[i] != 0) {
3427 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3428 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3429 if (!first) {
3430 strlcat(value, "|", sizeof(value));
3431 }
3432 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3433 first = false;
3434 break;
3435 }
3436 }
3437 i++;
3438 }
3439 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3440 if (str)
3441 free(str);
3442 str = str_parms_to_str(reply);
3443 }
3444
Alexy Joseph98988832017-01-13 14:56:59 -08003445 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3446 //only low latency track supports suspend_resume
3447 str_parms_add_int(reply, "supports_hw_suspend",
3448 (out->dynamic_pm_qos_enabled));
3449 if (str)
3450 free(str);
3451 str = str_parms_to_str(reply);
3452 }
3453
3454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 str_parms_destroy(query);
3456 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003457 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 return str;
3459}
3460
3461static uint32_t out_get_latency(const struct audio_stream_out *stream)
3462{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003463 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003465 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466
Alexy Josephaa54c872014-12-03 02:46:47 -08003467 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303468 lock_output_stream(out);
3469 latency = audio_extn_utils_compress_get_dsp_latency(out);
3470 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003471 } else if ((out->realtime) ||
3472 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003473 // since the buffer won't be filled up faster than realtime,
3474 // return a smaller number
3475 if (out->config.rate)
3476 period_ms = (out->af_period_multiplier * out->config.period_size *
3477 1000) / (out->config.rate);
3478 else
3479 period_ms = 0;
3480 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003481 } else {
3482 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003484 }
3485
yidongh0515e042017-07-06 15:00:34 +08003486 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003487 latency += audio_extn_a2dp_get_encoder_latency();
3488
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303489 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003490 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491}
3492
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303493static float AmpToDb(float amplification)
3494{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303495 float db = DSD_VOLUME_MIN_DB;
3496 if (amplification > 0) {
3497 db = 20 * log10(amplification);
3498 if(db < DSD_VOLUME_MIN_DB)
3499 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303500 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303501 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303502}
3503
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303504static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3505 float right)
3506{
3507 struct stream_out *out = (struct stream_out *)stream;
3508 int volume[2];
3509 char mixer_ctl_name[128];
3510 struct audio_device *adev = out->dev;
3511 struct mixer_ctl *ctl;
3512 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3513 PCM_PLAYBACK);
3514
3515 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3516 "Compress Playback %d Volume", pcm_device_id);
3517 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3518 if (!ctl) {
3519 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3520 __func__, mixer_ctl_name);
3521 return -EINVAL;
3522 }
3523 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3524 __func__, mixer_ctl_name, left, right);
3525 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3526 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3527 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3528
3529 return 0;
3530}
3531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532static int out_set_volume(struct audio_stream_out *stream, float left,
3533 float right)
3534{
Eric Laurenta9024de2013-04-04 09:19:12 -07003535 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003536 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303537 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003538
Eric Laurenta9024de2013-04-04 09:19:12 -07003539 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3540 /* only take left channel into account: the API is for stereo anyway */
3541 out->muted = (left == 0.0f);
3542 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003543 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303544 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003545 /*
3546 * Set mute or umute on HDMI passthrough stream.
3547 * Only take left channel into account.
3548 * Mute is 0 and unmute 1
3549 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303550 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303551 } else if (out->format == AUDIO_FORMAT_DSD){
3552 char mixer_ctl_name[128] = "DSD Volume";
3553 struct audio_device *adev = out->dev;
3554 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3555
3556 if (!ctl) {
3557 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3558 __func__, mixer_ctl_name);
3559 return -EINVAL;
3560 }
3561 volume[0] = (int)(AmpToDb(left));
3562 volume[1] = (int)(AmpToDb(right));
3563 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3564 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003565 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303566 pthread_mutex_lock(&out->compr_mute_lock);
3567 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3568 if (!out->a2dp_compress_mute)
3569 ret = out_set_compr_volume(stream, left, right);
3570 out->volume_l = left;
3571 out->volume_r = right;
3572 pthread_mutex_unlock(&out->compr_mute_lock);
3573 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003575 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3576 char mixer_ctl_name[] = "App Type Gain";
3577 struct audio_device *adev = out->dev;
3578 struct mixer_ctl *ctl;
3579 uint32_t set_values[4];
3580
3581 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3582 if (!ctl) {
3583 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3584 __func__, mixer_ctl_name);
3585 return -EINVAL;
3586 }
3587
3588 set_values[0] = 0; //0: Rx Session 1:Tx Session
3589 set_values[1] = out->app_type_cfg.app_type;
3590 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3591 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3592
3593 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3594 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003595 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 return -ENOSYS;
3598}
3599
Zhou Songc9672822017-08-16 16:01:39 +08003600static void update_frames_written(struct stream_out *out, size_t bytes)
3601{
3602 size_t bpf = 0;
3603
3604 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3605 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3606 bpf = 1;
3607 else if (!is_offload_usecase(out->usecase))
3608 bpf = audio_bytes_per_sample(out->format) *
3609 audio_channel_count_from_out_mask(out->channel_mask);
3610 if (bpf != 0)
3611 out->written += bytes / bpf;
3612}
3613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3615 size_t bytes)
3616{
3617 struct stream_out *out = (struct stream_out *)stream;
3618 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003619 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003621 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303622
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303623 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003624
Dhananjay Kumarac341582017-02-23 23:42:25 +05303625 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303626 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303627 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3628 pthread_mutex_unlock(&out->lock);
3629 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303630 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303631 ALOGD(" %s: sound card is not active/SSR state", __func__);
3632 ret= -EIO;
3633 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303634 }
3635 }
3636
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303637 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303638 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303639 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303640 goto exit;
3641 }
3642
Haynes Mathew George16081042017-05-31 17:16:49 -07003643 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3644 ret = -EINVAL;
3645 goto exit;
3646 }
3647
Manish Dewangan37864bc2017-06-09 12:28:37 +05303648 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3649 /*ADD audio_extn_passthru_is_passthrough_stream(out) check*/
3650 if ((audio_extn_passthru_is_enabled()) &&
3651 (!out->is_iec61937_info_available)) {
3652 audio_extn_passthru_update_stream_configuration(adev, out,
3653 buffer, bytes);
3654 out->is_iec61937_info_available = true;
3655 }
3656 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303657
3658 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3659 (audio_extn_a2dp_is_suspended())) {
3660 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3661 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303662 ret = -EIO;
3663 goto exit;
3664 }
3665 }
3666 }
3667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003669 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003670 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003671 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3672 ret = voice_extn_compress_voip_start_output_stream(out);
3673 else
3674 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003675 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003678 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 goto exit;
3680 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303681 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003682 if (last_known_cal_step != -1) {
3683 ALOGD("%s: retry previous failed cal level set", __func__);
3684 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303685 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688
Ashish Jain81eb2a82015-05-13 10:52:34 +05303689 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003690 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303691 adev->is_channel_status_set = true;
3692 }
3693
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003694 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003695 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003696 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003697 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003698 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3699 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303700 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3701 ALOGD("copl(%p):send next track params in gapless", out);
3702 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3703 out->send_next_track_params = false;
3704 out->is_compr_metadata_avail = false;
3705 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003706 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303707 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303708 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003709
Ashish Jain83a6cc22016-06-28 14:34:17 +05303710 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303711 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303712 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303713 pthread_mutex_unlock(&out->lock);
3714 return -EINVAL;
3715 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303716 audio_format_t dst_format = out->hal_op_format;
3717 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303718
3719 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3720 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3721
Ashish Jain83a6cc22016-06-28 14:34:17 +05303722 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303723 dst_format,
3724 buffer,
3725 src_format,
3726 frames);
3727
Ashish Jain83a6cc22016-06-28 14:34:17 +05303728 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303729 bytes_to_write);
3730
3731 /*Convert written bytes in audio flinger format*/
3732 if (ret > 0)
3733 ret = ((ret * format_to_bitwidth_table[out->format]) /
3734 format_to_bitwidth_table[dst_format]);
3735 }
3736 } else
3737 ret = compress_write(out->compr, buffer, bytes);
3738
Zhou Songc9672822017-08-16 16:01:39 +08003739 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
3740 update_frames_written(out, bytes);
3741
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303742 if (ret < 0)
3743 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303744 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303745 /*msg to cb thread only if non blocking write is enabled*/
3746 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303747 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003748 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303749 } else if (-ENETRESET == ret) {
3750 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303751 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303752 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303753 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303754 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755 }
Ashish Jain5106d362016-05-11 19:23:33 +05303756
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303757 /* Call compr start only when non-zero bytes of data is there to be rendered */
3758 if (!out->playback_started && ret > 0) {
3759 int status = compress_start(out->compr);
3760 if (status < 0) {
3761 ret = status;
3762 ALOGE("%s: compr start failed with err %d", __func__, errno);
3763 goto exit;
3764 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003765 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003766 out->playback_started = 1;
3767 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003768
3769 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3770 popcount(out->channel_mask),
3771 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003772 }
3773 pthread_mutex_unlock(&out->lock);
3774 return ret;
3775 } else {
3776 if (out->pcm) {
3777 if (out->muted)
3778 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003779
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303780 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003781
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003782 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003783
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003784 if (out->config.rate)
3785 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3786 out->config.rate;
3787
3788 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3789
3790 request_out_focus(out, ns);
3791
3792 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003793 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003794 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303795 out->convert_buffer != NULL) {
3796
3797 memcpy_by_audio_format(out->convert_buffer,
3798 out->hal_op_format,
3799 buffer,
3800 out->hal_ip_format,
3801 out->config.period_size * out->config.channels);
3802
3803 ret = pcm_write(out->pcm, out->convert_buffer,
3804 (out->config.period_size *
3805 out->config.channels *
3806 format_to_bitwidth_table[out->hal_op_format]));
3807 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303808 /*
3809 * To avoid underrun in DSP when the application is not pumping
3810 * data at required rate, check for the no. of bytes and ignore
3811 * pcm_write if it is less than actual buffer size.
3812 * It is a work around to a change in compress VOIP driver.
3813 */
3814 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3815 bytes < (out->config.period_size * out->config.channels *
3816 audio_bytes_per_sample(out->format))) {
3817 size_t voip_buf_size =
3818 out->config.period_size * out->config.channels *
3819 audio_bytes_per_sample(out->format);
3820 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3821 __func__, bytes, voip_buf_size);
3822 usleep(((uint64_t)voip_buf_size - bytes) *
3823 1000000 / audio_stream_out_frame_size(stream) /
3824 out_get_sample_rate(&out->stream.common));
3825 ret = 0;
3826 } else
3827 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303828 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003829
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003830 release_out_focus(out);
3831
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303832 if (ret < 0)
3833 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08003834 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303835 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 }
3838
3839exit:
Zhou Songc9672822017-08-16 16:01:39 +08003840 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303841 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303842 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303843 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 pthread_mutex_unlock(&out->lock);
3845
3846 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003847 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003848 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303849 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303850 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303851 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303852 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303853 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303854 out->standby = true;
3855 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303856 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303857 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3858 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3859 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 }
3861 return bytes;
3862}
3863
3864static int out_get_render_position(const struct audio_stream_out *stream,
3865 uint32_t *dsp_frames)
3866{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003867 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003868
3869 if (dsp_frames == NULL)
3870 return -EINVAL;
3871
3872 *dsp_frames = 0;
3873 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003874 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303875
3876 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3877 * this operation and adev_close_output_stream(where out gets reset).
3878 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303879 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303880 *dsp_frames = get_actual_pcm_frames_rendered(out);
3881 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3882 return 0;
3883 }
3884
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003885 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303886 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303887 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003888 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303889 if (ret < 0)
3890 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003891 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303892 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003893 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303894 if (-ENETRESET == ret) {
3895 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303896 out->card_status = CARD_STATUS_OFFLINE;
3897 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303898 } else if(ret < 0) {
3899 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303900 ret = -EINVAL;
3901 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303902 /*
3903 * Handle corner case where compress session is closed during SSR
3904 * and timestamp is queried
3905 */
3906 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303907 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303908 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303909 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303910 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303911 pthread_mutex_unlock(&out->lock);
3912 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003913 } else if (audio_is_linear_pcm(out->format)) {
3914 *dsp_frames = out->written;
3915 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003916 } else
3917 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918}
3919
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003920static int out_add_audio_effect(const struct audio_stream *stream __unused,
3921 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922{
3923 return 0;
3924}
3925
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003926static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3927 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928{
3929 return 0;
3930}
3931
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003932static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3933 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303935 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936}
3937
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003938static int out_get_presentation_position(const struct audio_stream_out *stream,
3939 uint64_t *frames, struct timespec *timestamp)
3940{
3941 struct stream_out *out = (struct stream_out *)stream;
3942 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003943 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003944
Ashish Jain5106d362016-05-11 19:23:33 +05303945 /* below piece of code is not guarded against any lock because audioFliner serializes
3946 * this operation and adev_close_output_stream( where out gets reset).
3947 */
3948 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303949 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303950 *frames = get_actual_pcm_frames_rendered(out);
3951 /* this is the best we can do */
3952 clock_gettime(CLOCK_MONOTONIC, timestamp);
3953 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3954 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3955 return 0;
3956 }
3957
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003958 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003959
Ashish Jain5106d362016-05-11 19:23:33 +05303960 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3961 ret = compress_get_tstamp(out->compr, &dsp_frames,
3962 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08003963 // Adjustment accounts for A2dp encoder latency with offload usecases
3964 // Note: Encoder latency is returned in ms.
3965 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3966 unsigned long offset =
3967 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3968 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3969 }
Ashish Jain5106d362016-05-11 19:23:33 +05303970 ALOGVV("%s rendered frames %ld sample_rate %d",
3971 __func__, dsp_frames, out->sample_rate);
3972 *frames = dsp_frames;
3973 if (ret < 0)
3974 ret = -errno;
3975 if (-ENETRESET == ret) {
3976 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303977 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303978 ret = -EINVAL;
3979 } else
3980 ret = 0;
3981 /* this is the best we can do */
3982 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003983 } else {
3984 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003985 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003986 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3987 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003988 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003989 // This adjustment accounts for buffering after app processor.
3990 // It is based on estimated DSP latency per use case, rather than exact.
3991 signed_frames -=
3992 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3993
Aniket Kumar Lataff613152017-07-18 18:19:21 -07003994 // Adjustment accounts for A2dp encoder latency with non offload usecases
3995 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3996 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3997 signed_frames -=
3998 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3999 }
4000
Eric Laurent949a0892013-09-20 09:20:13 -07004001 // It would be unusual for this value to be negative, but check just in case ...
4002 if (signed_frames >= 0) {
4003 *frames = signed_frames;
4004 ret = 0;
4005 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004006 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304007 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304008 *frames = out->written;
4009 clock_gettime(CLOCK_MONOTONIC, timestamp);
4010 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004011 }
4012 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004013 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004014 return ret;
4015}
4016
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004017static int out_set_callback(struct audio_stream_out *stream,
4018 stream_callback_t callback, void *cookie)
4019{
4020 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004021 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004022
4023 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004024 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004025 out->client_callback = callback;
4026 out->client_cookie = cookie;
4027 if (out->adsp_hdlr_stream_handle) {
4028 ret = audio_extn_adsp_hdlr_stream_set_callback(
4029 out->adsp_hdlr_stream_handle,
4030 callback,
4031 cookie);
4032 if (ret)
4033 ALOGW("%s:adsp hdlr callback registration failed %d",
4034 __func__, ret);
4035 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 pthread_mutex_unlock(&out->lock);
4037 return 0;
4038}
4039
4040static int out_pause(struct audio_stream_out* stream)
4041{
4042 struct stream_out *out = (struct stream_out *)stream;
4043 int status = -ENOSYS;
4044 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004045 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004046 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004047 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304049 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304050 status = compress_pause(out->compr);
4051
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004052 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004053
Mingming Yin21854652016-04-13 11:54:02 -07004054 if (audio_extn_passthru_is_active()) {
4055 ALOGV("offload use case, pause passthru");
4056 audio_extn_passthru_on_pause(out);
4057 }
4058
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304059 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004060 audio_extn_dts_notify_playback_state(out->usecase, 0,
4061 out->sample_rate, popcount(out->channel_mask),
4062 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004063 }
4064 pthread_mutex_unlock(&out->lock);
4065 }
4066 return status;
4067}
4068
4069static int out_resume(struct audio_stream_out* stream)
4070{
4071 struct stream_out *out = (struct stream_out *)stream;
4072 int status = -ENOSYS;
4073 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004074 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004075 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004076 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004077 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004078 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304079 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304080 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004081 }
4082 if (!status) {
4083 out->offload_state = OFFLOAD_STATE_PLAYING;
4084 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304085 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004086 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4087 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004088 }
4089 pthread_mutex_unlock(&out->lock);
4090 }
4091 return status;
4092}
4093
4094static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4095{
4096 struct stream_out *out = (struct stream_out *)stream;
4097 int status = -ENOSYS;
4098 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004099 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004100 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4102 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4103 else
4104 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4105 pthread_mutex_unlock(&out->lock);
4106 }
4107 return status;
4108}
4109
4110static int out_flush(struct audio_stream_out* stream)
4111{
4112 struct stream_out *out = (struct stream_out *)stream;
4113 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004114 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004115 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004116 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004117 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4118 stop_compressed_output_l(out);
4119 out->written = 0;
4120 } else {
4121 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4122 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004123 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004124 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004125 return 0;
4126 }
4127 return -ENOSYS;
4128}
4129
Haynes Mathew George16081042017-05-31 17:16:49 -07004130static int out_stop(const struct audio_stream_out* stream)
4131{
4132 struct stream_out *out = (struct stream_out *)stream;
4133 struct audio_device *adev = out->dev;
4134 int ret = -ENOSYS;
4135
4136 ALOGV("%s", __func__);
4137 pthread_mutex_lock(&adev->lock);
4138 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4139 out->playback_started && out->pcm != NULL) {
4140 pcm_stop(out->pcm);
4141 ret = stop_output_stream(out);
4142 out->playback_started = false;
4143 }
4144 pthread_mutex_unlock(&adev->lock);
4145 return ret;
4146}
4147
4148static int out_start(const struct audio_stream_out* stream)
4149{
4150 struct stream_out *out = (struct stream_out *)stream;
4151 struct audio_device *adev = out->dev;
4152 int ret = -ENOSYS;
4153
4154 ALOGV("%s", __func__);
4155 pthread_mutex_lock(&adev->lock);
4156 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4157 !out->playback_started && out->pcm != NULL) {
4158 ret = start_output_stream(out);
4159 if (ret == 0) {
4160 out->playback_started = true;
4161 }
4162 }
4163 pthread_mutex_unlock(&adev->lock);
4164 return ret;
4165}
4166
4167/*
4168 * Modify config->period_count based on min_size_frames
4169 */
4170static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4171{
4172 int periodCountRequested = (min_size_frames + config->period_size - 1)
4173 / config->period_size;
4174 int periodCount = MMAP_PERIOD_COUNT_MIN;
4175
4176 ALOGV("%s original config.period_size = %d config.period_count = %d",
4177 __func__, config->period_size, config->period_count);
4178
4179 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4180 periodCount *= 2;
4181 }
4182 config->period_count = periodCount;
4183
4184 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4185}
4186
4187static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4188 int32_t min_size_frames,
4189 struct audio_mmap_buffer_info *info)
4190{
4191 struct stream_out *out = (struct stream_out *)stream;
4192 struct audio_device *adev = out->dev;
4193 int ret = 0;
4194 unsigned int offset1;
4195 unsigned int frames1;
4196 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004197 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004198
4199 ALOGV("%s", __func__);
4200 pthread_mutex_lock(&adev->lock);
4201
4202 if (info == NULL || min_size_frames == 0) {
4203 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4204 ret = -EINVAL;
4205 goto exit;
4206 }
4207 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4208 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4209 ret = -ENOSYS;
4210 goto exit;
4211 }
4212 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4213 if (out->pcm_device_id < 0) {
4214 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4215 __func__, out->pcm_device_id, out->usecase);
4216 ret = -EINVAL;
4217 goto exit;
4218 }
4219
4220 adjust_mmap_period_count(&out->config, min_size_frames);
4221
4222 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4223 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4224 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4225 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4226 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4227 step = "open";
4228 ret = -ENODEV;
4229 goto exit;
4230 }
4231 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4232 if (ret < 0) {
4233 step = "begin";
4234 goto exit;
4235 }
4236 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4237 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004238 ret = platform_get_mmap_data_fd(adev->platform,
4239 out->pcm_device_id, 0 /*playback*/,
4240 &info->shared_memory_fd,
4241 &mmap_size);
4242 if (ret < 0) {
4243 step = "get_mmap_fd";
4244 goto exit;
4245 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004246 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004247 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004248
4249 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4250 if (ret < 0) {
4251 step = "commit";
4252 goto exit;
4253 }
4254
4255 out->standby = false;
4256 ret = 0;
4257
4258 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4259 __func__, info->shared_memory_address, info->buffer_size_frames);
4260
4261exit:
4262 if (ret != 0) {
4263 if (out->pcm == NULL) {
4264 ALOGE("%s: %s - %d", __func__, step, ret);
4265 } else {
4266 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4267 pcm_close(out->pcm);
4268 out->pcm = NULL;
4269 }
4270 }
4271 pthread_mutex_unlock(&adev->lock);
4272 return ret;
4273}
4274
4275static int out_get_mmap_position(const struct audio_stream_out *stream,
4276 struct audio_mmap_position *position)
4277{
4278 struct stream_out *out = (struct stream_out *)stream;
4279 ALOGVV("%s", __func__);
4280 if (position == NULL) {
4281 return -EINVAL;
4282 }
4283 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4284 return -ENOSYS;
4285 }
4286 if (out->pcm == NULL) {
4287 return -ENOSYS;
4288 }
4289
4290 struct timespec ts = { 0, 0 };
4291 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4292 if (ret < 0) {
4293 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4294 return ret;
4295 }
4296 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4297 return 0;
4298}
4299
4300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301/** audio_stream_in implementation **/
4302static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4303{
4304 struct stream_in *in = (struct stream_in *)stream;
4305
4306 return in->config.rate;
4307}
4308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004309static int in_set_sample_rate(struct audio_stream *stream __unused,
4310 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311{
4312 return -ENOSYS;
4313}
4314
4315static size_t in_get_buffer_size(const struct audio_stream *stream)
4316{
4317 struct stream_in *in = (struct stream_in *)stream;
4318
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004319 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4320 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004321 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4322 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 -07004323 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4324 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304325 else if(audio_extn_cin_attached_usecase(in->usecase))
4326 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004327
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004328 return in->config.period_size * in->af_period_multiplier *
4329 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330}
4331
4332static uint32_t in_get_channels(const struct audio_stream *stream)
4333{
4334 struct stream_in *in = (struct stream_in *)stream;
4335
4336 return in->channel_mask;
4337}
4338
4339static audio_format_t in_get_format(const struct audio_stream *stream)
4340{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004341 struct stream_in *in = (struct stream_in *)stream;
4342
4343 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344}
4345
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004346static int in_set_format(struct audio_stream *stream __unused,
4347 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348{
4349 return -ENOSYS;
4350}
4351
4352static int in_standby(struct audio_stream *stream)
4353{
4354 struct stream_in *in = (struct stream_in *)stream;
4355 struct audio_device *adev = in->dev;
4356 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304357 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4358 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004359 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304360
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004361 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004362 if (!in->standby && in->is_st_session) {
4363 ALOGD("%s: sound trigger pcm stop lab", __func__);
4364 audio_extn_sound_trigger_stop_lab(in);
4365 in->standby = 1;
4366 }
4367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004369 if (adev->adm_deregister_stream)
4370 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4371
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004372 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004374 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
4375 voice_extn_compress_voip_close_input_stream(stream);
4376 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004377 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4378 do_stop = in->capture_started;
4379 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004380 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304381 if (audio_extn_cin_attached_usecase(in->usecase))
4382 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08004383 if (in->pcm) {
4384 pcm_close(in->pcm);
4385 in->pcm = NULL;
4386 }
4387 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004388 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004389 if (in->pcm) {
4390 pcm_close(in->pcm);
4391 in->pcm = NULL;
4392 }
4393
4394 if (do_stop) {
4395 status = stop_input_stream(in);
4396 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004397 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398 }
4399 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004400 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401 return status;
4402}
4403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004404static int in_dump(const struct audio_stream *stream __unused,
4405 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406{
4407 return 0;
4408}
4409
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304410static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4411{
4412 if (!stream || !parms)
4413 return;
4414
4415 struct stream_in *in = (struct stream_in *)stream;
4416 struct audio_device *adev = in->dev;
4417
4418 card_status_t status;
4419 int card;
4420 if (parse_snd_card_status(parms, &card, &status) < 0)
4421 return;
4422
4423 pthread_mutex_lock(&adev->lock);
4424 bool valid_cb = (card == adev->snd_card);
4425 pthread_mutex_unlock(&adev->lock);
4426
4427 if (!valid_cb)
4428 return;
4429
4430 lock_input_stream(in);
4431 if (in->card_status != status)
4432 in->card_status = status;
4433 pthread_mutex_unlock(&in->lock);
4434
4435 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4436 use_case_table[in->usecase],
4437 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4438
4439 // a better solution would be to report error back to AF and let
4440 // it put the stream to standby
4441 if (status == CARD_STATUS_OFFLINE)
4442 in_standby(&in->stream.common);
4443
4444 return;
4445}
4446
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004447static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4448{
4449 struct stream_in *in = (struct stream_in *)stream;
4450 struct audio_device *adev = in->dev;
4451 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004453 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304455 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456 parms = str_parms_create_str(kvpairs);
4457
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304458 if (!parms)
4459 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004460 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004461 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004462
4463 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4464 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 val = atoi(value);
4466 /* no audio source uses val == 0 */
4467 if ((in->source != val) && (val != 0)) {
4468 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004469 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4470 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4471 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004472 (in->config.rate == 8000 || in->config.rate == 16000 ||
4473 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004474 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004475 err = voice_extn_compress_voip_open_input_stream(in);
4476 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004477 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004478 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004479 }
4480 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481 }
4482 }
4483
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004484 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4485 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004486 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004487 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488 in->device = val;
4489 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004490 if (!in->standby && !in->is_st_session) {
4491 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004492 if (adev->adm_on_routing_change)
4493 adev->adm_on_routing_change(adev->adm_data,
4494 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004495 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497 }
4498 }
4499
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304500 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4501 if (err >= 0) {
4502 strlcpy(in->profile, value, sizeof(in->profile));
4503 ALOGV("updating stream profile with value '%s'", in->profile);
4504 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4505 &adev->streams_input_cfg_list,
4506 in->device, in->flags, in->format,
4507 in->sample_rate, in->bit_width,
4508 in->profile, &in->app_type_cfg);
4509 }
4510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004512 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513
4514 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304515error:
Eric Laurent994a6932013-07-17 11:51:42 -07004516 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 return ret;
4518}
4519
4520static char* in_get_parameters(const struct audio_stream *stream,
4521 const char *keys)
4522{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004523 struct stream_in *in = (struct stream_in *)stream;
4524 struct str_parms *query = str_parms_create_str(keys);
4525 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004526 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004527
4528 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004529 if (reply) {
4530 str_parms_destroy(reply);
4531 }
4532 if (query) {
4533 str_parms_destroy(query);
4534 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004535 ALOGE("in_get_parameters: failed to create query or reply");
4536 return NULL;
4537 }
4538
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004539 ALOGV("%s: enter: keys - %s", __func__, keys);
4540
4541 voice_extn_in_get_parameters(in, query, reply);
4542
4543 str = str_parms_to_str(reply);
4544 str_parms_destroy(query);
4545 str_parms_destroy(reply);
4546
4547 ALOGV("%s: exit: returns - %s", __func__, str);
4548 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549}
4550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004551static int in_set_gain(struct audio_stream_in *stream __unused,
4552 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553{
4554 return 0;
4555}
4556
4557static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4558 size_t bytes)
4559{
4560 struct stream_in *in = (struct stream_in *)stream;
4561 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304562 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304563 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004565 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304566
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004567 if (in->is_st_session) {
4568 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4569 /* Read from sound trigger HAL */
4570 audio_extn_sound_trigger_read(in, buffer, bytes);
4571 pthread_mutex_unlock(&in->lock);
4572 return bytes;
4573 }
4574
Haynes Mathew George16081042017-05-31 17:16:49 -07004575 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4576 ret = -ENOSYS;
4577 goto exit;
4578 }
4579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004581 pthread_mutex_lock(&adev->lock);
4582 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4583 ret = voice_extn_compress_voip_start_input_stream(in);
4584 else
4585 ret = start_input_stream(in);
4586 pthread_mutex_unlock(&adev->lock);
4587 if (ret != 0) {
4588 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 }
4590 in->standby = 0;
4591 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004593 // what's the duration requested by the client?
4594 long ns = 0;
4595
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304596 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004597 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4598 in->config.rate;
4599
4600 request_in_focus(in, ns);
4601 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004602
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304603 if (audio_extn_cin_attached_usecase(in->usecase)) {
4604 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4605 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304606 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004607 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304608 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004609 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004610 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004611 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304612 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004613 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304614 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4615 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4616 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4617 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304618 ret = -EINVAL;
4619 goto exit;
4620 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304621 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304622 ret = -errno;
4623 }
4624 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304625 /* bytes read is always set to bytes for non compress usecases */
4626 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627 }
4628
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004629 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 /*
4632 * Instead of writing zeroes here, we could trust the hardware
4633 * to always provide zeroes when muted.
4634 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304635 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4636 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637 memset(buffer, 0, bytes);
4638
4639exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004640 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304641 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 pthread_mutex_unlock(&in->lock);
4643
4644 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304645 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304646 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304647 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304648 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304649 in->standby = true;
4650 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304651 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4652 bytes_read = bytes;
4653 memset(buffer, 0, bytes);
4654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004656 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304657 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304658 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304660 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661}
4662
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004663static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664{
4665 return 0;
4666}
4667
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004668static int add_remove_audio_effect(const struct audio_stream *stream,
4669 effect_handle_t effect,
4670 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004672 struct stream_in *in = (struct stream_in *)stream;
4673 int status = 0;
4674 effect_descriptor_t desc;
4675
4676 status = (*effect)->get_descriptor(effect, &desc);
4677 if (status != 0)
4678 return status;
4679
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004680 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004681 pthread_mutex_lock(&in->dev->lock);
4682 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4683 in->enable_aec != enable &&
4684 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4685 in->enable_aec = enable;
4686 if (!in->standby)
4687 select_devices(in->dev, in->usecase);
4688 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004689 if (in->enable_ns != enable &&
4690 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4691 in->enable_ns = enable;
4692 if (!in->standby)
4693 select_devices(in->dev, in->usecase);
4694 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004695 pthread_mutex_unlock(&in->dev->lock);
4696 pthread_mutex_unlock(&in->lock);
4697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698 return 0;
4699}
4700
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004701static int in_add_audio_effect(const struct audio_stream *stream,
4702 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703{
Eric Laurent994a6932013-07-17 11:51:42 -07004704 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004705 return add_remove_audio_effect(stream, effect, true);
4706}
4707
4708static int in_remove_audio_effect(const struct audio_stream *stream,
4709 effect_handle_t effect)
4710{
Eric Laurent994a6932013-07-17 11:51:42 -07004711 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004712 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713}
4714
Haynes Mathew George16081042017-05-31 17:16:49 -07004715static int in_stop(const struct audio_stream_in* stream)
4716{
4717 struct stream_in *in = (struct stream_in *)stream;
4718 struct audio_device *adev = in->dev;
4719
4720 int ret = -ENOSYS;
4721 ALOGV("%s", __func__);
4722 pthread_mutex_lock(&adev->lock);
4723 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4724 in->capture_started && in->pcm != NULL) {
4725 pcm_stop(in->pcm);
4726 ret = stop_input_stream(in);
4727 in->capture_started = false;
4728 }
4729 pthread_mutex_unlock(&adev->lock);
4730 return ret;
4731}
4732
4733static int in_start(const struct audio_stream_in* stream)
4734{
4735 struct stream_in *in = (struct stream_in *)stream;
4736 struct audio_device *adev = in->dev;
4737 int ret = -ENOSYS;
4738
4739 ALOGV("%s in %p", __func__, in);
4740 pthread_mutex_lock(&adev->lock);
4741 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4742 !in->capture_started && in->pcm != NULL) {
4743 if (!in->capture_started) {
4744 ret = start_input_stream(in);
4745 if (ret == 0) {
4746 in->capture_started = true;
4747 }
4748 }
4749 }
4750 pthread_mutex_unlock(&adev->lock);
4751 return ret;
4752}
4753
4754static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4755 int32_t min_size_frames,
4756 struct audio_mmap_buffer_info *info)
4757{
4758 struct stream_in *in = (struct stream_in *)stream;
4759 struct audio_device *adev = in->dev;
4760 int ret = 0;
4761 unsigned int offset1;
4762 unsigned int frames1;
4763 const char *step = "";
4764
4765 pthread_mutex_lock(&adev->lock);
4766 ALOGV("%s in %p", __func__, in);
4767
4768 if (info == NULL || min_size_frames == 0) {
4769 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4770 ret = -EINVAL;
4771 goto exit;
4772 }
4773 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4774 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4775 ALOGV("%s in %p", __func__, in);
4776 ret = -ENOSYS;
4777 goto exit;
4778 }
4779 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4780 if (in->pcm_device_id < 0) {
4781 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4782 __func__, in->pcm_device_id, in->usecase);
4783 ret = -EINVAL;
4784 goto exit;
4785 }
4786
4787 adjust_mmap_period_count(&in->config, min_size_frames);
4788
4789 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4790 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4791 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4792 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4793 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4794 step = "open";
4795 ret = -ENODEV;
4796 goto exit;
4797 }
4798
4799 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4800 if (ret < 0) {
4801 step = "begin";
4802 goto exit;
4803 }
4804 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4805 info->burst_size_frames = in->config.period_size;
4806 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4807
4808 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4809 info->buffer_size_frames));
4810
4811 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4812 if (ret < 0) {
4813 step = "commit";
4814 goto exit;
4815 }
4816
4817 in->standby = false;
4818 ret = 0;
4819
4820 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4821 __func__, info->shared_memory_address, info->buffer_size_frames);
4822
4823exit:
4824 if (ret != 0) {
4825 if (in->pcm == NULL) {
4826 ALOGE("%s: %s - %d", __func__, step, ret);
4827 } else {
4828 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
4829 pcm_close(in->pcm);
4830 in->pcm = NULL;
4831 }
4832 }
4833 pthread_mutex_unlock(&adev->lock);
4834 return ret;
4835}
4836
4837static int in_get_mmap_position(const struct audio_stream_in *stream,
4838 struct audio_mmap_position *position)
4839{
4840 struct stream_in *in = (struct stream_in *)stream;
4841 ALOGVV("%s", __func__);
4842 if (position == NULL) {
4843 return -EINVAL;
4844 }
4845 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
4846 return -ENOSYS;
4847 }
4848 if (in->pcm == NULL) {
4849 return -ENOSYS;
4850 }
4851 struct timespec ts = { 0, 0 };
4852 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
4853 if (ret < 0) {
4854 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
4855 return ret;
4856 }
4857 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4858 return 0;
4859}
4860
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304861int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07004862 audio_io_handle_t handle,
4863 audio_devices_t devices,
4864 audio_output_flags_t flags,
4865 struct audio_config *config,
4866 struct audio_stream_out **stream_out,
4867 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868{
4869 struct audio_device *adev = (struct audio_device *)dev;
4870 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304871 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004872 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004873 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4878
Mingming Yin3a941d42016-02-17 18:08:05 -08004879 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4880 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304881 devices, flags, &out->stream);
4882
4883
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004884 if (!out) {
4885 return -ENOMEM;
4886 }
4887
Haynes Mathew George204045b2015-02-25 20:32:03 -08004888 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004889 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304890 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004891 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 if (devices == AUDIO_DEVICE_NONE)
4894 devices = AUDIO_DEVICE_OUT_SPEAKER;
4895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896 out->flags = flags;
4897 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004898 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004899 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004900 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304901 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05304902 if (out->channel_mask == AUDIO_CHANNEL_NONE)
4903 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
4904 else
4905 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07004906 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004907 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004908 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304909 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304910 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304911 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08004912 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913
Mingming Yin3a941d42016-02-17 18:08:05 -08004914 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4915 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4916 pthread_mutex_lock(&adev->lock);
4917 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4918 ret = read_hdmi_sink_caps(out);
4919 pthread_mutex_unlock(&adev->lock);
4920 if (ret != 0) {
4921 if (ret == -ENOSYS) {
4922 /* ignore and go with default */
4923 ret = 0;
4924 } else {
4925 ALOGE("error reading hdmi sink caps");
4926 goto error_open;
4927 }
4928 }
4929 }
4930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 /* Init use case and pcm_config */
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004932#ifndef COMPRESS_VOIP_ENABLED
4933 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
4934 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
4935 out->sample_rate == 32000 || out->sample_rate == 48000)) {
4936 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
4937 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
4938 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4939
4940 out->config = default_pcm_config_voip_copp;
4941 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
4942 out->config.rate = out->sample_rate;
4943
4944#else
Dhananjay Kumarac341582017-02-23 23:42:25 +05304945 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004946 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004947 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004948 ret = voice_extn_compress_voip_open_output_stream(out);
4949 if (ret != 0) {
4950 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4951 __func__, ret);
4952 goto error_open;
4953 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004954#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07004955 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304956 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304957 pthread_mutex_lock(&adev->lock);
4958 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4959 pthread_mutex_unlock(&adev->lock);
4960
4961 // reject offload during card offline to allow
4962 // fallback to s/w paths
4963 if (offline) {
4964 ret = -ENODEV;
4965 goto error_open;
4966 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004967
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004968 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4969 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4970 ALOGE("%s: Unsupported Offload information", __func__);
4971 ret = -EINVAL;
4972 goto error_open;
4973 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004974
Mingming Yin3a941d42016-02-17 18:08:05 -08004975 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004976 if(config->offload_info.format == 0)
4977 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004978 if (config->offload_info.sample_rate == 0)
4979 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004980 }
4981
Mingming Yin90310102013-11-13 16:57:00 -08004982 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304983 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004984 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004985 ret = -EINVAL;
4986 goto error_open;
4987 }
4988
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004989 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4990 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4991 (audio_extn_passthru_is_passthrough_stream(out)) &&
4992 !((config->sample_rate == 48000) ||
4993 (config->sample_rate == 96000) ||
4994 (config->sample_rate == 192000))) {
4995 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4996 __func__, config->sample_rate, config->offload_info.format);
4997 ret = -EINVAL;
4998 goto error_open;
4999 }
5000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005001 out->compr_config.codec = (struct snd_codec *)
5002 calloc(1, sizeof(struct snd_codec));
5003
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005004 if (!out->compr_config.codec) {
5005 ret = -ENOMEM;
5006 goto error_open;
5007 }
5008
Dhananjay Kumarac341582017-02-23 23:42:25 +05305009 out->stream.pause = out_pause;
5010 out->stream.resume = out_resume;
5011 out->stream.flush = out_flush;
5012 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005013 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005014 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305015 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005016 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305017 } else {
5018 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5019 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005020 }
vivek mehta446c3962015-09-14 10:57:35 -07005021
5022 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005023 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5024 config->format == 0 && config->sample_rate == 0 &&
5025 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005026 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005027 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5028 } else {
5029 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5030 ret = -EEXIST;
5031 goto error_open;
5032 }
vivek mehta446c3962015-09-14 10:57:35 -07005033 }
5034
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005035 if (config->offload_info.channel_mask)
5036 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005037 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005038 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005039 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005040 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305041 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005042 ret = -EINVAL;
5043 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005044 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005045
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005046 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005047 out->sample_rate = config->offload_info.sample_rate;
5048
Mingming Yin3ee55c62014-08-04 14:23:35 -07005049 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005050
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305051 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
5052 if (audio_extn_is_dolby_format(config->offload_info.format)) {
5053 audio_extn_dolby_send_ddp_endp_params(adev);
5054 audio_extn_dolby_set_dmid(adev);
5055 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005056
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005057 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005058 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005059 out->compr_config.codec->bit_rate =
5060 config->offload_info.bit_rate;
5061 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305062 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005063 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305064 /* Update bit width only for non passthrough usecases.
5065 * For passthrough usecases, the output will always be opened @16 bit
5066 */
5067 if (!audio_extn_passthru_is_passthrough_stream(out))
5068 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305069
5070 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5071 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5072 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5073
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005074 /*TODO: Do we need to change it for passthrough */
5075 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005076
Manish Dewangana6fc5442015-08-24 20:30:31 +05305077 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5078 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305079 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305080 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305081 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5082 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305083
5084 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5085 AUDIO_FORMAT_PCM) {
5086
5087 /*Based on platform support, configure appropriate alsa format for corresponding
5088 *hal input format.
5089 */
5090 out->compr_config.codec->format = hal_format_to_alsa(
5091 config->offload_info.format);
5092
Ashish Jain83a6cc22016-06-28 14:34:17 +05305093 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305094 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305095 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305096
Dhananjay Kumarac341582017-02-23 23:42:25 +05305097 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305098 *hal input format and alsa format might differ based on platform support.
5099 */
5100 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305101 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305102
5103 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5104
5105 /* Check if alsa session is configured with the same format as HAL input format,
5106 * if not then derive correct fragment size needed to accomodate the
5107 * conversion of HAL input format to alsa format.
5108 */
5109 audio_extn_utils_update_direct_pcm_fragment_size(out);
5110
5111 /*if hal input and output fragment size is different this indicates HAL input format is
5112 *not same as the alsa format
5113 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305114 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305115 /*Allocate a buffer to convert input data to the alsa configured format.
5116 *size of convert buffer is equal to the size required to hold one fragment size
5117 *worth of pcm data, this is because flinger does not write more than fragment_size
5118 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305119 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5120 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305121 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5122 ret = -ENOMEM;
5123 goto error_open;
5124 }
5125 }
5126 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5127 out->compr_config.fragment_size =
5128 audio_extn_passthru_get_buffer_size(&config->offload_info);
5129 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5130 } else {
5131 out->compr_config.fragment_size =
5132 platform_get_compress_offload_buffer_size(&config->offload_info);
5133 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5134 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005135
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305136 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5137 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5138 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005139 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305140 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005141
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305142 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5143 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5144 }
5145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005146 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5147 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005148
Manish Dewangan69426c82017-01-30 17:35:36 +05305149 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5150 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5151 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5152 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5153 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5154 } else {
5155 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5156 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005157
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305158 memset(&out->channel_map_param, 0,
5159 sizeof(struct audio_out_channel_map_param));
5160
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005161 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305162 out->send_next_track_params = false;
5163 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005164 out->offload_state = OFFLOAD_STATE_IDLE;
5165 out->playback_started = 0;
5166
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005167 audio_extn_dts_create_state_notifier_node(out->usecase);
5168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005169 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5170 __func__, config->offload_info.version,
5171 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305172
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305173 /* Check if DSD audio format is supported in codec
5174 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305175 */
5176
5177 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305178 (!platform_check_codec_dsd_support(adev->platform) ||
5179 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305180 ret = -EINVAL;
5181 goto error_open;
5182 }
5183
Ashish Jain5106d362016-05-11 19:23:33 +05305184 /* Disable gapless if any of the following is true
5185 * passthrough playback
5186 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305187 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305188 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305189 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305190 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005191 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305192 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305193 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305194 check_and_set_gapless_mode(adev, false);
5195 } else
5196 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005197
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305198 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005199 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5200 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305201 if (config->format == AUDIO_FORMAT_DSD) {
5202 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5203 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5204 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005205
5206 create_offload_callback_thread(out);
5207
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005208 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305209 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005210 if (ret != 0) {
5211 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5212 __func__, ret);
5213 goto error_open;
5214 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005215 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5216 if (config->sample_rate == 0)
5217 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5218 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5219 config->sample_rate != 8000) {
5220 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5221 ret = -EINVAL;
5222 goto error_open;
5223 }
5224 out->sample_rate = config->sample_rate;
5225 out->config.rate = config->sample_rate;
5226 if (config->format == AUDIO_FORMAT_DEFAULT)
5227 config->format = AUDIO_FORMAT_PCM_16_BIT;
5228 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5229 config->format = AUDIO_FORMAT_PCM_16_BIT;
5230 ret = -EINVAL;
5231 goto error_open;
5232 }
5233 out->format = config->format;
5234 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5235 out->config = pcm_config_afe_proxy_playback;
5236 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005237 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305238 unsigned int channels = 0;
5239 /*Update config params to default if not set by the caller*/
5240 if (config->sample_rate == 0)
5241 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5242 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5243 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5244 if (config->format == AUDIO_FORMAT_DEFAULT)
5245 config->format = AUDIO_FORMAT_PCM_16_BIT;
5246
5247 channels = audio_channel_count_from_out_mask(out->channel_mask);
5248
Varun Balaraje49253e2017-07-06 19:48:56 +05305249 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5250 out->usecase = get_interactive_usecase(adev);
5251 out->config = pcm_config_low_latency;
5252 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305253 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005254 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5255 out->flags);
5256 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005257 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5258 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5259 out->config = pcm_config_mmap_playback;
5260 out->stream.start = out_start;
5261 out->stream.stop = out_stop;
5262 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5263 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305264 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5265 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005266 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5267 if (!out->dynamic_pm_qos_enabled) {
5268 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5269 } else {
5270 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5271 //the mixer path will be a string similar to "low-latency-playback resume"
5272 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5273 strlcat(out->pm_qos_mixer_path,
5274 " resume", MAX_MIXER_PATH_LEN);
5275 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5276 out->pm_qos_mixer_path);
5277 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305278 out->config = pcm_config_low_latency;
5279 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5280 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5281 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305282 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5283 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5284 if (out->config.period_size <= 0) {
5285 ALOGE("Invalid configuration period size is not valid");
5286 ret = -EINVAL;
5287 goto error_open;
5288 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305289 } else {
5290 /* primary path is the default path selected if no other outputs are available/suitable */
5291 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5292 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5293 }
5294 out->hal_ip_format = format = out->format;
5295 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5296 out->hal_op_format = pcm_format_to_hal(out->config.format);
5297 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5298 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005299 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305300 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305301 if (out->hal_ip_format != out->hal_op_format) {
5302 uint32_t buffer_size = out->config.period_size *
5303 format_to_bitwidth_table[out->hal_op_format] *
5304 out->config.channels;
5305 out->convert_buffer = calloc(1, buffer_size);
5306 if (out->convert_buffer == NULL){
5307 ALOGE("Allocation failed for convert buffer for size %d",
5308 out->compr_config.fragment_size);
5309 ret = -ENOMEM;
5310 goto error_open;
5311 }
5312 ALOGD("Convert buffer allocated of size %d", buffer_size);
5313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005314 }
5315
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005316 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5317 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305318
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005319 /* TODO remove this hardcoding and check why width is zero*/
5320 if (out->bit_width == 0)
5321 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305322 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005323 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05305324 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305325 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305326 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005327 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5328 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5329 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005330 if(adev->primary_output == NULL)
5331 adev->primary_output = out;
5332 else {
5333 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005334 ret = -EEXIST;
5335 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005336 }
5337 }
5338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339 /* Check if this usecase is already existing */
5340 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005341 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5342 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005343 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005344 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005345 ret = -EEXIST;
5346 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 pthread_mutex_unlock(&adev->lock);
5350
5351 out->stream.common.get_sample_rate = out_get_sample_rate;
5352 out->stream.common.set_sample_rate = out_set_sample_rate;
5353 out->stream.common.get_buffer_size = out_get_buffer_size;
5354 out->stream.common.get_channels = out_get_channels;
5355 out->stream.common.get_format = out_get_format;
5356 out->stream.common.set_format = out_set_format;
5357 out->stream.common.standby = out_standby;
5358 out->stream.common.dump = out_dump;
5359 out->stream.common.set_parameters = out_set_parameters;
5360 out->stream.common.get_parameters = out_get_parameters;
5361 out->stream.common.add_audio_effect = out_add_audio_effect;
5362 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5363 out->stream.get_latency = out_get_latency;
5364 out->stream.set_volume = out_set_volume;
5365 out->stream.write = out_write;
5366 out->stream.get_render_position = out_get_render_position;
5367 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005368 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369
Haynes Mathew George16081042017-05-31 17:16:49 -07005370 if (out->realtime)
5371 out->af_period_multiplier = af_period_multiplier;
5372 else
5373 out->af_period_multiplier = 1;
5374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005376 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005377 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005378
5379 config->format = out->stream.common.get_format(&out->stream.common);
5380 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5381 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5382
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305383 /*
5384 By locking output stream before registering, we allow the callback
5385 to update stream's state only after stream's initial state is set to
5386 adev state.
5387 */
5388 lock_output_stream(out);
5389 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5390 pthread_mutex_lock(&adev->lock);
5391 out->card_status = adev->card_status;
5392 pthread_mutex_unlock(&adev->lock);
5393 pthread_mutex_unlock(&out->lock);
5394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005395 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305396 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005397 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005398
5399 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5400 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5401 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005402 /* setup a channel for client <--> adsp communication for stream events */
5403 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005404 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
5405 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005406 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5407 out->usecase, PCM_PLAYBACK);
5408 hdlr_stream_cfg.flags = out->flags;
5409 hdlr_stream_cfg.type = PCM_PLAYBACK;
5410 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5411 &hdlr_stream_cfg);
5412 if (ret) {
5413 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5414 out->adsp_hdlr_stream_handle = NULL;
5415 }
5416 }
Naresh Tanniru85819452017-05-04 18:55:45 -07005417 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
5418 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
5419 if (ret < 0) {
5420 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5421 out->ip_hdlr_handle = NULL;
5422 }
5423 }
Eric Laurent994a6932013-07-17 11:51:42 -07005424 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005425 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005426
5427error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305428 if (out->convert_buffer)
5429 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005430 free(out);
5431 *stream_out = NULL;
5432 ALOGD("%s: exit: ret %d", __func__, ret);
5433 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005434}
5435
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305436void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005437 struct audio_stream_out *stream)
5438{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005439 struct stream_out *out = (struct stream_out *)stream;
5440 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005441 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005442
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305443 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5444
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305445 // must deregister from sndmonitor first to prevent races
5446 // between the callback and close_stream
5447 audio_extn_snd_mon_unregister_listener(out);
5448
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005449 /* close adsp hdrl session before standby */
5450 if (out->adsp_hdlr_stream_handle) {
5451 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5452 if (ret)
5453 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5454 out->adsp_hdlr_stream_handle = NULL;
5455 }
5456
Naresh Tanniru85819452017-05-04 18:55:45 -07005457 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
5458 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5459 out->ip_hdlr_handle = NULL;
5460 }
5461
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005462 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305463 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005464 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305465 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305466 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005467 if(ret != 0)
5468 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5469 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005470 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005471 out_standby(&stream->common);
5472
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005473 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005474 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005475 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005476 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005477 if (out->compr_config.codec != NULL)
5478 free(out->compr_config.codec);
5479 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005480
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305481 out->a2dp_compress_mute = false;
5482
Varun Balaraje49253e2017-07-06 19:48:56 +05305483 if (is_interactive_usecase(out->usecase))
5484 free_interactive_usecase(adev, out->usecase);
5485
Ashish Jain83a6cc22016-06-28 14:34:17 +05305486 if (out->convert_buffer != NULL) {
5487 free(out->convert_buffer);
5488 out->convert_buffer = NULL;
5489 }
5490
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005491 if (adev->voice_tx_output == out)
5492 adev->voice_tx_output = NULL;
5493
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305494 if (adev->primary_output == out)
5495 adev->primary_output = NULL;
5496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005497 pthread_cond_destroy(&out->cond);
5498 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005500 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005501}
5502
5503static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5504{
5505 struct audio_device *adev = (struct audio_device *)dev;
5506 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005508 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005509 int ret;
5510 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005511
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005512 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305515 if (!parms)
5516 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305517
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305518 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5519 if (ret >= 0) {
5520 /* When set to false, HAL should disable EC and NS */
5521 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5522 adev->bt_sco_on = true;
5523 else
5524 adev->bt_sco_on = false;
5525 }
5526
Naresh Tanniru4c630392014-05-12 01:05:52 +05305527 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005528 status = voice_set_parameters(adev, parms);
5529 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005530 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005532 status = platform_set_parameters(adev->platform, parms);
5533 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005534 goto done;
5535
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005536 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5537 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005538 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005539 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5540 adev->bluetooth_nrec = true;
5541 else
5542 adev->bluetooth_nrec = false;
5543 }
5544
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005545 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5546 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5548 adev->screen_off = false;
5549 else
5550 adev->screen_off = true;
5551 }
5552
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005553 ret = str_parms_get_int(parms, "rotation", &val);
5554 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005555 bool reverse_speakers = false;
5556 switch(val) {
5557 // FIXME: note that the code below assumes that the speakers are in the correct placement
5558 // relative to the user when the device is rotated 90deg from its default rotation. This
5559 // assumption is device-specific, not platform-specific like this code.
5560 case 270:
5561 reverse_speakers = true;
5562 break;
5563 case 0:
5564 case 90:
5565 case 180:
5566 break;
5567 default:
5568 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005569 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005570 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005571 if (status == 0) {
5572 if (adev->speaker_lr_swap != reverse_speakers) {
5573 adev->speaker_lr_swap = reverse_speakers;
5574 // only update the selected device if there is active pcm playback
5575 struct audio_usecase *usecase;
5576 struct listnode *node;
5577 list_for_each(node, &adev->usecase_list) {
5578 usecase = node_to_item(node, struct audio_usecase, list);
5579 if (usecase->type == PCM_PLAYBACK) {
5580 select_devices(adev, usecase->id);
5581 break;
5582 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005583 }
5584 }
5585 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005586 }
5587
Mingming Yin514a8bc2014-07-29 15:22:21 -07005588 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5589 if (ret >= 0) {
5590 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5591 adev->bt_wb_speech_enabled = true;
5592 else
5593 adev->bt_wb_speech_enabled = false;
5594 }
5595
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005596 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5597 if (ret >= 0) {
5598 val = atoi(value);
5599 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005600 ALOGV("cache new ext disp type and edid");
5601 ret = platform_get_ext_disp_type(adev->platform);
5602 if (ret < 0) {
5603 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005604 status = ret;
5605 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005606 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005607 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005608 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005609 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005610 /*
5611 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5612 * Per AudioPolicyManager, USB device is higher priority than WFD.
5613 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5614 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5615 * starting voice call on USB
5616 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005617 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5618 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005619 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5620 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005621 }
vivek mehta344576a2016-04-12 18:56:03 -07005622 ALOGV("detected USB connect .. disable proxy");
5623 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005624 }
5625 }
5626
5627 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5628 if (ret >= 0) {
5629 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005630 /*
5631 * The HDMI / Displayport disconnect handling has been moved to
5632 * audio extension to ensure that its parameters are not
5633 * invalidated prior to updating sysfs of the disconnect event
5634 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5635 */
5636 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005637 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005638 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5639 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305640 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5641 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005642 }
vivek mehta344576a2016-04-12 18:56:03 -07005643 ALOGV("detected USB disconnect .. enable proxy");
5644 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005645 }
5646 }
5647
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305648 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5649 if (ret >= 0) {
5650 struct audio_usecase *usecase;
5651 struct listnode *node;
5652 list_for_each(node, &adev->usecase_list) {
5653 usecase = node_to_item(node, struct audio_usecase, list);
5654 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005655 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305656 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005657
5658 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305659 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005660 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305661 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305662 //force device switch to re configure encoder
5663 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305664 audio_extn_a2dp_set_handoff_mode(false);
5665 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305666 break;
5667 }
5668 }
5669 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005670
5671 //handle vr audio setparam
5672 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5673 value, sizeof(value));
5674 if (ret >= 0) {
5675 ALOGI("Setting vr mode to be %s", value);
5676 if (!strncmp(value, "true", 4)) {
5677 adev->vr_audio_mode_enabled = true;
5678 ALOGI("Setting vr mode to true");
5679 } else if (!strncmp(value, "false", 5)) {
5680 adev->vr_audio_mode_enabled = false;
5681 ALOGI("Setting vr mode to false");
5682 } else {
5683 ALOGI("wrong vr mode set");
5684 }
5685 }
5686
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305687 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005688done:
5689 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005690 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305691error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005692 ALOGV("%s: exit with code(%d)", __func__, status);
5693 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005694}
5695
5696static char* adev_get_parameters(const struct audio_hw_device *dev,
5697 const char *keys)
5698{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005699 struct audio_device *adev = (struct audio_device *)dev;
5700 struct str_parms *reply = str_parms_create();
5701 struct str_parms *query = str_parms_create_str(keys);
5702 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305703 char value[256] = {0};
5704 int ret = 0;
5705
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005706 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005707 if (reply) {
5708 str_parms_destroy(reply);
5709 }
5710 if (query) {
5711 str_parms_destroy(query);
5712 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005713 ALOGE("adev_get_parameters: failed to create query or reply");
5714 return NULL;
5715 }
5716
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005717 //handle vr audio getparam
5718
5719 ret = str_parms_get_str(query,
5720 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5721 value, sizeof(value));
5722
5723 if (ret >= 0) {
5724 bool vr_audio_enabled = false;
5725 pthread_mutex_lock(&adev->lock);
5726 vr_audio_enabled = adev->vr_audio_mode_enabled;
5727 pthread_mutex_unlock(&adev->lock);
5728
5729 ALOGI("getting vr mode to %d", vr_audio_enabled);
5730
5731 if (vr_audio_enabled) {
5732 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5733 "true");
5734 goto exit;
5735 } else {
5736 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5737 "false");
5738 goto exit;
5739 }
5740 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005741
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005742 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005743 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005744 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005745 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305746 pthread_mutex_unlock(&adev->lock);
5747
Naresh Tannirud7205b62014-06-20 02:54:48 +05305748exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005749 str = str_parms_to_str(reply);
5750 str_parms_destroy(query);
5751 str_parms_destroy(reply);
5752
5753 ALOGV("%s: exit: returns - %s", __func__, str);
5754 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005755}
5756
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005757static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005758{
5759 return 0;
5760}
5761
5762static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5763{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005764 int ret;
5765 struct audio_device *adev = (struct audio_device *)dev;
5766 pthread_mutex_lock(&adev->lock);
5767 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005768 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005769 pthread_mutex_unlock(&adev->lock);
5770 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005771}
5772
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005773static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5774 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005775{
5776 return -ENOSYS;
5777}
5778
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005779static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5780 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005781{
5782 return -ENOSYS;
5783}
5784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005785static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5786 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005787{
5788 return -ENOSYS;
5789}
5790
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005791static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5792 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793{
5794 return -ENOSYS;
5795}
5796
5797static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5798{
5799 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005801 pthread_mutex_lock(&adev->lock);
5802 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005803 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005805 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005806 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005807 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005808 adev->current_call_output = NULL;
5809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005810 }
5811 pthread_mutex_unlock(&adev->lock);
5812 return 0;
5813}
5814
5815static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5816{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005817 int ret;
5818
5819 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005820 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005821 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5822 pthread_mutex_unlock(&adev->lock);
5823
5824 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005825}
5826
5827static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5828{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005829 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005830 return 0;
5831}
5832
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005833static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005834 const struct audio_config *config)
5835{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005836 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005837
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005838 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5839 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005840}
5841
5842static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005843 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 audio_devices_t devices,
5845 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005846 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305847 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005848 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005849 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005850{
5851 struct audio_device *adev = (struct audio_device *)dev;
5852 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005853 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005854 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005855 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305856 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005858 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305859 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5860 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005861 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005863
5864 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005865
5866 if (!in) {
5867 ALOGE("failed to allocate input stream");
5868 return -ENOMEM;
5869 }
5870
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305871 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305872 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5873 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005874 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005875 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005877 in->stream.common.get_sample_rate = in_get_sample_rate;
5878 in->stream.common.set_sample_rate = in_set_sample_rate;
5879 in->stream.common.get_buffer_size = in_get_buffer_size;
5880 in->stream.common.get_channels = in_get_channels;
5881 in->stream.common.get_format = in_get_format;
5882 in->stream.common.set_format = in_set_format;
5883 in->stream.common.standby = in_standby;
5884 in->stream.common.dump = in_dump;
5885 in->stream.common.set_parameters = in_set_parameters;
5886 in->stream.common.get_parameters = in_get_parameters;
5887 in->stream.common.add_audio_effect = in_add_audio_effect;
5888 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5889 in->stream.set_gain = in_set_gain;
5890 in->stream.read = in_read;
5891 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5892
5893 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005894 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005895 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005896 in->standby = 1;
5897 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005898 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005899 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305901 in->usecase = USECASE_AUDIO_RECORD;
5902 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07005903 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305904 is_low_latency = true;
5905#if LOW_LATENCY_CAPTURE_USE_CASE
5906 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5907#endif
5908 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5909 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005910 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07005911 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5912 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
5913 in->realtime = 0;
5914 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5915 in->config = pcm_config_mmap_capture;
5916 in->stream.start = in_start;
5917 in->stream.stop = in_stop;
5918 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5919 in->stream.get_mmap_position = in_get_mmap_position;
5920 in->af_period_multiplier = 1;
5921 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
5922 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005923 in->config = pcm_config_audio_capture_rt;
5924 in->sample_rate = in->config.rate;
5925 in->af_period_multiplier = af_period_multiplier;
5926 } else {
5927 in->config = pcm_config_audio_capture;
5928 in->config.rate = config->sample_rate;
5929 in->sample_rate = config->sample_rate;
5930 in->af_period_multiplier = 1;
5931 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305932 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305934 /* restrict 24 bit capture for unprocessed source only
5935 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5936 */
5937 if (config->format == AUDIO_FORMAT_DEFAULT) {
5938 config->format = AUDIO_FORMAT_PCM_16_BIT;
5939 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5940 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5941 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5942 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5943 bool ret_error = false;
5944 in->bit_width = 24;
5945 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5946 from HAL is 24_packed and 8_24
5947 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5948 24_packed return error indicating supported format is 24_packed
5949 *> In case of any other source requesting 24 bit or float return error
5950 indicating format supported is 16 bit only.
5951
5952 on error flinger will retry with supported format passed
5953 */
5954 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5955 (source != AUDIO_SOURCE_CAMCORDER)) {
5956 config->format = AUDIO_FORMAT_PCM_16_BIT;
5957 if (config->sample_rate > 48000)
5958 config->sample_rate = 48000;
5959 ret_error = true;
5960 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5961 in->config.format = PCM_FORMAT_S24_3LE;
5962 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5963 in->config.format = PCM_FORMAT_S24_LE;
5964 } else {
5965 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5966 ret_error = true;
5967 }
5968
5969 if (ret_error) {
5970 ret = -EINVAL;
5971 goto err_open;
5972 }
5973 }
5974
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305975 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305976 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5977 (adev->mode != AUDIO_MODE_IN_CALL)) {
5978 ret = -EINVAL;
5979 goto err_open;
5980 }
5981
5982 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5983 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005984 if (config->sample_rate == 0)
5985 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5986 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5987 config->sample_rate != 8000) {
5988 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5989 ret = -EINVAL;
5990 goto err_open;
5991 }
5992 if (config->format == AUDIO_FORMAT_DEFAULT)
5993 config->format = AUDIO_FORMAT_PCM_16_BIT;
5994 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5995 config->format = AUDIO_FORMAT_PCM_16_BIT;
5996 ret = -EINVAL;
5997 goto err_open;
5998 }
5999
6000 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6001 in->config = pcm_config_afe_proxy_record;
6002 in->config.channels = channel_count;
6003 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306004 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306005 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6006 in, config, &channel_mask_updated)) {
6007 if (channel_mask_updated == true) {
6008 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6009 __func__, config->channel_mask);
6010 ret = -EINVAL;
6011 goto err_open;
6012 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05306013 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006014 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006015 audio_extn_compr_cap_format_supported(config->format) &&
6016 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006017 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306018 } else if (audio_extn_cin_applicable_stream(in)) {
6019 ret = audio_extn_cin_configure_input_stream(in);
6020 if (ret)
6021 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006022 } else {
6023 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006024 if (!in->realtime) {
6025 in->format = config->format;
6026 frame_size = audio_stream_in_frame_size(&in->stream);
6027 buffer_size = get_input_buffer_size(config->sample_rate,
6028 config->format,
6029 channel_count,
6030 is_low_latency);
6031 in->config.period_size = buffer_size / frame_size;
6032 }
6033
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006034#ifndef COMPRESS_VOIP_ENABLED
6035 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6036 (in->config.rate == 8000 || in->config.rate == 16000 ||
6037 in->config.rate == 32000 || in->config.rate == 48000) &&
6038 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6039
6040 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6041 in->config = default_pcm_config_voip_copp;
6042 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6043 in->config.rate = in->sample_rate;
6044#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006045 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006046 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6047 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006048 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006049 (in->config.rate == 8000 || in->config.rate == 16000 ||
6050 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006051 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6052 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006053#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006054 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006055 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006056
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306057 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6058 &adev->streams_input_cfg_list,
6059 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306060 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306061
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006062 /* This stream could be for sound trigger lab,
6063 get sound trigger pcm if present */
6064 audio_extn_sound_trigger_check_and_get_session(in);
6065
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306066 lock_input_stream(in);
6067 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6068 pthread_mutex_lock(&adev->lock);
6069 in->card_status = adev->card_status;
6070 pthread_mutex_unlock(&adev->lock);
6071 pthread_mutex_unlock(&in->lock);
6072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006073 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006074 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006075 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006076
6077err_open:
6078 free(in);
6079 *stream_in = NULL;
6080 return ret;
6081}
6082
6083static void adev_close_input_stream(struct audio_hw_device *dev,
6084 struct audio_stream_in *stream)
6085{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006086 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006087 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006088 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306089
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306090 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006091
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306092 // must deregister from sndmonitor first to prevent races
6093 // between the callback and close_stream
6094 audio_extn_snd_mon_unregister_listener(stream);
6095
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306096 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006097 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306098
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006099 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306100 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006101 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306102 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006103 if (ret != 0)
6104 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6105 __func__, ret);
6106 } else
6107 in_standby(&stream->common);
6108
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006109 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006110 audio_extn_ssr_deinit();
6111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006112
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306113 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006114 audio_extn_compr_cap_format_supported(in->config.format))
6115 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306116
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306117 if (audio_extn_cin_attached_usecase(in->usecase))
6118 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006119
Mingming Yinfd7607b2016-01-22 12:48:44 -08006120 if (in->is_st_session) {
6121 ALOGV("%s: sound trigger pcm stop lab", __func__);
6122 audio_extn_sound_trigger_stop_lab(in);
6123 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006124 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006125 return;
6126}
6127
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306128int adev_create_audio_patch(struct audio_hw_device *dev,
6129 unsigned int num_sources,
6130 const struct audio_port_config *sources,
6131 unsigned int num_sinks,
6132 const struct audio_port_config *sinks,
6133 audio_patch_handle_t *handle)
6134{
6135
6136
6137 return audio_extn_hw_loopback_create_audio_patch(dev,
6138 num_sources,
6139 sources,
6140 num_sinks,
6141 sinks,
6142 handle);
6143
6144}
6145
6146int adev_release_audio_patch(struct audio_hw_device *dev,
6147 audio_patch_handle_t handle)
6148{
6149 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6150}
6151
6152int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6153{
6154 return audio_extn_hw_loopback_get_audio_port(dev, config);
6155}
6156
6157int adev_set_audio_port_config(struct audio_hw_device *dev,
6158 const struct audio_port_config *config)
6159{
6160 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6161}
6162
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006163static int adev_dump(const audio_hw_device_t *device __unused,
6164 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006165{
6166 return 0;
6167}
6168
6169static int adev_close(hw_device_t *device)
6170{
6171 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006172
6173 if (!adev)
6174 return 0;
6175
6176 pthread_mutex_lock(&adev_init_lock);
6177
6178 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306179 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006180 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006181 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306182 audio_extn_utils_release_streams_cfg_lists(
6183 &adev->streams_output_cfg_list,
6184 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306185 if (audio_extn_qaf_is_enabled())
6186 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006187 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006188 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006189 free(adev->snd_dev_ref_cnt);
6190 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006191 if (adev->adm_deinit)
6192 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306193 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006194 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306195 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306196 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306197 if (adev->device_cfg_params) {
6198 free(adev->device_cfg_params);
6199 adev->device_cfg_params = NULL;
6200 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006201 free(device);
6202 adev = NULL;
6203 }
6204 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006206 return 0;
6207}
6208
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006209/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6210 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6211 * just that it _might_ work.
6212 */
6213static int period_size_is_plausible_for_low_latency(int period_size)
6214{
6215 switch (period_size) {
6216 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006217 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006218 case 240:
6219 case 320:
6220 case 480:
6221 return 1;
6222 default:
6223 return 0;
6224 }
6225}
6226
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306227static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6228{
6229 bool is_snd_card_status = false;
6230 bool is_ext_device_status = false;
6231 char value[32];
6232 int card = -1;
6233 card_status_t status;
6234
6235 if (cookie != adev || !parms)
6236 return;
6237
6238 if (!parse_snd_card_status(parms, &card, &status)) {
6239 is_snd_card_status = true;
6240 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6241 is_ext_device_status = true;
6242 } else {
6243 // not a valid event
6244 return;
6245 }
6246
6247 pthread_mutex_lock(&adev->lock);
6248 if (card == adev->snd_card || is_ext_device_status) {
6249 if (is_snd_card_status && adev->card_status != status) {
6250 adev->card_status = status;
6251 platform_snd_card_update(adev->platform, status);
6252 audio_extn_fm_set_parameters(adev, parms);
6253 } else if (is_ext_device_status) {
6254 platform_set_parameters(adev->platform, parms);
6255 }
6256 }
6257 pthread_mutex_unlock(&adev->lock);
6258 return;
6259}
6260
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306261/* out and adev lock held */
6262static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6263{
6264 struct audio_usecase *uc_info;
6265 float left_p;
6266 float right_p;
6267 audio_devices_t devices;
6268
6269 uc_info = get_usecase_from_list(adev, out->usecase);
6270 if (uc_info == NULL) {
6271 ALOGE("%s: Could not find the usecase (%d) in the list",
6272 __func__, out->usecase);
6273 return -EINVAL;
6274 }
6275
6276 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6277 out->usecase, use_case_table[out->usecase]);
6278
6279 if (restore) {
6280 // restore A2DP device for active usecases and unmute if required
6281 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6282 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6283 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6284 select_devices(adev, uc_info->id);
6285 pthread_mutex_lock(&out->compr_mute_lock);
6286 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6287 (out->a2dp_compress_mute)) {
6288 out->a2dp_compress_mute = false;
6289 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6290 }
6291 pthread_mutex_unlock(&out->compr_mute_lock);
6292 }
6293 } else {
6294 // mute compress stream if suspended
6295 pthread_mutex_lock(&out->compr_mute_lock);
6296 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6297 (!out->a2dp_compress_mute)) {
6298 if (!out->standby) {
6299 ALOGD("%s: selecting speaker and muting stream", __func__);
6300 devices = out->devices;
6301 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6302 left_p = out->volume_l;
6303 right_p = out->volume_r;
6304 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6305 compress_pause(out->compr);
6306 out_set_compr_volume(&out->stream, (float)0, (float)0);
6307 out->a2dp_compress_mute = true;
6308 select_devices(adev, out->usecase);
6309 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6310 compress_resume(out->compr);
6311 out->devices = devices;
6312 out->volume_l = left_p;
6313 out->volume_r = right_p;
6314 }
6315 }
6316 pthread_mutex_unlock(&out->compr_mute_lock);
6317 }
6318 ALOGV("%s: exit", __func__);
6319 return 0;
6320}
6321
6322int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6323{
6324 int ret = 0;
6325
6326 lock_output_stream(out);
6327 pthread_mutex_lock(&adev->lock);
6328
6329 ret = check_a2dp_restore_l(adev, out, restore);
6330
6331 pthread_mutex_unlock(&adev->lock);
6332 pthread_mutex_unlock(&out->lock);
6333 return ret;
6334}
6335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006336static int adev_open(const hw_module_t *module, const char *name,
6337 hw_device_t **device)
6338{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306339 int ret;
6340
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006341 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006342 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6343
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006344 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006345 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006346 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006347 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006348 ALOGD("%s: returning existing instance of adev", __func__);
6349 ALOGD("%s: exit", __func__);
6350 pthread_mutex_unlock(&adev_init_lock);
6351 return 0;
6352 }
6353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006354 adev = calloc(1, sizeof(struct audio_device));
6355
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006356 if (!adev) {
6357 pthread_mutex_unlock(&adev_init_lock);
6358 return -ENOMEM;
6359 }
6360
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006361 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6362
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306363#ifdef DYNAMIC_LOG_ENABLED
6364 register_for_dynamic_logging("hal");
6365#endif
6366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006367 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6368 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6369 adev->device.common.module = (struct hw_module_t *)module;
6370 adev->device.common.close = adev_close;
6371
6372 adev->device.init_check = adev_init_check;
6373 adev->device.set_voice_volume = adev_set_voice_volume;
6374 adev->device.set_master_volume = adev_set_master_volume;
6375 adev->device.get_master_volume = adev_get_master_volume;
6376 adev->device.set_master_mute = adev_set_master_mute;
6377 adev->device.get_master_mute = adev_get_master_mute;
6378 adev->device.set_mode = adev_set_mode;
6379 adev->device.set_mic_mute = adev_set_mic_mute;
6380 adev->device.get_mic_mute = adev_get_mic_mute;
6381 adev->device.set_parameters = adev_set_parameters;
6382 adev->device.get_parameters = adev_get_parameters;
6383 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6384 adev->device.open_output_stream = adev_open_output_stream;
6385 adev->device.close_output_stream = adev_close_output_stream;
6386 adev->device.open_input_stream = adev_open_input_stream;
6387 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306388 adev->device.create_audio_patch = adev_create_audio_patch;
6389 adev->device.release_audio_patch = adev_release_audio_patch;
6390 adev->device.get_audio_port = adev_get_audio_port;
6391 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392 adev->device.dump = adev_dump;
6393
6394 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006395 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006396 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006397 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006398 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006399 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006400 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006401 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306402 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006403 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006404 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006405 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006406 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006407 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006408 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306409 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306410 adev->perf_lock_opts[0] = 0x101;
6411 adev->perf_lock_opts[1] = 0x20E;
6412 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006414 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006415 adev->platform = platform_init(adev);
6416 if (!adev->platform) {
6417 free(adev->snd_dev_ref_cnt);
6418 free(adev);
6419 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6420 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006421 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306422 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006423 return -EINVAL;
6424 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006425
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306426 if (audio_extn_qaf_is_enabled()) {
6427 ret = audio_extn_qaf_init(adev);
6428 if (ret < 0) {
6429 free(adev);
6430 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6431 *device = NULL;
6432 pthread_mutex_unlock(&adev_init_lock);
6433 pthread_mutex_destroy(&adev->lock);
6434 return ret;
6435 }
6436
6437 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6438 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6439 }
6440
Eric Laurentc4aef752013-09-12 17:45:53 -07006441 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6442 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6443 if (adev->visualizer_lib == NULL) {
6444 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6445 } else {
6446 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6447 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006448 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006449 "visualizer_hal_start_output");
6450 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006451 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006452 "visualizer_hal_stop_output");
6453 }
6454 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306455 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006456 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006457 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306458 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006459
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006460 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6461 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6462 if (adev->offload_effects_lib == NULL) {
6463 ALOGE("%s: DLOPEN failed for %s", __func__,
6464 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6465 } else {
6466 ALOGV("%s: DLOPEN successful for %s", __func__,
6467 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6468 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306469 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006470 "offload_effects_bundle_hal_start_output");
6471 adev->offload_effects_stop_output =
6472 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6473 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006474 adev->offload_effects_set_hpx_state =
6475 (int (*)(bool))dlsym(adev->offload_effects_lib,
6476 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306477 adev->offload_effects_get_parameters =
6478 (void (*)(struct str_parms *, struct str_parms *))
6479 dlsym(adev->offload_effects_lib,
6480 "offload_effects_bundle_get_parameters");
6481 adev->offload_effects_set_parameters =
6482 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6483 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006484 }
6485 }
6486
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006487 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6488 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6489 if (adev->adm_lib == NULL) {
6490 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6491 } else {
6492 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6493 adev->adm_init = (adm_init_t)
6494 dlsym(adev->adm_lib, "adm_init");
6495 adev->adm_deinit = (adm_deinit_t)
6496 dlsym(adev->adm_lib, "adm_deinit");
6497 adev->adm_register_input_stream = (adm_register_input_stream_t)
6498 dlsym(adev->adm_lib, "adm_register_input_stream");
6499 adev->adm_register_output_stream = (adm_register_output_stream_t)
6500 dlsym(adev->adm_lib, "adm_register_output_stream");
6501 adev->adm_deregister_stream = (adm_deregister_stream_t)
6502 dlsym(adev->adm_lib, "adm_deregister_stream");
6503 adev->adm_request_focus = (adm_request_focus_t)
6504 dlsym(adev->adm_lib, "adm_request_focus");
6505 adev->adm_abandon_focus = (adm_abandon_focus_t)
6506 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006507 adev->adm_set_config = (adm_set_config_t)
6508 dlsym(adev->adm_lib, "adm_set_config");
6509 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6510 dlsym(adev->adm_lib, "adm_request_focus_v2");
6511 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6512 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6513 adev->adm_on_routing_change = (adm_on_routing_change_t)
6514 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006515 }
6516 }
6517
Mingming Yin514a8bc2014-07-29 15:22:21 -07006518 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006519 //initialize this to false for now,
6520 //this will be set to true through set param
6521 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006522
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006523 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006524 *device = &adev->device.common;
6525
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306526 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6527 &adev->streams_output_cfg_list,
6528 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006529
Kiran Kandi910e1862013-10-29 13:29:42 -07006530 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006531
6532 char value[PROPERTY_VALUE_MAX];
6533 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006534 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006535 trial = atoi(value);
6536 if (period_size_is_plausible_for_low_latency(trial)) {
6537 pcm_config_low_latency.period_size = trial;
6538 pcm_config_low_latency.start_threshold = trial / 4;
6539 pcm_config_low_latency.avail_min = trial / 4;
6540 configured_low_latency_capture_period_size = trial;
6541 }
6542 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006543 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006544 trial = atoi(value);
6545 if (period_size_is_plausible_for_low_latency(trial)) {
6546 configured_low_latency_capture_period_size = trial;
6547 }
6548 }
6549
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006550 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006551 af_period_multiplier = atoi(value);
6552 if (af_period_multiplier < 0)
6553 af_period_multiplier = 2;
6554 else if (af_period_multiplier > 4)
6555 af_period_multiplier = 4;
6556
6557 ALOGV("new period_multiplier = %d", af_period_multiplier);
6558 }
6559
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006560 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006561 pthread_mutex_unlock(&adev_init_lock);
6562
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006563 if (adev->adm_init)
6564 adev->adm_data = adev->adm_init();
6565
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306566 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306567 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006568 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306569
6570 audio_extn_snd_mon_init();
6571 pthread_mutex_lock(&adev->lock);
6572 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6573 adev->card_status = CARD_STATUS_ONLINE;
6574 pthread_mutex_unlock(&adev->lock);
6575 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306576 /* Allocate memory for Device config params */
6577 adev->device_cfg_params = (struct audio_device_config_param*)
6578 calloc(platform_get_max_codec_backend(),
6579 sizeof(struct audio_device_config_param));
6580 if (adev->device_cfg_params == NULL)
6581 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306582
Eric Laurent994a6932013-07-17 11:51:42 -07006583 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584 return 0;
6585}
6586
6587static struct hw_module_methods_t hal_module_methods = {
6588 .open = adev_open,
6589};
6590
6591struct audio_module HAL_MODULE_INFO_SYM = {
6592 .common = {
6593 .tag = HARDWARE_MODULE_TAG,
6594 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6595 .hal_api_version = HARDWARE_HAL_API_VERSION,
6596 .id = AUDIO_HARDWARE_MODULE_ID,
6597 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006598 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006599 .methods = &hal_module_methods,
6600 },
6601};