blob: 5f9ffdc77ed9840e42c411bde18e91a5285f741c [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002 * Copyright (C) 2013-2014 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
18/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070019/*#define VERY_VERY_VERBOSE_LOGGING*/
20#ifdef VERY_VERY_VERBOSE_LOGGING
21#define ALOGVV ALOGV
22#else
23#define ALOGVV(a...) do { } while(0)
24#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080025
26#include <errno.h>
27#include <pthread.h>
28#include <stdint.h>
29#include <sys/time.h>
30#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080031#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070032#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070033#include <sys/resource.h>
34#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080035
36#include <cutils/log.h>
37#include <cutils/str_parms.h>
38#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070039#include <cutils/atomic.h>
40#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080041
Eric Laurentb23d5282013-05-14 15:27:20 -070042#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070043#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070044#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <audio_effects/effect_aec.h>
46#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080048#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include "platform_api.h"
50#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070051#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070053#include "sound/compress_params.h"
54
Marco Nelissen32093f52015-04-08 15:14:02 -070055#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070056// 2 buffers causes problems with high bitrate files
57#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058/* ToDo: Check and update a proper value in msec */
59#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
60#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
61
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070062#define PROXY_OPEN_RETRY_COUNT 100
63#define PROXY_OPEN_WAIT_TIME 20
64
Glenn Kasten4f993392014-05-14 07:30:48 -070065static unsigned int configured_low_latency_capture_period_size =
66 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
67
Andy Hung31aca912014-03-20 17:14:59 -070068/* This constant enables extended precision handling.
69 * TODO The flag is off until more testing is done.
70 */
71static const bool k_enable_extended_precision = false;
72
Eric Laurentb23d5282013-05-14 15:27:20 -070073struct pcm_config pcm_config_deep_buffer = {
74 .channels = 2,
75 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
76 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
77 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
78 .format = PCM_FORMAT_S16_LE,
79 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
80 .stop_threshold = INT_MAX,
81 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
82};
83
84struct pcm_config pcm_config_low_latency = {
85 .channels = 2,
86 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
87 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
88 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
89 .format = PCM_FORMAT_S16_LE,
90 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
91 .stop_threshold = INT_MAX,
92 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
93};
94
95struct pcm_config pcm_config_hdmi_multi = {
96 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
98 .period_size = HDMI_MULTI_PERIOD_SIZE,
99 .period_count = HDMI_MULTI_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = 0,
102 .stop_threshold = INT_MAX,
103 .avail_min = 0,
104};
105
106struct pcm_config pcm_config_audio_capture = {
107 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700108 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
109 .format = PCM_FORMAT_S16_LE,
110};
111
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700112#define AFE_PROXY_CHANNEL_COUNT 2
113#define AFE_PROXY_SAMPLING_RATE 48000
114
115#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
116#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
117
118struct pcm_config pcm_config_afe_proxy_playback = {
119 .channels = AFE_PROXY_CHANNEL_COUNT,
120 .rate = AFE_PROXY_SAMPLING_RATE,
121 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
122 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
125 .stop_threshold = INT_MAX,
126 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
127};
128
129#define AFE_PROXY_RECORD_PERIOD_SIZE 768
130#define AFE_PROXY_RECORD_PERIOD_COUNT 4
131
132struct pcm_config pcm_config_afe_proxy_record = {
133 .channels = AFE_PROXY_CHANNEL_COUNT,
134 .rate = AFE_PROXY_SAMPLING_RATE,
135 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
136 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
137 .format = PCM_FORMAT_S16_LE,
138 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
139 .stop_threshold = INT_MAX,
140 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
141};
142
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700143const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700144 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
145 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
146 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700147 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700148 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700149
Eric Laurentb23d5282013-05-14 15:27:20 -0700150 [USECASE_AUDIO_RECORD] = "audio-record",
151 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700152
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800153 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
154 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700155
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700157 [USECASE_VOICE2_CALL] = "voice2-call",
158 [USECASE_VOLTE_CALL] = "volte-call",
159 [USECASE_QCHAT_CALL] = "qchat-call",
160 [USECASE_VOWLAN_CALL] = "vowlan-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700161
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700162 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
163 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
164
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700165 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
166 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700167};
168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800169
170#define STRING_TO_ENUM(string) { #string, string }
171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800172struct string_to_enum {
173 const char *name;
174 uint32_t value;
175};
176
177static const struct string_to_enum out_channels_name_to_enum_table[] = {
178 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
179 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
180 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
181};
182
Haynes Mathew George5191a852013-09-11 14:19:36 -0700183static int set_voice_volume_l(struct audio_device *adev, float volume);
184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700185static bool is_supported_format(audio_format_t format)
186{
Eric Laurent8251ac82014-07-23 11:00:25 -0700187 switch (format) {
188 case AUDIO_FORMAT_MP3:
189 case AUDIO_FORMAT_AAC_LC:
190 case AUDIO_FORMAT_AAC_HE_V1:
191 case AUDIO_FORMAT_AAC_HE_V2:
192 return true;
193 default:
194 break;
195 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700196 return false;
197}
198
199static int get_snd_codec_id(audio_format_t format)
200{
201 int id = 0;
202
Eric Laurent8251ac82014-07-23 11:00:25 -0700203 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700204 case AUDIO_FORMAT_MP3:
205 id = SND_AUDIOCODEC_MP3;
206 break;
207 case AUDIO_FORMAT_AAC:
208 id = SND_AUDIOCODEC_AAC;
209 break;
210 default:
211 ALOGE("%s: Unsupported audio format", __func__);
212 }
213
214 return id;
215}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800216
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800217int enable_audio_route(struct audio_device *adev,
218 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700220 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800221 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800222
223 if (usecase == NULL)
224 return -EINVAL;
225
226 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
227
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800228 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700229 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800230 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700231 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800232
233 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500234 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Ravi Kumar Alamanda64026462014-09-15 00:08:58 -0700235 ALOGD("%s: apply and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700236 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800238 ALOGV("%s: exit", __func__);
239 return 0;
240}
241
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800242int disable_audio_route(struct audio_device *adev,
243 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800244{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700245 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800246 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800247
248 if (usecase == NULL)
249 return -EINVAL;
250
251 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700252 if (usecase->type == PCM_CAPTURE)
253 snd_device = usecase->in_snd_device;
254 else
255 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800256 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500257 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Ravi Kumar Alamanda64026462014-09-15 00:08:58 -0700258 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700259 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800261 ALOGV("%s: exit", __func__);
262 return 0;
263}
264
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800265int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700266 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800267{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800268 if (snd_device < SND_DEVICE_MIN ||
269 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800270 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800271 return -EINVAL;
272 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700273
274 adev->snd_dev_ref_cnt[snd_device]++;
275 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700276 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700277 __func__, snd_device, platform_get_snd_device_name(snd_device));
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700278 return 0;
279 }
280
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700281 /* due to the possibility of calibration overwrite between listen
282 and audio, notify sound trigger hal before audio calibration is sent */
283 audio_extn_sound_trigger_update_device_status(snd_device,
284 ST_EVENT_SND_DEVICE_BUSY);
285
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700286 if (audio_extn_spkr_prot_is_enabled())
287 audio_extn_spkr_prot_calib_cancel(adev);
288
Eric Laurentb23d5282013-05-14 15:27:20 -0700289 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700290 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700291 audio_extn_sound_trigger_update_device_status(snd_device,
292 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800293 return -EINVAL;
294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295
zhaoyang yin4211fad2015-06-04 21:13:25 +0800296 audio_extn_dsm_feedback_enable(adev, snd_device, true);
297
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700298 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
299 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
300 audio_extn_spkr_prot_is_enabled()) {
301 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
302 adev->snd_dev_ref_cnt[snd_device]--;
303 return -EINVAL;
304 }
305 if (audio_extn_spkr_prot_start_processing(snd_device)) {
306 ALOGE("%s: spkr_start_processing failed", __func__);
307 return -EINVAL;
308 }
309 } else {
310 const char * dev_path = platform_get_snd_device_name(snd_device);
311 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path);
312 audio_route_apply_and_update_path(adev->audio_route, dev_path);
313 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800315 return 0;
316}
317
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800318int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700319 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800320{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800321 if (snd_device < SND_DEVICE_MIN ||
322 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800323 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800324 return -EINVAL;
325 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700326 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
327 ALOGE("%s: device ref cnt is already 0", __func__);
328 return -EINVAL;
329 }
330 adev->snd_dev_ref_cnt[snd_device]--;
331 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700332 const char * dev_path = platform_get_snd_device_name(snd_device);
Ravi Kumar Alamanda64026462014-09-15 00:08:58 -0700333 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path);
zhaoyang yin4211fad2015-06-04 21:13:25 +0800334
335 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700336 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
337 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
338 audio_extn_spkr_prot_is_enabled()) {
339 audio_extn_spkr_prot_stop_processing(snd_device);
340 } else {
341 audio_route_reset_and_update_path(adev->audio_route, dev_path);
342 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700343 audio_extn_sound_trigger_update_device_status(snd_device,
344 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800346 return 0;
347}
348
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700349static void check_usecases_codec_backend(struct audio_device *adev,
350 struct audio_usecase *uc_info,
351 snd_device_t snd_device)
352{
353 struct listnode *node;
354 struct audio_usecase *usecase;
355 bool switch_device[AUDIO_USECASE_MAX];
356 int i, num_uc_to_switch = 0;
357
358 /*
359 * This function is to make sure that all the usecases that are active on
360 * the hardware codec backend are always routed to any one device that is
361 * handled by the hardware codec.
362 * For example, if low-latency and deep-buffer usecases are currently active
363 * on speaker and out_set_parameters(headset) is received on low-latency
364 * output, then we have to make sure deep-buffer is also switched to headset,
365 * because of the limitation that both the devices cannot be enabled
366 * at the same time as they share the same backend.
367 */
368 /* Disable all the usecases on the shared backend other than the
369 specified usecase */
370 for (i = 0; i < AUDIO_USECASE_MAX; i++)
371 switch_device[i] = false;
372
373 list_for_each(node, &adev->usecase_list) {
374 usecase = node_to_item(node, struct audio_usecase, list);
375 if (usecase->type != PCM_CAPTURE &&
376 usecase != uc_info &&
377 usecase->out_snd_device != snd_device &&
378 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
379 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
380 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700381 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700382 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700383 switch_device[usecase->id] = true;
384 num_uc_to_switch++;
385 }
386 }
387
388 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700389 list_for_each(node, &adev->usecase_list) {
390 usecase = node_to_item(node, struct audio_usecase, list);
391 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700392 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900393 }
394 }
395
396 list_for_each(node, &adev->usecase_list) {
397 usecase = node_to_item(node, struct audio_usecase, list);
398 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700399 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700400 }
401 }
402
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700403 /* Re-route all the usecases on the shared backend other than the
404 specified usecase to new snd devices */
405 list_for_each(node, &adev->usecase_list) {
406 usecase = node_to_item(node, struct audio_usecase, list);
407 /* Update the out_snd_device only before enabling the audio route */
408 if (switch_device[usecase->id] ) {
409 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700410 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700411 }
412 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700413 }
414}
415
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700416static void check_and_route_capture_usecases(struct audio_device *adev,
417 struct audio_usecase *uc_info,
418 snd_device_t snd_device)
419{
420 struct listnode *node;
421 struct audio_usecase *usecase;
422 bool switch_device[AUDIO_USECASE_MAX];
423 int i, num_uc_to_switch = 0;
424
425 /*
426 * This function is to make sure that all the active capture usecases
427 * are always routed to the same input sound device.
428 * For example, if audio-record and voice-call usecases are currently
429 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
430 * is received for voice call then we have to make sure that audio-record
431 * usecase is also switched to earpiece i.e. voice-dmic-ef,
432 * because of the limitation that two devices cannot be enabled
433 * at the same time if they share the same backend.
434 */
435 for (i = 0; i < AUDIO_USECASE_MAX; i++)
436 switch_device[i] = false;
437
438 list_for_each(node, &adev->usecase_list) {
439 usecase = node_to_item(node, struct audio_usecase, list);
440 if (usecase->type != PCM_PLAYBACK &&
441 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700442 usecase->in_snd_device != snd_device &&
443 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700444 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
445 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700446 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700447 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700448 switch_device[usecase->id] = true;
449 num_uc_to_switch++;
450 }
451 }
452
453 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700454 list_for_each(node, &adev->usecase_list) {
455 usecase = node_to_item(node, struct audio_usecase, list);
456 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700457 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700458 }
459 }
460
461 list_for_each(node, &adev->usecase_list) {
462 usecase = node_to_item(node, struct audio_usecase, list);
463 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700464 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700465 }
466 }
467
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700468 /* Re-route all the usecases on the shared backend other than the
469 specified usecase to new snd devices */
470 list_for_each(node, &adev->usecase_list) {
471 usecase = node_to_item(node, struct audio_usecase, list);
472 /* Update the in_snd_device only before enabling the audio route */
473 if (switch_device[usecase->id] ) {
474 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700475 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700476 }
477 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700478 }
479}
480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700482static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800483{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700484 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700485 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800486
487 switch (channels) {
488 /*
489 * Do not handle stereo output in Multi-channel cases
490 * Stereo case is handled in normal playback path
491 */
492 case 6:
493 ALOGV("%s: HDMI supports 5.1", __func__);
494 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
495 break;
496 case 8:
497 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
498 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
499 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
500 break;
501 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700502 ALOGE("HDMI does not support multi channel playback");
503 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800504 break;
505 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700506 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800507}
508
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700509static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
510{
511 struct audio_usecase *usecase;
512 struct listnode *node;
513
514 list_for_each(node, &adev->usecase_list) {
515 usecase = node_to_item(node, struct audio_usecase, list);
516 if (usecase->type == VOICE_CALL) {
517 ALOGV("%s: usecase id %d", __func__, usecase->id);
518 return usecase->id;
519 }
520 }
521 return USECASE_INVALID;
522}
523
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800524struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
525 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700526{
527 struct audio_usecase *usecase;
528 struct listnode *node;
529
530 list_for_each(node, &adev->usecase_list) {
531 usecase = node_to_item(node, struct audio_usecase, list);
532 if (usecase->id == uc_id)
533 return usecase;
534 }
535 return NULL;
536}
537
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800538int select_devices(struct audio_device *adev,
539 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800540{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800541 snd_device_t out_snd_device = SND_DEVICE_NONE;
542 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700543 struct audio_usecase *usecase = NULL;
544 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800545 struct audio_usecase *hfp_usecase = NULL;
546 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800547 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700550 usecase = get_usecase_from_list(adev, uc_id);
551 if (usecase == NULL) {
552 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
553 return -EINVAL;
554 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800556 if ((usecase->type == VOICE_CALL) ||
557 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700558 out_snd_device = platform_get_output_snd_device(adev->platform,
559 usecase->stream.out->devices);
560 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 usecase->devices = usecase->stream.out->devices;
562 } else {
563 /*
564 * If the voice call is active, use the sound devices of voice call usecase
565 * so that it would not result any device switch. All the usecases will
566 * be switched to new device when select_devices() is called for voice call
567 * usecase. This is to avoid switching devices for voice call when
568 * check_usecases_codec_backend() is called below.
569 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700570 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700571 vc_usecase = get_usecase_from_list(adev,
572 get_voice_usecase_id_from_list(adev));
573 if ((vc_usecase != NULL) &&
574 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
575 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 in_snd_device = vc_usecase->in_snd_device;
577 out_snd_device = vc_usecase->out_snd_device;
578 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800579 } else if (audio_extn_hfp_is_active(adev)) {
580 hfp_ucid = audio_extn_hfp_get_usecase();
581 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
582 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
583 in_snd_device = hfp_usecase->in_snd_device;
584 out_snd_device = hfp_usecase->out_snd_device;
585 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 }
587 if (usecase->type == PCM_PLAYBACK) {
588 usecase->devices = usecase->stream.out->devices;
589 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700590 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700591 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700593 if (usecase->stream.out == adev->primary_output &&
594 adev->active_input &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800595 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
596 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700597 select_devices(adev, adev->active_input->usecase);
598 }
599 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 } else if (usecase->type == PCM_CAPTURE) {
601 usecase->devices = usecase->stream.in->device;
602 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700603 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700604 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700605 if (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
606 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700607 out_device = adev->primary_output->devices;
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800608 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700609 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
610 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700611 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700612 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700613 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 }
615 }
616
617 if (out_snd_device == usecase->out_snd_device &&
618 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800619 return 0;
620 }
621
sangwoobc677242013-08-08 16:53:43 +0900622 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700623 out_snd_device, platform_get_snd_device_name(out_snd_device),
624 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800626 /*
627 * Limitation: While in call, to do a device switch we need to disable
628 * and enable both RX and TX devices though one of them is same as current
629 * device.
630 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700631 if ((usecase->type == VOICE_CALL) &&
632 (usecase->in_snd_device != SND_DEVICE_NONE) &&
633 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700634 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800635 }
636
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 /* Disable current sound devices */
638 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700639 disable_audio_route(adev, usecase);
640 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800641 }
642
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 disable_audio_route(adev, usecase);
645 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800646 }
647
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700648 /* Applicable only on the targets that has external modem.
649 * New device information should be sent to modem before enabling
650 * the devices to reduce in-call device switch time.
651 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700652 if ((usecase->type == VOICE_CALL) &&
653 (usecase->in_snd_device != SND_DEVICE_NONE) &&
654 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700655 status = platform_switch_voice_call_enable_device_config(adev->platform,
656 out_snd_device,
657 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700658 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700659
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 /* Enable new sound devices */
661 if (out_snd_device != SND_DEVICE_NONE) {
662 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
663 check_usecases_codec_backend(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700664 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665 }
666
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700667 if (in_snd_device != SND_DEVICE_NONE) {
668 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700669 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671
Eric Laurentb23d5282013-05-14 15:27:20 -0700672 if (usecase->type == VOICE_CALL)
673 status = platform_switch_voice_call_device_post(adev->platform,
674 out_snd_device,
675 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800676
sangwoo170731f2013-06-08 15:36:36 +0900677 usecase->in_snd_device = in_snd_device;
678 usecase->out_snd_device = out_snd_device;
679
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700680 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900681
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700682 /* Applicable only on the targets that has external modem.
683 * Enable device command should be sent to modem only after
684 * enabling voice call mixer controls
685 */
686 if (usecase->type == VOICE_CALL)
687 status = platform_switch_voice_call_usecase_route_post(adev->platform,
688 out_snd_device,
689 in_snd_device);
690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800691 return status;
692}
693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694static int stop_input_stream(struct stream_in *in)
695{
696 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697 struct audio_usecase *uc_info;
698 struct audio_device *adev = in->dev;
699
Eric Laurentc8400632013-02-14 19:04:54 -0800700 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701
Eric Laurent994a6932013-07-17 11:51:42 -0700702 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704 uc_info = get_usecase_from_list(adev, in->usecase);
705 if (uc_info == NULL) {
706 ALOGE("%s: Could not find the usecase (%d) in the list",
707 __func__, in->usecase);
708 return -EINVAL;
709 }
710
Eric Laurent150dbfe2013-02-27 14:31:02 -0800711 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700712 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713
714 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700715 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800716
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800717 list_remove(&uc_info->list);
718 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800719
Eric Laurent994a6932013-07-17 11:51:42 -0700720 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 return ret;
722}
723
724int start_input_stream(struct stream_in *in)
725{
726 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800727 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728 struct audio_usecase *uc_info;
729 struct audio_device *adev = in->dev;
730
Eric Laurent994a6932013-07-17 11:51:42 -0700731 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700732 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733 if (in->pcm_device_id < 0) {
734 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
735 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800736 ret = -EINVAL;
737 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800738 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739
740 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
742 uc_info->id = in->usecase;
743 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800744 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 uc_info->devices = in->device;
746 uc_info->in_snd_device = SND_DEVICE_NONE;
747 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800748
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800749 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700750 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751
Eric Laurentc8400632013-02-14 19:04:54 -0800752 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700753 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700754
755 unsigned int flags = PCM_IN;
756 unsigned int pcm_open_retry_count = 0;
757
758 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
759 flags |= PCM_MMAP | PCM_NOIRQ;
760 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800761 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700762
763 while (1) {
764 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
765 flags, &in->config);
766 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
767 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
768 if (in->pcm != NULL) {
769 pcm_close(in->pcm);
770 in->pcm = NULL;
771 }
772 if (pcm_open_retry_count-- == 0) {
773 ret = -EIO;
774 goto error_open;
775 }
776 usleep(PROXY_OPEN_WAIT_TIME * 1000);
777 continue;
778 }
779 break;
780 }
781
Eric Laurent994a6932013-07-17 11:51:42 -0700782 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -0800783 return ret;
784
785error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -0800787
788error_config:
789 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -0800791
792 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793}
794
Eric Laurentef26c642015-06-19 16:30:44 -0700795void lock_input_stream(struct stream_in *in)
796{
797 pthread_mutex_lock(&in->pre_lock);
798 pthread_mutex_lock(&in->lock);
799 pthread_mutex_unlock(&in->pre_lock);
800}
801
802void lock_output_stream(struct stream_out *out)
803{
804 pthread_mutex_lock(&out->pre_lock);
805 pthread_mutex_lock(&out->lock);
806 pthread_mutex_unlock(&out->pre_lock);
807}
808
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700809/* must be called with out->lock locked */
810static int send_offload_cmd_l(struct stream_out* out, int command)
811{
812 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
813
814 ALOGVV("%s %d", __func__, command);
815
816 cmd->cmd = command;
817 list_add_tail(&out->offload_cmd_list, &cmd->node);
818 pthread_cond_signal(&out->offload_cond);
819 return 0;
820}
821
822/* must be called iwth out->lock locked */
823static void stop_compressed_output_l(struct stream_out *out)
824{
825 out->offload_state = OFFLOAD_STATE_IDLE;
826 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700827 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700828 if (out->compr != NULL) {
829 compress_stop(out->compr);
830 while (out->offload_thread_blocked) {
831 pthread_cond_wait(&out->cond, &out->lock);
832 }
833 }
834}
835
836static void *offload_thread_loop(void *context)
837{
838 struct stream_out *out = (struct stream_out *) context;
839 struct listnode *item;
840
841 out->offload_state = OFFLOAD_STATE_IDLE;
842 out->playback_started = 0;
843
844 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
845 set_sched_policy(0, SP_FOREGROUND);
846 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
847
848 ALOGV("%s", __func__);
Eric Laurentef26c642015-06-19 16:30:44 -0700849 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700850 for (;;) {
851 struct offload_cmd *cmd = NULL;
852 stream_callback_event_t event;
853 bool send_callback = false;
854
855 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
856 __func__, list_empty(&out->offload_cmd_list),
857 out->offload_state);
858 if (list_empty(&out->offload_cmd_list)) {
859 ALOGV("%s SLEEPING", __func__);
860 pthread_cond_wait(&out->offload_cond, &out->lock);
861 ALOGV("%s RUNNING", __func__);
862 continue;
863 }
864
865 item = list_head(&out->offload_cmd_list);
866 cmd = node_to_item(item, struct offload_cmd, node);
867 list_remove(item);
868
869 ALOGVV("%s STATE %d CMD %d out->compr %p",
870 __func__, out->offload_state, cmd->cmd, out->compr);
871
872 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
873 free(cmd);
874 break;
875 }
876
877 if (out->compr == NULL) {
878 ALOGE("%s: Compress handle is NULL", __func__);
879 pthread_cond_signal(&out->cond);
880 continue;
881 }
882 out->offload_thread_blocked = true;
883 pthread_mutex_unlock(&out->lock);
884 send_callback = false;
885 switch(cmd->cmd) {
886 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
887 compress_wait(out->compr, -1);
888 send_callback = true;
889 event = STREAM_CBK_EVENT_WRITE_READY;
890 break;
891 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -0700892 compress_next_track(out->compr);
893 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700894 send_callback = true;
895 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -0800896 /* Resend the metadata for next iteration */
897 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700898 break;
899 case OFFLOAD_CMD_DRAIN:
900 compress_drain(out->compr);
901 send_callback = true;
902 event = STREAM_CBK_EVENT_DRAIN_READY;
903 break;
904 default:
905 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
906 break;
907 }
Eric Laurentef26c642015-06-19 16:30:44 -0700908 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700909 out->offload_thread_blocked = false;
910 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -0700911 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -0800912 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700913 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -0700914 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700915 free(cmd);
916 }
917
918 pthread_cond_signal(&out->cond);
919 while (!list_empty(&out->offload_cmd_list)) {
920 item = list_head(&out->offload_cmd_list);
921 list_remove(item);
922 free(node_to_item(item, struct offload_cmd, node));
923 }
924 pthread_mutex_unlock(&out->lock);
925
926 return NULL;
927}
928
929static int create_offload_callback_thread(struct stream_out *out)
930{
931 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
932 list_init(&out->offload_cmd_list);
933 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
934 offload_thread_loop, out);
935 return 0;
936}
937
938static int destroy_offload_callback_thread(struct stream_out *out)
939{
Eric Laurentef26c642015-06-19 16:30:44 -0700940 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700941 stop_compressed_output_l(out);
942 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
943
944 pthread_mutex_unlock(&out->lock);
945 pthread_join(out->offload_thread, (void **) NULL);
946 pthread_cond_destroy(&out->offload_cond);
947
948 return 0;
949}
950
Eric Laurent07eeafd2013-10-06 12:52:49 -0700951static bool allow_hdmi_channel_config(struct audio_device *adev)
952{
953 struct listnode *node;
954 struct audio_usecase *usecase;
955 bool ret = true;
956
957 list_for_each(node, &adev->usecase_list) {
958 usecase = node_to_item(node, struct audio_usecase, list);
959 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
960 /*
961 * If voice call is already existing, do not proceed further to avoid
962 * disabling/enabling both RX and TX devices, CSD calls, etc.
963 * Once the voice call done, the HDMI channels can be configured to
964 * max channels of remaining use cases.
965 */
966 if (usecase->id == USECASE_VOICE_CALL) {
967 ALOGD("%s: voice call is active, no change in HDMI channels",
968 __func__);
969 ret = false;
970 break;
971 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
972 ALOGD("%s: multi channel playback is active, "
973 "no change in HDMI channels", __func__);
974 ret = false;
975 break;
976 }
977 }
978 }
979 return ret;
980}
981
982static int check_and_set_hdmi_channels(struct audio_device *adev,
983 unsigned int channels)
984{
985 struct listnode *node;
986 struct audio_usecase *usecase;
987
988 /* Check if change in HDMI channel config is allowed */
989 if (!allow_hdmi_channel_config(adev))
990 return 0;
991
992 if (channels == adev->cur_hdmi_channels) {
993 ALOGD("%s: Requested channels are same as current", __func__);
994 return 0;
995 }
996
997 platform_set_hdmi_channels(adev->platform, channels);
998 adev->cur_hdmi_channels = channels;
999
1000 /*
1001 * Deroute all the playback streams routed to HDMI so that
1002 * the back end is deactivated. Note that backend will not
1003 * be deactivated if any one stream is connected to it.
1004 */
1005 list_for_each(node, &adev->usecase_list) {
1006 usecase = node_to_item(node, struct audio_usecase, list);
1007 if (usecase->type == PCM_PLAYBACK &&
1008 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001009 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001010 }
1011 }
1012
1013 /*
1014 * Enable all the streams disabled above. Now the HDMI backend
1015 * will be activated with new channel configuration
1016 */
1017 list_for_each(node, &adev->usecase_list) {
1018 usecase = node_to_item(node, struct audio_usecase, list);
1019 if (usecase->type == PCM_PLAYBACK &&
1020 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001021 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001022 }
1023 }
1024
1025 return 0;
1026}
1027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028static int stop_output_stream(struct stream_out *out)
1029{
1030 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 struct audio_usecase *uc_info;
1032 struct audio_device *adev = out->dev;
1033
Eric Laurent994a6932013-07-17 11:51:42 -07001034 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 uc_info = get_usecase_from_list(adev, out->usecase);
1037 if (uc_info == NULL) {
1038 ALOGE("%s: Could not find the usecase (%d) in the list",
1039 __func__, out->usecase);
1040 return -EINVAL;
1041 }
1042
Haynes Mathew George41f86652014-06-17 14:22:15 -07001043 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1044 if (adev->visualizer_stop_output != NULL)
1045 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1046 if (adev->offload_effects_stop_output != NULL)
1047 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1048 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001049
Eric Laurent150dbfe2013-02-27 14:31:02 -08001050 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001051 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052
1053 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001054 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001056 list_remove(&uc_info->list);
1057 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Eric Laurent0499d4f2014-08-25 22:39:29 -05001059 audio_extn_extspk_update(adev->extspk);
1060
Eric Laurent07eeafd2013-10-06 12:52:49 -07001061 /* Must be called after removing the usecase from list */
1062 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1063 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1064
Eric Laurent994a6932013-07-17 11:51:42 -07001065 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 return ret;
1067}
1068
1069int start_output_stream(struct stream_out *out)
1070{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 struct audio_usecase *uc_info;
1073 struct audio_device *adev = out->dev;
1074
Eric Laurent994a6932013-07-17 11:51:42 -07001075 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001077 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 if (out->pcm_device_id < 0) {
1079 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1080 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001081 ret = -EINVAL;
1082 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083 }
1084
1085 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1086 uc_info->id = out->usecase;
1087 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001088 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001089 uc_info->devices = out->devices;
1090 uc_info->in_snd_device = SND_DEVICE_NONE;
1091 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092
Eric Laurent07eeafd2013-10-06 12:52:49 -07001093 /* This must be called before adding this usecase to the list */
1094 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1095 check_and_set_hdmi_channels(adev, out->config.channels);
1096
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001097 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001099 select_devices(adev, out->usecase);
1100
Eric Laurent0499d4f2014-08-25 22:39:29 -05001101 audio_extn_extspk_update(adev->extspk);
1102
Andy Hung31aca912014-03-20 17:14:59 -07001103 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001104 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001105 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001106 unsigned int flags = PCM_OUT;
1107 unsigned int pcm_open_retry_count = 0;
1108 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1109 flags |= PCM_MMAP | PCM_NOIRQ;
1110 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1111 } else
1112 flags |= PCM_MONOTONIC;
1113
1114 while (1) {
1115 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1116 flags, &out->config);
1117 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1118 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1119 if (out->pcm != NULL) {
1120 pcm_close(out->pcm);
1121 out->pcm = NULL;
1122 }
1123 if (pcm_open_retry_count-- == 0) {
1124 ret = -EIO;
1125 goto error_open;
1126 }
1127 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1128 continue;
1129 }
1130 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001131 }
1132 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001134 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001135 COMPRESS_IN, &out->compr_config);
1136 if (out->compr && !is_compress_ready(out->compr)) {
1137 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1138 compress_close(out->compr);
1139 out->compr = NULL;
1140 ret = -EIO;
1141 goto error_open;
1142 }
1143 if (out->offload_callback)
1144 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001145
1146 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001147 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1148 if (adev->offload_effects_start_output != NULL)
1149 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 }
Eric Laurent994a6932013-07-17 11:51:42 -07001151 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001152 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001153error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001155error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001156 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157}
1158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159static int check_input_parameters(uint32_t sample_rate,
1160 audio_format_t format,
1161 int channel_count)
1162{
1163 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
1164
1165 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
1166
1167 switch (sample_rate) {
1168 case 8000:
1169 case 11025:
1170 case 12000:
1171 case 16000:
1172 case 22050:
1173 case 24000:
1174 case 32000:
1175 case 44100:
1176 case 48000:
1177 break;
1178 default:
1179 return -EINVAL;
1180 }
1181
1182 return 0;
1183}
1184
1185static size_t get_input_buffer_size(uint32_t sample_rate,
1186 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001187 int channel_count,
1188 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189{
1190 size_t size = 0;
1191
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001192 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1193 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001194
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001195 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001196 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001197 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001198 /* ToDo: should use frame_size computed based on the format and
1199 channel_count here. */
1200 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201
Glenn Kasten4f993392014-05-14 07:30:48 -07001202 /* make sure the size is multiple of 32 bytes
1203 * At 48 kHz mono 16-bit PCM:
1204 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1205 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1206 */
1207 size += 0x1f;
1208 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001209
1210 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211}
1212
1213static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1214{
1215 struct stream_out *out = (struct stream_out *)stream;
1216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218}
1219
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001220static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221{
1222 return -ENOSYS;
1223}
1224
1225static size_t out_get_buffer_size(const struct audio_stream *stream)
1226{
1227 struct stream_out *out = (struct stream_out *)stream;
1228
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001229 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1230 return out->compr_config.fragment_size;
1231 }
Eric Laurentfdf296a2014-07-03 16:41:51 -07001232 return out->config.period_size *
1233 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001234}
1235
1236static uint32_t out_get_channels(const struct audio_stream *stream)
1237{
1238 struct stream_out *out = (struct stream_out *)stream;
1239
1240 return out->channel_mask;
1241}
1242
1243static audio_format_t out_get_format(const struct audio_stream *stream)
1244{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001245 struct stream_out *out = (struct stream_out *)stream;
1246
1247 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001248}
1249
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001250static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251{
1252 return -ENOSYS;
1253}
1254
1255static int out_standby(struct audio_stream *stream)
1256{
1257 struct stream_out *out = (struct stream_out *)stream;
1258 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001259
Eric Laurent994a6932013-07-17 11:51:42 -07001260 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001261 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262
Eric Laurentef26c642015-06-19 16:30:44 -07001263 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001265 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001267 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1268 if (out->pcm) {
1269 pcm_close(out->pcm);
1270 out->pcm = NULL;
1271 }
1272 } else {
1273 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001274 out->gapless_mdata.encoder_delay = 0;
1275 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 if (out->compr != NULL) {
1277 compress_close(out->compr);
1278 out->compr = NULL;
1279 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001280 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001282 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283 }
1284 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001285 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286 return 0;
1287}
1288
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001289static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290{
1291 return 0;
1292}
1293
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001294static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1295{
1296 int ret = 0;
1297 char value[32];
1298 struct compr_gapless_mdata tmp_mdata;
1299
1300 if (!out || !parms) {
1301 return -EINVAL;
1302 }
1303
1304 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1305 if (ret >= 0) {
1306 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1307 } else {
1308 return -EINVAL;
1309 }
1310
1311 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1312 if (ret >= 0) {
1313 tmp_mdata.encoder_padding = atoi(value);
1314 } else {
1315 return -EINVAL;
1316 }
1317
1318 out->gapless_mdata = tmp_mdata;
1319 out->send_new_metadata = 1;
1320 ALOGV("%s new encoder delay %u and padding %u", __func__,
1321 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1322
1323 return 0;
1324}
1325
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001326static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1327{
1328 return out == adev->primary_output || out == adev->voice_tx_output;
1329}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1332{
1333 struct stream_out *out = (struct stream_out *)stream;
1334 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001335 struct audio_usecase *usecase;
1336 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337 struct str_parms *parms;
1338 char value[32];
1339 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001340 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001341 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342
sangwoobc677242013-08-08 16:53:43 +09001343 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001344 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001345 parms = str_parms_create_str(kvpairs);
1346 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1347 if (ret >= 0) {
1348 val = atoi(value);
Eric Laurentef26c642015-06-19 16:30:44 -07001349 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001350 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001351
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 /*
1353 * When HDMI cable is unplugged the music playback is paused and
1354 * the policy manager sends routing=0. But the audioflinger
1355 * continues to write data until standby time (3sec).
1356 * As the HDMI core is turned off, the write gets blocked.
1357 * Avoid this by routing audio to speaker until standby.
1358 */
1359 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1360 val == AUDIO_DEVICE_NONE) {
1361 val = AUDIO_DEVICE_OUT_SPEAKER;
1362 }
1363
1364 /*
1365 * select_devices() call below switches all the usecases on the same
1366 * backend to the new device. Refer to check_usecases_codec_backend() in
1367 * the select_devices(). But how do we undo this?
1368 *
1369 * For example, music playback is active on headset (deep-buffer usecase)
1370 * and if we go to ringtones and select a ringtone, low-latency usecase
1371 * will be started on headset+speaker. As we can't enable headset+speaker
1372 * and headset devices at the same time, select_devices() switches the music
1373 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1374 * So when the ringtone playback is completed, how do we undo the same?
1375 *
1376 * We are relying on the out_set_parameters() call on deep-buffer output,
1377 * once the ringtone playback is ended.
1378 * NOTE: We should not check if the current devices are same as new devices.
1379 * Because select_devices() must be called to switch back the music
1380 * playback to headset.
1381 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001382 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 out->devices = val;
1384
1385 if (!out->standby)
1386 select_devices(adev, out->usecase);
1387
Eric Laurenta7657192014-10-09 21:09:33 -07001388 if (output_drives_call(adev, out)) {
1389 if (!voice_is_in_call(adev)) {
1390 if (adev->mode == AUDIO_MODE_IN_CALL) {
1391 adev->current_call_output = out;
1392 ret = voice_start_call(adev);
1393 }
1394 } else {
1395 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001396 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001397 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001398 }
1399 }
1400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001402 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001403
1404 /*handles device and call state changes*/
1405 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001407
1408 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1409 parse_compress_metadata(out, parms);
1410 }
1411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001413 ALOGV("%s: exit: code(%d)", __func__, status);
1414 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415}
1416
1417static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1418{
1419 struct stream_out *out = (struct stream_out *)stream;
1420 struct str_parms *query = str_parms_create_str(keys);
1421 char *str;
1422 char value[256];
1423 struct str_parms *reply = str_parms_create();
1424 size_t i, j;
1425 int ret;
1426 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001427 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1429 if (ret >= 0) {
1430 value[0] = '\0';
1431 i = 0;
1432 while (out->supported_channel_masks[i] != 0) {
1433 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1434 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1435 if (!first) {
1436 strcat(value, "|");
1437 }
1438 strcat(value, out_channels_name_to_enum_table[j].name);
1439 first = false;
1440 break;
1441 }
1442 }
1443 i++;
1444 }
1445 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1446 str = str_parms_to_str(reply);
1447 } else {
1448 str = strdup(keys);
1449 }
1450 str_parms_destroy(query);
1451 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001452 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453 return str;
1454}
1455
1456static uint32_t out_get_latency(const struct audio_stream_out *stream)
1457{
1458 struct stream_out *out = (struct stream_out *)stream;
1459
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001460 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1461 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
1462
1463 return (out->config.period_count * out->config.period_size * 1000) /
1464 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465}
1466
1467static int out_set_volume(struct audio_stream_out *stream, float left,
1468 float right)
1469{
Eric Laurenta9024de2013-04-04 09:19:12 -07001470 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001471 int volume[2];
1472
Eric Laurenta9024de2013-04-04 09:19:12 -07001473 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1474 /* only take left channel into account: the API is for stereo anyway */
1475 out->muted = (left == 0.0f);
1476 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001477 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1478 const char *mixer_ctl_name = "Compress Playback Volume";
1479 struct audio_device *adev = out->dev;
1480 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1482 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07001483 /* try with the control based on device id */
1484 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1485 PCM_PLAYBACK);
1486 char ctl_name[128] = {0};
1487 snprintf(ctl_name, sizeof(ctl_name),
1488 "Compress Playback %d Volume", pcm_device_id);
1489 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
1490 if (!ctl) {
1491 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
1492 return -EINVAL;
1493 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001494 }
1495 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1496 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1497 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1498 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001499 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 return -ENOSYS;
1502}
1503
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001504#ifdef NO_AUDIO_OUT
1505static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
1506 const void *buffer, size_t bytes)
1507{
1508 struct stream_out *out = (struct stream_out *)stream;
1509
1510 /* No Output device supported other than BT for playback.
1511 * Sleep for the amount of buffer duration
1512 */
Eric Laurentef26c642015-06-19 16:30:44 -07001513 lock_output_stream(out);
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001514 usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
1515 out_get_sample_rate(&out->stream.common));
1516 pthread_mutex_unlock(&out->lock);
1517 return bytes;
1518}
1519#endif
1520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1522 size_t bytes)
1523{
1524 struct stream_out *out = (struct stream_out *)stream;
1525 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001526 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527
Eric Laurentef26c642015-06-19 16:30:44 -07001528 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001530 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001531 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001533 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001536 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 goto exit;
1538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001541 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001542 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1543 if (out->send_new_metadata) {
1544 ALOGVV("send new gapless metadata");
1545 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1546 out->send_new_metadata = 0;
1547 }
1548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001549 ret = compress_write(out->compr, buffer, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001550 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07001551 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1553 }
1554 if (!out->playback_started) {
1555 compress_start(out->compr);
1556 out->playback_started = 1;
1557 out->offload_state = OFFLOAD_STATE_PLAYING;
1558 }
1559 pthread_mutex_unlock(&out->lock);
1560 return ret;
1561 } else {
1562 if (out->pcm) {
1563 if (out->muted)
1564 memset((void *)buffer, 0, bytes);
1565 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001566 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1567 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
1568 }
1569 else
1570 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001571 if (ret == 0)
1572 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001573 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574 }
1575
1576exit:
1577 pthread_mutex_unlock(&out->lock);
1578
1579 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001580 if (out->pcm)
1581 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 out_standby(&out->stream.common);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001583 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 out_get_sample_rate(&out->stream.common));
1585 }
1586 return bytes;
1587}
1588
1589static int out_get_render_position(const struct audio_stream_out *stream,
1590 uint32_t *dsp_frames)
1591{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001592 struct stream_out *out = (struct stream_out *)stream;
1593 *dsp_frames = 0;
1594 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurentef26c642015-06-19 16:30:44 -07001595 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596 if (out->compr != NULL) {
1597 compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
1598 &out->sample_rate);
1599 ALOGVV("%s rendered frames %d sample_rate %d",
1600 __func__, *dsp_frames, out->sample_rate);
1601 }
1602 pthread_mutex_unlock(&out->lock);
1603 return 0;
1604 } else
1605 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606}
1607
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001608static int out_add_audio_effect(const struct audio_stream *stream __unused,
1609 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610{
1611 return 0;
1612}
1613
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001614static int out_remove_audio_effect(const struct audio_stream *stream __unused,
1615 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616{
1617 return 0;
1618}
1619
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001620static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
1621 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622{
1623 return -EINVAL;
1624}
1625
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001626static int out_get_presentation_position(const struct audio_stream_out *stream,
1627 uint64_t *frames, struct timespec *timestamp)
1628{
1629 struct stream_out *out = (struct stream_out *)stream;
1630 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07001631 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001632
Eric Laurentef26c642015-06-19 16:30:44 -07001633 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001634
Eric Laurent949a0892013-09-20 09:20:13 -07001635 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1636 if (out->compr != NULL) {
1637 compress_get_tstamp(out->compr, &dsp_frames,
1638 &out->sample_rate);
1639 ALOGVV("%s rendered frames %ld sample_rate %d",
1640 __func__, dsp_frames, out->sample_rate);
1641 *frames = dsp_frames;
1642 ret = 0;
1643 /* this is the best we can do */
1644 clock_gettime(CLOCK_MONOTONIC, timestamp);
1645 }
1646 } else {
1647 if (out->pcm) {
1648 size_t avail;
1649 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
1650 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07001651 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07001652 // This adjustment accounts for buffering after app processor.
1653 // It is based on estimated DSP latency per use case, rather than exact.
1654 signed_frames -=
1655 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
1656
Eric Laurent949a0892013-09-20 09:20:13 -07001657 // It would be unusual for this value to be negative, but check just in case ...
1658 if (signed_frames >= 0) {
1659 *frames = signed_frames;
1660 ret = 0;
1661 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001662 }
1663 }
1664 }
1665
1666 pthread_mutex_unlock(&out->lock);
1667
1668 return ret;
1669}
1670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671static int out_set_callback(struct audio_stream_out *stream,
1672 stream_callback_t callback, void *cookie)
1673{
1674 struct stream_out *out = (struct stream_out *)stream;
1675
1676 ALOGV("%s", __func__);
Eric Laurentef26c642015-06-19 16:30:44 -07001677 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001678 out->offload_callback = callback;
1679 out->offload_cookie = cookie;
1680 pthread_mutex_unlock(&out->lock);
1681 return 0;
1682}
1683
1684static int out_pause(struct audio_stream_out* stream)
1685{
1686 struct stream_out *out = (struct stream_out *)stream;
1687 int status = -ENOSYS;
1688 ALOGV("%s", __func__);
1689 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurentef26c642015-06-19 16:30:44 -07001690 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001691 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
1692 status = compress_pause(out->compr);
1693 out->offload_state = OFFLOAD_STATE_PAUSED;
1694 }
1695 pthread_mutex_unlock(&out->lock);
1696 }
1697 return status;
1698}
1699
1700static int out_resume(struct audio_stream_out* stream)
1701{
1702 struct stream_out *out = (struct stream_out *)stream;
1703 int status = -ENOSYS;
1704 ALOGV("%s", __func__);
1705 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1706 status = 0;
Eric Laurentef26c642015-06-19 16:30:44 -07001707 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
1709 status = compress_resume(out->compr);
1710 out->offload_state = OFFLOAD_STATE_PLAYING;
1711 }
1712 pthread_mutex_unlock(&out->lock);
1713 }
1714 return status;
1715}
1716
1717static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
1718{
1719 struct stream_out *out = (struct stream_out *)stream;
1720 int status = -ENOSYS;
1721 ALOGV("%s", __func__);
1722 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurentef26c642015-06-19 16:30:44 -07001723 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
1725 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
1726 else
1727 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
1728 pthread_mutex_unlock(&out->lock);
1729 }
1730 return status;
1731}
1732
1733static int out_flush(struct audio_stream_out* stream)
1734{
1735 struct stream_out *out = (struct stream_out *)stream;
1736 ALOGV("%s", __func__);
1737 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurentef26c642015-06-19 16:30:44 -07001738 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 stop_compressed_output_l(out);
1740 pthread_mutex_unlock(&out->lock);
1741 return 0;
1742 }
1743 return -ENOSYS;
1744}
1745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746/** audio_stream_in implementation **/
1747static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1748{
1749 struct stream_in *in = (struct stream_in *)stream;
1750
1751 return in->config.rate;
1752}
1753
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001754static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755{
1756 return -ENOSYS;
1757}
1758
1759static size_t in_get_buffer_size(const struct audio_stream *stream)
1760{
1761 struct stream_in *in = (struct stream_in *)stream;
1762
Eric Laurentfdf296a2014-07-03 16:41:51 -07001763 return in->config.period_size *
1764 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765}
1766
1767static uint32_t in_get_channels(const struct audio_stream *stream)
1768{
1769 struct stream_in *in = (struct stream_in *)stream;
1770
1771 return in->channel_mask;
1772}
1773
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001774static audio_format_t in_get_format(const struct audio_stream *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775{
1776 return AUDIO_FORMAT_PCM_16_BIT;
1777}
1778
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001779static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780{
1781 return -ENOSYS;
1782}
1783
1784static int in_standby(struct audio_stream *stream)
1785{
1786 struct stream_in *in = (struct stream_in *)stream;
1787 struct audio_device *adev = in->dev;
1788 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07001789 ALOGV("%s: enter", __func__);
Eric Laurentef26c642015-06-19 16:30:44 -07001790
1791 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07001792
1793 if (!in->standby && in->is_st_session) {
1794 ALOGD("%s: sound trigger pcm stop lab", __func__);
1795 audio_extn_sound_trigger_stop_lab(in);
1796 in->standby = true;
1797 }
1798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001800 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001802 if (in->pcm) {
1803 pcm_close(in->pcm);
1804 in->pcm = NULL;
1805 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05001806 adev->enable_voicerx = false;
1807 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001809 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 }
1811 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001812 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 return status;
1814}
1815
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001816static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817{
1818 return 0;
1819}
1820
1821static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1822{
1823 struct stream_in *in = (struct stream_in *)stream;
1824 struct audio_device *adev = in->dev;
1825 struct str_parms *parms;
1826 char *str;
1827 char value[32];
1828 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07001829 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
Eric Laurent994a6932013-07-17 11:51:42 -07001831 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832 parms = str_parms_create_str(kvpairs);
1833
1834 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
1835
Eric Laurentef26c642015-06-19 16:30:44 -07001836 lock_input_stream(in);
1837
Eric Laurent150dbfe2013-02-27 14:31:02 -08001838 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 if (ret >= 0) {
1840 val = atoi(value);
1841 /* no audio source uses val == 0 */
1842 if ((in->source != val) && (val != 0)) {
1843 in->source = val;
1844 }
1845 }
1846
1847 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07001848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 if (ret >= 0) {
1850 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001851 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 in->device = val;
1853 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001854 if (!in->standby)
Eric Laurent03f09432014-03-25 18:09:11 -07001855 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 }
1857 }
1858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001860 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861
1862 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001863 ALOGV("%s: exit: status(%d)", __func__, status);
1864 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865}
1866
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001867static char* in_get_parameters(const struct audio_stream *stream __unused,
1868 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869{
1870 return strdup("");
1871}
1872
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001873static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874{
1875 return 0;
1876}
1877
1878static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
1879 size_t bytes)
1880{
1881 struct stream_in *in = (struct stream_in *)stream;
1882 struct audio_device *adev = in->dev;
1883 int i, ret = -1;
1884
Eric Laurentef26c642015-06-19 16:30:44 -07001885 lock_input_stream(in);
1886
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07001887 if (in->is_st_session) {
1888 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
1889 /* Read from sound trigger HAL */
1890 audio_extn_sound_trigger_read(in, buffer, bytes);
1891 pthread_mutex_unlock(&in->lock);
1892 return bytes;
1893 }
1894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001896 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001898 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900 goto exit;
1901 }
1902 in->standby = 0;
1903 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
1905 if (in->pcm) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001906 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1907 ret = pcm_mmap_read(in->pcm, buffer, bytes);
1908 } else
1909 ret = pcm_read(in->pcm, buffer, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 }
1911
1912 /*
1913 * Instead of writing zeroes here, we could trust the hardware
1914 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07001915 * No need to acquire adev->lock to read mic_muted here as we don't change its state.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07001917 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 memset(buffer, 0, bytes);
1919
1920exit:
1921 pthread_mutex_unlock(&in->lock);
1922
1923 if (ret != 0) {
1924 in_standby(&in->stream.common);
1925 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001926 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 in_get_sample_rate(&in->stream.common));
1928 }
1929 return bytes;
1930}
1931
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001932static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933{
1934 return 0;
1935}
1936
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001937static int add_remove_audio_effect(const struct audio_stream *stream,
1938 effect_handle_t effect,
1939 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001941 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05001942 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001943 int status = 0;
1944 effect_descriptor_t desc;
1945
1946 status = (*effect)->get_descriptor(effect, &desc);
1947 if (status != 0)
1948 return status;
1949
Eric Laurentef26c642015-06-19 16:30:44 -07001950 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001951 pthread_mutex_lock(&in->dev->lock);
1952 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
1953 in->enable_aec != enable &&
1954 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
1955 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05001956 if (!enable)
1957 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
1958 adev->enable_voicerx = enable;
1959 struct audio_usecase *usecase;
1960 struct listnode *node;
1961 list_for_each(node, &adev->usecase_list) {
1962 usecase = node_to_item(node, struct audio_usecase, list);
1963 if (usecase->type == PCM_PLAYBACK) {
1964 select_devices(adev, usecase->id);
1965 break;
1966 }
1967 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001968 if (!in->standby)
1969 select_devices(in->dev, in->usecase);
1970 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07001971 if (in->enable_ns != enable &&
1972 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
1973 in->enable_ns = enable;
1974 if (!in->standby)
1975 select_devices(in->dev, in->usecase);
1976 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001977 pthread_mutex_unlock(&in->dev->lock);
1978 pthread_mutex_unlock(&in->lock);
1979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 return 0;
1981}
1982
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001983static int in_add_audio_effect(const struct audio_stream *stream,
1984 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985{
Eric Laurent994a6932013-07-17 11:51:42 -07001986 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001987 return add_remove_audio_effect(stream, effect, true);
1988}
1989
1990static int in_remove_audio_effect(const struct audio_stream *stream,
1991 effect_handle_t effect)
1992{
Eric Laurent994a6932013-07-17 11:51:42 -07001993 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07001994 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995}
1996
1997static int adev_open_output_stream(struct audio_hw_device *dev,
1998 audio_io_handle_t handle,
1999 audio_devices_t devices,
2000 audio_output_flags_t flags,
2001 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002002 struct audio_stream_out **stream_out,
2003 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004{
2005 struct audio_device *adev = (struct audio_device *)dev;
2006 struct stream_out *out;
2007 int i, ret;
2008
Eric Laurent994a6932013-07-17 11:51:42 -07002009 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 __func__, config->sample_rate, config->channel_mask, devices, flags);
2011 *stream_out = NULL;
2012 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2013
2014 if (devices == AUDIO_DEVICE_NONE)
2015 devices = AUDIO_DEVICE_OUT_SPEAKER;
2016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 out->flags = flags;
2018 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002019 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 out->format = config->format;
2021 out->sample_rate = config->sample_rate;
2022 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2023 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002024 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025
2026 /* Init use case and pcm_config */
2027 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002028 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002030 pthread_mutex_lock(&adev->lock);
2031 ret = read_hdmi_channel_masks(out);
2032 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002033 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002034 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002035
2036 if (config->sample_rate == 0)
2037 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2038 if (config->channel_mask == 0)
2039 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2040
2041 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2044 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002046 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2049 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2050 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2051 ALOGE("%s: Unsupported Offload information", __func__);
2052 ret = -EINVAL;
2053 goto error_open;
2054 }
2055 if (!is_supported_format(config->offload_info.format)) {
2056 ALOGE("%s: Unsupported audio format", __func__);
2057 ret = -EINVAL;
2058 goto error_open;
2059 }
2060
2061 out->compr_config.codec = (struct snd_codec *)
2062 calloc(1, sizeof(struct snd_codec));
2063
2064 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2065 if (config->offload_info.channel_mask)
2066 out->channel_mask = config->offload_info.channel_mask;
2067 else if (config->channel_mask)
2068 out->channel_mask = config->channel_mask;
2069 out->format = config->offload_info.format;
2070 out->sample_rate = config->offload_info.sample_rate;
2071
2072 out->stream.set_callback = out_set_callback;
2073 out->stream.pause = out_pause;
2074 out->stream.resume = out_resume;
2075 out->stream.drain = out_drain;
2076 out->stream.flush = out_flush;
2077
2078 out->compr_config.codec->id =
2079 get_snd_codec_id(config->offload_info.format);
2080 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2081 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002082 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 out->compr_config.codec->bit_rate =
2084 config->offload_info.bit_rate;
2085 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002086 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2088
2089 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2090 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002091
2092 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 create_offload_callback_thread(out);
2094 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2095 __func__, config->offload_info.version,
2096 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002097 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2098 if (config->sample_rate == 0)
2099 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2100 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2101 config->sample_rate != 8000) {
2102 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2103 ret = -EINVAL;
2104 goto error_open;
2105 }
2106 out->sample_rate = config->sample_rate;
2107 out->config.rate = config->sample_rate;
2108 if (config->format == AUDIO_FORMAT_DEFAULT)
2109 config->format = AUDIO_FORMAT_PCM_16_BIT;
2110 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2111 config->format = AUDIO_FORMAT_PCM_16_BIT;
2112 ret = -EINVAL;
2113 goto error_open;
2114 }
2115 out->format = config->format;
2116 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2117 out->config = pcm_config_afe_proxy_playback;
2118 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002120 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2121 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2122 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002123 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2124 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2125 out->config = pcm_config_deep_buffer;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002126 } else {
2127 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2128 out->config = pcm_config_low_latency;
2129 }
2130 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2131 if (k_enable_extended_precision
2132 && pcm_params_format_test(adev->use_case_table[out->usecase],
2133 pcm_format_from_audio_format(config->format))) {
2134 out->config.format = pcm_format_from_audio_format(config->format);
2135 /* out->format already set to config->format */
2136 } else {
2137 /* deny the externally proposed config format
2138 * and use the one specified in audio_hw layer configuration.
2139 * Note: out->format is returned by out->stream.common.get_format()
2140 * and is used to set config->format in the code several lines below.
2141 */
2142 out->format = audio_format_from_pcm_format(out->config.format);
2143 }
2144 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002147 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2148 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002150 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002151 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002152 adev->primary_output = out;
2153 else {
2154 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002155 ret = -EEXIST;
2156 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002157 }
2158 }
2159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 /* Check if this usecase is already existing */
2161 pthread_mutex_lock(&adev->lock);
2162 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2163 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002165 ret = -EEXIST;
2166 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 }
2168 pthread_mutex_unlock(&adev->lock);
2169
2170 out->stream.common.get_sample_rate = out_get_sample_rate;
2171 out->stream.common.set_sample_rate = out_set_sample_rate;
2172 out->stream.common.get_buffer_size = out_get_buffer_size;
2173 out->stream.common.get_channels = out_get_channels;
2174 out->stream.common.get_format = out_get_format;
2175 out->stream.common.set_format = out_set_format;
2176 out->stream.common.standby = out_standby;
2177 out->stream.common.dump = out_dump;
2178 out->stream.common.set_parameters = out_set_parameters;
2179 out->stream.common.get_parameters = out_get_parameters;
2180 out->stream.common.add_audio_effect = out_add_audio_effect;
2181 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2182 out->stream.get_latency = out_get_latency;
2183 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002184#ifdef NO_AUDIO_OUT
2185 out->stream.write = out_write_for_no_output;
2186#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002188#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 out->stream.get_render_position = out_get_render_position;
2190 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002191 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002194 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002195 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurentef26c642015-06-19 16:30:44 -07002198 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 config->format = out->stream.common.get_format(&out->stream.common);
2202 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2203 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2204
2205 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002206 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002208
2209error_open:
2210 free(out);
2211 *stream_out = NULL;
2212 ALOGD("%s: exit: ret %d", __func__, ret);
2213 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214}
2215
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002216static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 struct audio_stream_out *stream)
2218{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 struct stream_out *out = (struct stream_out *)stream;
2220 struct audio_device *adev = out->dev;
2221
Eric Laurent994a6932013-07-17 11:51:42 -07002222 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2225 destroy_offload_callback_thread(out);
2226
2227 if (out->compr_config.codec != NULL)
2228 free(out->compr_config.codec);
2229 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002230
2231 if (adev->voice_tx_output == out)
2232 adev->voice_tx_output = NULL;
2233
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 pthread_cond_destroy(&out->cond);
2235 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002237 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238}
2239
2240static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2241{
2242 struct audio_device *adev = (struct audio_device *)dev;
2243 struct str_parms *parms;
2244 char *str;
2245 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002246 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002248 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002250 ALOGD("%s: enter: %s", __func__, kvpairs);
2251
2252 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253
2254 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002255 status = voice_set_parameters(adev, parms);
2256 if (status != 0) {
2257 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 }
2259
2260 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2261 if (ret >= 0) {
2262 /* When set to false, HAL should disable EC and NS
2263 * But it is currently not supported.
2264 */
2265 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2266 adev->bluetooth_nrec = true;
2267 else
2268 adev->bluetooth_nrec = false;
2269 }
2270
2271 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2272 if (ret >= 0) {
2273 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2274 adev->screen_off = false;
2275 else
2276 adev->screen_off = true;
2277 }
2278
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002279 ret = str_parms_get_int(parms, "rotation", &val);
2280 if (ret >= 0) {
2281 bool reverse_speakers = false;
2282 switch(val) {
2283 // FIXME: note that the code below assumes that the speakers are in the correct placement
2284 // relative to the user when the device is rotated 90deg from its default rotation. This
2285 // assumption is device-specific, not platform-specific like this code.
2286 case 270:
2287 reverse_speakers = true;
2288 break;
2289 case 0:
2290 case 90:
2291 case 180:
2292 break;
2293 default:
2294 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07002295 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002296 }
Eric Laurent03f09432014-03-25 18:09:11 -07002297 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07002298 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002299 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002300 }
2301
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002302 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2303 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002304 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002305 }
2306
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08002307 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002308done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002310 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07002311 ALOGV("%s: exit with code(%d)", __func__, status);
2312 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313}
2314
2315static char* adev_get_parameters(const struct audio_hw_device *dev,
2316 const char *keys)
2317{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002318 struct audio_device *adev = (struct audio_device *)dev;
2319 struct str_parms *reply = str_parms_create();
2320 struct str_parms *query = str_parms_create_str(keys);
2321 char *str;
2322
2323 pthread_mutex_lock(&adev->lock);
2324
2325 voice_get_parameters(adev, query, reply);
2326 str = str_parms_to_str(reply);
2327 str_parms_destroy(query);
2328 str_parms_destroy(reply);
2329
2330 pthread_mutex_unlock(&adev->lock);
2331 ALOGV("%s: exit: returns - %s", __func__, str);
2332 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333}
2334
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002335static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336{
2337 return 0;
2338}
2339
Haynes Mathew George5191a852013-09-11 14:19:36 -07002340static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2341{
2342 int ret;
2343 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002344
Eric Laurent4cc4ce12014-09-10 13:21:01 -05002345 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
2346
Haynes Mathew George5191a852013-09-11 14:19:36 -07002347 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002348 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002349 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002350
Haynes Mathew George5191a852013-09-11 14:19:36 -07002351 return ret;
2352}
2353
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002354static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355{
2356 return -ENOSYS;
2357}
2358
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002359static int adev_get_master_volume(struct audio_hw_device *dev __unused,
2360 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361{
2362 return -ENOSYS;
2363}
2364
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002365static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366{
2367 return -ENOSYS;
2368}
2369
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002370static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371{
2372 return -ENOSYS;
2373}
2374
2375static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2376{
2377 struct audio_device *adev = (struct audio_device *)dev;
2378
2379 pthread_mutex_lock(&adev->lock);
2380 if (adev->mode != mode) {
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002381 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07002383 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
2384 voice_is_in_call(adev)) {
2385 voice_stop_call(adev);
2386 adev->current_call_output = NULL;
2387 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 }
2389 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002390
2391 audio_extn_extspk_set_mode(adev->extspk, mode);
2392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 return 0;
2394}
2395
2396static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2397{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002398 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002401 ALOGD("%s: state %d\n", __func__, state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002402 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002403 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002404 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00002405 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002406
2407 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408}
2409
2410static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2411{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002412 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413 return 0;
2414}
2415
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002416static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417 const struct audio_config *config)
2418{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002419 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002421 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
2422 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423}
2424
2425static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002426 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 audio_devices_t devices,
2428 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002429 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07002430 audio_input_flags_t flags,
2431 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05002432 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433{
2434 struct audio_device *adev = (struct audio_device *)dev;
2435 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002436 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002437 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002438 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439
Eric Laurent994a6932013-07-17 11:51:42 -07002440 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 *stream_in = NULL;
2442 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2443 return -EINVAL;
2444
2445 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2446
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002447 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurentef26c642015-06-19 16:30:44 -07002448 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 in->stream.common.get_sample_rate = in_get_sample_rate;
2451 in->stream.common.set_sample_rate = in_set_sample_rate;
2452 in->stream.common.get_buffer_size = in_get_buffer_size;
2453 in->stream.common.get_channels = in_get_channels;
2454 in->stream.common.get_format = in_get_format;
2455 in->stream.common.set_format = in_set_format;
2456 in->stream.common.standby = in_standby;
2457 in->stream.common.dump = in_dump;
2458 in->stream.common.set_parameters = in_set_parameters;
2459 in->stream.common.get_parameters = in_get_parameters;
2460 in->stream.common.add_audio_effect = in_add_audio_effect;
2461 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2462 in->stream.set_gain = in_set_gain;
2463 in->stream.read = in_read;
2464 in->stream.get_input_frames_lost = in_get_input_frames_lost;
2465
2466 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002467 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 in->standby = 1;
2470 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002471 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472
2473 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002474 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
2475 if (config->sample_rate == 0)
2476 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2477 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2478 config->sample_rate != 8000) {
2479 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2480 ret = -EINVAL;
2481 goto err_open;
2482 }
2483 if (config->format == AUDIO_FORMAT_DEFAULT)
2484 config->format = AUDIO_FORMAT_PCM_16_BIT;
2485 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2486 config->format = AUDIO_FORMAT_PCM_16_BIT;
2487 ret = -EINVAL;
2488 goto err_open;
2489 }
2490
2491 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
2492 in->config = pcm_config_afe_proxy_record;
2493 } else {
2494 in->usecase = USECASE_AUDIO_RECORD;
2495 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
2496 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
2497 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07002498#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002499 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07002500#endif
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002501 }
2502 in->config = pcm_config_audio_capture;
2503
2504 frame_size = audio_stream_in_frame_size(&in->stream);
2505 buffer_size = get_input_buffer_size(config->sample_rate,
2506 config->format,
2507 channel_count,
2508 is_low_latency);
2509 in->config.period_size = buffer_size / frame_size;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 in->config.channels = channel_count;
2512 in->config.rate = config->sample_rate;
2513
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002514 /* This stream could be for sound trigger lab,
2515 get sound trigger pcm if present */
2516 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517
2518 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002519 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 return 0;
2521
2522err_open:
2523 free(in);
2524 *stream_in = NULL;
2525 return ret;
2526}
2527
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002528static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 struct audio_stream_in *stream)
2530{
Eric Laurent994a6932013-07-17 11:51:42 -07002531 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 in_standby(&stream->common);
2534 free(stream);
2535
2536 return;
2537}
2538
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002539static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540{
2541 return 0;
2542}
2543
Andy Hung31aca912014-03-20 17:14:59 -07002544/* verifies input and output devices and their capabilities.
2545 *
2546 * This verification is required when enabling extended bit-depth or
2547 * sampling rates, as not all qcom products support it.
2548 *
2549 * Suitable for calling only on initialization such as adev_open().
2550 * It fills the audio_device use_case_table[] array.
2551 *
2552 * Has a side-effect that it needs to configure audio routing / devices
2553 * in order to power up the devices and read the device parameters.
2554 * It does not acquire any hw device lock. Should restore the devices
2555 * back to "normal state" upon completion.
2556 */
2557static int adev_verify_devices(struct audio_device *adev)
2558{
2559 /* enumeration is a bit difficult because one really wants to pull
2560 * the use_case, device id, etc from the hidden pcm_device_table[].
2561 * In this case there are the following use cases and device ids.
2562 *
2563 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
2564 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
2565 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
2566 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
2567 * [USECASE_AUDIO_RECORD] = {0, 0},
2568 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
2569 * [USECASE_VOICE_CALL] = {2, 2},
2570 *
2571 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
2572 * USECASE_VOICE_CALL omitted, but possible for either input or output.
2573 */
2574
2575 /* should be the usecases enabled in adev_open_input_stream() */
2576 static const int test_in_usecases[] = {
2577 USECASE_AUDIO_RECORD,
2578 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
2579 };
2580 /* should be the usecases enabled in adev_open_output_stream()*/
2581 static const int test_out_usecases[] = {
2582 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
2583 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
2584 };
2585 static const usecase_type_t usecase_type_by_dir[] = {
2586 PCM_PLAYBACK,
2587 PCM_CAPTURE,
2588 };
2589 static const unsigned flags_by_dir[] = {
2590 PCM_OUT,
2591 PCM_IN,
2592 };
2593
2594 size_t i;
2595 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002596 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07002597 char info[512]; /* for possible debug info */
2598
2599 for (dir = 0; dir < 2; ++dir) {
2600 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
2601 const unsigned flags_dir = flags_by_dir[dir];
2602 const size_t testsize =
2603 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
2604 const int *testcases =
2605 dir ? test_in_usecases : test_out_usecases;
2606 const audio_devices_t audio_device =
2607 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
2608
2609 for (i = 0; i < testsize; ++i) {
2610 const audio_usecase_t audio_usecase = testcases[i];
2611 int device_id;
2612 snd_device_t snd_device;
2613 struct pcm_params **pparams;
2614 struct stream_out out;
2615 struct stream_in in;
2616 struct audio_usecase uc_info;
2617 int retval;
2618
2619 pparams = &adev->use_case_table[audio_usecase];
2620 pcm_params_free(*pparams); /* can accept null input */
2621 *pparams = NULL;
2622
2623 /* find the device ID for the use case (signed, for error) */
2624 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
2625 if (device_id < 0)
2626 continue;
2627
2628 /* prepare structures for device probing */
2629 memset(&uc_info, 0, sizeof(uc_info));
2630 uc_info.id = audio_usecase;
2631 uc_info.type = usecase_type;
2632 if (dir) {
2633 adev->active_input = &in;
2634 memset(&in, 0, sizeof(in));
2635 in.device = audio_device;
2636 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
2637 uc_info.stream.in = &in;
2638 } else {
2639 adev->active_input = NULL;
2640 }
2641 memset(&out, 0, sizeof(out));
2642 out.devices = audio_device; /* only field needed in select_devices */
2643 uc_info.stream.out = &out;
2644 uc_info.devices = audio_device;
2645 uc_info.in_snd_device = SND_DEVICE_NONE;
2646 uc_info.out_snd_device = SND_DEVICE_NONE;
2647 list_add_tail(&adev->usecase_list, &uc_info.list);
2648
2649 /* select device - similar to start_(in/out)put_stream() */
2650 retval = select_devices(adev, audio_usecase);
2651 if (retval >= 0) {
2652 *pparams = pcm_params_get(card_id, device_id, flags_dir);
2653#if LOG_NDEBUG == 0
2654 if (*pparams) {
2655 ALOGV("%s: (%s) card %d device %d", __func__,
2656 dir ? "input" : "output", card_id, device_id);
2657 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
2658 ALOGV(info); /* print parameters */
2659 } else {
2660 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
2661 }
2662#endif
2663 }
2664
2665 /* deselect device - similar to stop_(in/out)put_stream() */
2666 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07002667 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07002668 /* 2. Disable the rx device */
2669 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07002670 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07002671 list_remove(&uc_info.list);
2672 }
2673 }
2674 adev->active_input = NULL; /* restore adev state */
2675 return 0;
2676}
2677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678static int adev_close(hw_device_t *device)
2679{
Andy Hung31aca912014-03-20 17:14:59 -07002680 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 struct audio_device *adev = (struct audio_device *)device;
2682 audio_route_free(adev->audio_route);
Eric Laurentb23d5282013-05-14 15:27:20 -07002683 free(adev->snd_dev_ref_cnt);
2684 platform_deinit(adev->platform);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002685 audio_extn_extspk_deinit(adev->extspk);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002686 audio_extn_sound_trigger_deinit(adev);
Andy Hung31aca912014-03-20 17:14:59 -07002687 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
2688 pcm_params_free(adev->use_case_table[i]);
2689 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 free(device);
2691 return 0;
2692}
2693
Glenn Kasten4f993392014-05-14 07:30:48 -07002694/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
2695 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
2696 * just that it _might_ work.
2697 */
2698static int period_size_is_plausible_for_low_latency(int period_size)
2699{
2700 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07002701 case 48:
2702 case 96:
2703 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07002704 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07002705 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07002706 case 240:
2707 case 320:
2708 case 480:
2709 return 1;
2710 default:
2711 return 0;
2712 }
2713}
2714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715static int adev_open(const hw_module_t *module, const char *name,
2716 hw_device_t **device)
2717{
2718 struct audio_device *adev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002719 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002721 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
2723
2724 adev = calloc(1, sizeof(struct audio_device));
2725
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002726 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
2727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 adev->device.common.tag = HARDWARE_DEVICE_TAG;
2729 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
2730 adev->device.common.module = (struct hw_module_t *)module;
2731 adev->device.common.close = adev_close;
2732
2733 adev->device.init_check = adev_init_check;
2734 adev->device.set_voice_volume = adev_set_voice_volume;
2735 adev->device.set_master_volume = adev_set_master_volume;
2736 adev->device.get_master_volume = adev_get_master_volume;
2737 adev->device.set_master_mute = adev_set_master_mute;
2738 adev->device.get_master_mute = adev_get_master_mute;
2739 adev->device.set_mode = adev_set_mode;
2740 adev->device.set_mic_mute = adev_set_mic_mute;
2741 adev->device.get_mic_mute = adev_get_mic_mute;
2742 adev->device.set_parameters = adev_set_parameters;
2743 adev->device.get_parameters = adev_get_parameters;
2744 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
2745 adev->device.open_output_stream = adev_open_output_stream;
2746 adev->device.close_output_stream = adev_close_output_stream;
2747 adev->device.open_input_stream = adev_open_input_stream;
2748 adev->device.close_input_stream = adev_close_input_stream;
2749 adev->device.dump = adev_dump;
2750
2751 /* Set the default route before the PCM stream is opened */
2752 pthread_mutex_lock(&adev->lock);
2753 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08002754 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002755 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08002757 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07002758 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07002759 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002760 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002761 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 pthread_mutex_unlock(&adev->lock);
2763
2764 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07002765 adev->platform = platform_init(adev);
2766 if (!adev->platform) {
2767 free(adev->snd_dev_ref_cnt);
2768 free(adev);
2769 ALOGE("%s: Failed to init platform data, aborting.", __func__);
2770 *device = NULL;
2771 return -EINVAL;
2772 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002773
Eric Laurent0499d4f2014-08-25 22:39:29 -05002774 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002775 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002776
Eric Laurentc4aef752013-09-12 17:45:53 -07002777 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
2778 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
2779 if (adev->visualizer_lib == NULL) {
2780 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
2781 } else {
2782 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
2783 adev->visualizer_start_output =
Haynes Mathew George41f86652014-06-17 14:22:15 -07002784 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07002785 "visualizer_hal_start_output");
2786 adev->visualizer_stop_output =
Haynes Mathew George41f86652014-06-17 14:22:15 -07002787 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07002788 "visualizer_hal_stop_output");
2789 }
2790 }
2791
Haynes Mathew George41f86652014-06-17 14:22:15 -07002792 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
2793 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
2794 if (adev->offload_effects_lib == NULL) {
2795 ALOGE("%s: DLOPEN failed for %s", __func__,
2796 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
2797 } else {
2798 ALOGV("%s: DLOPEN successful for %s", __func__,
2799 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
2800 adev->offload_effects_start_output =
2801 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
2802 "offload_effects_bundle_hal_start_output");
2803 adev->offload_effects_stop_output =
2804 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
2805 "offload_effects_bundle_hal_stop_output");
2806 }
2807 }
2808
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002809 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002810 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 *device = &adev->device.common;
Andy Hung31aca912014-03-20 17:14:59 -07002813 if (k_enable_extended_precision)
2814 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815
Glenn Kasten4f993392014-05-14 07:30:48 -07002816 char value[PROPERTY_VALUE_MAX];
2817 int trial;
2818 if (property_get("audio_hal.period_size", value, NULL) > 0) {
2819 trial = atoi(value);
2820 if (period_size_is_plausible_for_low_latency(trial)) {
2821 pcm_config_low_latency.period_size = trial;
2822 pcm_config_low_latency.start_threshold = trial / 4;
2823 pcm_config_low_latency.avail_min = trial / 4;
2824 configured_low_latency_capture_period_size = trial;
2825 }
2826 }
2827 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
2828 trial = atoi(value);
2829 if (period_size_is_plausible_for_low_latency(trial)) {
2830 configured_low_latency_capture_period_size = trial;
2831 }
2832 }
2833
Eric Laurent994a6932013-07-17 11:51:42 -07002834 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 return 0;
2836}
2837
2838static struct hw_module_methods_t hal_module_methods = {
2839 .open = adev_open,
2840};
2841
2842struct audio_module HAL_MODULE_INFO_SYM = {
2843 .common = {
2844 .tag = HARDWARE_MODULE_TAG,
2845 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
2846 .hal_api_version = HARDWARE_HAL_API_VERSION,
2847 .id = AUDIO_HARDWARE_MODULE_ID,
2848 .name = "QCOM Audio HAL",
2849 .author = "Code Aurora Forum",
2850 .methods = &hal_module_methods,
2851 },
2852};