blob: 4ef9c00a370f6abaf056c022e1b23f649cdcf0c2 [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
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001518uint32_t adev_get_dsp_bit_width_enforce_mode()
1519{
1520 if (adev == NULL) {
1521 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1522 return 0;
1523 }
1524 return adev->dsp_bit_width_enforce_mode;
1525}
1526
1527static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1528{
1529 char value[PROPERTY_VALUE_MAX];
1530 int trial;
1531 uint32_t dsp_bit_width_enforce_mode = 0;
1532
1533 if (!mixer) {
1534 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1535 __func__);
1536 return 0;
1537 }
1538
1539 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1540 value, NULL) > 0) {
1541 trial = atoi(value);
1542 switch (trial) {
1543 case 16:
1544 dsp_bit_width_enforce_mode = 16;
1545 break;
1546 case 24:
1547 dsp_bit_width_enforce_mode = 24;
1548 break;
1549 case 32:
1550 dsp_bit_width_enforce_mode = 32;
1551 break;
1552 default:
1553 dsp_bit_width_enforce_mode = 0;
1554 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1555 break;
1556 }
1557 }
1558
1559 return dsp_bit_width_enforce_mode;
1560}
1561
1562static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1563 uint32_t enforce_mode,
1564 bool enable)
1565{
1566 struct mixer_ctl *ctl = NULL;
1567 const char *mixer_ctl_name = "ASM Bit Width";
1568 uint32_t asm_bit_width_mode = 0;
1569
1570 if (enforce_mode == 0) {
1571 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1572 return;
1573 }
1574
1575 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1576 if (!ctl) {
1577 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1578 __func__, mixer_ctl_name);
1579 return;
1580 }
1581
1582 if (enable)
1583 asm_bit_width_mode = enforce_mode;
1584 else
1585 asm_bit_width_mode = 0;
1586
1587 ALOGV("%s DSP bit width feature status is %d width=%d",
1588 __func__, enable, asm_bit_width_mode);
1589 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1590 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1591 asm_bit_width_mode);
1592
1593 return;
1594}
1595
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301596/*
1597 * if native DSD playback active
1598 */
1599bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1600{
1601 bool active = false;
1602 struct listnode *node = NULL;
1603 struct audio_usecase *uc = NULL;
1604 struct stream_out *curr_out = NULL;
1605
1606 list_for_each(node, &adev->usecase_list) {
1607 uc = node_to_item(node, struct audio_usecase, list);
1608 curr_out = (struct stream_out*) uc->stream.out;
1609
1610 if (curr_out && PCM_PLAYBACK == uc->type &&
1611 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1612 active = true;
1613 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301614 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301615 }
1616 }
1617 return active;
1618}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301619
1620static bool force_device_switch(struct audio_usecase *usecase)
1621{
1622 bool ret = false;
1623 bool is_it_true_mode = false;
1624
1625 if (is_offload_usecase(usecase->id) &&
1626 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001627 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1628 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1629 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301630 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1631 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1632 (!is_it_true_mode && adev->native_playback_enabled)){
1633 ret = true;
1634 ALOGD("napb: time to toggle native mode");
1635 }
1636 }
1637
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301638 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301639 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1640 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301641 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001642 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301643 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301644 ALOGD("Force a2dp device switch to update new encoder config");
1645 ret = true;
1646 }
1647
Manish Dewangan671a4202017-08-18 17:30:46 +05301648 if (usecase->stream.out->stream_config_changed) {
1649 ALOGD("Force stream_config_changed to update iec61937 transmission config");
1650 return true;
1651 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301652 return ret;
1653}
1654
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301655bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1656{
1657 bool ret=false;
1658 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1659 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1660 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1661 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1662 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1663 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1664 ret = true;
1665
1666 return ret;
1667}
1668
1669bool is_a2dp_device(snd_device_t out_snd_device)
1670{
1671 bool ret=false;
1672 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1673 ret = true;
1674
1675 return ret;
1676}
1677
1678bool is_bt_soc_on(struct audio_device *adev)
1679{
1680 struct mixer_ctl *ctl;
1681 char *mixer_ctl_name = "BT SOC status";
1682 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1683 bool bt_soc_status = true;
1684 if (!ctl) {
1685 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1686 __func__, mixer_ctl_name);
1687 /*This is to ensure we dont break targets which dont have the kernel change*/
1688 return true;
1689 }
1690 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1691 ALOGD("BT SOC status: %d",bt_soc_status);
1692 return bt_soc_status;
1693}
1694
1695int out_standby_l(struct audio_stream *stream);
1696
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001697int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001699 snd_device_t out_snd_device = SND_DEVICE_NONE;
1700 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701 struct audio_usecase *usecase = NULL;
1702 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001703 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001704 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301705 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001706 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301709 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1710
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711 usecase = get_usecase_from_list(adev, uc_id);
1712 if (usecase == NULL) {
1713 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1714 return -EINVAL;
1715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001717 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001718 (usecase->type == VOIP_CALL) ||
1719 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301720 if(usecase->stream.out == NULL) {
1721 ALOGE("%s: stream.out is NULL", __func__);
1722 return -EINVAL;
1723 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001724 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001725 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001726 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301728 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1729 if (usecase->stream.inout == NULL) {
1730 ALOGE("%s: stream.inout is NULL", __func__);
1731 return -EINVAL;
1732 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05301733 stream_out.devices = usecase->stream.inout->out_config.devices;
1734 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
1735 stream_out.format = usecase->stream.inout->out_config.format;
1736 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
1737 out_snd_device = platform_get_output_snd_device(adev->platform,
1738 &stream_out);
1739 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301740 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 } else {
1742 /*
1743 * If the voice call is active, use the sound devices of voice call usecase
1744 * so that it would not result any device switch. All the usecases will
1745 * be switched to new device when select_devices() is called for voice call
1746 * usecase. This is to avoid switching devices for voice call when
1747 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001748 * choose voice call device only if the use case device is
1749 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001751 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001752 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001753 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001754 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1755 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301756 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1757 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001758 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 in_snd_device = vc_usecase->in_snd_device;
1760 out_snd_device = vc_usecase->out_snd_device;
1761 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001763 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001764 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001765 if ((voip_usecase != NULL) &&
1766 (usecase->type == PCM_PLAYBACK) &&
1767 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001768 out_snd_device_backend_match = platform_check_backends_match(
1769 voip_usecase->out_snd_device,
1770 platform_get_output_snd_device(
1771 adev->platform,
1772 usecase->stream.out));
1773 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001774 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001775 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1776 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001777 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001778 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001779 in_snd_device = voip_usecase->in_snd_device;
1780 out_snd_device = voip_usecase->out_snd_device;
1781 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001782 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001783 hfp_ucid = audio_extn_hfp_get_usecase();
1784 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001785 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001786 in_snd_device = hfp_usecase->in_snd_device;
1787 out_snd_device = hfp_usecase->out_snd_device;
1788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 }
1790 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301791 if (usecase->stream.out == NULL) {
1792 ALOGE("%s: stream.out is NULL", __func__);
1793 return -EINVAL;
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 usecase->devices = usecase->stream.out->devices;
1796 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001797 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001798 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001799 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001800 if (usecase->stream.out == adev->primary_output &&
1801 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001802 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001803 select_devices(adev, adev->active_input->usecase);
1804 }
1805 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301807 if (usecase->stream.in == NULL) {
1808 ALOGE("%s: stream.in is NULL", __func__);
1809 return -EINVAL;
1810 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811 usecase->devices = usecase->stream.in->device;
1812 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001813 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001814 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001815 if (adev->active_input &&
1816 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301817 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1818 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1819 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001820 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001821 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001822 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1823 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001824 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001825 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 }
1828 }
1829
1830 if (out_snd_device == usecase->out_snd_device &&
1831 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301832
1833 if (!force_device_switch(usecase))
1834 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 }
1836
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301837 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1838 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1839 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1840 return 0;
1841 }
1842
sangwoobc677242013-08-08 16:53:43 +09001843 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001844 out_snd_device, platform_get_snd_device_name(out_snd_device),
1845 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 /*
1848 * Limitation: While in call, to do a device switch we need to disable
1849 * and enable both RX and TX devices though one of them is same as current
1850 * device.
1851 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001852 if ((usecase->type == VOICE_CALL) &&
1853 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1854 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001855 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001856 }
1857
1858 if (((usecase->type == VOICE_CALL) ||
1859 (usecase->type == VOIP_CALL)) &&
1860 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1861 /* Disable sidetone only if voice/voip call already exists */
1862 if (voice_is_call_state_active(adev) ||
1863 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001864 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001865
1866 /* Disable aanc only if voice call exists */
1867 if (voice_is_call_state_active(adev))
1868 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001869 }
1870
Zhou Songc66eb7e2017-08-08 18:29:07 +08001871 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301872 (!audio_extn_a2dp_is_ready())) {
1873 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Zhou Songc66eb7e2017-08-08 18:29:07 +08001874 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05301875 }
1876
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 /* Disable current sound devices */
1878 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001879 disable_audio_route(adev, usecase);
1880 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001884 disable_audio_route(adev, usecase);
1885 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001888 /* Applicable only on the targets that has external modem.
1889 * New device information should be sent to modem before enabling
1890 * the devices to reduce in-call device switch time.
1891 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001892 if ((usecase->type == VOICE_CALL) &&
1893 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1894 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001895 status = platform_switch_voice_call_enable_device_config(adev->platform,
1896 out_snd_device,
1897 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001898 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001899
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001900 /* Enable new sound devices */
1901 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001902 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301903 if (platform_check_codec_asrc_support(adev->platform))
1904 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001905 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
1907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301909 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001910 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001911 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912
Avinash Vaish71a8b972014-07-24 15:36:33 +05301913 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001914 status = platform_switch_voice_call_device_post(adev->platform,
1915 out_snd_device,
1916 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301917 enable_audio_route_for_voice_usecases(adev, usecase);
1918 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001919
sangwoo170731f2013-06-08 15:36:36 +09001920 usecase->in_snd_device = in_snd_device;
1921 usecase->out_snd_device = out_snd_device;
1922
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301923 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1924 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301925 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001926 if ((24 == usecase->stream.out->bit_width) &&
1927 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1928 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1929 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1930 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1931 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1932 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1933 /*
1934 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1935 * configured device sample rate, if not update the COPP rate to be equal to the
1936 * device sample rate, else open COPP at stream sample rate
1937 */
1938 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1939 usecase->stream.out->sample_rate,
1940 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301941 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1942 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001943 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1944 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1945 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1946 }
1947
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001948 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001949 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001950 audio_extn_gef_notify_device_config(
1951 usecase->stream.out->devices,
1952 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001953 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001954 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001955 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301956 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001957 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001958
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001959 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001960 /* Enable aanc only if voice call exists */
1961 if (voice_is_call_state_active(adev))
1962 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1963
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001964 /* Enable sidetone only if other voice/voip call already exists */
1965 if (voice_is_call_state_active(adev) ||
1966 voice_extn_compress_voip_is_started(adev))
1967 voice_set_sidetone(adev, out_snd_device, true);
1968 }
1969
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001970 /* Applicable only on the targets that has external modem.
1971 * Enable device command should be sent to modem only after
1972 * enabling voice call mixer controls
1973 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001974 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001975 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1976 out_snd_device,
1977 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301978
1979 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1980
1981 if (usecase->type == VOIP_CALL) {
1982 if (adev->active_input != NULL &&
1983 !adev->active_input->standby) {
1984 if (is_bt_soc_on(adev) == false){
1985 ALOGD("BT SCO MIC disconnected while in connection");
1986 if (adev->active_input->pcm != NULL)
1987 pcm_stop(adev->active_input->pcm);
1988 }
1989 }
1990 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1991 && usecase->stream.out->started) {
1992 if (is_bt_soc_on(adev) == false) {
1993 ALOGD("BT SCO/A2DP disconnected while in connection");
1994 out_standby_l(&usecase->stream.out->stream.common);
1995 }
1996 }
1997 } else if ((usecase->stream.out != NULL) &&
1998 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1999 usecase->stream.out->started) {
2000 if (is_bt_soc_on(adev) == false) {
2001 ALOGD("BT SCO/A2dp disconnected while in connection");
2002 out_standby_l(&usecase->stream.out->stream.common);
2003 }
2004 }
2005 }
2006
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302007 ALOGD("%s: done",__func__);
2008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 return status;
2010}
2011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012static int stop_input_stream(struct stream_in *in)
2013{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302014 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 struct audio_usecase *uc_info;
2016 struct audio_device *adev = in->dev;
2017
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002019 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 uc_info = get_usecase_from_list(adev, in->usecase);
2021 if (uc_info == NULL) {
2022 ALOGE("%s: Could not find the usecase (%d) in the list",
2023 __func__, in->usecase);
2024 return -EINVAL;
2025 }
2026
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002027 /* Close in-call recording streams */
2028 voice_check_and_stop_incall_rec_usecase(adev, in);
2029
Eric Laurent150dbfe2013-02-27 14:31:02 -08002030 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002031 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002032
2033 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002034 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002036 list_remove(&uc_info->list);
2037 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002039 adev->active_input = get_next_active_input(adev);
2040
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 return ret;
2043}
2044
2045int start_input_stream(struct stream_in *in)
2046{
2047 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002048 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 struct audio_usecase *uc_info;
2050 struct audio_device *adev = in->dev;
2051
Mingming Yin2664a5b2015-09-03 10:53:11 -07002052 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
2053 if (get_usecase_from_list(adev, usecase) == NULL)
2054 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302055 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2056 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002057
Naresh Tanniru80659832014-06-04 18:17:56 +05302058
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302059 if (CARD_STATUS_OFFLINE == in->card_status||
2060 CARD_STATUS_OFFLINE == adev->card_status) {
2061 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302062 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302063 goto error_config;
2064 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302065
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302066 if (audio_is_bluetooth_sco_device(in->device)) {
2067 if (!adev->bt_sco_on) {
2068 ALOGE("%s: SCO profile is not ready, return error", __func__);
2069 ret = -EIO;
2070 goto error_config;
2071 }
2072 }
2073
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002074 /* Check if source matches incall recording usecase criteria */
2075 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2076 if (ret)
2077 goto error_config;
2078 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002079 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2080
2081 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2082 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2083 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002084 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002085 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002086
Eric Laurentb23d5282013-05-14 15:27:20 -07002087 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 if (in->pcm_device_id < 0) {
2089 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2090 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002091 ret = -EINVAL;
2092 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002094
2095 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002097
2098 if (!uc_info) {
2099 ret = -ENOMEM;
2100 goto error_config;
2101 }
2102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 uc_info->id = in->usecase;
2104 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002105 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106 uc_info->devices = in->device;
2107 uc_info->in_snd_device = SND_DEVICE_NONE;
2108 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002110 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302111 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2112 adev->perf_lock_opts,
2113 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002114 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115
Haynes Mathew George16081042017-05-31 17:16:49 -07002116 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302117 ret = audio_extn_cin_start_input_stream(in);
2118 if (ret)
2119 goto error_open;
2120 else
2121 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002122 }
2123
Haynes Mathew George16081042017-05-31 17:16:49 -07002124 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002125 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002126 ALOGE("%s: pcm stream not ready", __func__);
2127 goto error_open;
2128 }
2129 ret = pcm_start(in->pcm);
2130 if (ret < 0) {
2131 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2132 goto error_open;
2133 }
2134 } else {
2135 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2136 unsigned int pcm_open_retry_count = 0;
2137
2138 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2139 flags |= PCM_MMAP | PCM_NOIRQ;
2140 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2141 } else if (in->realtime) {
2142 flags |= PCM_MMAP | PCM_NOIRQ;
2143 }
2144
2145 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2146 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2147
2148 while (1) {
2149 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2150 flags, &in->config);
2151 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2152 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2153 if (in->pcm != NULL) {
2154 pcm_close(in->pcm);
2155 in->pcm = NULL;
2156 }
2157 if (pcm_open_retry_count-- == 0) {
2158 ret = -EIO;
2159 goto error_open;
2160 }
2161 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2162 continue;
2163 }
2164 break;
2165 }
2166
2167 ALOGV("%s: pcm_prepare", __func__);
2168 ret = pcm_prepare(in->pcm);
2169 if (ret < 0) {
2170 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2171 pcm_close(in->pcm);
2172 in->pcm = NULL;
2173 goto error_open;
2174 }
2175 register_in_stream(in);
2176 if (in->realtime) {
2177 ret = pcm_start(in->pcm);
2178 if (ret < 0) {
2179 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002180 pcm_close(in->pcm);
2181 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002182 goto error_open;
2183 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002184 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002185 }
2186
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302187done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302188 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002189 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002190
Eric Laurentc8400632013-02-14 19:04:54 -08002191 return ret;
2192
2193error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302194 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002196error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302197 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302198 /*
2199 * sleep 50ms to allow sufficient time for kernel
2200 * drivers to recover incases like SSR.
2201 */
2202 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002203 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002204
2205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206}
2207
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002208void lock_input_stream(struct stream_in *in)
2209{
2210 pthread_mutex_lock(&in->pre_lock);
2211 pthread_mutex_lock(&in->lock);
2212 pthread_mutex_unlock(&in->pre_lock);
2213}
2214
2215void lock_output_stream(struct stream_out *out)
2216{
2217 pthread_mutex_lock(&out->pre_lock);
2218 pthread_mutex_lock(&out->lock);
2219 pthread_mutex_unlock(&out->pre_lock);
2220}
2221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222/* must be called with out->lock locked */
2223static int send_offload_cmd_l(struct stream_out* out, int command)
2224{
2225 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2226
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002227 if (!cmd) {
2228 ALOGE("failed to allocate mem for command 0x%x", command);
2229 return -ENOMEM;
2230 }
2231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 ALOGVV("%s %d", __func__, command);
2233
2234 cmd->cmd = command;
2235 list_add_tail(&out->offload_cmd_list, &cmd->node);
2236 pthread_cond_signal(&out->offload_cond);
2237 return 0;
2238}
2239
2240/* must be called iwth out->lock locked */
2241static void stop_compressed_output_l(struct stream_out *out)
2242{
2243 out->offload_state = OFFLOAD_STATE_IDLE;
2244 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 if (out->compr != NULL) {
2247 compress_stop(out->compr);
2248 while (out->offload_thread_blocked) {
2249 pthread_cond_wait(&out->cond, &out->lock);
2250 }
2251 }
2252}
2253
Varun Balaraje49253e2017-07-06 19:48:56 +05302254bool is_interactive_usecase(audio_usecase_t uc_id)
2255{
2256 unsigned int i;
2257 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2258 if (uc_id == interactive_usecases[i])
2259 return true;
2260 }
2261 return false;
2262}
2263
2264static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2265{
2266 audio_usecase_t ret_uc = USECASE_INVALID;
2267 unsigned int intract_uc_index;
2268 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2269
2270 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2271 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2272 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2273 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2274 ret_uc = interactive_usecases[intract_uc_index];
2275 break;
2276 }
2277 }
2278
2279 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2280 return ret_uc;
2281}
2282
2283static void free_interactive_usecase(struct audio_device *adev,
2284 audio_usecase_t uc_id)
2285{
2286 unsigned int interact_uc_index;
2287 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2288
2289 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2290 if (interactive_usecases[interact_uc_index] == uc_id) {
2291 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2292 break;
2293 }
2294 }
2295 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2296}
2297
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002298bool is_offload_usecase(audio_usecase_t uc_id)
2299{
2300 unsigned int i;
2301 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2302 if (uc_id == offload_usecases[i])
2303 return true;
2304 }
2305 return false;
2306}
2307
Dhananjay Kumarac341582017-02-23 23:42:25 +05302308static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002309{
vivek mehta446c3962015-09-14 10:57:35 -07002310 audio_usecase_t ret_uc = USECASE_INVALID;
2311 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002312 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002313 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302314 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002315 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2316 else
2317 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002318
vivek mehta446c3962015-09-14 10:57:35 -07002319 pthread_mutex_lock(&adev->lock);
2320 if (get_usecase_from_list(adev, ret_uc) != NULL)
2321 ret_uc = USECASE_INVALID;
2322 pthread_mutex_unlock(&adev->lock);
2323
2324 return ret_uc;
2325 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002326
2327 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002328 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2329 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2330 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2331 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002332 break;
2333 }
2334 }
vivek mehta446c3962015-09-14 10:57:35 -07002335
2336 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2337 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002338}
2339
2340static void free_offload_usecase(struct audio_device *adev,
2341 audio_usecase_t uc_id)
2342{
vivek mehta446c3962015-09-14 10:57:35 -07002343 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002344 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002345
2346 if (!adev->multi_offload_enable)
2347 return;
2348
2349 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2350 if (offload_usecases[offload_uc_index] == uc_id) {
2351 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002352 break;
2353 }
2354 }
2355 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2356}
2357
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358static void *offload_thread_loop(void *context)
2359{
2360 struct stream_out *out = (struct stream_out *) context;
2361 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002362 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2365 set_sched_policy(0, SP_FOREGROUND);
2366 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2367
2368 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002369 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 for (;;) {
2371 struct offload_cmd *cmd = NULL;
2372 stream_callback_event_t event;
2373 bool send_callback = false;
2374
2375 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2376 __func__, list_empty(&out->offload_cmd_list),
2377 out->offload_state);
2378 if (list_empty(&out->offload_cmd_list)) {
2379 ALOGV("%s SLEEPING", __func__);
2380 pthread_cond_wait(&out->offload_cond, &out->lock);
2381 ALOGV("%s RUNNING", __func__);
2382 continue;
2383 }
2384
2385 item = list_head(&out->offload_cmd_list);
2386 cmd = node_to_item(item, struct offload_cmd, node);
2387 list_remove(item);
2388
2389 ALOGVV("%s STATE %d CMD %d out->compr %p",
2390 __func__, out->offload_state, cmd->cmd, out->compr);
2391
2392 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2393 free(cmd);
2394 break;
2395 }
2396
2397 if (out->compr == NULL) {
2398 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002399 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400 pthread_cond_signal(&out->cond);
2401 continue;
2402 }
2403 out->offload_thread_blocked = true;
2404 pthread_mutex_unlock(&out->lock);
2405 send_callback = false;
2406 switch(cmd->cmd) {
2407 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002408 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002410 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002411 send_callback = true;
2412 event = STREAM_CBK_EVENT_WRITE_READY;
2413 break;
2414 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002415 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302416 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002417 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302418 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002419 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302420 if (ret < 0)
2421 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302422 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302423 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002424 compress_drain(out->compr);
2425 else
2426 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302427 if (ret != -ENETRESET) {
2428 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302429 pthread_mutex_lock(&out->lock);
2430 out->send_new_metadata = 1;
2431 out->send_next_track_params = true;
2432 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302433 event = STREAM_CBK_EVENT_DRAIN_READY;
2434 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2435 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302436 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 break;
2438 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002439 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002441 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 send_callback = true;
2443 event = STREAM_CBK_EVENT_DRAIN_READY;
2444 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302445 case OFFLOAD_CMD_ERROR:
2446 ALOGD("copl(%p): sending error callback to AF", out);
2447 send_callback = true;
2448 event = STREAM_CBK_EVENT_ERROR;
2449 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002450 default:
2451 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2452 break;
2453 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 out->offload_thread_blocked = false;
2456 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002457 if (send_callback && out->client_callback) {
2458 ALOGVV("%s: sending client_callback event %d", __func__, event);
2459 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002460 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 free(cmd);
2462 }
2463
2464 pthread_cond_signal(&out->cond);
2465 while (!list_empty(&out->offload_cmd_list)) {
2466 item = list_head(&out->offload_cmd_list);
2467 list_remove(item);
2468 free(node_to_item(item, struct offload_cmd, node));
2469 }
2470 pthread_mutex_unlock(&out->lock);
2471
2472 return NULL;
2473}
2474
2475static int create_offload_callback_thread(struct stream_out *out)
2476{
2477 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2478 list_init(&out->offload_cmd_list);
2479 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2480 offload_thread_loop, out);
2481 return 0;
2482}
2483
2484static int destroy_offload_callback_thread(struct stream_out *out)
2485{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002486 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 stop_compressed_output_l(out);
2488 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2489
2490 pthread_mutex_unlock(&out->lock);
2491 pthread_join(out->offload_thread, (void **) NULL);
2492 pthread_cond_destroy(&out->offload_cond);
2493
2494 return 0;
2495}
2496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497static int stop_output_stream(struct stream_out *out)
2498{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302499 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 struct audio_usecase *uc_info;
2501 struct audio_device *adev = out->dev;
2502
Eric Laurent994a6932013-07-17 11:51:42 -07002503 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002504 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 uc_info = get_usecase_from_list(adev, out->usecase);
2506 if (uc_info == NULL) {
2507 ALOGE("%s: Could not find the usecase (%d) in the list",
2508 __func__, out->usecase);
2509 return -EINVAL;
2510 }
2511
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002512 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302513 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002514 if (adev->visualizer_stop_output != NULL)
2515 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002516
2517 audio_extn_dts_remove_state_notifier_node(out->usecase);
2518
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002519 if (adev->offload_effects_stop_output != NULL)
2520 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2521 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002522
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002524 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002525
2526 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002527 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002529 if (is_offload_usecase(out->usecase)) {
2530 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2531 adev->dsp_bit_width_enforce_mode,
2532 false);
2533 }
2534
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002535 list_remove(&uc_info->list);
2536 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302537 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002538 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302539 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002540 ALOGV("Disable passthrough , reset mixer to pcm");
2541 /* NO_PASSTHROUGH */
2542 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002543 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002544 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2545 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002546
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302547 /* Must be called after removing the usecase from list */
2548 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302549 audio_extn_keep_alive_start();
2550
Manish Dewangan21a850a2017-08-14 12:03:55 +05302551 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07002552 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2553 if (ret < 0)
2554 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2555 }
2556
Eric Laurent994a6932013-07-17 11:51:42 -07002557 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 return ret;
2559}
2560
2561int start_output_stream(struct stream_out *out)
2562{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 struct audio_usecase *uc_info;
2565 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002566 char mixer_ctl_name[128];
2567 struct mixer_ctl *ctl = NULL;
2568 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302569 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002571 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2572 ret = -EINVAL;
2573 goto error_config;
2574 }
2575
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302576 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2577 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2578 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302579
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302580 if (CARD_STATUS_OFFLINE == out->card_status ||
2581 CARD_STATUS_OFFLINE == adev->card_status) {
2582 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302583 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302584 goto error_config;
2585 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302587 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2588 if (!audio_extn_a2dp_is_ready()) {
2589 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302590 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302591 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302592 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2593 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2594 ret = -EAGAIN;
2595 goto error_config;
2596 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302597 }
2598 }
2599 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302600 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2601 if (!adev->bt_sco_on) {
2602 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2603 //combo usecase just by pass a2dp
2604 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2605 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2606 } else {
2607 ALOGE("%s: SCO profile is not ready, return error", __func__);
2608 ret = -EAGAIN;
2609 goto error_config;
2610 }
2611 }
2612 }
2613
Eric Laurentb23d5282013-05-14 15:27:20 -07002614 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 if (out->pcm_device_id < 0) {
2616 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2617 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002618 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002619 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 }
2621
2622 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002623
2624 if (!uc_info) {
2625 ret = -ENOMEM;
2626 goto error_config;
2627 }
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 uc_info->id = out->usecase;
2630 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002631 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002632 uc_info->devices = out->devices;
2633 uc_info->in_snd_device = SND_DEVICE_NONE;
2634 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002635 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302637 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2638 adev->perf_lock_opts,
2639 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302640
2641 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2642 audio_extn_keep_alive_stop();
2643 if (audio_extn_passthru_is_enabled() &&
2644 audio_extn_passthru_is_passthrough_stream(out)) {
2645 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302646 }
2647 }
2648
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302649 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2650 (!audio_extn_a2dp_is_ready())) {
2651 if (!a2dp_combo) {
2652 check_a2dp_restore_l(adev, out, false);
2653 } else {
2654 audio_devices_t dev = out->devices;
2655 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2656 select_devices(adev, out->usecase);
2657 out->devices = dev;
2658 }
2659 } else {
2660 select_devices(adev, out->usecase);
2661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002662
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002663 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2664 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07002665
2666 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2667 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2668 ALOGE("%s: pcm stream not ready", __func__);
2669 goto error_open;
2670 }
2671 ret = pcm_start(out->pcm);
2672 if (ret < 0) {
2673 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2674 goto error_open;
2675 }
2676 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002677 unsigned int flags = PCM_OUT;
2678 unsigned int pcm_open_retry_count = 0;
2679 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2680 flags |= PCM_MMAP | PCM_NOIRQ;
2681 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002682 } else if (out->realtime) {
2683 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002684 } else
2685 flags |= PCM_MONOTONIC;
2686
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002687 if ((adev->vr_audio_mode_enabled) &&
2688 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2689 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2690 "PCM_Dev %d Topology", out->pcm_device_id);
2691 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2692 if (!ctl) {
2693 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2694 __func__, mixer_ctl_name);
2695 } else {
2696 //if success use ULLPP
2697 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2698 __func__, mixer_ctl_name, out->pcm_device_id);
2699 //There is a still a possibility that some sessions
2700 // that request for FAST|RAW when 3D audio is active
2701 //can go through ULLPP. Ideally we expects apps to
2702 //listen to audio focus and stop concurrent playback
2703 //Also, we will look for mode flag (voice_in_communication)
2704 //before enabling the realtime flag.
2705 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2706 }
2707 }
2708
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002709 while (1) {
2710 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2711 flags, &out->config);
2712 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2713 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2714 if (out->pcm != NULL) {
2715 pcm_close(out->pcm);
2716 out->pcm = NULL;
2717 }
2718 if (pcm_open_retry_count-- == 0) {
2719 ret = -EIO;
2720 goto error_open;
2721 }
2722 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2723 continue;
2724 }
2725 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002726 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002727
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002728 ALOGV("%s: pcm_prepare", __func__);
2729 if (pcm_is_ready(out->pcm)) {
2730 ret = pcm_prepare(out->pcm);
2731 if (ret < 0) {
2732 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2733 pcm_close(out->pcm);
2734 out->pcm = NULL;
2735 goto error_open;
2736 }
2737 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302738 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302739 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002741 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002742 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302743 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002744 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2745 adev->dsp_bit_width_enforce_mode,
2746 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002748 out->compr = compress_open(adev->snd_card,
2749 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 COMPRESS_IN, &out->compr_config);
2751 if (out->compr && !is_compress_ready(out->compr)) {
2752 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2753 compress_close(out->compr);
2754 out->compr = NULL;
2755 ret = -EIO;
2756 goto error_open;
2757 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302758 /* compress_open sends params of the track, so reset the flag here */
2759 out->is_compr_metadata_avail = false;
2760
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002761 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002763
Fred Oh3f43e742015-03-04 18:42:34 -08002764 /* Since small bufs uses blocking writes, a write will be blocked
2765 for the default max poll time (20s) in the event of an SSR.
2766 Reduce the poll time to observe and deal with SSR faster.
2767 */
Ashish Jain5106d362016-05-11 19:23:33 +05302768 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002769 compress_set_max_poll_wait(out->compr, 1000);
2770 }
2771
Manish Dewangan69426c82017-01-30 17:35:36 +05302772 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302773 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302774
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002775 audio_extn_dts_create_state_notifier_node(out->usecase);
2776 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2777 popcount(out->channel_mask),
2778 out->playback_started);
2779
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002780#ifdef DS1_DOLBY_DDP_ENABLED
2781 if (audio_extn_is_dolby_format(out->format))
2782 audio_extn_dolby_send_ddp_endp_params(adev);
2783#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302784 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2785 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002786 if (adev->visualizer_start_output != NULL)
2787 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2788 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302789 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002790 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002793
2794 if (ret == 0) {
2795 register_out_stream(out);
2796 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07002797 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2798 ALOGE("%s: pcm stream not ready", __func__);
2799 goto error_open;
2800 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002801 ret = pcm_start(out->pcm);
2802 if (ret < 0)
2803 goto error_open;
2804 }
2805 }
2806
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302807 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002808 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002809
Manish Dewangan21a850a2017-08-14 12:03:55 +05302810 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002811 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002812 if (ret < 0)
2813 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2814 }
2815
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002816 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302818 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002820error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302821 /*
2822 * sleep 50ms to allow sufficient time for kernel
2823 * drivers to recover incases like SSR.
2824 */
2825 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002826 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827}
2828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829static int check_input_parameters(uint32_t sample_rate,
2830 audio_format_t format,
2831 int channel_count)
2832{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002833 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302835 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2836 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2837 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002838 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302839 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002840
2841 switch (channel_count) {
2842 case 1:
2843 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302844 case 3:
2845 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002846 case 6:
2847 break;
2848 default:
2849 ret = -EINVAL;
2850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851
2852 switch (sample_rate) {
2853 case 8000:
2854 case 11025:
2855 case 12000:
2856 case 16000:
2857 case 22050:
2858 case 24000:
2859 case 32000:
2860 case 44100:
2861 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302862 case 96000:
2863 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864 break;
2865 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002866 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 }
2868
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002869 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870}
2871
2872static size_t get_input_buffer_size(uint32_t sample_rate,
2873 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002874 int channel_count,
2875 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876{
2877 size_t size = 0;
2878
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002879 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2880 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002882 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002883 if (is_low_latency)
2884 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302885
2886 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002888 /* make sure the size is multiple of 32 bytes
2889 * At 48 kHz mono 16-bit PCM:
2890 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2891 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2892 */
2893 size += 0x1f;
2894 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002895
2896 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897}
2898
Ashish Jain058165c2016-09-28 23:18:48 +05302899static size_t get_output_period_size(uint32_t sample_rate,
2900 audio_format_t format,
2901 int channel_count,
2902 int duration /*in millisecs*/)
2903{
2904 size_t size = 0;
2905 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2906
2907 if ((duration == 0) || (sample_rate == 0) ||
2908 (bytes_per_sample == 0) || (channel_count == 0)) {
2909 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2910 bytes_per_sample, channel_count);
2911 return -EINVAL;
2912 }
2913
2914 size = (sample_rate *
2915 duration *
2916 bytes_per_sample *
2917 channel_count) / 1000;
2918 /*
2919 * To have same PCM samples for all channels, the buffer size requires to
2920 * be multiple of (number of channels * bytes per sample)
2921 * For writes to succeed, the buffer must be written at address which is multiple of 32
2922 */
2923 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2924
2925 return (size/(channel_count * bytes_per_sample));
2926}
2927
Ashish Jain5106d362016-05-11 19:23:33 +05302928static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2929{
2930 uint64_t actual_frames_rendered = 0;
2931 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2932
2933 /* This adjustment accounts for buffering after app processor.
2934 * It is based on estimated DSP latency per use case, rather than exact.
2935 */
2936 int64_t platform_latency = platform_render_latency(out->usecase) *
2937 out->sample_rate / 1000000LL;
2938
2939 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2940 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2941 * hence only estimate.
2942 */
2943 int64_t signed_frames = out->written - kernel_buffer_size;
2944
2945 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2946
2947 if (signed_frames > 0)
2948 actual_frames_rendered = signed_frames;
2949
2950 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2951 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2952 (long long int)out->written, (int)kernel_buffer_size,
2953 audio_bytes_per_sample(out->compr_config.codec->format),
2954 popcount(out->channel_mask));
2955
2956 return actual_frames_rendered;
2957}
2958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2960{
2961 struct stream_out *out = (struct stream_out *)stream;
2962
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964}
2965
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002966static int out_set_sample_rate(struct audio_stream *stream __unused,
2967 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968{
2969 return -ENOSYS;
2970}
2971
2972static size_t out_get_buffer_size(const struct audio_stream *stream)
2973{
2974 struct stream_out *out = (struct stream_out *)stream;
2975
Varun Balaraje49253e2017-07-06 19:48:56 +05302976 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05302977 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05302978 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302979 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2980 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2981 else
2982 return out->compr_config.fragment_size;
2983 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002984 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07002985 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
2986 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 +05302987 else if (is_offload_usecase(out->usecase) &&
2988 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302989 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002990
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002991 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002992 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993}
2994
2995static uint32_t out_get_channels(const struct audio_stream *stream)
2996{
2997 struct stream_out *out = (struct stream_out *)stream;
2998
2999 return out->channel_mask;
3000}
3001
3002static audio_format_t out_get_format(const struct audio_stream *stream)
3003{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 struct stream_out *out = (struct stream_out *)stream;
3005
3006 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007}
3008
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003009static int out_set_format(struct audio_stream *stream __unused,
3010 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011{
3012 return -ENOSYS;
3013}
3014
3015static int out_standby(struct audio_stream *stream)
3016{
3017 struct stream_out *out = (struct stream_out *)stream;
3018 struct audio_device *adev = out->dev;
kunleiza9d11682017-08-04 14:14:09 +08003019 struct audio_usecase *uc_info;
3020 struct listnode *node;
Haynes Mathew George16081042017-05-31 17:16:49 -07003021 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303023 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3024 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003026 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003028 if (adev->adm_deregister_stream)
3029 adev->adm_deregister_stream(adev->adm_data, out->handle);
3030
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003031 if (is_offload_usecase(out->usecase))
3032 stop_compressed_output_l(out);
3033
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003034 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003036 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3037 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303038 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003039 pthread_mutex_unlock(&adev->lock);
3040 pthread_mutex_unlock(&out->lock);
3041 ALOGD("VOIP output entered standby");
3042 return 0;
3043 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 if (out->pcm) {
3045 pcm_close(out->pcm);
3046 out->pcm = NULL;
3047 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003048 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3049 do_stop = out->playback_started;
3050 out->playback_started = false;
3051 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003052 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003053 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303054 out->send_next_track_params = false;
3055 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003056 out->gapless_mdata.encoder_delay = 0;
3057 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058 if (out->compr != NULL) {
3059 compress_close(out->compr);
3060 out->compr = NULL;
3061 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003062 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003063 if (do_stop) {
3064 stop_output_stream(out);
3065 }
kunleiza9d11682017-08-04 14:14:09 +08003066 //restore output device for active usecase when current snd device and output device mismatch
3067 list_for_each(node, &adev->usecase_list) {
3068 uc_info = node_to_item(node, struct audio_usecase, list);
3069 if ((uc_info->type == PCM_PLAYBACK) &&
3070 (uc_info->out_snd_device != platform_get_output_snd_device(adev->platform, uc_info->stream.out)))
3071 select_devices(adev, uc_info->id);
3072 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003073 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 }
3075 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303076 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 return 0;
3078}
3079
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303080static int out_on_error(struct audio_stream *stream)
3081{
3082 struct stream_out *out = (struct stream_out *)stream;
3083 bool do_standby = false;
3084
3085 lock_output_stream(out);
3086 if (!out->standby) {
3087 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3088 stop_compressed_output_l(out);
3089 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
3090 } else
3091 do_standby = true;
3092 }
3093 pthread_mutex_unlock(&out->lock);
3094
3095 if (do_standby)
3096 return out_standby(&out->stream.common);
3097
3098 return 0;
3099}
3100
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303101/*
3102 *standby implementation without locks, assumes that the callee already
3103 *has taken adev and out lock.
3104 */
3105int out_standby_l(struct audio_stream *stream)
3106{
3107 struct stream_out *out = (struct stream_out *)stream;
3108 struct audio_device *adev = out->dev;
3109
3110 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3111 stream, out->usecase, use_case_table[out->usecase]);
3112
3113 if (!out->standby) {
3114 if (adev->adm_deregister_stream)
3115 adev->adm_deregister_stream(adev->adm_data, out->handle);
3116
3117 if (is_offload_usecase(out->usecase))
3118 stop_compressed_output_l(out);
3119
3120 out->standby = true;
3121 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3122 voice_extn_compress_voip_close_output_stream(stream);
3123 out->started = 0;
3124 ALOGD("VOIP output entered standby");
3125 return 0;
3126 } else if (!is_offload_usecase(out->usecase)) {
3127 if (out->pcm) {
3128 pcm_close(out->pcm);
3129 out->pcm = NULL;
3130 }
3131 } else {
3132 ALOGD("copl(%p):standby", out);
3133 out->send_next_track_params = false;
3134 out->is_compr_metadata_avail = false;
3135 out->gapless_mdata.encoder_delay = 0;
3136 out->gapless_mdata.encoder_padding = 0;
3137 if (out->compr != NULL) {
3138 compress_close(out->compr);
3139 out->compr = NULL;
3140 }
3141 }
3142 stop_output_stream(out);
3143 }
3144 ALOGD("%s: exit", __func__);
3145 return 0;
3146}
3147
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003148static int out_dump(const struct audio_stream *stream __unused,
3149 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150{
3151 return 0;
3152}
3153
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003154static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
3155{
3156 int ret = 0;
3157 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08003158
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003159 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003160 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003161 return -EINVAL;
3162 }
3163
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303164 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08003165
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003166 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
3167 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303168 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003169 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003170 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
3171 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05303172 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003173 }
3174
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003175 ALOGV("%s new encoder delay %u and padding %u", __func__,
3176 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
3177
3178 return 0;
3179}
3180
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003181static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
3182{
3183 return out == adev->primary_output || out == adev->voice_tx_output;
3184}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003185
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303186// note: this call is safe only if the stream_cb is
3187// removed first in close_output_stream (as is done now).
3188static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3189{
3190 if (!stream || !parms)
3191 return;
3192
3193 struct stream_out *out = (struct stream_out *)stream;
3194 struct audio_device *adev = out->dev;
3195
3196 card_status_t status;
3197 int card;
3198 if (parse_snd_card_status(parms, &card, &status) < 0)
3199 return;
3200
3201 pthread_mutex_lock(&adev->lock);
3202 bool valid_cb = (card == adev->snd_card);
3203 pthread_mutex_unlock(&adev->lock);
3204
3205 if (!valid_cb)
3206 return;
3207
3208 lock_output_stream(out);
3209 if (out->card_status != status)
3210 out->card_status = status;
3211 pthread_mutex_unlock(&out->lock);
3212
3213 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3214 use_case_table[out->usecase],
3215 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3216
3217 if (status == CARD_STATUS_OFFLINE)
3218 out_on_error(stream);
3219
3220 return;
3221}
3222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3224{
3225 struct stream_out *out = (struct stream_out *)stream;
3226 struct audio_device *adev = out->dev;
3227 struct str_parms *parms;
3228 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003229 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303230 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231
sangwoobc677242013-08-08 16:53:43 +09003232 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003233 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303235 if (!parms)
3236 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003237 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3238 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003240 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003241 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003243 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003244 * When HDMI cable is unplugged the music playback is paused and
3245 * the policy manager sends routing=0. But the audioflinger continues
3246 * to write data until standby time (3sec). As the HDMI core is
3247 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003248 * Avoid this by routing audio to speaker until standby.
3249 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003250 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3251 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303252 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003253 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3254 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003255 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303256 /*
3257 * When A2DP is disconnected the
3258 * music playback is paused and the policy manager sends routing=0
3259 * But the audioflingercontinues to write data until standby time
3260 * (3sec). As BT is turned off, the write gets blocked.
3261 * Avoid this by routing audio to speaker until standby.
3262 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003263 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303264 (val == AUDIO_DEVICE_NONE)) {
3265 val = AUDIO_DEVICE_OUT_SPEAKER;
3266 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303267 /* To avoid a2dp to sco overlapping / BT device improper state
3268 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303269 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303270 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3271 if (!audio_extn_a2dp_is_ready()) {
3272 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3273 //combo usecase just by pass a2dp
3274 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303275 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303276 } else {
3277 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3278 /* update device to a2dp and don't route as BT returned error
3279 * However it is still possible a2dp routing called because
3280 * of current active device disconnection (like wired headset)
3281 */
3282 out->devices = val;
3283 pthread_mutex_unlock(&out->lock);
3284 pthread_mutex_unlock(&adev->lock);
3285 goto error;
3286 }
3287 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303288 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003289 /*
3290 * select_devices() call below switches all the usecases on the same
3291 * backend to the new device. Refer to check_usecases_codec_backend() in
3292 * the select_devices(). But how do we undo this?
3293 *
3294 * For example, music playback is active on headset (deep-buffer usecase)
3295 * and if we go to ringtones and select a ringtone, low-latency usecase
3296 * will be started on headset+speaker. As we can't enable headset+speaker
3297 * and headset devices at the same time, select_devices() switches the music
3298 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3299 * So when the ringtone playback is completed, how do we undo the same?
3300 *
3301 * We are relying on the out_set_parameters() call on deep-buffer output,
3302 * once the ringtone playback is ended.
3303 * NOTE: We should not check if the current devices are same as new devices.
3304 * Because select_devices() must be called to switch back the music
3305 * playback to headset.
3306 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003307 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003308 audio_devices_t new_dev = val;
3309 bool same_dev = out->devices == new_dev;
3310 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003311
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003312 if (output_drives_call(adev, out)) {
3313 if(!voice_is_in_call(adev)) {
3314 if (adev->mode == AUDIO_MODE_IN_CALL) {
3315 adev->current_call_output = out;
3316 ret = voice_start_call(adev);
3317 }
3318 } else {
3319 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003321 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003322 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003323
3324 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003325 if (!same_dev) {
3326 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303327 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3328 adev->perf_lock_opts,
3329 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003330 if (adev->adm_on_routing_change)
3331 adev->adm_on_routing_change(adev->adm_data,
3332 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003333 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303334 if (!bypass_a2dp) {
3335 select_devices(adev, out->usecase);
3336 } else {
3337 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3338 select_devices(adev, out->usecase);
3339 out->devices = new_dev;
3340 }
Sudheer Papothi80266982016-08-16 02:36:18 +05303341 if (!same_dev)
3342 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303343 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3344 out->a2dp_compress_mute &&
Zhou Songc66eb7e2017-08-08 18:29:07 +08003345 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303346 pthread_mutex_lock(&out->compr_mute_lock);
3347 out->a2dp_compress_mute = false;
3348 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3349 pthread_mutex_unlock(&out->compr_mute_lock);
3350 }
3351
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003352 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003353 }
3354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003356 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003358
3359 if (out == adev->primary_output) {
3360 pthread_mutex_lock(&adev->lock);
3361 audio_extn_set_parameters(adev, parms);
3362 pthread_mutex_unlock(&adev->lock);
3363 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003364 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003365 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003366 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003367
3368 audio_extn_dts_create_state_notifier_node(out->usecase);
3369 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3370 popcount(out->channel_mask),
3371 out->playback_started);
3372
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003373 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003374 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003375
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303376 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3377 if (err >= 0) {
3378 strlcpy(out->profile, value, sizeof(out->profile));
3379 ALOGV("updating stream profile with value '%s'", out->profile);
3380 lock_output_stream(out);
3381 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3382 &adev->streams_output_cfg_list,
3383 out->devices, out->flags, out->format,
3384 out->sample_rate, out->bit_width,
3385 out->channel_mask, out->profile,
3386 &out->app_type_cfg);
3387 pthread_mutex_unlock(&out->lock);
3388 }
3389
Alexy Joseph98988832017-01-13 14:56:59 -08003390 //suspend, resume handling block
3391 if (out->dynamic_pm_qos_enabled) {
3392 //check suspend parameter only for low latency and if the property
3393 //is enabled
3394 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
3395 ALOGI("%s: got suspend_playback %s", __func__, value);
3396 lock_output_stream(out);
3397 if (!strncmp(value, "false", 5)) {
3398 //suspend_playback=false is supposed to set QOS value back to 75%
3399 //the mixer control sent with value Enable will achieve that
3400 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3401 } else if (!strncmp (value, "true", 4)) {
3402 //suspend_playback=true is supposed to remove QOS value
3403 //resetting the mixer control will set the default value
3404 //for the mixer control which is Disable and this removes the QOS vote
3405 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
3406 } else {
3407 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
3408 " got %s", __func__, value);
3409 ret = -1;
3410 }
3411
3412 if (ret != 0) {
3413 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
3414 __func__, out->pm_qos_mixer_path, ret);
3415 }
3416
3417 pthread_mutex_unlock(&out->lock);
3418 }
3419 }
3420 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303422error:
Eric Laurent994a6932013-07-17 11:51:42 -07003423 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 return ret;
3425}
3426
3427static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3428{
3429 struct stream_out *out = (struct stream_out *)stream;
3430 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003431 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432 char value[256];
3433 struct str_parms *reply = str_parms_create();
3434 size_t i, j;
3435 int ret;
3436 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003437
3438 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003439 if (reply) {
3440 str_parms_destroy(reply);
3441 }
3442 if (query) {
3443 str_parms_destroy(query);
3444 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003445 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3446 return NULL;
3447 }
3448
Eric Laurent994a6932013-07-17 11:51:42 -07003449 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3451 if (ret >= 0) {
3452 value[0] = '\0';
3453 i = 0;
3454 while (out->supported_channel_masks[i] != 0) {
3455 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3456 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3457 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003458 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003460 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 first = false;
3462 break;
3463 }
3464 }
3465 i++;
3466 }
3467 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3468 str = str_parms_to_str(reply);
3469 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003470 voice_extn_out_get_parameters(out, query, reply);
3471 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003473
Alexy Joseph62142aa2015-11-16 15:10:34 -08003474
3475 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3476 if (ret >= 0) {
3477 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303478 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3479 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003480 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303481 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003482 } else {
3483 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303484 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003485 }
3486 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003487 if (str)
3488 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003489 str = str_parms_to_str(reply);
3490 }
3491
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003492 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3493 if (ret >= 0) {
3494 value[0] = '\0';
3495 i = 0;
3496 first = true;
3497 while (out->supported_formats[i] != 0) {
3498 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3499 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3500 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003501 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003502 }
3503 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3504 first = false;
3505 break;
3506 }
3507 }
3508 i++;
3509 }
3510 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003511 if (str)
3512 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003513 str = str_parms_to_str(reply);
3514 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003515
3516 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3517 if (ret >= 0) {
3518 value[0] = '\0';
3519 i = 0;
3520 first = true;
3521 while (out->supported_sample_rates[i] != 0) {
3522 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3523 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3524 if (!first) {
3525 strlcat(value, "|", sizeof(value));
3526 }
3527 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3528 first = false;
3529 break;
3530 }
3531 }
3532 i++;
3533 }
3534 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3535 if (str)
3536 free(str);
3537 str = str_parms_to_str(reply);
3538 }
3539
Alexy Joseph98988832017-01-13 14:56:59 -08003540 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
3541 //only low latency track supports suspend_resume
3542 str_parms_add_int(reply, "supports_hw_suspend",
3543 (out->dynamic_pm_qos_enabled));
3544 if (str)
3545 free(str);
3546 str = str_parms_to_str(reply);
3547 }
3548
3549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 str_parms_destroy(query);
3551 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003552 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 return str;
3554}
3555
3556static uint32_t out_get_latency(const struct audio_stream_out *stream)
3557{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003558 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003560 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561
Alexy Josephaa54c872014-12-03 02:46:47 -08003562 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303563 lock_output_stream(out);
3564 latency = audio_extn_utils_compress_get_dsp_latency(out);
3565 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07003566 } else if ((out->realtime) ||
3567 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003568 // since the buffer won't be filled up faster than realtime,
3569 // return a smaller number
3570 if (out->config.rate)
3571 period_ms = (out->af_period_multiplier * out->config.period_size *
3572 1000) / (out->config.rate);
3573 else
3574 period_ms = 0;
3575 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003576 } else {
3577 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003579 }
3580
yidongh0515e042017-07-06 15:00:34 +08003581 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003582 latency += audio_extn_a2dp_get_encoder_latency();
3583
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303584 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003585 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586}
3587
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303588static float AmpToDb(float amplification)
3589{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303590 float db = DSD_VOLUME_MIN_DB;
3591 if (amplification > 0) {
3592 db = 20 * log10(amplification);
3593 if(db < DSD_VOLUME_MIN_DB)
3594 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303595 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303596 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303597}
3598
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303599static int out_set_compr_volume(struct audio_stream_out *stream, float left,
3600 float right)
3601{
3602 struct stream_out *out = (struct stream_out *)stream;
3603 int volume[2];
3604 char mixer_ctl_name[128];
3605 struct audio_device *adev = out->dev;
3606 struct mixer_ctl *ctl;
3607 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3608 PCM_PLAYBACK);
3609
3610 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3611 "Compress Playback %d Volume", pcm_device_id);
3612 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3613 if (!ctl) {
3614 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3615 __func__, mixer_ctl_name);
3616 return -EINVAL;
3617 }
3618 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
3619 __func__, mixer_ctl_name, left, right);
3620 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3621 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3622 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3623
3624 return 0;
3625}
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627static int out_set_volume(struct audio_stream_out *stream, float left,
3628 float right)
3629{
Eric Laurenta9024de2013-04-04 09:19:12 -07003630 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003631 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303632 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633
Eric Laurenta9024de2013-04-04 09:19:12 -07003634 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3635 /* only take left channel into account: the API is for stereo anyway */
3636 out->muted = (left == 0.0f);
3637 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003638 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303639 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003640 /*
3641 * Set mute or umute on HDMI passthrough stream.
3642 * Only take left channel into account.
3643 * Mute is 0 and unmute 1
3644 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303645 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303646 } else if (out->format == AUDIO_FORMAT_DSD){
3647 char mixer_ctl_name[128] = "DSD Volume";
3648 struct audio_device *adev = out->dev;
3649 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3650
3651 if (!ctl) {
3652 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3653 __func__, mixer_ctl_name);
3654 return -EINVAL;
3655 }
3656 volume[0] = (int)(AmpToDb(left));
3657 volume[1] = (int)(AmpToDb(right));
3658 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3659 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003660 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303661 pthread_mutex_lock(&out->compr_mute_lock);
3662 ALOGE("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3663 if (!out->a2dp_compress_mute)
3664 ret = out_set_compr_volume(stream, left, right);
3665 out->volume_l = left;
3666 out->volume_r = right;
3667 pthread_mutex_unlock(&out->compr_mute_lock);
3668 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003670 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
3671 char mixer_ctl_name[] = "App Type Gain";
3672 struct audio_device *adev = out->dev;
3673 struct mixer_ctl *ctl;
3674 uint32_t set_values[4];
3675
3676 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3677 if (!ctl) {
3678 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3679 __func__, mixer_ctl_name);
3680 return -EINVAL;
3681 }
3682
3683 set_values[0] = 0; //0: Rx Session 1:Tx Session
3684 set_values[1] = out->app_type_cfg.app_type;
3685 set_values[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3686 set_values[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3687
3688 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
3689 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003690 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 return -ENOSYS;
3693}
3694
Zhou Songc9672822017-08-16 16:01:39 +08003695static void update_frames_written(struct stream_out *out, size_t bytes)
3696{
3697 size_t bpf = 0;
3698
3699 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3700 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3701 bpf = 1;
3702 else if (!is_offload_usecase(out->usecase))
3703 bpf = audio_bytes_per_sample(out->format) *
3704 audio_channel_count_from_out_mask(out->channel_mask);
3705 if (bpf != 0)
3706 out->written += bytes / bpf;
3707}
3708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3710 size_t bytes)
3711{
3712 struct stream_out *out = (struct stream_out *)stream;
3713 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003714 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303715 int channels = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003717 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303718
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303719 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003720
Dhananjay Kumarac341582017-02-23 23:42:25 +05303721 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303722 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303723 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3724 pthread_mutex_unlock(&out->lock);
3725 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303726 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05303727 ALOGD(" %s: sound card is not active/SSR state", __func__);
3728 ret= -EIO;
3729 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303730 }
3731 }
3732
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303733 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303734 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303735 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303736 goto exit;
3737 }
3738
Haynes Mathew George16081042017-05-31 17:16:49 -07003739 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3740 ret = -EINVAL;
3741 goto exit;
3742 }
3743
Manish Dewangan37864bc2017-06-09 12:28:37 +05303744 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303745 channels = platform_edid_get_max_channels(out->dev->platform);
Manish Dewangan672001f2017-08-16 13:44:07 +05303746 if (audio_extn_passthru_is_enabled() &&
3747 !out->is_iec61937_info_available &&
3748 audio_extn_passthru_is_passthrough_stream(out)) {
Manish Dewangan37864bc2017-06-09 12:28:37 +05303749 audio_extn_passthru_update_stream_configuration(adev, out,
3750 buffer, bytes);
3751 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05303752
3753 if((out->format == AUDIO_FORMAT_DTS) ||
3754 (out->format == AUDIO_FORMAT_DTS_HD)) {
3755 ret = audio_extn_passthru_update_dts_stream_configuration(out,
3756 buffer, bytes);
3757 if (ret) {
3758 if (ret != -ENOSYS) {
3759 out->is_iec61937_info_available = false;
3760 ALOGD("iec61937 transmission info not yet updated retry");
3761 }
3762 } else {
3763 /* if stream has started and after that there is
3764 * stream config change (iec transmission config)
3765 * then trigger select_device to update backend configuration.
3766 */
3767 out->stream_config_changed = true;
3768 pthread_mutex_lock(&adev->lock);
3769 select_devices(adev, out->usecase);
3770 pthread_mutex_unlock(&adev->lock);
3771 out->stream_config_changed = false;
3772 out->is_iec61937_info_available = true;
3773 }
3774 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303775
Garmond Leung317cbf12017-09-13 16:20:50 -07003776 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05303777 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
3778 (out->is_iec61937_info_available == true)) {
3779 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
3780 ret = -EINVAL;
3781 goto exit;
3782 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05303783 }
3784 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303785
3786 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3787 (audio_extn_a2dp_is_suspended())) {
3788 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
3789 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303790 ret = -EIO;
3791 goto exit;
3792 }
3793 }
3794 }
3795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003797 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003798 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003799 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3800 ret = voice_extn_compress_voip_start_output_stream(out);
3801 else
3802 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003803 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003804 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003806 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 goto exit;
3808 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303809 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003810 if (last_known_cal_step != -1) {
3811 ALOGD("%s: retry previous failed cal level set", __func__);
3812 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303813 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003814 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816
Ashish Jain81eb2a82015-05-13 10:52:34 +05303817 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003818 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303819 adev->is_channel_status_set = true;
3820 }
3821
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003822 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003823 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003824 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003825 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003826 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3827 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303828 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3829 ALOGD("copl(%p):send next track params in gapless", out);
3830 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3831 out->send_next_track_params = false;
3832 out->is_compr_metadata_avail = false;
3833 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003834 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303835 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303836 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003837
Ashish Jain83a6cc22016-06-28 14:34:17 +05303838 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303839 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303840 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303841 pthread_mutex_unlock(&out->lock);
3842 return -EINVAL;
3843 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303844 audio_format_t dst_format = out->hal_op_format;
3845 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303846
3847 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3848 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3849
Ashish Jain83a6cc22016-06-28 14:34:17 +05303850 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303851 dst_format,
3852 buffer,
3853 src_format,
3854 frames);
3855
Ashish Jain83a6cc22016-06-28 14:34:17 +05303856 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303857 bytes_to_write);
3858
3859 /*Convert written bytes in audio flinger format*/
3860 if (ret > 0)
3861 ret = ((ret * format_to_bitwidth_table[out->format]) /
3862 format_to_bitwidth_table[dst_format]);
3863 }
3864 } else
3865 ret = compress_write(out->compr, buffer, bytes);
3866
Zhou Songc9672822017-08-16 16:01:39 +08003867 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
3868 update_frames_written(out, bytes);
3869
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303870 if (ret < 0)
3871 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303872 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303873 /*msg to cb thread only if non blocking write is enabled*/
3874 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303875 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003876 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303877 } else if (-ENETRESET == ret) {
3878 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303879 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303880 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05303881 out_on_error(&out->stream.common);
Naresh Tanniru80659832014-06-04 18:17:56 +05303882 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003883 }
Ashish Jain5106d362016-05-11 19:23:33 +05303884
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303885 /* Call compr start only when non-zero bytes of data is there to be rendered */
3886 if (!out->playback_started && ret > 0) {
3887 int status = compress_start(out->compr);
3888 if (status < 0) {
3889 ret = status;
3890 ALOGE("%s: compr start failed with err %d", __func__, errno);
3891 goto exit;
3892 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003893 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003894 out->playback_started = 1;
3895 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003896
3897 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3898 popcount(out->channel_mask),
3899 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003900 }
3901 pthread_mutex_unlock(&out->lock);
3902 return ret;
3903 } else {
3904 if (out->pcm) {
3905 if (out->muted)
3906 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003907
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303908 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003909
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003910 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003911
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003912 if (out->config.rate)
3913 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3914 out->config.rate;
3915
3916 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3917
3918 request_out_focus(out, ns);
3919
3920 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003921 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003922 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303923 out->convert_buffer != NULL) {
3924
3925 memcpy_by_audio_format(out->convert_buffer,
3926 out->hal_op_format,
3927 buffer,
3928 out->hal_ip_format,
3929 out->config.period_size * out->config.channels);
3930
3931 ret = pcm_write(out->pcm, out->convert_buffer,
3932 (out->config.period_size *
3933 out->config.channels *
3934 format_to_bitwidth_table[out->hal_op_format]));
3935 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303936 /*
3937 * To avoid underrun in DSP when the application is not pumping
3938 * data at required rate, check for the no. of bytes and ignore
3939 * pcm_write if it is less than actual buffer size.
3940 * It is a work around to a change in compress VOIP driver.
3941 */
3942 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3943 bytes < (out->config.period_size * out->config.channels *
3944 audio_bytes_per_sample(out->format))) {
3945 size_t voip_buf_size =
3946 out->config.period_size * out->config.channels *
3947 audio_bytes_per_sample(out->format);
3948 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3949 __func__, bytes, voip_buf_size);
3950 usleep(((uint64_t)voip_buf_size - bytes) *
3951 1000000 / audio_stream_out_frame_size(stream) /
3952 out_get_sample_rate(&out->stream.common));
3953 ret = 0;
3954 } else
3955 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303956 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003957
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003958 release_out_focus(out);
3959
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303960 if (ret < 0)
3961 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08003962 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303963 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003965 }
3966
3967exit:
Zhou Songc9672822017-08-16 16:01:39 +08003968 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303969 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303970 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303971 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 pthread_mutex_unlock(&out->lock);
3973
3974 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003975 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003976 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303977 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303978 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303979 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303980 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303981 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303982 out->standby = true;
3983 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303984 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303985 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3986 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3987 out_get_sample_rate(&out->stream.common));
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07003988
3989 if (audio_extn_passthru_is_passthrough_stream(out)) {
Garmond Leung317cbf12017-09-13 16:20:50 -07003990 ALOGE("%s: write error, ret = %ld", __func__, ret);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07003991 return ret;
3992 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993 }
3994 return bytes;
3995}
3996
3997static int out_get_render_position(const struct audio_stream_out *stream,
3998 uint32_t *dsp_frames)
3999{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004000 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08004001
4002 if (dsp_frames == NULL)
4003 return -EINVAL;
4004
4005 *dsp_frames = 0;
4006 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08004007 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304008
4009 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
4010 * this operation and adev_close_output_stream(where out gets reset).
4011 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304012 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304013 *dsp_frames = get_actual_pcm_frames_rendered(out);
4014 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
4015 return 0;
4016 }
4017
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004018 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05304019 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304020 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004021 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05304022 if (ret < 0)
4023 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004024 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05304025 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004026 }
Naresh Tanniru80659832014-06-04 18:17:56 +05304027 if (-ENETRESET == ret) {
4028 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304029 out->card_status = CARD_STATUS_OFFLINE;
4030 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304031 } else if(ret < 0) {
4032 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304033 ret = -EINVAL;
4034 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05304035 /*
4036 * Handle corner case where compress session is closed during SSR
4037 * and timestamp is queried
4038 */
4039 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304040 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304041 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304042 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05304043 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304044 pthread_mutex_unlock(&out->lock);
4045 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08004046 } else if (audio_is_linear_pcm(out->format)) {
4047 *dsp_frames = out->written;
4048 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004049 } else
4050 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051}
4052
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004053static int out_add_audio_effect(const struct audio_stream *stream __unused,
4054 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055{
4056 return 0;
4057}
4058
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004059static int out_remove_audio_effect(const struct audio_stream *stream __unused,
4060 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061{
4062 return 0;
4063}
4064
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004065static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
4066 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304068 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069}
4070
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004071static int out_get_presentation_position(const struct audio_stream_out *stream,
4072 uint64_t *frames, struct timespec *timestamp)
4073{
4074 struct stream_out *out = (struct stream_out *)stream;
4075 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07004076 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004077
Ashish Jain5106d362016-05-11 19:23:33 +05304078 /* below piece of code is not guarded against any lock because audioFliner serializes
4079 * this operation and adev_close_output_stream( where out gets reset).
4080 */
4081 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05304082 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304083 *frames = get_actual_pcm_frames_rendered(out);
4084 /* this is the best we can do */
4085 clock_gettime(CLOCK_MONOTONIC, timestamp);
4086 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
4087 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
4088 return 0;
4089 }
4090
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004091 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004092
Ashish Jain5106d362016-05-11 19:23:33 +05304093 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
4094 ret = compress_get_tstamp(out->compr, &dsp_frames,
4095 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08004096 // Adjustment accounts for A2dp encoder latency with offload usecases
4097 // Note: Encoder latency is returned in ms.
4098 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4099 unsigned long offset =
4100 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4101 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
4102 }
Ashish Jain5106d362016-05-11 19:23:33 +05304103 ALOGVV("%s rendered frames %ld sample_rate %d",
4104 __func__, dsp_frames, out->sample_rate);
4105 *frames = dsp_frames;
4106 if (ret < 0)
4107 ret = -errno;
4108 if (-ENETRESET == ret) {
4109 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304110 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05304111 ret = -EINVAL;
4112 } else
4113 ret = 0;
4114 /* this is the best we can do */
4115 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07004116 } else {
4117 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004118 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07004119 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
4120 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07004121 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07004122 // This adjustment accounts for buffering after app processor.
4123 // It is based on estimated DSP latency per use case, rather than exact.
4124 signed_frames -=
4125 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
4126
Aniket Kumar Lataff613152017-07-18 18:19:21 -07004127 // Adjustment accounts for A2dp encoder latency with non offload usecases
4128 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
4129 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
4130 signed_frames -=
4131 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
4132 }
4133
Eric Laurent949a0892013-09-20 09:20:13 -07004134 // It would be unusual for this value to be negative, but check just in case ...
4135 if (signed_frames >= 0) {
4136 *frames = signed_frames;
4137 ret = 0;
4138 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004139 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304140 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05304141 *frames = out->written;
4142 clock_gettime(CLOCK_MONOTONIC, timestamp);
4143 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004144 }
4145 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004146 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004147 return ret;
4148}
4149
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004150static int out_set_callback(struct audio_stream_out *stream,
4151 stream_callback_t callback, void *cookie)
4152{
4153 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004154 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004155
4156 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004157 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004158 out->client_callback = callback;
4159 out->client_cookie = cookie;
4160 if (out->adsp_hdlr_stream_handle) {
4161 ret = audio_extn_adsp_hdlr_stream_set_callback(
4162 out->adsp_hdlr_stream_handle,
4163 callback,
4164 cookie);
4165 if (ret)
4166 ALOGW("%s:adsp hdlr callback registration failed %d",
4167 __func__, ret);
4168 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004169 pthread_mutex_unlock(&out->lock);
4170 return 0;
4171}
4172
4173static int out_pause(struct audio_stream_out* stream)
4174{
4175 struct stream_out *out = (struct stream_out *)stream;
4176 int status = -ENOSYS;
4177 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004178 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004179 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004180 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004181 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304182 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05304183 status = compress_pause(out->compr);
4184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004185 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004186
Mingming Yin21854652016-04-13 11:54:02 -07004187 if (audio_extn_passthru_is_active()) {
4188 ALOGV("offload use case, pause passthru");
4189 audio_extn_passthru_on_pause(out);
4190 }
4191
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304192 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004193 audio_extn_dts_notify_playback_state(out->usecase, 0,
4194 out->sample_rate, popcount(out->channel_mask),
4195 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004196 }
4197 pthread_mutex_unlock(&out->lock);
4198 }
4199 return status;
4200}
4201
4202static int out_resume(struct audio_stream_out* stream)
4203{
4204 struct stream_out *out = (struct stream_out *)stream;
4205 int status = -ENOSYS;
4206 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004207 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004208 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004209 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004210 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004211 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304212 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05304213 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07004214 }
4215 if (!status) {
4216 out->offload_state = OFFLOAD_STATE_PLAYING;
4217 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05304218 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004219 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4220 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004221 }
4222 pthread_mutex_unlock(&out->lock);
4223 }
4224 return status;
4225}
4226
4227static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
4228{
4229 struct stream_out *out = (struct stream_out *)stream;
4230 int status = -ENOSYS;
4231 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004232 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004233 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004234 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
4235 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
4236 else
4237 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
4238 pthread_mutex_unlock(&out->lock);
4239 }
4240 return status;
4241}
4242
4243static int out_flush(struct audio_stream_out* stream)
4244{
4245 struct stream_out *out = (struct stream_out *)stream;
4246 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004247 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004248 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004249 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07004250 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
4251 stop_compressed_output_l(out);
4252 out->written = 0;
4253 } else {
4254 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
4255 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004256 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004257 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004258 return 0;
4259 }
4260 return -ENOSYS;
4261}
4262
Haynes Mathew George16081042017-05-31 17:16:49 -07004263static int out_stop(const struct audio_stream_out* stream)
4264{
4265 struct stream_out *out = (struct stream_out *)stream;
4266 struct audio_device *adev = out->dev;
4267 int ret = -ENOSYS;
4268
4269 ALOGV("%s", __func__);
4270 pthread_mutex_lock(&adev->lock);
4271 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4272 out->playback_started && out->pcm != NULL) {
4273 pcm_stop(out->pcm);
4274 ret = stop_output_stream(out);
4275 out->playback_started = false;
4276 }
4277 pthread_mutex_unlock(&adev->lock);
4278 return ret;
4279}
4280
4281static int out_start(const struct audio_stream_out* stream)
4282{
4283 struct stream_out *out = (struct stream_out *)stream;
4284 struct audio_device *adev = out->dev;
4285 int ret = -ENOSYS;
4286
4287 ALOGV("%s", __func__);
4288 pthread_mutex_lock(&adev->lock);
4289 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
4290 !out->playback_started && out->pcm != NULL) {
4291 ret = start_output_stream(out);
4292 if (ret == 0) {
4293 out->playback_started = true;
4294 }
4295 }
4296 pthread_mutex_unlock(&adev->lock);
4297 return ret;
4298}
4299
4300/*
4301 * Modify config->period_count based on min_size_frames
4302 */
4303static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
4304{
4305 int periodCountRequested = (min_size_frames + config->period_size - 1)
4306 / config->period_size;
4307 int periodCount = MMAP_PERIOD_COUNT_MIN;
4308
4309 ALOGV("%s original config.period_size = %d config.period_count = %d",
4310 __func__, config->period_size, config->period_count);
4311
4312 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
4313 periodCount *= 2;
4314 }
4315 config->period_count = periodCount;
4316
4317 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
4318}
4319
4320static int out_create_mmap_buffer(const struct audio_stream_out *stream,
4321 int32_t min_size_frames,
4322 struct audio_mmap_buffer_info *info)
4323{
4324 struct stream_out *out = (struct stream_out *)stream;
4325 struct audio_device *adev = out->dev;
4326 int ret = 0;
4327 unsigned int offset1;
4328 unsigned int frames1;
4329 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004330 uint32_t mmap_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07004331
4332 ALOGV("%s", __func__);
4333 pthread_mutex_lock(&adev->lock);
4334
4335 if (info == NULL || min_size_frames == 0) {
4336 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
4337 ret = -EINVAL;
4338 goto exit;
4339 }
4340 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
4341 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
4342 ret = -ENOSYS;
4343 goto exit;
4344 }
4345 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4346 if (out->pcm_device_id < 0) {
4347 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4348 __func__, out->pcm_device_id, out->usecase);
4349 ret = -EINVAL;
4350 goto exit;
4351 }
4352
4353 adjust_mmap_period_count(&out->config, min_size_frames);
4354
4355 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4356 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
4357 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
4358 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
4359 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4360 step = "open";
4361 ret = -ENODEV;
4362 goto exit;
4363 }
4364 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
4365 if (ret < 0) {
4366 step = "begin";
4367 goto exit;
4368 }
4369 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
4370 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004371 ret = platform_get_mmap_data_fd(adev->platform,
4372 out->pcm_device_id, 0 /*playback*/,
4373 &info->shared_memory_fd,
4374 &mmap_size);
4375 if (ret < 0) {
4376 step = "get_mmap_fd";
4377 goto exit;
4378 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004379 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07004380 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07004381
4382 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4383 if (ret < 0) {
4384 step = "commit";
4385 goto exit;
4386 }
4387
4388 out->standby = false;
4389 ret = 0;
4390
4391 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4392 __func__, info->shared_memory_address, info->buffer_size_frames);
4393
4394exit:
4395 if (ret != 0) {
4396 if (out->pcm == NULL) {
4397 ALOGE("%s: %s - %d", __func__, step, ret);
4398 } else {
4399 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
4400 pcm_close(out->pcm);
4401 out->pcm = NULL;
4402 }
4403 }
4404 pthread_mutex_unlock(&adev->lock);
4405 return ret;
4406}
4407
4408static int out_get_mmap_position(const struct audio_stream_out *stream,
4409 struct audio_mmap_position *position)
4410{
4411 struct stream_out *out = (struct stream_out *)stream;
4412 ALOGVV("%s", __func__);
4413 if (position == NULL) {
4414 return -EINVAL;
4415 }
4416 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
4417 return -ENOSYS;
4418 }
4419 if (out->pcm == NULL) {
4420 return -ENOSYS;
4421 }
4422
4423 struct timespec ts = { 0, 0 };
4424 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
4425 if (ret < 0) {
4426 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
4427 return ret;
4428 }
4429 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4430 return 0;
4431}
4432
4433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434/** audio_stream_in implementation **/
4435static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4436{
4437 struct stream_in *in = (struct stream_in *)stream;
4438
4439 return in->config.rate;
4440}
4441
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004442static int in_set_sample_rate(struct audio_stream *stream __unused,
4443 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444{
4445 return -ENOSYS;
4446}
4447
4448static size_t in_get_buffer_size(const struct audio_stream *stream)
4449{
4450 struct stream_in *in = (struct stream_in *)stream;
4451
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004452 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
4453 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004454 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
4455 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 -07004456 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
4457 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304458 else if(audio_extn_cin_attached_usecase(in->usecase))
4459 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004460
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004461 return in->config.period_size * in->af_period_multiplier *
4462 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463}
4464
4465static uint32_t in_get_channels(const struct audio_stream *stream)
4466{
4467 struct stream_in *in = (struct stream_in *)stream;
4468
4469 return in->channel_mask;
4470}
4471
4472static audio_format_t in_get_format(const struct audio_stream *stream)
4473{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004474 struct stream_in *in = (struct stream_in *)stream;
4475
4476 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477}
4478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004479static int in_set_format(struct audio_stream *stream __unused,
4480 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481{
4482 return -ENOSYS;
4483}
4484
4485static int in_standby(struct audio_stream *stream)
4486{
4487 struct stream_in *in = (struct stream_in *)stream;
4488 struct audio_device *adev = in->dev;
4489 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304490 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4491 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07004492 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304493
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004494 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004495 if (!in->standby && in->is_st_session) {
4496 ALOGD("%s: sound trigger pcm stop lab", __func__);
4497 audio_extn_sound_trigger_stop_lab(in);
4498 in->standby = 1;
4499 }
4500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004501 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004502 if (adev->adm_deregister_stream)
4503 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4504
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004505 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004507 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08004508 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08004509 voice_extn_compress_voip_close_input_stream(stream);
4510 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07004511 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4512 do_stop = in->capture_started;
4513 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08004514 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304515 if (audio_extn_cin_attached_usecase(in->usecase))
4516 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08004517 }
4518
4519 if (do_stop) {
Zhou Songa8895042016-07-05 17:54:22 +08004520 if (in->pcm) {
4521 pcm_close(in->pcm);
4522 in->pcm = NULL;
4523 }
4524 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004525 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004526 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 }
4528 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004529 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530 return status;
4531}
4532
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004533static int in_dump(const struct audio_stream *stream __unused,
4534 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535{
4536 return 0;
4537}
4538
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304539static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4540{
4541 if (!stream || !parms)
4542 return;
4543
4544 struct stream_in *in = (struct stream_in *)stream;
4545 struct audio_device *adev = in->dev;
4546
4547 card_status_t status;
4548 int card;
4549 if (parse_snd_card_status(parms, &card, &status) < 0)
4550 return;
4551
4552 pthread_mutex_lock(&adev->lock);
4553 bool valid_cb = (card == adev->snd_card);
4554 pthread_mutex_unlock(&adev->lock);
4555
4556 if (!valid_cb)
4557 return;
4558
4559 lock_input_stream(in);
4560 if (in->card_status != status)
4561 in->card_status = status;
4562 pthread_mutex_unlock(&in->lock);
4563
4564 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4565 use_case_table[in->usecase],
4566 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4567
4568 // a better solution would be to report error back to AF and let
4569 // it put the stream to standby
4570 if (status == CARD_STATUS_OFFLINE)
4571 in_standby(&in->stream.common);
4572
4573 return;
4574}
4575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4577{
4578 struct stream_in *in = (struct stream_in *)stream;
4579 struct audio_device *adev = in->dev;
4580 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004582 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304584 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004585 parms = str_parms_create_str(kvpairs);
4586
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304587 if (!parms)
4588 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004589 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004590 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004591
4592 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4593 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594 val = atoi(value);
4595 /* no audio source uses val == 0 */
4596 if ((in->source != val) && (val != 0)) {
4597 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004598 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4599 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4600 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004601 (in->config.rate == 8000 || in->config.rate == 16000 ||
4602 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004603 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004604 err = voice_extn_compress_voip_open_input_stream(in);
4605 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004606 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004607 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004608 }
4609 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610 }
4611 }
4612
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004613 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4614 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004616 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 in->device = val;
4618 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004619 if (!in->standby && !in->is_st_session) {
4620 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004621 if (adev->adm_on_routing_change)
4622 adev->adm_on_routing_change(adev->adm_data,
4623 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004624 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626 }
4627 }
4628
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304629 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4630 if (err >= 0) {
4631 strlcpy(in->profile, value, sizeof(in->profile));
4632 ALOGV("updating stream profile with value '%s'", in->profile);
4633 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4634 &adev->streams_input_cfg_list,
4635 in->device, in->flags, in->format,
4636 in->sample_rate, in->bit_width,
4637 in->profile, &in->app_type_cfg);
4638 }
4639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004641 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642
4643 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304644error:
Eric Laurent994a6932013-07-17 11:51:42 -07004645 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 return ret;
4647}
4648
4649static char* in_get_parameters(const struct audio_stream *stream,
4650 const char *keys)
4651{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004652 struct stream_in *in = (struct stream_in *)stream;
4653 struct str_parms *query = str_parms_create_str(keys);
4654 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004655 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004656
4657 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004658 if (reply) {
4659 str_parms_destroy(reply);
4660 }
4661 if (query) {
4662 str_parms_destroy(query);
4663 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004664 ALOGE("in_get_parameters: failed to create query or reply");
4665 return NULL;
4666 }
4667
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004668 ALOGV("%s: enter: keys - %s", __func__, keys);
4669
4670 voice_extn_in_get_parameters(in, query, reply);
4671
4672 str = str_parms_to_str(reply);
4673 str_parms_destroy(query);
4674 str_parms_destroy(reply);
4675
4676 ALOGV("%s: exit: returns - %s", __func__, str);
4677 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678}
4679
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004680static int in_set_gain(struct audio_stream_in *stream __unused,
4681 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682{
4683 return 0;
4684}
4685
4686static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4687 size_t bytes)
4688{
4689 struct stream_in *in = (struct stream_in *)stream;
4690 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304691 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304692 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004694 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304695
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004696 if (in->is_st_session) {
4697 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4698 /* Read from sound trigger HAL */
4699 audio_extn_sound_trigger_read(in, buffer, bytes);
4700 pthread_mutex_unlock(&in->lock);
4701 return bytes;
4702 }
4703
Haynes Mathew George16081042017-05-31 17:16:49 -07004704 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4705 ret = -ENOSYS;
4706 goto exit;
4707 }
4708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004710 pthread_mutex_lock(&adev->lock);
4711 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4712 ret = voice_extn_compress_voip_start_input_stream(in);
4713 else
4714 ret = start_input_stream(in);
4715 pthread_mutex_unlock(&adev->lock);
4716 if (ret != 0) {
4717 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718 }
4719 in->standby = 0;
4720 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004722 // what's the duration requested by the client?
4723 long ns = 0;
4724
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304725 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004726 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4727 in->config.rate;
4728
4729 request_in_focus(in, ns);
4730 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004731
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304732 if (audio_extn_cin_attached_usecase(in->usecase)) {
4733 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4734 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304735 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004736 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304737 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004738 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004739 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004740 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304741 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004742 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304743 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4744 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4745 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4746 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304747 ret = -EINVAL;
4748 goto exit;
4749 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304750 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304751 ret = -errno;
4752 }
4753 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304754 /* bytes read is always set to bytes for non compress usecases */
4755 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004756 }
4757
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004758 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 /*
4761 * Instead of writing zeroes here, we could trust the hardware
4762 * to always provide zeroes when muted.
4763 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304764 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4765 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 memset(buffer, 0, bytes);
4767
4768exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004769 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304770 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 pthread_mutex_unlock(&in->lock);
4772
4773 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304774 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304775 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304776 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304777 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304778 in->standby = true;
4779 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304780 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4781 bytes_read = bytes;
4782 memset(buffer, 0, bytes);
4783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004785 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304786 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304787 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304789 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790}
4791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004792static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793{
4794 return 0;
4795}
4796
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004797static int add_remove_audio_effect(const struct audio_stream *stream,
4798 effect_handle_t effect,
4799 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004801 struct stream_in *in = (struct stream_in *)stream;
4802 int status = 0;
4803 effect_descriptor_t desc;
4804
4805 status = (*effect)->get_descriptor(effect, &desc);
4806 if (status != 0)
4807 return status;
4808
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004809 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004810 pthread_mutex_lock(&in->dev->lock);
4811 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4812 in->enable_aec != enable &&
4813 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4814 in->enable_aec = enable;
4815 if (!in->standby)
4816 select_devices(in->dev, in->usecase);
4817 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004818 if (in->enable_ns != enable &&
4819 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4820 in->enable_ns = enable;
4821 if (!in->standby)
4822 select_devices(in->dev, in->usecase);
4823 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004824 pthread_mutex_unlock(&in->dev->lock);
4825 pthread_mutex_unlock(&in->lock);
4826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827 return 0;
4828}
4829
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004830static int in_add_audio_effect(const struct audio_stream *stream,
4831 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832{
Eric Laurent994a6932013-07-17 11:51:42 -07004833 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004834 return add_remove_audio_effect(stream, effect, true);
4835}
4836
4837static int in_remove_audio_effect(const struct audio_stream *stream,
4838 effect_handle_t effect)
4839{
Eric Laurent994a6932013-07-17 11:51:42 -07004840 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004841 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842}
4843
Haynes Mathew George16081042017-05-31 17:16:49 -07004844static int in_stop(const struct audio_stream_in* stream)
4845{
4846 struct stream_in *in = (struct stream_in *)stream;
4847 struct audio_device *adev = in->dev;
4848
4849 int ret = -ENOSYS;
4850 ALOGV("%s", __func__);
4851 pthread_mutex_lock(&adev->lock);
4852 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4853 in->capture_started && in->pcm != NULL) {
4854 pcm_stop(in->pcm);
4855 ret = stop_input_stream(in);
4856 in->capture_started = false;
4857 }
4858 pthread_mutex_unlock(&adev->lock);
4859 return ret;
4860}
4861
4862static int in_start(const struct audio_stream_in* stream)
4863{
4864 struct stream_in *in = (struct stream_in *)stream;
4865 struct audio_device *adev = in->dev;
4866 int ret = -ENOSYS;
4867
4868 ALOGV("%s in %p", __func__, in);
4869 pthread_mutex_lock(&adev->lock);
4870 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4871 !in->capture_started && in->pcm != NULL) {
4872 if (!in->capture_started) {
4873 ret = start_input_stream(in);
4874 if (ret == 0) {
4875 in->capture_started = true;
4876 }
4877 }
4878 }
4879 pthread_mutex_unlock(&adev->lock);
4880 return ret;
4881}
4882
4883static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4884 int32_t min_size_frames,
4885 struct audio_mmap_buffer_info *info)
4886{
4887 struct stream_in *in = (struct stream_in *)stream;
4888 struct audio_device *adev = in->dev;
4889 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004890 unsigned int offset1 = 0;
4891 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07004892 const char *step = "";
4893
4894 pthread_mutex_lock(&adev->lock);
4895 ALOGV("%s in %p", __func__, in);
4896
4897 if (info == NULL || min_size_frames == 0) {
4898 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
4899 ret = -EINVAL;
4900 goto exit;
4901 }
4902 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
4903 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
4904 ALOGV("%s in %p", __func__, in);
4905 ret = -ENOSYS;
4906 goto exit;
4907 }
4908 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4909 if (in->pcm_device_id < 0) {
4910 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4911 __func__, in->pcm_device_id, in->usecase);
4912 ret = -EINVAL;
4913 goto exit;
4914 }
4915
4916 adjust_mmap_period_count(&in->config, min_size_frames);
4917
4918 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4919 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4920 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4921 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4922 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4923 step = "open";
4924 ret = -ENODEV;
4925 goto exit;
4926 }
4927
4928 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4929 if (ret < 0) {
4930 step = "begin";
4931 goto exit;
4932 }
4933 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
4934 info->burst_size_frames = in->config.period_size;
4935 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4936
4937 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
4938 info->buffer_size_frames));
4939
4940 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4941 if (ret < 0) {
4942 step = "commit";
4943 goto exit;
4944 }
4945
4946 in->standby = false;
4947 ret = 0;
4948
4949 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4950 __func__, info->shared_memory_address, info->buffer_size_frames);
4951
4952exit:
4953 if (ret != 0) {
4954 if (in->pcm == NULL) {
4955 ALOGE("%s: %s - %d", __func__, step, ret);
4956 } else {
4957 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
4958 pcm_close(in->pcm);
4959 in->pcm = NULL;
4960 }
4961 }
4962 pthread_mutex_unlock(&adev->lock);
4963 return ret;
4964}
4965
4966static int in_get_mmap_position(const struct audio_stream_in *stream,
4967 struct audio_mmap_position *position)
4968{
4969 struct stream_in *in = (struct stream_in *)stream;
4970 ALOGVV("%s", __func__);
4971 if (position == NULL) {
4972 return -EINVAL;
4973 }
4974 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
4975 return -ENOSYS;
4976 }
4977 if (in->pcm == NULL) {
4978 return -ENOSYS;
4979 }
4980 struct timespec ts = { 0, 0 };
4981 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
4982 if (ret < 0) {
4983 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
4984 return ret;
4985 }
4986 position->time_nanoseconds = ts.tv_sec*1000000000L + ts.tv_nsec;
4987 return 0;
4988}
4989
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304990int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07004991 audio_io_handle_t handle,
4992 audio_devices_t devices,
4993 audio_output_flags_t flags,
4994 struct audio_config *config,
4995 struct audio_stream_out **stream_out,
4996 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997{
4998 struct audio_device *adev = (struct audio_device *)dev;
4999 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305000 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005001 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005002 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05305003 bool is_direct_passthough = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
5008
Mingming Yin3a941d42016-02-17 18:08:05 -08005009 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
5010 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305011 devices, flags, &out->stream);
5012
5013
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005014 if (!out) {
5015 return -ENOMEM;
5016 }
5017
Haynes Mathew George204045b2015-02-25 20:32:03 -08005018 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005019 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305020 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08005021 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005023 if (devices == AUDIO_DEVICE_NONE)
5024 devices = AUDIO_DEVICE_OUT_SPEAKER;
5025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026 out->flags = flags;
5027 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07005028 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005029 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005030 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05305031 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05305032 if (out->channel_mask == AUDIO_CHANNEL_NONE)
5033 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
5034 else
5035 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07005036 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005037 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08005038 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305039 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305040 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305041 out->a2dp_compress_mute = false;
Alexy Joseph98988832017-01-13 14:56:59 -08005042 out->dynamic_pm_qos_enabled = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05305044 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Ben Romberger6c4d3812017-06-13 17:46:45 -07005045 (property_get_bool("audio.matrix.limiter.enable", false)))
5046 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
5047
Mingming Yin3a941d42016-02-17 18:08:05 -08005048 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5049 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
5050 pthread_mutex_lock(&adev->lock);
5051 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
5052 ret = read_hdmi_sink_caps(out);
5053 pthread_mutex_unlock(&adev->lock);
5054 if (ret != 0) {
5055 if (ret == -ENOSYS) {
5056 /* ignore and go with default */
5057 ret = 0;
5058 } else {
5059 ALOGE("error reading hdmi sink caps");
5060 goto error_open;
5061 }
5062 }
5063 }
5064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065 /* Init use case and pcm_config */
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305066#ifndef COMPRES_ENABLED
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005067 if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5068 (out->sample_rate == 8000 || out->sample_rate == 16000 ||
5069 out->sample_rate == 32000 || out->sample_rate == 48000)) {
5070 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
5071 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
5072 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5073
5074 out->config = default_pcm_config_voip_copp;
5075 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
5076 out->config.rate = out->sample_rate;
5077
5078#else
Nikhil Latukar2e6f6242017-08-15 13:37:07 +05305079 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005080 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08005081 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005082 ret = voice_extn_compress_voip_open_output_stream(out);
5083 if (ret != 0) {
5084 ALOGE("%s: Compress voip output cannot be opened, error:%d",
5085 __func__, ret);
5086 goto error_open;
5087 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005088#endif
vivek mehta0ea887a2015-08-26 14:01:20 -07005089 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305090 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305091 pthread_mutex_lock(&adev->lock);
5092 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5093 pthread_mutex_unlock(&adev->lock);
5094
5095 // reject offload during card offline to allow
5096 // fallback to s/w paths
5097 if (offline) {
5098 ret = -ENODEV;
5099 goto error_open;
5100 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005101
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005102 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5103 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5104 ALOGE("%s: Unsupported Offload information", __func__);
5105 ret = -EINVAL;
5106 goto error_open;
5107 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005108
Mingming Yin3a941d42016-02-17 18:08:05 -08005109 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005110 if(config->offload_info.format == 0)
5111 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08005112 if (config->offload_info.sample_rate == 0)
5113 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005114 }
5115
Mingming Yin90310102013-11-13 16:57:00 -08005116 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305117 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07005118 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005119 ret = -EINVAL;
5120 goto error_open;
5121 }
5122
Ben Romberger0f8c87b2017-05-24 17:41:11 -07005123 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
5124 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
5125 (audio_extn_passthru_is_passthrough_stream(out)) &&
5126 !((config->sample_rate == 48000) ||
5127 (config->sample_rate == 96000) ||
5128 (config->sample_rate == 192000))) {
5129 ALOGE("%s: Unsupported sample rate %d for audio format %x",
5130 __func__, config->sample_rate, config->offload_info.format);
5131 ret = -EINVAL;
5132 goto error_open;
5133 }
5134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005135 out->compr_config.codec = (struct snd_codec *)
5136 calloc(1, sizeof(struct snd_codec));
5137
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005138 if (!out->compr_config.codec) {
5139 ret = -ENOMEM;
5140 goto error_open;
5141 }
5142
Dhananjay Kumarac341582017-02-23 23:42:25 +05305143 out->stream.pause = out_pause;
5144 out->stream.resume = out_resume;
5145 out->stream.flush = out_flush;
5146 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07005147 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07005148 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05305149 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07005150 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05305151 } else {
5152 out->usecase = get_offload_usecase(adev, false /* is_compress */);
5153 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07005154 }
vivek mehta446c3962015-09-14 10:57:35 -07005155
5156 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005157 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
5158 config->format == 0 && config->sample_rate == 0 &&
5159 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07005160 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08005161 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
5162 } else {
5163 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
5164 ret = -EEXIST;
5165 goto error_open;
5166 }
vivek mehta446c3962015-09-14 10:57:35 -07005167 }
5168
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005169 if (config->offload_info.channel_mask)
5170 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005171 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005172 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005173 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005174 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05305175 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005176 ret = -EINVAL;
5177 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08005178 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07005179
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005180 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005181 out->sample_rate = config->offload_info.sample_rate;
5182
Mingming Yin3ee55c62014-08-04 14:23:35 -07005183 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005184
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305185 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
5186 if (audio_extn_is_dolby_format(config->offload_info.format)) {
5187 audio_extn_dolby_send_ddp_endp_params(adev);
5188 audio_extn_dolby_set_dmid(adev);
5189 }
vivek mehta0ea887a2015-08-26 14:01:20 -07005190
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005191 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08005192 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005193 out->compr_config.codec->bit_rate =
5194 config->offload_info.bit_rate;
5195 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05305196 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005197 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05305198 /* Update bit width only for non passthrough usecases.
5199 * For passthrough usecases, the output will always be opened @16 bit
5200 */
5201 if (!audio_extn_passthru_is_passthrough_stream(out))
5202 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305203
5204 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
5205 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
5206 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
5207
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005208 /*TODO: Do we need to change it for passthrough */
5209 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005210
Manish Dewangana6fc5442015-08-24 20:30:31 +05305211 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
5212 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305213 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05305214 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05305215 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
5216 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305217
5218 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
5219 AUDIO_FORMAT_PCM) {
5220
5221 /*Based on platform support, configure appropriate alsa format for corresponding
5222 *hal input format.
5223 */
5224 out->compr_config.codec->format = hal_format_to_alsa(
5225 config->offload_info.format);
5226
Ashish Jain83a6cc22016-06-28 14:34:17 +05305227 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05305228 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305229 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305230
Dhananjay Kumarac341582017-02-23 23:42:25 +05305231 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05305232 *hal input format and alsa format might differ based on platform support.
5233 */
5234 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05305235 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305236
5237 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
5238
5239 /* Check if alsa session is configured with the same format as HAL input format,
5240 * if not then derive correct fragment size needed to accomodate the
5241 * conversion of HAL input format to alsa format.
5242 */
5243 audio_extn_utils_update_direct_pcm_fragment_size(out);
5244
5245 /*if hal input and output fragment size is different this indicates HAL input format is
5246 *not same as the alsa format
5247 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305248 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305249 /*Allocate a buffer to convert input data to the alsa configured format.
5250 *size of convert buffer is equal to the size required to hold one fragment size
5251 *worth of pcm data, this is because flinger does not write more than fragment_size
5252 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05305253 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
5254 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05305255 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
5256 ret = -ENOMEM;
5257 goto error_open;
5258 }
5259 }
5260 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
5261 out->compr_config.fragment_size =
5262 audio_extn_passthru_get_buffer_size(&config->offload_info);
5263 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5264 } else {
5265 out->compr_config.fragment_size =
5266 platform_get_compress_offload_buffer_size(&config->offload_info);
5267 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
5268 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07005269
Naresh Tanniruee3499a2017-01-05 14:05:35 +05305270 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5271 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
5272 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07005273 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05305274 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07005275
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05305276 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
5277 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
5278 }
5279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005280 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5281 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005282
Manish Dewangan69426c82017-01-30 17:35:36 +05305283 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
5284 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
5285 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
5286 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
5287 out->render_mode = RENDER_MODE_AUDIO_MASTER;
5288 } else {
5289 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
5290 }
Alexy Josephaa54c872014-12-03 02:46:47 -08005291
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05305292 memset(&out->channel_map_param, 0,
5293 sizeof(struct audio_out_channel_map_param));
5294
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005295 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305296 out->send_next_track_params = false;
5297 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08005298 out->offload_state = OFFLOAD_STATE_IDLE;
5299 out->playback_started = 0;
5300
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005301 audio_extn_dts_create_state_notifier_node(out->usecase);
5302
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005303 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5304 __func__, config->offload_info.version,
5305 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05305306
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305307 /* Check if DSD audio format is supported in codec
5308 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305309 */
5310
5311 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305312 (!platform_check_codec_dsd_support(adev->platform) ||
5313 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305314 ret = -EINVAL;
5315 goto error_open;
5316 }
5317
Ashish Jain5106d362016-05-11 19:23:33 +05305318 /* Disable gapless if any of the following is true
5319 * passthrough playback
5320 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05305321 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05305322 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305323 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305324 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07005325 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305326 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05305327 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05305328 check_and_set_gapless_mode(adev, false);
5329 } else
5330 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07005331
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305332 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07005333 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5334 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305335 if (config->format == AUDIO_FORMAT_DSD) {
5336 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
5337 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
5338 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07005339
5340 create_offload_callback_thread(out);
5341
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005342 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305343 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07005344 if (ret != 0) {
5345 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
5346 __func__, ret);
5347 goto error_open;
5348 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005349 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
5350 if (config->sample_rate == 0)
5351 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5352 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5353 config->sample_rate != 8000) {
5354 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5355 ret = -EINVAL;
5356 goto error_open;
5357 }
5358 out->sample_rate = config->sample_rate;
5359 out->config.rate = config->sample_rate;
5360 if (config->format == AUDIO_FORMAT_DEFAULT)
5361 config->format = AUDIO_FORMAT_PCM_16_BIT;
5362 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5363 config->format = AUDIO_FORMAT_PCM_16_BIT;
5364 ret = -EINVAL;
5365 goto error_open;
5366 }
5367 out->format = config->format;
5368 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5369 out->config = pcm_config_afe_proxy_playback;
5370 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005371 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05305372 unsigned int channels = 0;
5373 /*Update config params to default if not set by the caller*/
5374 if (config->sample_rate == 0)
5375 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5376 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5377 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5378 if (config->format == AUDIO_FORMAT_DEFAULT)
5379 config->format = AUDIO_FORMAT_PCM_16_BIT;
5380
5381 channels = audio_channel_count_from_out_mask(out->channel_mask);
5382
Varun Balaraje49253e2017-07-06 19:48:56 +05305383 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
5384 out->usecase = get_interactive_usecase(adev);
5385 out->config = pcm_config_low_latency;
5386 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305387 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005388 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
5389 out->flags);
5390 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07005391 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
5392 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5393 out->config = pcm_config_mmap_playback;
5394 out->stream.start = out_start;
5395 out->stream.stop = out_stop;
5396 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5397 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305398 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
5399 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Alexy Joseph98988832017-01-13 14:56:59 -08005400 out->dynamic_pm_qos_enabled = property_get_bool("vendor.audio.dynamic.qos.enable", false);
5401 if (!out->dynamic_pm_qos_enabled) {
5402 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
5403 } else {
5404 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
5405 //the mixer path will be a string similar to "low-latency-playback resume"
5406 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
5407 strlcat(out->pm_qos_mixer_path,
5408 " resume", MAX_MIXER_PATH_LEN);
5409 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
5410 out->pm_qos_mixer_path);
5411 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305412 out->config = pcm_config_low_latency;
5413 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
5414 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5415 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05305416 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
5417 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
5418 if (out->config.period_size <= 0) {
5419 ALOGE("Invalid configuration period size is not valid");
5420 ret = -EINVAL;
5421 goto error_open;
5422 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305423 } else {
5424 /* primary path is the default path selected if no other outputs are available/suitable */
5425 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
5426 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
5427 }
5428 out->hal_ip_format = format = out->format;
5429 out->config.format = hal_format_to_pcm(out->hal_ip_format);
5430 out->hal_op_format = pcm_format_to_hal(out->config.format);
5431 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
5432 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07005433 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05305434 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05305435 if (out->hal_ip_format != out->hal_op_format) {
5436 uint32_t buffer_size = out->config.period_size *
5437 format_to_bitwidth_table[out->hal_op_format] *
5438 out->config.channels;
5439 out->convert_buffer = calloc(1, buffer_size);
5440 if (out->convert_buffer == NULL){
5441 ALOGE("Allocation failed for convert buffer for size %d",
5442 out->compr_config.fragment_size);
5443 ret = -ENOMEM;
5444 goto error_open;
5445 }
5446 ALOGD("Convert buffer allocated of size %d", buffer_size);
5447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005448 }
5449
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005450 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
5451 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05305452
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005453 /* TODO remove this hardcoding and check why width is zero*/
5454 if (out->bit_width == 0)
5455 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305456 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005457 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05305458 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305459 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05305460 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08005461 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
5462 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
5463 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005464 if(adev->primary_output == NULL)
5465 adev->primary_output = out;
5466 else {
5467 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005468 ret = -EEXIST;
5469 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005470 }
5471 }
5472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 /* Check if this usecase is already existing */
5474 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07005475 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
5476 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005479 ret = -EEXIST;
5480 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005481 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005483 pthread_mutex_unlock(&adev->lock);
5484
5485 out->stream.common.get_sample_rate = out_get_sample_rate;
5486 out->stream.common.set_sample_rate = out_set_sample_rate;
5487 out->stream.common.get_buffer_size = out_get_buffer_size;
5488 out->stream.common.get_channels = out_get_channels;
5489 out->stream.common.get_format = out_get_format;
5490 out->stream.common.set_format = out_set_format;
5491 out->stream.common.standby = out_standby;
5492 out->stream.common.dump = out_dump;
5493 out->stream.common.set_parameters = out_set_parameters;
5494 out->stream.common.get_parameters = out_get_parameters;
5495 out->stream.common.add_audio_effect = out_add_audio_effect;
5496 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5497 out->stream.get_latency = out_get_latency;
5498 out->stream.set_volume = out_set_volume;
5499 out->stream.write = out_write;
5500 out->stream.get_render_position = out_get_render_position;
5501 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005502 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005503
Haynes Mathew George16081042017-05-31 17:16:49 -07005504 if (out->realtime)
5505 out->af_period_multiplier = af_period_multiplier;
5506 else
5507 out->af_period_multiplier = 1;
5508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005510 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005511 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005512
5513 config->format = out->stream.common.get_format(&out->stream.common);
5514 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5515 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5516
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305517 /*
5518 By locking output stream before registering, we allow the callback
5519 to update stream's state only after stream's initial state is set to
5520 adev state.
5521 */
5522 lock_output_stream(out);
5523 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5524 pthread_mutex_lock(&adev->lock);
5525 out->card_status = adev->card_status;
5526 pthread_mutex_unlock(&adev->lock);
5527 pthread_mutex_unlock(&out->lock);
5528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005529 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305530 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07005531 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005532
5533 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
5534 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5535 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005536 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05305537 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005538 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07005539 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05305540 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005541 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
5542 out->usecase, PCM_PLAYBACK);
5543 hdlr_stream_cfg.flags = out->flags;
5544 hdlr_stream_cfg.type = PCM_PLAYBACK;
5545 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
5546 &hdlr_stream_cfg);
5547 if (ret) {
5548 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
5549 out->adsp_hdlr_stream_handle = NULL;
5550 }
5551 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05305552 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07005553 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07005554 if (ret < 0) {
5555 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
5556 out->ip_hdlr_handle = NULL;
5557 }
5558 }
Eric Laurent994a6932013-07-17 11:51:42 -07005559 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005560 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005561
5562error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05305563 if (out->convert_buffer)
5564 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005565 free(out);
5566 *stream_out = NULL;
5567 ALOGD("%s: exit: ret %d", __func__, ret);
5568 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569}
5570
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305571void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005572 struct audio_stream_out *stream)
5573{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005574 struct stream_out *out = (struct stream_out *)stream;
5575 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005576 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005577
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305578 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
5579
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305580 // must deregister from sndmonitor first to prevent races
5581 // between the callback and close_stream
5582 audio_extn_snd_mon_unregister_listener(out);
5583
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005584 /* close adsp hdrl session before standby */
5585 if (out->adsp_hdlr_stream_handle) {
5586 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
5587 if (ret)
5588 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
5589 out->adsp_hdlr_stream_handle = NULL;
5590 }
5591
Manish Dewangan21a850a2017-08-14 12:03:55 +05305592 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07005593 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
5594 out->ip_hdlr_handle = NULL;
5595 }
5596
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005597 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305598 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005599 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305600 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305601 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005602 if(ret != 0)
5603 ALOGE("%s: Compress voip output cannot be closed, error:%d",
5604 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005605 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005606 out_standby(&stream->common);
5607
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005608 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005609 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005611 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005612 if (out->compr_config.codec != NULL)
5613 free(out->compr_config.codec);
5614 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005615
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305616 out->a2dp_compress_mute = false;
5617
Varun Balaraje49253e2017-07-06 19:48:56 +05305618 if (is_interactive_usecase(out->usecase))
5619 free_interactive_usecase(adev, out->usecase);
5620
Ashish Jain83a6cc22016-06-28 14:34:17 +05305621 if (out->convert_buffer != NULL) {
5622 free(out->convert_buffer);
5623 out->convert_buffer = NULL;
5624 }
5625
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005626 if (adev->voice_tx_output == out)
5627 adev->voice_tx_output = NULL;
5628
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05305629 if (adev->primary_output == out)
5630 adev->primary_output = NULL;
5631
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005632 pthread_cond_destroy(&out->cond);
5633 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005634 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005635 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005636}
5637
5638static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5639{
5640 struct audio_device *adev = (struct audio_device *)dev;
5641 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005643 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005644 int ret;
5645 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005646
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005647 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005648 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005649
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305650 if (!parms)
5651 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305652
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305653 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5654 if (ret >= 0) {
5655 /* When set to false, HAL should disable EC and NS */
5656 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5657 adev->bt_sco_on = true;
5658 else
5659 adev->bt_sco_on = false;
5660 }
5661
Naresh Tanniru4c630392014-05-12 01:05:52 +05305662 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005663 status = voice_set_parameters(adev, parms);
5664 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005665 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005666
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005667 status = platform_set_parameters(adev->platform, parms);
5668 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005669 goto done;
5670
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005671 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5672 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07005673 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005674 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5675 adev->bluetooth_nrec = true;
5676 else
5677 adev->bluetooth_nrec = false;
5678 }
5679
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005680 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5681 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005682 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5683 adev->screen_off = false;
5684 else
5685 adev->screen_off = true;
5686 }
5687
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005688 ret = str_parms_get_int(parms, "rotation", &val);
5689 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005690 bool reverse_speakers = false;
5691 switch(val) {
5692 // FIXME: note that the code below assumes that the speakers are in the correct placement
5693 // relative to the user when the device is rotated 90deg from its default rotation. This
5694 // assumption is device-specific, not platform-specific like this code.
5695 case 270:
5696 reverse_speakers = true;
5697 break;
5698 case 0:
5699 case 90:
5700 case 180:
5701 break;
5702 default:
5703 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005704 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005705 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005706 if (status == 0) {
5707 if (adev->speaker_lr_swap != reverse_speakers) {
5708 adev->speaker_lr_swap = reverse_speakers;
5709 // only update the selected device if there is active pcm playback
5710 struct audio_usecase *usecase;
5711 struct listnode *node;
5712 list_for_each(node, &adev->usecase_list) {
5713 usecase = node_to_item(node, struct audio_usecase, list);
5714 if (usecase->type == PCM_PLAYBACK) {
5715 select_devices(adev, usecase->id);
5716 break;
5717 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005718 }
5719 }
5720 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005721 }
5722
Mingming Yin514a8bc2014-07-29 15:22:21 -07005723 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5724 if (ret >= 0) {
5725 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5726 adev->bt_wb_speech_enabled = true;
5727 else
5728 adev->bt_wb_speech_enabled = false;
5729 }
5730
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005731 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5732 if (ret >= 0) {
5733 val = atoi(value);
5734 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005735 ALOGV("cache new ext disp type and edid");
5736 ret = platform_get_ext_disp_type(adev->platform);
5737 if (ret < 0) {
5738 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08005739 status = ret;
5740 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07005741 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005742 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005743 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005744 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07005745 /*
5746 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
5747 * Per AudioPolicyManager, USB device is higher priority than WFD.
5748 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
5749 * If WFD use case occupies AFE proxy, it may result unintended behavior while
5750 * starting voice call on USB
5751 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005752 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5753 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08005754 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5755 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005756 }
vivek mehta344576a2016-04-12 18:56:03 -07005757 ALOGV("detected USB connect .. disable proxy");
5758 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005759 }
5760 }
5761
5762 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5763 if (ret >= 0) {
5764 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005765 /*
5766 * The HDMI / Displayport disconnect handling has been moved to
5767 * audio extension to ensure that its parameters are not
5768 * invalidated prior to updating sysfs of the disconnect event
5769 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5770 */
5771 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005772 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005773 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5774 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305775 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5776 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005777 }
vivek mehta344576a2016-04-12 18:56:03 -07005778 ALOGV("detected USB disconnect .. enable proxy");
5779 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005780 }
5781 }
5782
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305783 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5784 if (ret >= 0) {
5785 struct audio_usecase *usecase;
5786 struct listnode *node;
5787 list_for_each(node, &adev->usecase_list) {
5788 usecase = node_to_item(node, struct audio_usecase, list);
5789 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005790 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305791 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005792
5793 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305794 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005795 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305796 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305797 //force device switch to re configure encoder
5798 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305799 audio_extn_a2dp_set_handoff_mode(false);
5800 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305801 break;
5802 }
5803 }
5804 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005805
5806 //handle vr audio setparam
5807 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5808 value, sizeof(value));
5809 if (ret >= 0) {
5810 ALOGI("Setting vr mode to be %s", value);
5811 if (!strncmp(value, "true", 4)) {
5812 adev->vr_audio_mode_enabled = true;
5813 ALOGI("Setting vr mode to true");
5814 } else if (!strncmp(value, "false", 5)) {
5815 adev->vr_audio_mode_enabled = false;
5816 ALOGI("Setting vr mode to false");
5817 } else {
5818 ALOGI("wrong vr mode set");
5819 }
5820 }
5821
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305822 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005823done:
5824 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005825 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305826error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005827 ALOGV("%s: exit with code(%d)", __func__, status);
5828 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005829}
5830
5831static char* adev_get_parameters(const struct audio_hw_device *dev,
5832 const char *keys)
5833{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005834 struct audio_device *adev = (struct audio_device *)dev;
5835 struct str_parms *reply = str_parms_create();
5836 struct str_parms *query = str_parms_create_str(keys);
5837 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305838 char value[256] = {0};
5839 int ret = 0;
5840
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005841 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005842 if (reply) {
5843 str_parms_destroy(reply);
5844 }
5845 if (query) {
5846 str_parms_destroy(query);
5847 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005848 ALOGE("adev_get_parameters: failed to create query or reply");
5849 return NULL;
5850 }
5851
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005852 //handle vr audio getparam
5853
5854 ret = str_parms_get_str(query,
5855 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5856 value, sizeof(value));
5857
5858 if (ret >= 0) {
5859 bool vr_audio_enabled = false;
5860 pthread_mutex_lock(&adev->lock);
5861 vr_audio_enabled = adev->vr_audio_mode_enabled;
5862 pthread_mutex_unlock(&adev->lock);
5863
5864 ALOGI("getting vr mode to %d", vr_audio_enabled);
5865
5866 if (vr_audio_enabled) {
5867 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5868 "true");
5869 goto exit;
5870 } else {
5871 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5872 "false");
5873 goto exit;
5874 }
5875 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005876
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005877 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005878 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005879 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005880 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305881 pthread_mutex_unlock(&adev->lock);
5882
Naresh Tannirud7205b62014-06-20 02:54:48 +05305883exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005884 str = str_parms_to_str(reply);
5885 str_parms_destroy(query);
5886 str_parms_destroy(reply);
5887
5888 ALOGV("%s: exit: returns - %s", __func__, str);
5889 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005890}
5891
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005892static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005893{
5894 return 0;
5895}
5896
5897static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5898{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005899 int ret;
5900 struct audio_device *adev = (struct audio_device *)dev;
5901 pthread_mutex_lock(&adev->lock);
5902 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005903 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005904 pthread_mutex_unlock(&adev->lock);
5905 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005906}
5907
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005908static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5909 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005910{
5911 return -ENOSYS;
5912}
5913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005914static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5915 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005916{
5917 return -ENOSYS;
5918}
5919
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005920static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5921 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005922{
5923 return -ENOSYS;
5924}
5925
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005926static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5927 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005928{
5929 return -ENOSYS;
5930}
5931
5932static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5933{
5934 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005936 pthread_mutex_lock(&adev->lock);
5937 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005938 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005939 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005940 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005941 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005942 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005943 adev->current_call_output = NULL;
5944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005945 }
5946 pthread_mutex_unlock(&adev->lock);
5947 return 0;
5948}
5949
5950static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5951{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005952 int ret;
5953
5954 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005955 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005956 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5957 pthread_mutex_unlock(&adev->lock);
5958
5959 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005960}
5961
5962static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5963{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005964 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005965 return 0;
5966}
5967
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005968static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005969 const struct audio_config *config)
5970{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005971 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005972
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005973 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5974 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975}
5976
5977static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005978 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005979 audio_devices_t devices,
5980 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005981 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305982 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005983 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005984 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005985{
5986 struct audio_device *adev = (struct audio_device *)dev;
5987 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005988 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005989 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005990 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305991 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005993 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305994 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5995 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005996 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305997 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005998
5999 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006000
6001 if (!in) {
6002 ALOGE("failed to allocate input stream");
6003 return -ENOMEM;
6004 }
6005
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306006 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306007 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
6008 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006009 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006010 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006012 in->stream.common.get_sample_rate = in_get_sample_rate;
6013 in->stream.common.set_sample_rate = in_set_sample_rate;
6014 in->stream.common.get_buffer_size = in_get_buffer_size;
6015 in->stream.common.get_channels = in_get_channels;
6016 in->stream.common.get_format = in_get_format;
6017 in->stream.common.set_format = in_set_format;
6018 in->stream.common.standby = in_standby;
6019 in->stream.common.dump = in_dump;
6020 in->stream.common.set_parameters = in_set_parameters;
6021 in->stream.common.get_parameters = in_get_parameters;
6022 in->stream.common.add_audio_effect = in_add_audio_effect;
6023 in->stream.common.remove_audio_effect = in_remove_audio_effect;
6024 in->stream.set_gain = in_set_gain;
6025 in->stream.read = in_read;
6026 in->stream.get_input_frames_lost = in_get_input_frames_lost;
6027
6028 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006029 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006030 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006031 in->standby = 1;
6032 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006033 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006034 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006035
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306036 in->usecase = USECASE_AUDIO_RECORD;
6037 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006038 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Dhananjay Kumar973fc362017-01-09 18:48:15 +05306039 is_low_latency = true;
6040#if LOW_LATENCY_CAPTURE_USE_CASE
6041 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
6042#endif
6043 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
6044 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006045 in->format = config->format;
Haynes Mathew George16081042017-05-31 17:16:49 -07006046 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6047 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
6048 in->realtime = 0;
6049 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6050 in->config = pcm_config_mmap_capture;
6051 in->stream.start = in_start;
6052 in->stream.stop = in_stop;
6053 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6054 in->stream.get_mmap_position = in_get_mmap_position;
6055 in->af_period_multiplier = 1;
6056 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
6057 } else if (in->realtime) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006058 in->config = pcm_config_audio_capture_rt;
6059 in->sample_rate = in->config.rate;
6060 in->af_period_multiplier = af_period_multiplier;
6061 } else {
6062 in->config = pcm_config_audio_capture;
6063 in->config.rate = config->sample_rate;
6064 in->sample_rate = config->sample_rate;
6065 in->af_period_multiplier = 1;
6066 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306067 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006068
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306069 /* restrict 24 bit capture for unprocessed source only
6070 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
6071 */
6072 if (config->format == AUDIO_FORMAT_DEFAULT) {
6073 config->format = AUDIO_FORMAT_PCM_16_BIT;
6074 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
6075 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
6076 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
6077 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6078 bool ret_error = false;
6079 in->bit_width = 24;
6080 /* 24 bit is restricted to UNPROCESSED source only,also format supported
6081 from HAL is 24_packed and 8_24
6082 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
6083 24_packed return error indicating supported format is 24_packed
6084 *> In case of any other source requesting 24 bit or float return error
6085 indicating format supported is 16 bit only.
6086
6087 on error flinger will retry with supported format passed
6088 */
6089 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
6090 (source != AUDIO_SOURCE_CAMCORDER)) {
6091 config->format = AUDIO_FORMAT_PCM_16_BIT;
6092 if (config->sample_rate > 48000)
6093 config->sample_rate = 48000;
6094 ret_error = true;
6095 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
6096 in->config.format = PCM_FORMAT_S24_3LE;
6097 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
6098 in->config.format = PCM_FORMAT_S24_LE;
6099 } else {
6100 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
6101 ret_error = true;
6102 }
6103
6104 if (ret_error) {
6105 ret = -EINVAL;
6106 goto err_open;
6107 }
6108 }
6109
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306110 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05306111 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
6112 (adev->mode != AUDIO_MODE_IN_CALL)) {
6113 ret = -EINVAL;
6114 goto err_open;
6115 }
6116
6117 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
6118 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006119 if (config->sample_rate == 0)
6120 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6121 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
6122 config->sample_rate != 8000) {
6123 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
6124 ret = -EINVAL;
6125 goto err_open;
6126 }
6127 if (config->format == AUDIO_FORMAT_DEFAULT)
6128 config->format = AUDIO_FORMAT_PCM_16_BIT;
6129 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
6130 config->format = AUDIO_FORMAT_PCM_16_BIT;
6131 ret = -EINVAL;
6132 goto err_open;
6133 }
6134
6135 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
6136 in->config = pcm_config_afe_proxy_record;
6137 in->config.channels = channel_count;
6138 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306139 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05306140 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
6141 in, config, &channel_mask_updated)) {
6142 if (channel_mask_updated == true) {
6143 ALOGD("%s: return error to retry with updated channel mask (%#x)",
6144 __func__, config->channel_mask);
6145 ret = -EINVAL;
6146 goto err_open;
6147 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05306148 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07006149 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006150 audio_extn_compr_cap_format_supported(config->format) &&
6151 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006152 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306153 } else if (audio_extn_cin_applicable_stream(in)) {
6154 ret = audio_extn_cin_configure_input_stream(in);
6155 if (ret)
6156 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006157 } else {
6158 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006159 if (!in->realtime) {
6160 in->format = config->format;
6161 frame_size = audio_stream_in_frame_size(&in->stream);
6162 buffer_size = get_input_buffer_size(config->sample_rate,
6163 config->format,
6164 channel_count,
6165 is_low_latency);
6166 in->config.period_size = buffer_size / frame_size;
6167 }
6168
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006169#ifndef COMPRESS_VOIP_ENABLED
6170 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6171 (in->config.rate == 8000 || in->config.rate == 16000 ||
6172 in->config.rate == 32000 || in->config.rate == 48000) &&
6173 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6174
6175 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6176 in->config = default_pcm_config_voip_copp;
6177 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6178 in->config.rate = in->sample_rate;
6179#else
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006180 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
Haynes Mathew George16081042017-05-31 17:16:49 -07006181 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6182 voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006183 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006184 (in->config.rate == 8000 || in->config.rate == 16000 ||
6185 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006186 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6187 voice_extn_compress_voip_open_input_stream(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006188#endif
Vidyakumar Athota5c398212015-03-31 21:53:21 -07006189 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006191
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306192 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6193 &adev->streams_input_cfg_list,
6194 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306195 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306196
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006197 /* This stream could be for sound trigger lab,
6198 get sound trigger pcm if present */
6199 audio_extn_sound_trigger_check_and_get_session(in);
6200
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306201 lock_input_stream(in);
6202 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6203 pthread_mutex_lock(&adev->lock);
6204 in->card_status = adev->card_status;
6205 pthread_mutex_unlock(&adev->lock);
6206 pthread_mutex_unlock(&in->lock);
6207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006208 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006209 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08006210 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211
6212err_open:
6213 free(in);
6214 *stream_in = NULL;
6215 return ret;
6216}
6217
6218static void adev_close_input_stream(struct audio_hw_device *dev,
6219 struct audio_stream_in *stream)
6220{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006221 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006222 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006223 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306224
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306225 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006226
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306227 // must deregister from sndmonitor first to prevent races
6228 // between the callback and close_stream
6229 audio_extn_snd_mon_unregister_listener(stream);
6230
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306231 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07006232 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05306233
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006234 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306235 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006236 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306237 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006238 if (ret != 0)
6239 ALOGE("%s: Compress voip input cannot be closed, error:%d",
6240 __func__, ret);
6241 } else
6242 in_standby(&stream->common);
6243
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07006244 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006245 audio_extn_ssr_deinit();
6246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006247
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306248 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07006249 audio_extn_compr_cap_format_supported(in->config.format))
6250 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05306251
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306252 if (audio_extn_cin_attached_usecase(in->usecase))
6253 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006254
Mingming Yinfd7607b2016-01-22 12:48:44 -08006255 if (in->is_st_session) {
6256 ALOGV("%s: sound trigger pcm stop lab", __func__);
6257 audio_extn_sound_trigger_stop_lab(in);
6258 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006259 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006260 return;
6261}
6262
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306263int adev_create_audio_patch(struct audio_hw_device *dev,
6264 unsigned int num_sources,
6265 const struct audio_port_config *sources,
6266 unsigned int num_sinks,
6267 const struct audio_port_config *sinks,
6268 audio_patch_handle_t *handle)
6269{
6270
6271
6272 return audio_extn_hw_loopback_create_audio_patch(dev,
6273 num_sources,
6274 sources,
6275 num_sinks,
6276 sinks,
6277 handle);
6278
6279}
6280
6281int adev_release_audio_patch(struct audio_hw_device *dev,
6282 audio_patch_handle_t handle)
6283{
6284 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
6285}
6286
6287int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
6288{
6289 return audio_extn_hw_loopback_get_audio_port(dev, config);
6290}
6291
6292int adev_set_audio_port_config(struct audio_hw_device *dev,
6293 const struct audio_port_config *config)
6294{
6295 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
6296}
6297
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006298static int adev_dump(const audio_hw_device_t *device __unused,
6299 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300{
6301 return 0;
6302}
6303
6304static int adev_close(hw_device_t *device)
6305{
6306 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07006307
6308 if (!adev)
6309 return 0;
6310
6311 pthread_mutex_lock(&adev_init_lock);
6312
6313 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306314 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006315 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08006316 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306317 audio_extn_utils_release_streams_cfg_lists(
6318 &adev->streams_output_cfg_list,
6319 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306320 if (audio_extn_qaf_is_enabled())
6321 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006322 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006323 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07006324 free(adev->snd_dev_ref_cnt);
6325 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006326 if (adev->adm_deinit)
6327 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306328 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006329 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306330 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306331 audio_extn_hw_loopback_deinit(adev);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306332 if (adev->device_cfg_params) {
6333 free(adev->device_cfg_params);
6334 adev->device_cfg_params = NULL;
6335 }
Kiran Kandi910e1862013-10-29 13:29:42 -07006336 free(device);
6337 adev = NULL;
6338 }
6339 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006341 return 0;
6342}
6343
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006344/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6345 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6346 * just that it _might_ work.
6347 */
6348static int period_size_is_plausible_for_low_latency(int period_size)
6349{
6350 switch (period_size) {
6351 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07006352 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006353 case 240:
6354 case 320:
6355 case 480:
6356 return 1;
6357 default:
6358 return 0;
6359 }
6360}
6361
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306362static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
6363{
6364 bool is_snd_card_status = false;
6365 bool is_ext_device_status = false;
6366 char value[32];
6367 int card = -1;
6368 card_status_t status;
6369
6370 if (cookie != adev || !parms)
6371 return;
6372
6373 if (!parse_snd_card_status(parms, &card, &status)) {
6374 is_snd_card_status = true;
6375 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
6376 is_ext_device_status = true;
6377 } else {
6378 // not a valid event
6379 return;
6380 }
6381
6382 pthread_mutex_lock(&adev->lock);
6383 if (card == adev->snd_card || is_ext_device_status) {
6384 if (is_snd_card_status && adev->card_status != status) {
6385 adev->card_status = status;
6386 platform_snd_card_update(adev->platform, status);
6387 audio_extn_fm_set_parameters(adev, parms);
6388 } else if (is_ext_device_status) {
6389 platform_set_parameters(adev->platform, parms);
6390 }
6391 }
6392 pthread_mutex_unlock(&adev->lock);
6393 return;
6394}
6395
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306396/* out and adev lock held */
6397static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6398{
6399 struct audio_usecase *uc_info;
6400 float left_p;
6401 float right_p;
6402 audio_devices_t devices;
6403
6404 uc_info = get_usecase_from_list(adev, out->usecase);
6405 if (uc_info == NULL) {
6406 ALOGE("%s: Could not find the usecase (%d) in the list",
6407 __func__, out->usecase);
6408 return -EINVAL;
6409 }
6410
6411 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6412 out->usecase, use_case_table[out->usecase]);
6413
6414 if (restore) {
6415 // restore A2DP device for active usecases and unmute if required
6416 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6417 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
6418 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
6419 select_devices(adev, uc_info->id);
6420 pthread_mutex_lock(&out->compr_mute_lock);
6421 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6422 (out->a2dp_compress_mute)) {
6423 out->a2dp_compress_mute = false;
6424 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6425 }
6426 pthread_mutex_unlock(&out->compr_mute_lock);
6427 }
6428 } else {
6429 // mute compress stream if suspended
6430 pthread_mutex_lock(&out->compr_mute_lock);
6431 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6432 (!out->a2dp_compress_mute)) {
6433 if (!out->standby) {
6434 ALOGD("%s: selecting speaker and muting stream", __func__);
6435 devices = out->devices;
6436 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6437 left_p = out->volume_l;
6438 right_p = out->volume_r;
6439 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6440 compress_pause(out->compr);
6441 out_set_compr_volume(&out->stream, (float)0, (float)0);
6442 out->a2dp_compress_mute = true;
6443 select_devices(adev, out->usecase);
6444 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6445 compress_resume(out->compr);
6446 out->devices = devices;
6447 out->volume_l = left_p;
6448 out->volume_r = right_p;
6449 }
6450 }
6451 pthread_mutex_unlock(&out->compr_mute_lock);
6452 }
6453 ALOGV("%s: exit", __func__);
6454 return 0;
6455}
6456
6457int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6458{
6459 int ret = 0;
6460
6461 lock_output_stream(out);
6462 pthread_mutex_lock(&adev->lock);
6463
6464 ret = check_a2dp_restore_l(adev, out, restore);
6465
6466 pthread_mutex_unlock(&adev->lock);
6467 pthread_mutex_unlock(&out->lock);
6468 return ret;
6469}
6470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006471static int adev_open(const hw_module_t *module, const char *name,
6472 hw_device_t **device)
6473{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306474 int ret;
6475
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006476 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006477 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
6478
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006479 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07006480 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006481 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07006482 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006483 ALOGD("%s: returning existing instance of adev", __func__);
6484 ALOGD("%s: exit", __func__);
6485 pthread_mutex_unlock(&adev_init_lock);
6486 return 0;
6487 }
6488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006489 adev = calloc(1, sizeof(struct audio_device));
6490
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006491 if (!adev) {
6492 pthread_mutex_unlock(&adev_init_lock);
6493 return -ENOMEM;
6494 }
6495
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07006496 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6497
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05306498#ifdef DYNAMIC_LOG_ENABLED
6499 register_for_dynamic_logging("hal");
6500#endif
6501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006502 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6503 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6504 adev->device.common.module = (struct hw_module_t *)module;
6505 adev->device.common.close = adev_close;
6506
6507 adev->device.init_check = adev_init_check;
6508 adev->device.set_voice_volume = adev_set_voice_volume;
6509 adev->device.set_master_volume = adev_set_master_volume;
6510 adev->device.get_master_volume = adev_get_master_volume;
6511 adev->device.set_master_mute = adev_set_master_mute;
6512 adev->device.get_master_mute = adev_get_master_mute;
6513 adev->device.set_mode = adev_set_mode;
6514 adev->device.set_mic_mute = adev_set_mic_mute;
6515 adev->device.get_mic_mute = adev_get_mic_mute;
6516 adev->device.set_parameters = adev_set_parameters;
6517 adev->device.get_parameters = adev_get_parameters;
6518 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6519 adev->device.open_output_stream = adev_open_output_stream;
6520 adev->device.close_output_stream = adev_close_output_stream;
6521 adev->device.open_input_stream = adev_open_input_stream;
6522 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05306523 adev->device.create_audio_patch = adev_create_audio_patch;
6524 adev->device.release_audio_patch = adev_release_audio_patch;
6525 adev->device.get_audio_port = adev_get_audio_port;
6526 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006527 adev->device.dump = adev_dump;
6528
6529 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08006531 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006532 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006533 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006534 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006535 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07006536 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306537 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006538 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006539 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006540 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006541 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08006542 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006543 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05306544 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306545 adev->perf_lock_opts[0] = 0x101;
6546 adev->perf_lock_opts[1] = 0x20E;
6547 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006548 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006550 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006551 adev->platform = platform_init(adev);
6552 if (!adev->platform) {
6553 free(adev->snd_dev_ref_cnt);
6554 free(adev);
6555 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6556 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08006557 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306558 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006559 return -EINVAL;
6560 }
Eric Laurentc4aef752013-09-12 17:45:53 -07006561
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306562 if (audio_extn_qaf_is_enabled()) {
6563 ret = audio_extn_qaf_init(adev);
6564 if (ret < 0) {
6565 free(adev);
6566 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6567 *device = NULL;
6568 pthread_mutex_unlock(&adev_init_lock);
6569 pthread_mutex_destroy(&adev->lock);
6570 return ret;
6571 }
6572
6573 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
6574 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
6575 }
6576
Eric Laurentc4aef752013-09-12 17:45:53 -07006577 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
6578 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6579 if (adev->visualizer_lib == NULL) {
6580 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6581 } else {
6582 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6583 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006584 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006585 "visualizer_hal_start_output");
6586 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006587 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07006588 "visualizer_hal_stop_output");
6589 }
6590 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05306591 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08006592 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08006593 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05306594 audio_extn_hw_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07006595
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006596 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
6597 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6598 if (adev->offload_effects_lib == NULL) {
6599 ALOGE("%s: DLOPEN failed for %s", __func__,
6600 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6601 } else {
6602 ALOGV("%s: DLOPEN successful for %s", __func__,
6603 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6604 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05306605 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006606 "offload_effects_bundle_hal_start_output");
6607 adev->offload_effects_stop_output =
6608 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6609 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006610 adev->offload_effects_set_hpx_state =
6611 (int (*)(bool))dlsym(adev->offload_effects_lib,
6612 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05306613 adev->offload_effects_get_parameters =
6614 (void (*)(struct str_parms *, struct str_parms *))
6615 dlsym(adev->offload_effects_lib,
6616 "offload_effects_bundle_get_parameters");
6617 adev->offload_effects_set_parameters =
6618 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
6619 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08006620 }
6621 }
6622
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006623 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
6624 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6625 if (adev->adm_lib == NULL) {
6626 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6627 } else {
6628 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6629 adev->adm_init = (adm_init_t)
6630 dlsym(adev->adm_lib, "adm_init");
6631 adev->adm_deinit = (adm_deinit_t)
6632 dlsym(adev->adm_lib, "adm_deinit");
6633 adev->adm_register_input_stream = (adm_register_input_stream_t)
6634 dlsym(adev->adm_lib, "adm_register_input_stream");
6635 adev->adm_register_output_stream = (adm_register_output_stream_t)
6636 dlsym(adev->adm_lib, "adm_register_output_stream");
6637 adev->adm_deregister_stream = (adm_deregister_stream_t)
6638 dlsym(adev->adm_lib, "adm_deregister_stream");
6639 adev->adm_request_focus = (adm_request_focus_t)
6640 dlsym(adev->adm_lib, "adm_request_focus");
6641 adev->adm_abandon_focus = (adm_abandon_focus_t)
6642 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006643 adev->adm_set_config = (adm_set_config_t)
6644 dlsym(adev->adm_lib, "adm_set_config");
6645 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6646 dlsym(adev->adm_lib, "adm_request_focus_v2");
6647 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6648 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6649 adev->adm_on_routing_change = (adm_on_routing_change_t)
6650 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006651 }
6652 }
6653
Mingming Yin514a8bc2014-07-29 15:22:21 -07006654 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08006655 //initialize this to false for now,
6656 //this will be set to true through set param
6657 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07006658
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07006659 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006660 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08006661 adev->dsp_bit_width_enforce_mode =
6662 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663
Dhananjay Kumard6d32152016-10-13 16:11:03 +05306664 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
6665 &adev->streams_output_cfg_list,
6666 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006667
Kiran Kandi910e1862013-10-29 13:29:42 -07006668 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006669
6670 char value[PROPERTY_VALUE_MAX];
6671 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006672 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006673 trial = atoi(value);
6674 if (period_size_is_plausible_for_low_latency(trial)) {
6675 pcm_config_low_latency.period_size = trial;
6676 pcm_config_low_latency.start_threshold = trial / 4;
6677 pcm_config_low_latency.avail_min = trial / 4;
6678 configured_low_latency_capture_period_size = trial;
6679 }
6680 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006681 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07006682 trial = atoi(value);
6683 if (period_size_is_plausible_for_low_latency(trial)) {
6684 configured_low_latency_capture_period_size = trial;
6685 }
6686 }
6687
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006688 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006689 af_period_multiplier = atoi(value);
6690 if (af_period_multiplier < 0)
6691 af_period_multiplier = 2;
6692 else if (af_period_multiplier > 4)
6693 af_period_multiplier = 4;
6694
6695 ALOGV("new period_multiplier = %d", af_period_multiplier);
6696 }
6697
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07006698 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07006699 pthread_mutex_unlock(&adev_init_lock);
6700
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006701 if (adev->adm_init)
6702 adev->adm_data = adev->adm_init();
6703
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306704 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05306705 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006706 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306707
6708 audio_extn_snd_mon_init();
6709 pthread_mutex_lock(&adev->lock);
6710 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
6711 adev->card_status = CARD_STATUS_ONLINE;
6712 pthread_mutex_unlock(&adev->lock);
6713 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05306714 /* Allocate memory for Device config params */
6715 adev->device_cfg_params = (struct audio_device_config_param*)
6716 calloc(platform_get_max_codec_backend(),
6717 sizeof(struct audio_device_config_param));
6718 if (adev->device_cfg_params == NULL)
6719 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306720
Eric Laurent994a6932013-07-17 11:51:42 -07006721 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006722 return 0;
6723}
6724
6725static struct hw_module_methods_t hal_module_methods = {
6726 .open = adev_open,
6727};
6728
6729struct audio_module HAL_MODULE_INFO_SYM = {
6730 .common = {
6731 .tag = HARDWARE_MODULE_TAG,
6732 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6733 .hal_api_version = HARDWARE_HAL_API_VERSION,
6734 .id = AUDIO_HARDWARE_MODULE_ID,
6735 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08006736 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006737 .methods = &hal_module_methods,
6738 },
6739};