blob: 34e1f2ce39528bf94c99b3fa491531f8b4e32a1f [file] [log] [blame]
Simon Wilson15f60a82012-04-24 20:56:32 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
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*/
19
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
23#include <stdlib.h>
24#include <sys/time.h>
Eric Laurent688880c2012-09-07 16:46:00 -070025#include <fcntl.h>
Simon Wilson15f60a82012-04-24 20:56:32 -070026
27#include <cutils/log.h>
28#include <cutils/properties.h>
29#include <cutils/str_parms.h>
30
31#include <hardware/audio.h>
32#include <hardware/hardware.h>
33
Christopher Ferrisf4d123f2013-12-04 16:22:55 -080034#include <linux/videodev2.h>
Simon Wilsonf051bcf2012-09-26 14:10:07 -070035#include <videodev2_exynos_media.h>
36
Simon Wilson15f60a82012-04-24 20:56:32 -070037#include <system/audio.h>
38
39#include <tinyalsa/asoundlib.h>
40
41#include <audio_utils/resampler.h>
Simon Wilson759c6f02013-01-15 16:38:56 -080042#include <audio_route/audio_route.h>
Simon Wilson15f60a82012-04-24 20:56:32 -070043
Eric Laurenta989ebf2012-10-15 15:14:44 -070044#include <BubbleLevel.h>
45
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -070046#include <eS305VoiceProcessing.h>
47
Simon Wilson15f60a82012-04-24 20:56:32 -070048#define PCM_CARD 0
Simon Wilson56d84e22012-08-17 13:55:27 -070049#define PCM_CARD_SPDIF 1
50#define PCM_TOTAL 2
51
Simon Wilson15f60a82012-04-24 20:56:32 -070052#define PCM_DEVICE 0
Glenn Kastene0aa8f32012-08-17 09:26:58 -070053#define PCM_DEVICE_DEEP 1
Simon Wilsona282d2f2012-09-12 16:14:24 -070054#define PCM_DEVICE_VOICE 2
55#define PCM_DEVICE_SCO 3
Simon Wilson15f60a82012-04-24 20:56:32 -070056
Simon Wilson759c6f02013-01-15 16:38:56 -080057#define MIXER_CARD 0
58
Eric Laurent1a0c0a72012-08-24 11:29:04 -070059/* duration in ms of volume ramp applied when starting capture to remove plop */
60#define CAPTURE_START_RAMP_MS 100
61
Eric Laurentb2c0b4f2012-09-21 11:42:48 -070062/* default sampling for HDMI multichannel output */
63#define HDMI_MULTI_DEFAULT_SAMPLING_RATE 44100
64/* maximum number of channel mask configurations supported. Currently the primary
65 * output only supports 1 (stereo) and the multi channel HDMI output 2 (5.1 and 7.1) */
66#define MAX_SUPPORTED_CHANNEL_MASKS 2
67
68#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
69
Simon Wilson15f60a82012-04-24 20:56:32 -070070struct pcm_config pcm_config = {
71 .channels = 2,
72 .rate = 44100,
Glenn Kasten22db1772012-09-04 09:26:50 -070073 .period_size = 256,
Glenn Kastenb9366272012-07-18 14:06:12 -070074 .period_count = 2,
Simon Wilson15f60a82012-04-24 20:56:32 -070075 .format = PCM_FORMAT_S16_LE,
76};
77
Glenn Kasten7ecf6232012-09-28 12:01:31 -070078struct pcm_config pcm_config_in = {
79 .channels = 2,
80 .rate = 44100,
Glenn Kasten9ee451c2014-07-28 15:14:28 -070081 .period_size = 1024,
Glenn Kastena83d9a12014-07-15 10:28:31 -070082 .period_count = 2,
83 .format = PCM_FORMAT_S16_LE,
84};
85
86struct pcm_config pcm_config_in_low_latency = {
87 .channels = 2,
88 .rate = 44100,
Glenn Kasten344070a2014-05-12 14:41:05 -070089 .period_size = 256,
Glenn Kasten7ecf6232012-09-28 12:01:31 -070090 .period_count = 2,
91 .format = PCM_FORMAT_S16_LE,
92};
93
Simon Wilsona282d2f2012-09-12 16:14:24 -070094struct pcm_config pcm_config_sco = {
95 .channels = 1,
96 .rate = 8000,
97 .period_size = 128,
98 .period_count = 2,
99 .format = PCM_FORMAT_S16_LE,
100};
101
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700102struct pcm_config pcm_config_deep = {
103 .channels = 2,
104 .rate = 44100,
105 /* FIXME This is an arbitrary number, may change.
106 * Dynamic configuration based on screen on/off is not implemented;
107 * let's see what power consumption is first to see if necessary.
108 */
109 .period_size = 8192,
110 .period_count = 2,
111 .format = PCM_FORMAT_S16_LE,
112};
113
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700114struct pcm_config pcm_config_hdmi_multi = {
115 .channels = 6, /* changed when the stream is opened */
116 .rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE,
117 .period_size = 1024,
118 .period_count = 4,
119 .format = PCM_FORMAT_S16_LE,
120};
121
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700122enum output_type {
123 OUTPUT_DEEP_BUF, // deep PCM buffers output stream
124 OUTPUT_LOW_LATENCY, // low latency output stream
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700125 OUTPUT_HDMI, // HDMI multi channel
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700126 OUTPUT_TOTAL
127};
128
Simon Wilson15f60a82012-04-24 20:56:32 -0700129struct audio_device {
130 struct audio_hw_device hw_device;
131
132 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700133 audio_devices_t out_device; /* "or" of stream_out.device for all active output streams */
Eric Laurent42531fa2012-10-03 09:06:14 -0700134 audio_devices_t in_device;
Simon Wilson15f60a82012-04-24 20:56:32 -0700135 bool mic_mute;
136 struct audio_route *ar;
Eric Laurent87532032012-07-16 13:53:20 -0700137 audio_source_t input_source;
138 int cur_route_id; /* current route ID: combination of input source
139 * and output device IDs */
Simon Wilsona282d2f2012-09-12 16:14:24 -0700140 struct pcm *pcm_voice_out;
141 struct pcm *pcm_sco_out;
142 struct pcm *pcm_voice_in;
143 struct pcm *pcm_sco_in;
Eric Laurent688880c2012-09-07 16:46:00 -0700144 int es305_preset;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700145 int es305_new_mode;
Eric Laurent688880c2012-09-07 16:46:00 -0700146 int es305_mode;
Glenn Kasten22f45632014-09-05 10:34:40 -0700147 int hdmi_drv_fd; /* either an fd >= 0 or -1 */
Eric Laurenta989ebf2012-10-15 15:14:44 -0700148 struct bubble_level *bubble_level;
Eric Laurentb52afc82013-01-18 15:12:57 -0800149 audio_channel_mask_t in_channel_mask;
Eric Laurent4f1aece2013-04-19 17:10:25 -0700150 unsigned int sco_on_count;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700151
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700152 struct stream_out *outputs[OUTPUT_TOTAL];
Glenn Kasten22f45632014-09-05 10:34:40 -0700153 pthread_mutex_t lock_outputs; /* see note below on mutex acquisition order */
Simon Wilson15f60a82012-04-24 20:56:32 -0700154};
155
156struct stream_out {
157 struct audio_stream_out stream;
158
159 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson56d84e22012-08-17 13:55:27 -0700160 struct pcm *pcm[PCM_TOTAL];
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700161 struct pcm_config config;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700162 unsigned int pcm_device;
Simon Wilson56d84e22012-08-17 13:55:27 -0700163 bool standby; /* true if all PCMs are inactive */
Eric Laurent42531fa2012-10-03 09:06:14 -0700164 audio_devices_t device;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700165 /* FIXME: when HDMI multichannel output is active, other outputs must be disabled as
166 * HDMI and WM1811 share the same I2S. This means that notifications and other sounds are
167 * silent when watching a 5.1 movie. */
168 bool disabled;
169 audio_channel_mask_t channel_mask;
170 /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
171 audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
Eric Laurent3948fda2013-04-04 09:24:22 -0700172 bool muted;
Glenn Kasten21169cb2013-08-20 15:36:18 -0700173 uint64_t written; /* total frames written, not cleared when entering standby */
Simon Wilson15f60a82012-04-24 20:56:32 -0700174
175 struct audio_device *dev;
176};
177
178struct stream_in {
179 struct audio_stream_in stream;
180
181 pthread_mutex_t lock; /* see note below on mutex acquisition order */
182 struct pcm *pcm;
183 bool standby;
184
185 unsigned int requested_rate;
186 struct resampler_itfe *resampler;
187 struct resampler_buffer_provider buf_provider;
188 int16_t *buffer;
189 size_t frames_in;
190 int read_status;
Eric Laurent87532032012-07-16 13:53:20 -0700191 audio_source_t input_source;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700192 audio_io_handle_t io_handle;
Eric Laurent42531fa2012-10-03 09:06:14 -0700193 audio_devices_t device;
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700194 uint16_t ramp_vol;
195 uint16_t ramp_step;
196 size_t ramp_frames;
Eric Laurentb52afc82013-01-18 15:12:57 -0800197 audio_channel_mask_t channel_mask;
Glenn Kastena83d9a12014-07-15 10:28:31 -0700198 audio_input_flags_t flags;
199 struct pcm_config *config;
Simon Wilson15f60a82012-04-24 20:56:32 -0700200
201 struct audio_device *dev;
202};
203
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700204#define STRING_TO_ENUM(string) { #string, string }
205
206struct string_to_enum {
207 const char *name;
208 uint32_t value;
209};
210
211const struct string_to_enum out_channels_name_to_enum_table[] = {
212 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
213 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
214 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
215};
216
Eric Laurent87532032012-07-16 13:53:20 -0700217enum {
218 OUT_DEVICE_SPEAKER,
219 OUT_DEVICE_HEADSET,
220 OUT_DEVICE_HEADPHONES,
221 OUT_DEVICE_BT_SCO,
222 OUT_DEVICE_SPEAKER_AND_HEADSET,
223 OUT_DEVICE_TAB_SIZE, /* number of rows in route_configs[][] */
224 OUT_DEVICE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700225 OUT_DEVICE_CNT
226};
227
228enum {
229 IN_SOURCE_MIC,
230 IN_SOURCE_CAMCORDER,
231 IN_SOURCE_VOICE_RECOGNITION,
232 IN_SOURCE_VOICE_COMMUNICATION,
233 IN_SOURCE_TAB_SIZE, /* number of lines in route_configs[][] */
234 IN_SOURCE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700235 IN_SOURCE_CNT
236};
237
Eric Laurent688880c2012-09-07 16:46:00 -0700238enum {
Eric Laurent688880c2012-09-07 16:46:00 -0700239 ES305_MODE_DEFAULT,
Eric Laurenta989ebf2012-10-15 15:14:44 -0700240 ES305_MODE_LEVEL,
Eric Laurent688880c2012-09-07 16:46:00 -0700241 ES305_NUM_MODES,
242};
243
Eric Laurent42531fa2012-10-03 09:06:14 -0700244int get_output_device_id(audio_devices_t device)
Eric Laurent87532032012-07-16 13:53:20 -0700245{
Eric Laurent6a466d72012-08-28 12:13:38 -0700246 if (device == AUDIO_DEVICE_NONE)
Eric Laurent87532032012-07-16 13:53:20 -0700247 return OUT_DEVICE_NONE;
248
249 if (popcount(device) == 2) {
250 if ((device == (AUDIO_DEVICE_OUT_SPEAKER |
251 AUDIO_DEVICE_OUT_WIRED_HEADSET)) ||
252 (device == (AUDIO_DEVICE_OUT_SPEAKER |
253 AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
254 return OUT_DEVICE_SPEAKER_AND_HEADSET;
255 else
Simon Wilsona6b94122012-09-12 12:52:24 -0700256 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700257 }
258
259 if (popcount(device) != 1)
Simon Wilsona6b94122012-09-12 12:52:24 -0700260 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700261
262 switch (device) {
263 case AUDIO_DEVICE_OUT_SPEAKER:
264 return OUT_DEVICE_SPEAKER;
265 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
266 return OUT_DEVICE_HEADSET;
267 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
268 return OUT_DEVICE_HEADPHONES;
269 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
270 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
271 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
272 return OUT_DEVICE_BT_SCO;
273 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700274 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700275 }
276}
277
278int get_input_source_id(audio_source_t source)
279{
280 switch (source) {
281 case AUDIO_SOURCE_DEFAULT:
282 return IN_SOURCE_NONE;
283 case AUDIO_SOURCE_MIC:
284 return IN_SOURCE_MIC;
285 case AUDIO_SOURCE_CAMCORDER:
286 return IN_SOURCE_CAMCORDER;
287 case AUDIO_SOURCE_VOICE_RECOGNITION:
288 return IN_SOURCE_VOICE_RECOGNITION;
289 case AUDIO_SOURCE_VOICE_COMMUNICATION:
290 return IN_SOURCE_VOICE_COMMUNICATION;
291 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700292 return IN_SOURCE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700293 }
294}
295
296struct route_config {
297 const char * const output_route;
298 const char * const input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700299 int es305_preset[ES305_NUM_MODES]; // es305 preset for this route.
300 // -1 means es305 bypass
Eric Laurent87532032012-07-16 13:53:20 -0700301};
302
303const struct route_config media_speaker = {
304 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700305 "media-main-mic",
306 { ES305_PRESET_OFF,
307 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700308};
309
310const struct route_config media_headphones = {
311 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700312 "media-main-mic",
313 { ES305_PRESET_OFF,
314 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700315};
316
317const struct route_config media_headset = {
318 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700319 "media-headset-mic",
320 { ES305_PRESET_OFF,
321 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700322};
323
324const struct route_config camcorder_speaker = {
325 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700326 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700327 { ES305_PRESET_CAMCORDER,
328 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700329};
330
331const struct route_config camcorder_headphones = {
332 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700333 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700334 { ES305_PRESET_CAMCORDER,
335 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700336};
337
338const struct route_config voice_rec_speaker = {
339 "voice-rec-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700340 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700341 { ES305_PRESET_ASRA_HANDHELD,
342 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700343};
344
345const struct route_config voice_rec_headphones = {
346 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700347 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700348 { ES305_PRESET_ASRA_HANDHELD,
349 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700350};
351
352const struct route_config voice_rec_headset = {
353 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700354 "voice-rec-headset-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700355 { ES305_PRESET_ASRA_HEADSET,
356 ES305_PRESET_ASRA_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700357};
358
359const struct route_config communication_speaker = {
360 "communication-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700361 "communication-main-mic",
362 { ES305_PRESET_VOIP_HANDHELD,
363 ES305_PRESET_VOIP_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700364};
365
366const struct route_config communication_headphones = {
367 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700368 "communication-main-mic",
369 { ES305_PRESET_VOIP_HEADPHONES,
370 ES305_PRESET_VOIP_HP_DESKTOP}
Eric Laurent87532032012-07-16 13:53:20 -0700371};
372
373const struct route_config communication_headset = {
374 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700375 "communication-headset-mic",
376 { ES305_PRESET_VOIP_HEADSET,
377 ES305_PRESET_VOIP_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700378};
379
380const struct route_config speaker_and_headphones = {
381 "speaker-and-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700382 "main-mic",
383 { ES305_PRESET_CURRENT,
384 ES305_PRESET_CURRENT }
Eric Laurent87532032012-07-16 13:53:20 -0700385};
386
387const struct route_config bluetooth_sco = {
388 "bt-sco-headset",
Eric Laurent688880c2012-09-07 16:46:00 -0700389 "bt-sco-mic",
390 { ES305_PRESET_OFF,
391 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700392};
393
394const struct route_config * const route_configs[IN_SOURCE_TAB_SIZE]
395 [OUT_DEVICE_TAB_SIZE] = {
396 { /* IN_SOURCE_MIC */
397 &media_speaker, /* OUT_DEVICE_SPEAKER */
398 &media_headset, /* OUT_DEVICE_HEADSET */
399 &media_headphones, /* OUT_DEVICE_HEADPHONES */
400 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
401 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
402 },
403 { /* IN_SOURCE_CAMCORDER */
404 &camcorder_speaker, /* OUT_DEVICE_SPEAKER */
405 &camcorder_headphones, /* OUT_DEVICE_HEADSET */
406 &camcorder_headphones, /* OUT_DEVICE_HEADPHONES */
407 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
408 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
409 },
410 { /* IN_SOURCE_VOICE_RECOGNITION */
411 &voice_rec_speaker, /* OUT_DEVICE_SPEAKER */
412 &voice_rec_headset, /* OUT_DEVICE_HEADSET */
413 &voice_rec_headphones, /* OUT_DEVICE_HEADPHONES */
414 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
415 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
416 },
417 { /* IN_SOURCE_VOICE_COMMUNICATION */
418 &communication_speaker, /* OUT_DEVICE_SPEAKER */
419 &communication_headset, /* OUT_DEVICE_HEADSET */
420 &communication_headphones, /* OUT_DEVICE_HEADPHONES */
421 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
422 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
423 }
424};
425
Glenn Kasten22f45632014-09-05 10:34:40 -0700426static void do_out_standby(struct stream_out *out);
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700427
Simon Wilson15f60a82012-04-24 20:56:32 -0700428/**
Glenn Kasten22f45632014-09-05 10:34:40 -0700429 * NOTE: when multiple mutexes have to be acquired, always respect the following order:
430 * lock_outputs for hw device outputs list only
431 * in stream
432 * out stream(s) in enum output_type order
433 * hw device
434 * TODO investigate whether we ever actually take both in stream and out stream
Simon Wilson15f60a82012-04-24 20:56:32 -0700435 */
436
437/* Helper functions */
438
Glenn Kasten64083912014-09-05 10:33:42 -0700439/* must be called with hw device mutex locked */
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700440static int open_hdmi_driver(struct audio_device *adev)
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700441{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700442 if (adev->hdmi_drv_fd < 0) {
443 adev->hdmi_drv_fd = open("/dev/video16", O_RDWR);
444 if (adev->hdmi_drv_fd < 0)
445 ALOGE("%s cannot open video16 (%d)", __func__, adev->hdmi_drv_fd);
446 }
447 return adev->hdmi_drv_fd;
448}
449
450/* must be called with hw device mutex locked */
451static int enable_hdmi_audio(struct audio_device *adev, int enable)
452{
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700453 int ret;
454 struct v4l2_control ctrl;
455
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700456 ret = open_hdmi_driver(adev);
457 if (ret < 0)
458 return ret;
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700459
460 ctrl.id = V4L2_CID_TV_ENABLE_HDMI_AUDIO;
461 ctrl.value = !!enable;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700462 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700463
464 if (ret < 0)
465 ALOGE("V4L2_CID_TV_ENABLE_HDMI_AUDIO ioctl error (%d)", errno);
466
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700467 return ret;
468}
469
Glenn Kasten64083912014-09-05 10:33:42 -0700470/* must be called with hw device mutex locked
471 * Called from adev_open_output_stream with no stream lock,
472 * but this is OK because stream is not yet visible
473 */
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700474static int read_hdmi_channel_masks(struct audio_device *adev, struct stream_out *out) {
475 int ret;
476 struct v4l2_control ctrl;
477
478 ret = open_hdmi_driver(adev);
479 if (ret < 0)
480 return ret;
481
482 ctrl.id = V4L2_CID_TV_MAX_AUDIO_CHANNELS;
483 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_G_CTRL, &ctrl);
484 if (ret < 0) {
485 ALOGE("V4L2_CID_TV_MAX_AUDIO_CHANNELS ioctl error (%d)", errno);
486 return ret;
487 }
488
489 ALOGV("%s ioctl %d got %d max channels", __func__, ret, ctrl.value);
490
491 if (ctrl.value != 6 && ctrl.value != 8)
492 return -ENOSYS;
493
494 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
495 if (ctrl.value == 8)
496 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
497
498 return ret;
499}
500
501/* must be called with hw device mutex locked */
502static int set_hdmi_channels(struct audio_device *adev, int channels) {
503 int ret;
504 struct v4l2_control ctrl;
505
506 ret = open_hdmi_driver(adev);
507 if (ret < 0)
508 return ret;
509
510 ctrl.id = V4L2_CID_TV_SET_NUM_CHANNELS;
511 ctrl.value = channels;
512 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
513 if (ret < 0)
514 ALOGE("V4L2_CID_TV_SET_NUM_CHANNELS ioctl error (%d)", errno);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700515
516 return ret;
517}
518
Glenn Kasten64083912014-09-05 10:33:42 -0700519/* must be called with hw device mutex locked */
Simon Wilson15f60a82012-04-24 20:56:32 -0700520static void select_devices(struct audio_device *adev)
521{
Eric Laurent6a466d72012-08-28 12:13:38 -0700522 int output_device_id = get_output_device_id(adev->out_device);
Eric Laurent87532032012-07-16 13:53:20 -0700523 int input_source_id = get_input_source_id(adev->input_source);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700524 const char *output_route = NULL;
525 const char *input_route = NULL;
Eric Laurent87532032012-07-16 13:53:20 -0700526 int new_route_id;
Eric Laurent688880c2012-09-07 16:46:00 -0700527 int new_es305_preset = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -0700528
Simon Wilson759c6f02013-01-15 16:38:56 -0800529 audio_route_reset(adev->ar);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700530
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700531 enable_hdmi_audio(adev, adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL);
Simon Wilsonab5dda62012-10-01 17:44:38 -0700532
Eric Laurent87532032012-07-16 13:53:20 -0700533 new_route_id = (1 << (input_source_id + OUT_DEVICE_CNT)) + (1 << output_device_id);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700534 if ((new_route_id == adev->cur_route_id) && (adev->es305_mode == adev->es305_new_mode))
Eric Laurent87532032012-07-16 13:53:20 -0700535 return;
536 adev->cur_route_id = new_route_id;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700537 adev->es305_mode = adev->es305_new_mode;
Simon Wilson15f60a82012-04-24 20:56:32 -0700538
Eric Laurent87532032012-07-16 13:53:20 -0700539 if (input_source_id != IN_SOURCE_NONE) {
540 if (output_device_id != OUT_DEVICE_NONE) {
541 input_route =
542 route_configs[input_source_id][output_device_id]->input_route;
543 output_route =
544 route_configs[input_source_id][output_device_id]->output_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700545 new_es305_preset =
546 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700547 } else {
Eric Laurent42531fa2012-10-03 09:06:14 -0700548 switch (adev->in_device) {
Eric Laurent4f1aece2013-04-19 17:10:25 -0700549 case AUDIO_DEVICE_IN_WIRED_HEADSET & ~AUDIO_DEVICE_BIT_IN:
Eric Laurent42531fa2012-10-03 09:06:14 -0700550 output_device_id = OUT_DEVICE_HEADSET;
551 break;
Eric Laurent4f1aece2013-04-19 17:10:25 -0700552 case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET & ~AUDIO_DEVICE_BIT_IN:
Eric Laurent42531fa2012-10-03 09:06:14 -0700553 output_device_id = OUT_DEVICE_BT_SCO;
554 break;
555 default:
556 output_device_id = OUT_DEVICE_SPEAKER;
557 break;
558 }
Eric Laurent87532032012-07-16 13:53:20 -0700559 input_route =
Eric Laurent42531fa2012-10-03 09:06:14 -0700560 route_configs[input_source_id][output_device_id]->input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700561 new_es305_preset =
Eric Laurent42531fa2012-10-03 09:06:14 -0700562 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700563 }
Eric Laurentb52afc82013-01-18 15:12:57 -0800564 // disable noise suppression when capturing front and back mic for voice recognition
565 if ((adev->input_source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -0700566 (adev->in_channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK))
Eric Laurentb52afc82013-01-18 15:12:57 -0800567 new_es305_preset = -1;
Eric Laurent87532032012-07-16 13:53:20 -0700568 } else {
569 if (output_device_id != OUT_DEVICE_NONE) {
570 output_route =
571 route_configs[IN_SOURCE_MIC][output_device_id]->output_route;
572 }
573 }
574
575 ALOGV("select_devices() devices %#x input src %d output route %s input route %s",
Eric Laurent6a466d72012-08-28 12:13:38 -0700576 adev->out_device, adev->input_source,
Simon Wilsonc4006be2012-08-17 11:23:38 -0700577 output_route ? output_route : "none",
578 input_route ? input_route : "none");
Eric Laurent87532032012-07-16 13:53:20 -0700579
Simon Wilsonc4006be2012-08-17 11:23:38 -0700580 if (output_route)
581 audio_route_apply_path(adev->ar, output_route);
582 if (input_route)
583 audio_route_apply_path(adev->ar, input_route);
Simon Wilson15f60a82012-04-24 20:56:32 -0700584
Eric Laurent688880c2012-09-07 16:46:00 -0700585 if ((new_es305_preset != ES305_PRESET_CURRENT) &&
586 (new_es305_preset != adev->es305_preset)) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700587 ALOGV(" select_devices() changing es305 preset from %d to %d",
588 adev->es305_preset, new_es305_preset);
589 if (eS305_UsePreset(new_es305_preset) == 0) {
Eric Laurent688880c2012-09-07 16:46:00 -0700590 adev->es305_preset = new_es305_preset;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700591 }
Eric Laurent688880c2012-09-07 16:46:00 -0700592 }
593
Simon Wilson759c6f02013-01-15 16:38:56 -0800594 audio_route_update_mixer(adev->ar);
Simon Wilson15f60a82012-04-24 20:56:32 -0700595}
596
Glenn Kasten64083912014-09-05 10:33:42 -0700597/* must be called with hw device mutex unlocked */
Eric Laurenta989ebf2012-10-15 15:14:44 -0700598void bubblelevel_callback(bool is_level, void *user_data)
599{
600 struct audio_device *adev = (struct audio_device *)user_data;
601 int es305_mode;
602
603 if (is_level)
604 es305_mode = ES305_MODE_LEVEL;
605 else
606 es305_mode = ES305_MODE_DEFAULT;
607
608 pthread_mutex_lock(&adev->lock);
609 if (es305_mode != adev->es305_mode) {
610 adev->es305_new_mode = es305_mode;
611 select_devices(adev);
612 ALOGV("bubblelevel_callback is_level %d es305_mode %d", is_level, es305_mode);
613 }
614 pthread_mutex_unlock(&adev->lock);
615}
616
Eric Laurent429f24d2012-11-02 14:37:38 -0700617/* must be called with hw device mutex locked */
618bool get_bubblelevel(struct audio_device *adev)
619{
620 if (!adev->bubble_level) {
621 adev->bubble_level = bubble_level_create();
622 if (adev->bubble_level)
623 adev->bubble_level->set_callback(adev->bubble_level, bubblelevel_callback, adev);
624 }
625 return (adev->bubble_level != NULL);
626}
627
Glenn Kasten22f45632014-09-05 10:34:40 -0700628/* must be called with hw device outputs list, all out streams, and hw device mutexes locked */
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700629static void force_non_hdmi_out_standby(struct audio_device *adev)
630{
631 enum output_type type;
632 struct stream_out *out;
633
634 for (type = 0; type < OUTPUT_TOTAL; ++type) {
635 out = adev->outputs[type];
636 if (type == OUTPUT_HDMI || !out)
637 continue;
Glenn Kasten22f45632014-09-05 10:34:40 -0700638 /* This will never recurse more than 2 levels deep. */
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700639 do_out_standby(out);
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700640 }
641}
642
Eric Laurent4f1aece2013-04-19 17:10:25 -0700643/* must be called with the hw device mutex locked, OK to hold other mutexes */
644static void start_bt_sco(struct audio_device *adev) {
645 if (adev->sco_on_count++ > 0)
646 return;
647
Glenn Kasten21169cb2013-08-20 15:36:18 -0700648 adev->pcm_voice_out = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_OUT | PCM_MONOTONIC,
Eric Laurent4f1aece2013-04-19 17:10:25 -0700649 &pcm_config_sco);
650 if (adev->pcm_voice_out && !pcm_is_ready(adev->pcm_voice_out)) {
651 ALOGE("pcm_open(VOICE_OUT) failed: %s", pcm_get_error(adev->pcm_voice_out));
652 goto err_voice_out;
653 }
Glenn Kasten21169cb2013-08-20 15:36:18 -0700654 adev->pcm_sco_out = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_OUT | PCM_MONOTONIC,
Eric Laurent4f1aece2013-04-19 17:10:25 -0700655 &pcm_config_sco);
656 if (adev->pcm_sco_out && !pcm_is_ready(adev->pcm_sco_out)) {
657 ALOGE("pcm_open(SCO_OUT) failed: %s", pcm_get_error(adev->pcm_sco_out));
658 goto err_sco_out;
659 }
660 adev->pcm_voice_in = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_IN,
661 &pcm_config_sco);
662 if (adev->pcm_voice_in && !pcm_is_ready(adev->pcm_voice_in)) {
663 ALOGE("pcm_open(VOICE_IN) failed: %s", pcm_get_error(adev->pcm_voice_in));
664 goto err_voice_in;
665 }
666 adev->pcm_sco_in = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_IN,
667 &pcm_config_sco);
668 if (adev->pcm_sco_in && !pcm_is_ready(adev->pcm_sco_in)) {
669 ALOGE("pcm_open(SCO_IN) failed: %s", pcm_get_error(adev->pcm_sco_in));
670 goto err_sco_in;
671 }
672
673 pcm_start(adev->pcm_voice_out);
674 pcm_start(adev->pcm_sco_out);
675 pcm_start(adev->pcm_voice_in);
676 pcm_start(adev->pcm_sco_in);
677
678 return;
679
680err_sco_in:
681 pcm_close(adev->pcm_sco_in);
682err_voice_in:
683 pcm_close(adev->pcm_voice_in);
684err_sco_out:
685 pcm_close(adev->pcm_sco_out);
686err_voice_out:
687 pcm_close(adev->pcm_voice_out);
688}
689
690/* must be called with the hw device mutex locked, OK to hold other mutexes */
691static void stop_bt_sco(struct audio_device *adev) {
692 if (adev->sco_on_count == 0 || --adev->sco_on_count > 0)
693 return;
694
695 pcm_stop(adev->pcm_voice_out);
696 pcm_stop(adev->pcm_sco_out);
697 pcm_stop(adev->pcm_voice_in);
698 pcm_stop(adev->pcm_sco_in);
699
700 pcm_close(adev->pcm_voice_out);
701 pcm_close(adev->pcm_sco_out);
702 pcm_close(adev->pcm_voice_in);
703 pcm_close(adev->pcm_sco_in);
704}
705
Glenn Kasten22f45632014-09-05 10:34:40 -0700706/* must be called with hw device outputs list, output stream, and hw device mutexes locked */
Simon Wilson15f60a82012-04-24 20:56:32 -0700707static int start_output_stream(struct stream_out *out)
708{
709 struct audio_device *adev = out->dev;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700710 int type;
711
712 if (out == adev->outputs[OUTPUT_HDMI]) {
713 force_non_hdmi_out_standby(adev);
714 } else if (adev->outputs[OUTPUT_HDMI] && !adev->outputs[OUTPUT_HDMI]->standby) {
715 out->disabled = true;
716 return 0;
717 }
718
719 out->disabled = false;
Simon Wilson15f60a82012-04-24 20:56:32 -0700720
Simon Wilson56d84e22012-08-17 13:55:27 -0700721 if (out->device & (AUDIO_DEVICE_OUT_SPEAKER |
722 AUDIO_DEVICE_OUT_WIRED_HEADSET |
723 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
Simon Wilsona282d2f2012-09-12 16:14:24 -0700724 AUDIO_DEVICE_OUT_AUX_DIGITAL |
725 AUDIO_DEVICE_OUT_ALL_SCO)) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700726
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700727 out->pcm[PCM_CARD] = pcm_open(PCM_CARD, out->pcm_device,
Glenn Kasten21169cb2013-08-20 15:36:18 -0700728 PCM_OUT | PCM_MONOTONIC, &out->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700729
Simon Wilson56d84e22012-08-17 13:55:27 -0700730 if (out->pcm[PCM_CARD] && !pcm_is_ready(out->pcm[PCM_CARD])) {
731 ALOGE("pcm_open(PCM_CARD) failed: %s",
732 pcm_get_error(out->pcm[PCM_CARD]));
733 pcm_close(out->pcm[PCM_CARD]);
734 return -ENOMEM;
735 }
736 }
737
738 if (out->device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700739 out->pcm[PCM_CARD_SPDIF] = pcm_open(PCM_CARD_SPDIF, out->pcm_device,
Glenn Kasten21169cb2013-08-20 15:36:18 -0700740 PCM_OUT | PCM_MONOTONIC, &out->config);
Simon Wilson56d84e22012-08-17 13:55:27 -0700741
742 if (out->pcm[PCM_CARD_SPDIF] &&
743 !pcm_is_ready(out->pcm[PCM_CARD_SPDIF])) {
744 ALOGE("pcm_open(PCM_CARD_SPDIF) failed: %s",
745 pcm_get_error(out->pcm[PCM_CARD_SPDIF]));
746 pcm_close(out->pcm[PCM_CARD_SPDIF]);
747 return -ENOMEM;
748 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700749 }
750
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700751 adev->out_device |= out->device;
Eric Laurent87532032012-07-16 13:53:20 -0700752 select_devices(adev);
753
Eric Laurent4f1aece2013-04-19 17:10:25 -0700754 if (out->device & AUDIO_DEVICE_OUT_ALL_SCO)
755 start_bt_sco(adev);
756
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700757 if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL)
758 set_hdmi_channels(adev, out->config.channels);
759
Eric Laurenta989ebf2012-10-15 15:14:44 -0700760 /* anticipate level measurement in case we start capture later */
Eric Laurent429f24d2012-11-02 14:37:38 -0700761 if (get_bubblelevel(adev))
762 adev->bubble_level->poll_once(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700763
Simon Wilson15f60a82012-04-24 20:56:32 -0700764 return 0;
765}
766
Glenn Kasten22f45632014-09-05 10:34:40 -0700767/* must be called with input stream and hw device mutexes locked */
Simon Wilson15f60a82012-04-24 20:56:32 -0700768static int start_input_stream(struct stream_in *in)
769{
770 struct audio_device *adev = in->dev;
771
Glenn Kastena83d9a12014-07-15 10:28:31 -0700772 in->pcm = pcm_open(PCM_CARD, PCM_DEVICE, PCM_IN, in->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700773
774 if (in->pcm && !pcm_is_ready(in->pcm)) {
775 ALOGE("pcm_open() failed: %s", pcm_get_error(in->pcm));
776 pcm_close(in->pcm);
777 return -ENOMEM;
778 }
779
780 /* if no supported sample rate is available, use the resampler */
781 if (in->resampler)
782 in->resampler->reset(in->resampler);
783
Eric Laurentf4231822012-08-22 16:06:38 -0700784 in->frames_in = 0;
Eric Laurent87532032012-07-16 13:53:20 -0700785 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -0700786 adev->in_device = in->device;
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -0700787 adev->in_channel_mask = in->channel_mask;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700788
789 eS305_SetActiveIoHandle(in->io_handle);
Eric Laurent87532032012-07-16 13:53:20 -0700790 select_devices(adev);
791
Eric Laurent4f1aece2013-04-19 17:10:25 -0700792 if (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)
793 start_bt_sco(adev);
794
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700795 /* initialize volume ramp */
796 in->ramp_frames = (CAPTURE_START_RAMP_MS * in->requested_rate) / 1000;
797 in->ramp_step = (uint16_t)(USHRT_MAX / in->ramp_frames);
798 in->ramp_vol = 0;;
799
Eric Laurent429f24d2012-11-02 14:37:38 -0700800 if (get_bubblelevel(adev)) {
801 adev->bubble_level->set_poll_interval(adev->bubble_level, BL_POLL_INTERVAL_MIN_SEC);
802 adev->bubble_level->start_polling(adev->bubble_level);
803 }
Eric Laurenta989ebf2012-10-15 15:14:44 -0700804
Simon Wilson15f60a82012-04-24 20:56:32 -0700805 return 0;
806}
807
808static size_t get_input_buffer_size(unsigned int sample_rate,
809 audio_format_t format,
Glenn Kastena83d9a12014-07-15 10:28:31 -0700810 unsigned int channel_count,
811 bool is_low_latency)
Simon Wilson15f60a82012-04-24 20:56:32 -0700812{
Glenn Kastena83d9a12014-07-15 10:28:31 -0700813 const struct pcm_config *config = is_low_latency ?
814 &pcm_config_in_low_latency : &pcm_config_in;
Simon Wilson15f60a82012-04-24 20:56:32 -0700815 size_t size;
816
817 /*
818 * take resampling into account and return the closest majoring
819 * multiple of 16 frames, as audioflinger expects audio buffers to
820 * be a multiple of 16 frames
821 */
Glenn Kastena83d9a12014-07-15 10:28:31 -0700822 size = (config->period_size * sample_rate) / config->rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700823 size = ((size + 15) / 16) * 16;
824
825 return size * channel_count * audio_bytes_per_sample(format);
826}
827
828static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
829 struct resampler_buffer* buffer)
830{
831 struct stream_in *in;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700832 size_t i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700833
834 if (buffer_provider == NULL || buffer == NULL)
835 return -EINVAL;
836
837 in = (struct stream_in *)((char *)buffer_provider -
838 offsetof(struct stream_in, buf_provider));
839
840 if (in->pcm == NULL) {
841 buffer->raw = NULL;
842 buffer->frame_count = 0;
843 in->read_status = -ENODEV;
844 return -ENODEV;
845 }
846
847 if (in->frames_in == 0) {
848 in->read_status = pcm_read(in->pcm,
849 (void*)in->buffer,
Glenn Kastena83d9a12014-07-15 10:28:31 -0700850 pcm_frames_to_bytes(in->pcm, in->config->period_size));
Simon Wilson15f60a82012-04-24 20:56:32 -0700851 if (in->read_status != 0) {
852 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
853 buffer->raw = NULL;
854 buffer->frame_count = 0;
855 return in->read_status;
856 }
Eric Laurentd7abdd02012-07-27 14:54:41 -0700857
Glenn Kastena83d9a12014-07-15 10:28:31 -0700858 in->frames_in = in->config->period_size;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700859
860 /* Do stereo to mono conversion in place by discarding right channel */
Eric Laurentb52afc82013-01-18 15:12:57 -0800861 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
862 for (i = 1; i < in->frames_in; i++)
863 in->buffer[i] = in->buffer[i * 2];
Simon Wilson15f60a82012-04-24 20:56:32 -0700864 }
865
866 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
867 in->frames_in : buffer->frame_count;
Eric Laurentb52afc82013-01-18 15:12:57 -0800868 buffer->i16 = in->buffer +
Glenn Kastena83d9a12014-07-15 10:28:31 -0700869 (in->config->period_size - in->frames_in) *
Eric Laurent1e7184b2014-07-01 20:29:10 -0700870 audio_channel_count_from_in_mask(in->channel_mask);
Simon Wilson15f60a82012-04-24 20:56:32 -0700871
872 return in->read_status;
873
874}
875
876static void release_buffer(struct resampler_buffer_provider *buffer_provider,
877 struct resampler_buffer* buffer)
878{
879 struct stream_in *in;
880
881 if (buffer_provider == NULL || buffer == NULL)
882 return;
883
884 in = (struct stream_in *)((char *)buffer_provider -
885 offsetof(struct stream_in, buf_provider));
886
887 in->frames_in -= buffer->frame_count;
888}
889
890/* read_frames() reads frames from kernel driver, down samples to capture rate
891 * if necessary and output the number of frames requested to the buffer specified */
892static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
893{
894 ssize_t frames_wr = 0;
Eric Laurent84c33732014-07-03 16:35:46 -0700895 size_t frame_size = audio_stream_in_frame_size(&in->stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700896
897 while (frames_wr < frames) {
898 size_t frames_rd = frames - frames_wr;
899 if (in->resampler != NULL) {
900 in->resampler->resample_from_provider(in->resampler,
901 (int16_t *)((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700902 frames_wr * frame_size),
Simon Wilson15f60a82012-04-24 20:56:32 -0700903 &frames_rd);
904 } else {
905 struct resampler_buffer buf = {
906 { raw : NULL, },
907 frame_count : frames_rd,
908 };
909 get_next_buffer(&in->buf_provider, &buf);
910 if (buf.raw != NULL) {
911 memcpy((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700912 frames_wr * frame_size,
Simon Wilson15f60a82012-04-24 20:56:32 -0700913 buf.raw,
Eric Laurentd7abdd02012-07-27 14:54:41 -0700914 buf.frame_count * frame_size);
Simon Wilson15f60a82012-04-24 20:56:32 -0700915 frames_rd = buf.frame_count;
916 }
917 release_buffer(&in->buf_provider, &buf);
918 }
919 /* in->read_status is updated by getNextBuffer() also called by
920 * in->resampler->resample_from_provider() */
921 if (in->read_status != 0)
922 return in->read_status;
923
924 frames_wr += frames_rd;
925 }
926 return frames_wr;
927}
928
929/* API functions */
930
931static uint32_t out_get_sample_rate(const struct audio_stream *stream)
932{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700933 struct stream_out *out = (struct stream_out *)stream;
934
935 return out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700936}
937
938static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
939{
940 return -ENOSYS;
941}
942
943static size_t out_get_buffer_size(const struct audio_stream *stream)
944{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700945 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700946
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700947 return out->config.period_size *
Eric Laurent84c33732014-07-03 16:35:46 -0700948 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700949}
950
Glenn Kastenca1414b2012-06-25 10:38:47 -0700951static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
Simon Wilson15f60a82012-04-24 20:56:32 -0700952{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700953 struct stream_out *out = (struct stream_out *)stream;
954
955 return out->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700956}
957
958static audio_format_t out_get_format(const struct audio_stream *stream)
959{
960 return AUDIO_FORMAT_PCM_16_BIT;
961}
962
963static int out_set_format(struct audio_stream *stream, audio_format_t format)
964{
965 return -ENOSYS;
966}
967
Glenn Kasten068b84e2012-09-26 12:34:51 -0700968/* Return the set of output devices associated with active streams
969 * other than out. Assumes out is non-NULL and out->dev is locked.
970 */
971static audio_devices_t output_devices(struct stream_out *out)
972{
973 struct audio_device *dev = out->dev;
974 enum output_type type;
975 audio_devices_t devices = AUDIO_DEVICE_NONE;
976
977 for (type = 0; type < OUTPUT_TOTAL; ++type) {
978 struct stream_out *other = dev->outputs[type];
979 if (other && (other != out) && !other->standby) {
Glenn Kasten22f45632014-09-05 10:34:40 -0700980 // TODO no longer accurate
Glenn Kasten068b84e2012-09-26 12:34:51 -0700981 /* safe to access other stream without a mutex,
982 * because we hold the dev lock,
983 * which prevents the other stream from being closed
984 */
985 devices |= other->device;
986 }
987 }
988
989 return devices;
990}
991
Glenn Kasten22f45632014-09-05 10:34:40 -0700992/* must be called with hw device outputs list, all out streams, and hw device mutex locked */
993static void do_out_standby(struct stream_out *out)
Simon Wilson15f60a82012-04-24 20:56:32 -0700994{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700995 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -0700996 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700997
Simon Wilson15f60a82012-04-24 20:56:32 -0700998 if (!out->standby) {
Simon Wilson56d84e22012-08-17 13:55:27 -0700999 for (i = 0; i < PCM_TOTAL; i++) {
1000 if (out->pcm[i]) {
1001 pcm_close(out->pcm[i]);
1002 out->pcm[i] = NULL;
1003 }
1004 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001005 out->standby = true;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001006
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001007 if (out == adev->outputs[OUTPUT_HDMI]) {
1008 /* force standby on low latency output stream so that it can reuse HDMI driver if
1009 * necessary when restarted */
1010 force_non_hdmi_out_standby(adev);
1011 }
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001012
Eric Laurent4f1aece2013-04-19 17:10:25 -07001013 if (out->device & AUDIO_DEVICE_OUT_ALL_SCO)
1014 stop_bt_sco(adev);
1015
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001016 /* re-calculate the set of active devices from other streams */
1017 adev->out_device = output_devices(out);
Simon Wilson79a2e012012-10-19 14:20:33 -07001018
1019 /* Skip resetting the mixer if no output device is active */
1020 if (adev->out_device)
1021 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001022 }
Glenn Kasten22f45632014-09-05 10:34:40 -07001023}
Simon Wilson15f60a82012-04-24 20:56:32 -07001024
Glenn Kasten22f45632014-09-05 10:34:40 -07001025/* lock outputs list, all output streams, and device */
1026static void lock_all_outputs(struct audio_device *adev)
1027{
1028 enum output_type type;
1029 pthread_mutex_lock(&adev->lock_outputs);
1030 for (type = 0; type < OUTPUT_TOTAL; ++type) {
1031 struct stream_out *out = adev->outputs[type];
1032 if (out)
1033 pthread_mutex_lock(&out->lock);
1034 }
1035 pthread_mutex_lock(&adev->lock);
1036}
1037
1038/* unlock device, all output streams (except specified stream), and outputs list */
1039static void unlock_all_outputs(struct audio_device *adev, struct stream_out *except)
1040{
1041 /* unlock order is irrelevant, but for cleanliness we unlock in reverse order */
1042 pthread_mutex_unlock(&adev->lock);
1043 enum output_type type = OUTPUT_TOTAL;
1044 do {
1045 struct stream_out *out = adev->outputs[--type];
1046 if (out && out != except)
1047 pthread_mutex_unlock(&out->lock);
1048 } while (type != (enum output_type) 0);
1049 pthread_mutex_unlock(&adev->lock_outputs);
Simon Wilson459d5bd2012-08-21 12:18:07 -07001050}
1051
1052static int out_standby(struct audio_stream *stream)
1053{
1054 struct stream_out *out = (struct stream_out *)stream;
Glenn Kasten22f45632014-09-05 10:34:40 -07001055 struct audio_device *adev = out->dev;
Simon Wilson459d5bd2012-08-21 12:18:07 -07001056
Glenn Kasten22f45632014-09-05 10:34:40 -07001057 lock_all_outputs(adev);
Simon Wilson459d5bd2012-08-21 12:18:07 -07001058
Glenn Kasten22f45632014-09-05 10:34:40 -07001059 do_out_standby(out);
Simon Wilson459d5bd2012-08-21 12:18:07 -07001060
Glenn Kasten22f45632014-09-05 10:34:40 -07001061 unlock_all_outputs(adev, NULL);
Simon Wilson15f60a82012-04-24 20:56:32 -07001062
Glenn Kasten22f45632014-09-05 10:34:40 -07001063 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001064}
1065
1066static int out_dump(const struct audio_stream *stream, int fd)
1067{
1068 return 0;
1069}
1070
1071static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1072{
1073 struct stream_out *out = (struct stream_out *)stream;
1074 struct audio_device *adev = out->dev;
1075 struct str_parms *parms;
1076 char value[32];
1077 int ret;
1078 unsigned int val;
1079
1080 parms = str_parms_create_str(kvpairs);
1081
1082 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1083 value, sizeof(value));
Glenn Kasten22f45632014-09-05 10:34:40 -07001084 lock_all_outputs(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001085 if (ret >= 0) {
1086 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001087 if ((out->device != val) && (val != 0)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001088 /* Force standby if moving to/from SPDIF or if the output
1089 * device changes when in SPDIF mode */
1090 if (((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent6a466d72012-08-28 12:13:38 -07001091 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1092 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001093 do_out_standby(out);
1094 }
1095
Eric Laurent4f1aece2013-04-19 17:10:25 -07001096 /* force output standby to start or stop SCO pcm stream if needed */
Simon Wilsona282d2f2012-09-12 16:14:24 -07001097 if ((val & AUDIO_DEVICE_OUT_ALL_SCO) ^
Eric Laurent4f1aece2013-04-19 17:10:25 -07001098 (out->device & AUDIO_DEVICE_OUT_ALL_SCO)) {
1099 do_out_standby(out);
Simon Wilsona282d2f2012-09-12 16:14:24 -07001100 }
1101
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001102 if (!out->standby && (out == adev->outputs[OUTPUT_HDMI] ||
1103 !adev->outputs[OUTPUT_HDMI] ||
1104 adev->outputs[OUTPUT_HDMI]->standby)) {
1105 adev->out_device = output_devices(out) | val;
Eric Laurent87532032012-07-16 13:53:20 -07001106 select_devices(adev);
1107 }
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001108 out->device = val;
Simon Wilson15f60a82012-04-24 20:56:32 -07001109 }
1110 }
Glenn Kasten22f45632014-09-05 10:34:40 -07001111 unlock_all_outputs(adev, NULL);
Simon Wilson15f60a82012-04-24 20:56:32 -07001112
1113 str_parms_destroy(parms);
1114 return ret;
1115}
1116
1117static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1118{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001119 struct stream_out *out = (struct stream_out *)stream;
1120 struct str_parms *query = str_parms_create_str(keys);
1121 char *str;
1122 char value[256];
1123 struct str_parms *reply = str_parms_create();
1124 size_t i, j;
1125 int ret;
1126 bool first = true;
1127
1128 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1129 if (ret >= 0) {
1130 value[0] = '\0';
1131 i = 0;
1132 /* the last entry in supported_channel_masks[] is always 0 */
1133 while (out->supported_channel_masks[i] != 0) {
1134 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1135 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1136 if (!first) {
1137 strcat(value, "|");
1138 }
1139 strcat(value, out_channels_name_to_enum_table[j].name);
1140 first = false;
1141 break;
1142 }
1143 }
1144 i++;
1145 }
1146 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1147 str = str_parms_to_str(reply);
1148 } else {
1149 str = strdup(keys);
1150 }
1151
1152 str_parms_destroy(query);
1153 str_parms_destroy(reply);
1154 return str;
Simon Wilson15f60a82012-04-24 20:56:32 -07001155}
1156
1157static uint32_t out_get_latency(const struct audio_stream_out *stream)
1158{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001159 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001160
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001161 return (out->config.period_size * out->config.period_count * 1000) /
1162 out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -07001163}
1164
1165static int out_set_volume(struct audio_stream_out *stream, float left,
1166 float right)
1167{
Eric Laurent3948fda2013-04-04 09:24:22 -07001168 struct stream_out *out = (struct stream_out *)stream;
1169 struct audio_device *adev = out->dev;
1170
Glenn Kasten22f45632014-09-05 10:34:40 -07001171 /* The mutex lock is not needed, because the client
1172 * is not allowed to close the stream concurrently with this API
1173 * pthread_mutex_lock(&adev->lock_outputs);
1174 */
1175 bool is_HDMI = out == adev->outputs[OUTPUT_HDMI];
1176 /* pthread_mutex_unlock(&adev->lock_outputs); */
1177 if (is_HDMI) {
Eric Laurent3948fda2013-04-04 09:24:22 -07001178 /* only take left channel into account: the API is for stereo anyway */
1179 out->muted = (left == 0.0f);
1180 return 0;
1181 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001182 return -ENOSYS;
1183}
1184
1185static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
1186 size_t bytes)
1187{
Glenn Kastenf2d98022013-08-30 16:20:49 -07001188 int ret = 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001189 struct stream_out *out = (struct stream_out *)stream;
1190 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -07001191 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -07001192
Glenn Kasten22f45632014-09-05 10:34:40 -07001193 /* FIXME This comment is no longer correct
Simon Wilson15f60a82012-04-24 20:56:32 -07001194 * acquiring hw device mutex systematically is useful if a low
1195 * priority thread is waiting on the output stream mutex - e.g.
1196 * executing out_set_parameters() while holding the hw device
1197 * mutex
1198 */
Simon Wilson15f60a82012-04-24 20:56:32 -07001199 pthread_mutex_lock(&out->lock);
1200 if (out->standby) {
Glenn Kasten22f45632014-09-05 10:34:40 -07001201 pthread_mutex_unlock(&out->lock);
1202 lock_all_outputs(adev);
1203 if (!out->standby) {
1204 unlock_all_outputs(adev, out);
1205 goto false_alarm;
1206 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001207 ret = start_output_stream(out);
Glenn Kasten22f45632014-09-05 10:34:40 -07001208 if (ret < 0) {
1209 unlock_all_outputs(adev, NULL);
1210 goto final_exit;
Simon Wilson15f60a82012-04-24 20:56:32 -07001211 }
1212 out->standby = false;
Glenn Kasten22f45632014-09-05 10:34:40 -07001213 unlock_all_outputs(adev, out);
Simon Wilson15f60a82012-04-24 20:56:32 -07001214 }
Glenn Kasten22f45632014-09-05 10:34:40 -07001215false_alarm:
Simon Wilson15f60a82012-04-24 20:56:32 -07001216
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001217 if (out->disabled) {
1218 ret = -EPIPE;
1219 goto exit;
1220 }
1221
Eric Laurent3948fda2013-04-04 09:24:22 -07001222 if (out->muted)
1223 memset((void *)buffer, 0, bytes);
1224
Simon Wilson56d84e22012-08-17 13:55:27 -07001225 /* Write to all active PCMs */
1226 for (i = 0; i < PCM_TOTAL; i++)
Glenn Kasten21169cb2013-08-20 15:36:18 -07001227 if (out->pcm[i]) {
1228 ret = pcm_write(out->pcm[i], (void *)buffer, bytes);
1229 if (ret != 0)
1230 break;
1231 }
1232 if (ret == 0)
1233 out->written += bytes / (out->config.channels * sizeof(short));
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001234
Simon Wilson15f60a82012-04-24 20:56:32 -07001235exit:
1236 pthread_mutex_unlock(&out->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001237final_exit:
Simon Wilson15f60a82012-04-24 20:56:32 -07001238
1239 if (ret != 0) {
Eric Laurent84c33732014-07-03 16:35:46 -07001240 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Simon Wilson15f60a82012-04-24 20:56:32 -07001241 out_get_sample_rate(&stream->common));
1242 }
1243
1244 return bytes;
1245}
1246
1247static int out_get_render_position(const struct audio_stream_out *stream,
1248 uint32_t *dsp_frames)
1249{
1250 return -EINVAL;
1251}
1252
1253static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1254{
1255 return 0;
1256}
1257
1258static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1259{
1260 return 0;
1261}
1262
1263static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1264 int64_t *timestamp)
1265{
1266 return -EINVAL;
1267}
1268
Glenn Kasten21169cb2013-08-20 15:36:18 -07001269static int out_get_presentation_position(const struct audio_stream_out *stream,
1270 uint64_t *frames, struct timespec *timestamp)
1271{
1272 struct stream_out *out = (struct stream_out *)stream;
1273 int ret = -1;
1274
1275 pthread_mutex_lock(&out->lock);
1276
1277 int i;
1278 // There is a question how to implement this correctly when there is more than one PCM stream.
1279 // We are just interested in the frames pending for playback in the kernel buffer here,
1280 // not the total played since start. The current behavior should be safe because the
1281 // cases where both cards are active are marginal.
1282 for (i = 0; i < PCM_TOTAL; i++)
1283 if (out->pcm[i]) {
1284 size_t avail;
1285 if (pcm_get_htimestamp(out->pcm[i], &avail, timestamp) == 0) {
1286 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
1287 // FIXME This calculation is incorrect if there is buffering after app processor
1288 int64_t signed_frames = out->written - kernel_buffer_size + avail;
1289 // It would be unusual for this value to be negative, but check just in case ...
1290 if (signed_frames >= 0) {
1291 *frames = signed_frames;
1292 ret = 0;
1293 }
1294 break;
1295 }
1296 }
1297
1298 pthread_mutex_unlock(&out->lock);
1299
1300 return ret;
1301}
1302
Simon Wilson15f60a82012-04-24 20:56:32 -07001303/** audio_stream_in implementation **/
1304static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1305{
1306 struct stream_in *in = (struct stream_in *)stream;
1307
1308 return in->requested_rate;
1309}
1310
1311static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1312{
1313 return 0;
1314}
1315
Eric Laurentd7abdd02012-07-27 14:54:41 -07001316static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
1317{
Eric Laurentb52afc82013-01-18 15:12:57 -08001318 struct stream_in *in = (struct stream_in *)stream;
1319
1320 return in->channel_mask;
Eric Laurentd7abdd02012-07-27 14:54:41 -07001321}
1322
1323
Simon Wilson15f60a82012-04-24 20:56:32 -07001324static size_t in_get_buffer_size(const struct audio_stream *stream)
1325{
1326 struct stream_in *in = (struct stream_in *)stream;
1327
1328 return get_input_buffer_size(in->requested_rate,
1329 AUDIO_FORMAT_PCM_16_BIT,
Glenn Kastena83d9a12014-07-15 10:28:31 -07001330 audio_channel_count_from_in_mask(in_get_channels(stream)),
1331 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0);
Simon Wilson15f60a82012-04-24 20:56:32 -07001332}
1333
1334static audio_format_t in_get_format(const struct audio_stream *stream)
1335{
1336 return AUDIO_FORMAT_PCM_16_BIT;
1337}
1338
1339static int in_set_format(struct audio_stream *stream, audio_format_t format)
1340{
1341 return -ENOSYS;
1342}
1343
Glenn Kasten64083912014-09-05 10:33:42 -07001344/* must be called with in stream and hw device mutex locked */
Glenn Kasten22f45632014-09-05 10:34:40 -07001345static void do_in_standby(struct stream_in *in)
Simon Wilson15f60a82012-04-24 20:56:32 -07001346{
Eric Laurent4f1aece2013-04-19 17:10:25 -07001347 struct audio_device *adev = in->dev;
Simon Wilson15f60a82012-04-24 20:56:32 -07001348
1349 if (!in->standby) {
1350 pcm_close(in->pcm);
1351 in->pcm = NULL;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001352
1353 if (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)
1354 stop_bt_sco(adev);
1355
Eric Laurent87532032012-07-16 13:53:20 -07001356 in->dev->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001357 in->dev->in_device = AUDIO_DEVICE_NONE;
Jean-Michel Trivi3f467de2013-06-06 15:26:01 -07001358 in->dev->in_channel_mask = 0;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001359 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001360 in->standby = true;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001361
Eric Laurent4f1aece2013-04-19 17:10:25 -07001362 if (get_bubblelevel(adev))
1363 in->dev->bubble_level->stop_polling(adev->bubble_level);
Simon Wilson15f60a82012-04-24 20:56:32 -07001364 }
1365
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001366 eS305_SetActiveIoHandle(ES305_IO_HANDLE_NONE);
Eric Laurent4f1aece2013-04-19 17:10:25 -07001367}
1368
1369static int in_standby(struct audio_stream *stream)
1370{
1371 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001372
Eric Laurent4f1aece2013-04-19 17:10:25 -07001373 pthread_mutex_lock(&in->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001374 pthread_mutex_lock(&in->dev->lock);
Eric Laurent4f1aece2013-04-19 17:10:25 -07001375
Glenn Kasten22f45632014-09-05 10:34:40 -07001376 do_in_standby(in);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001377
Simon Wilson15f60a82012-04-24 20:56:32 -07001378 pthread_mutex_unlock(&in->dev->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001379 pthread_mutex_unlock(&in->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001380
Glenn Kasten22f45632014-09-05 10:34:40 -07001381 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001382}
1383
1384static int in_dump(const struct audio_stream *stream, int fd)
1385{
1386 return 0;
1387}
1388
1389static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1390{
1391 struct stream_in *in = (struct stream_in *)stream;
1392 struct audio_device *adev = in->dev;
1393 struct str_parms *parms;
1394 char value[32];
1395 int ret;
1396 unsigned int val;
Eric Laurent87532032012-07-16 13:53:20 -07001397 bool apply_now = false;
Simon Wilson15f60a82012-04-24 20:56:32 -07001398
1399 parms = str_parms_create_str(kvpairs);
1400
Eric Laurent87532032012-07-16 13:53:20 -07001401 pthread_mutex_lock(&in->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001402 pthread_mutex_lock(&adev->lock);
Eric Laurent42531fa2012-10-03 09:06:14 -07001403 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
1404 value, sizeof(value));
Simon Wilson15f60a82012-04-24 20:56:32 -07001405 if (ret >= 0) {
1406 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001407 /* no audio source uses val == 0 */
1408 if ((in->input_source != val) && (val != 0)) {
1409 in->input_source = val;
1410 apply_now = !in->standby;
Simon Wilson15f60a82012-04-24 20:56:32 -07001411 }
1412 }
Eric Laurent87532032012-07-16 13:53:20 -07001413
Eric Laurent42531fa2012-10-03 09:06:14 -07001414 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1415 value, sizeof(value));
1416 if (ret >= 0) {
Eric Laurent4f1aece2013-04-19 17:10:25 -07001417 /* strip AUDIO_DEVICE_BIT_IN to allow bitwise comparisons */
1418 val = atoi(value) & ~AUDIO_DEVICE_BIT_IN;
Eric Laurent42531fa2012-10-03 09:06:14 -07001419 /* no audio device uses val == 0 */
1420 if ((in->device != val) && (val != 0)) {
Eric Laurent4f1aece2013-04-19 17:10:25 -07001421 /* force output standby to start or stop SCO pcm stream if needed */
1422 if ((val & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) ^
1423 (in->device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
1424 do_in_standby(in);
1425 }
Eric Laurent42531fa2012-10-03 09:06:14 -07001426 in->device = val;
1427 apply_now = !in->standby;
1428 }
1429 }
1430
Eric Laurent87532032012-07-16 13:53:20 -07001431 if (apply_now) {
Eric Laurent87532032012-07-16 13:53:20 -07001432 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -07001433 adev->in_device = in->device;
Eric Laurent87532032012-07-16 13:53:20 -07001434 select_devices(adev);
1435 }
1436
Simon Wilson15f60a82012-04-24 20:56:32 -07001437 pthread_mutex_unlock(&adev->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001438 pthread_mutex_unlock(&in->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001439
1440 str_parms_destroy(parms);
1441 return ret;
1442}
1443
1444static char * in_get_parameters(const struct audio_stream *stream,
1445 const char *keys)
1446{
1447 return strdup("");
1448}
1449
1450static int in_set_gain(struct audio_stream_in *stream, float gain)
1451{
1452 return 0;
1453}
1454
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001455static void in_apply_ramp(struct stream_in *in, int16_t *buffer, size_t frames)
1456{
1457 size_t i;
1458 uint16_t vol = in->ramp_vol;
1459 uint16_t step = in->ramp_step;
1460
1461 frames = (frames < in->ramp_frames) ? frames : in->ramp_frames;
1462
Eric Laurentb52afc82013-01-18 15:12:57 -08001463 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
1464 for (i = 0; i < frames; i++)
1465 {
1466 buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
1467 vol += step;
1468 }
1469 else
1470 for (i = 0; i < frames; i++)
1471 {
1472 buffer[2*i] = (int16_t)((buffer[2*i] * vol) >> 16);
1473 buffer[2*i + 1] = (int16_t)((buffer[2*i + 1] * vol) >> 16);
1474 vol += step;
1475 }
1476
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001477
1478 in->ramp_vol = vol;
1479 in->ramp_frames -= frames;
1480}
1481
Simon Wilson15f60a82012-04-24 20:56:32 -07001482static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1483 size_t bytes)
1484{
1485 int ret = 0;
1486 struct stream_in *in = (struct stream_in *)stream;
1487 struct audio_device *adev = in->dev;
Eric Laurent84c33732014-07-03 16:35:46 -07001488 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Simon Wilson15f60a82012-04-24 20:56:32 -07001489
1490 /*
1491 * acquiring hw device mutex systematically is useful if a low
1492 * priority thread is waiting on the input stream mutex - e.g.
1493 * executing in_set_parameters() while holding the hw device
1494 * mutex
1495 */
Simon Wilson15f60a82012-04-24 20:56:32 -07001496 pthread_mutex_lock(&in->lock);
1497 if (in->standby) {
Glenn Kasten22f45632014-09-05 10:34:40 -07001498 pthread_mutex_lock(&adev->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001499 ret = start_input_stream(in);
Glenn Kasten22f45632014-09-05 10:34:40 -07001500 pthread_mutex_unlock(&adev->lock);
1501 if (ret < 0)
1502 goto exit;
1503 in->standby = false;
Simon Wilson15f60a82012-04-24 20:56:32 -07001504 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001505
1506 /*if (in->num_preprocessors != 0)
1507 ret = process_frames(in, buffer, frames_rq);
Eric Laurentd7abdd02012-07-27 14:54:41 -07001508 else */
1509 ret = read_frames(in, buffer, frames_rq);
Simon Wilson15f60a82012-04-24 20:56:32 -07001510
1511 if (ret > 0)
1512 ret = 0;
1513
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001514 if (in->ramp_frames > 0)
1515 in_apply_ramp(in, buffer, frames_rq);
1516
Simon Wilson15f60a82012-04-24 20:56:32 -07001517 /*
1518 * Instead of writing zeroes here, we could trust the hardware
1519 * to always provide zeroes when muted.
1520 */
1521 if (ret == 0 && adev->mic_mute)
1522 memset(buffer, 0, bytes);
1523
1524exit:
1525 if (ret < 0)
Eric Laurent84c33732014-07-03 16:35:46 -07001526 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Simon Wilson15f60a82012-04-24 20:56:32 -07001527 in_get_sample_rate(&stream->common));
1528
1529 pthread_mutex_unlock(&in->lock);
1530 return bytes;
1531}
1532
1533static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1534{
1535 return 0;
1536}
1537
1538static int in_add_audio_effect(const struct audio_stream *stream,
1539 effect_handle_t effect)
1540{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001541 struct stream_in *in = (struct stream_in *)stream;
1542 effect_descriptor_t descr;
1543 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1544
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001545 pthread_mutex_lock(&in->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001546 pthread_mutex_lock(&in->dev->lock);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001547
1548 eS305_AddEffect(&descr, in->io_handle);
1549
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001550 pthread_mutex_unlock(&in->dev->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001551 pthread_mutex_unlock(&in->lock);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001552 }
1553
Simon Wilson15f60a82012-04-24 20:56:32 -07001554 return 0;
1555}
1556
1557static int in_remove_audio_effect(const struct audio_stream *stream,
1558 effect_handle_t effect)
1559{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001560 struct stream_in *in = (struct stream_in *)stream;
1561 effect_descriptor_t descr;
1562 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1563
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001564 pthread_mutex_lock(&in->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001565 pthread_mutex_lock(&in->dev->lock);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001566
1567 eS305_RemoveEffect(&descr, in->io_handle);
1568
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001569 pthread_mutex_unlock(&in->dev->lock);
Glenn Kasten22f45632014-09-05 10:34:40 -07001570 pthread_mutex_unlock(&in->lock);
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001571 }
1572
Simon Wilson15f60a82012-04-24 20:56:32 -07001573 return 0;
1574}
1575
Simon Wilson15f60a82012-04-24 20:56:32 -07001576static int adev_open_output_stream(struct audio_hw_device *dev,
1577 audio_io_handle_t handle,
1578 audio_devices_t devices,
1579 audio_output_flags_t flags,
1580 struct audio_config *config,
Eric Laurent2f4b8092014-07-27 17:23:22 -07001581 struct audio_stream_out **stream_out,
1582 const char *address __unused)
Simon Wilson15f60a82012-04-24 20:56:32 -07001583{
1584 struct audio_device *adev = (struct audio_device *)dev;
1585 struct stream_out *out;
1586 int ret;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001587 enum output_type type;
Simon Wilson15f60a82012-04-24 20:56:32 -07001588
1589 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1590 if (!out)
1591 return -ENOMEM;
1592
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001593 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1594 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1595 if (devices == AUDIO_DEVICE_NONE)
1596 devices = AUDIO_DEVICE_OUT_SPEAKER;
1597 out->device = devices;
1598
1599 if (flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1600 devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1601 pthread_mutex_lock(&adev->lock);
1602 ret = read_hdmi_channel_masks(adev, out);
1603 pthread_mutex_unlock(&adev->lock);
1604 if (ret != 0)
1605 goto err_open;
1606 if (config->sample_rate == 0)
1607 config->sample_rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE;
1608 if (config->channel_mask == 0)
1609 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1610 out->channel_mask = config->channel_mask;
1611 out->config = pcm_config_hdmi_multi;
1612 out->config.rate = config->sample_rate;
Eric Laurent1e7184b2014-07-01 20:29:10 -07001613 out->config.channels = audio_channel_count_from_out_mask(config->channel_mask);
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001614 out->pcm_device = PCM_DEVICE;
1615 type = OUTPUT_HDMI;
1616 } else if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1617 out->config = pcm_config_deep;
1618 out->pcm_device = PCM_DEVICE_DEEP;
1619 type = OUTPUT_DEEP_BUF;
1620 } else {
1621 out->config = pcm_config;
1622 out->pcm_device = PCM_DEVICE;
1623 type = OUTPUT_LOW_LATENCY;
1624 }
1625
Simon Wilson15f60a82012-04-24 20:56:32 -07001626 out->stream.common.get_sample_rate = out_get_sample_rate;
1627 out->stream.common.set_sample_rate = out_set_sample_rate;
1628 out->stream.common.get_buffer_size = out_get_buffer_size;
1629 out->stream.common.get_channels = out_get_channels;
1630 out->stream.common.get_format = out_get_format;
1631 out->stream.common.set_format = out_set_format;
1632 out->stream.common.standby = out_standby;
1633 out->stream.common.dump = out_dump;
1634 out->stream.common.set_parameters = out_set_parameters;
1635 out->stream.common.get_parameters = out_get_parameters;
1636 out->stream.common.add_audio_effect = out_add_audio_effect;
1637 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1638 out->stream.get_latency = out_get_latency;
1639 out->stream.set_volume = out_set_volume;
1640 out->stream.write = out_write;
1641 out->stream.get_render_position = out_get_render_position;
1642 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten21169cb2013-08-20 15:36:18 -07001643 out->stream.get_presentation_position = out_get_presentation_position;
Simon Wilson15f60a82012-04-24 20:56:32 -07001644
1645 out->dev = adev;
1646
1647 config->format = out_get_format(&out->stream.common);
1648 config->channel_mask = out_get_channels(&out->stream.common);
1649 config->sample_rate = out_get_sample_rate(&out->stream.common);
1650
1651 out->standby = true;
Eric Laurent3948fda2013-04-04 09:24:22 -07001652 /* out->muted = false; by calloc() */
Glenn Kasten21169cb2013-08-20 15:36:18 -07001653 /* out->written = 0; by calloc() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001654
Glenn Kasten22f45632014-09-05 10:34:40 -07001655 pthread_mutex_lock(&adev->lock_outputs);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001656 if (adev->outputs[type]) {
Glenn Kasten22f45632014-09-05 10:34:40 -07001657 pthread_mutex_unlock(&adev->lock_outputs);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001658 ret = -EBUSY;
1659 goto err_open;
1660 }
1661 adev->outputs[type] = out;
Glenn Kasten22f45632014-09-05 10:34:40 -07001662 pthread_mutex_unlock(&adev->lock_outputs);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001663
Simon Wilson15f60a82012-04-24 20:56:32 -07001664 *stream_out = &out->stream;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001665
Simon Wilson15f60a82012-04-24 20:56:32 -07001666 return 0;
1667
1668err_open:
1669 free(out);
1670 *stream_out = NULL;
1671 return ret;
1672}
1673
1674static void adev_close_output_stream(struct audio_hw_device *dev,
1675 struct audio_stream_out *stream)
1676{
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001677 struct audio_device *adev;
1678 enum output_type type;
1679
Simon Wilson15f60a82012-04-24 20:56:32 -07001680 out_standby(&stream->common);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001681 adev = (struct audio_device *)dev;
Glenn Kasten22f45632014-09-05 10:34:40 -07001682 pthread_mutex_lock(&adev->lock_outputs);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001683 for (type = 0; type < OUTPUT_TOTAL; ++type) {
1684 if (adev->outputs[type] == (struct stream_out *) stream) {
1685 adev->outputs[type] = NULL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001686 break;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001687 }
1688 }
Glenn Kasten22f45632014-09-05 10:34:40 -07001689 pthread_mutex_unlock(&adev->lock_outputs);
Simon Wilson15f60a82012-04-24 20:56:32 -07001690 free(stream);
1691}
1692
1693static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1694{
Eric Laurenta989ebf2012-10-15 15:14:44 -07001695 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001696}
1697
1698static char * adev_get_parameters(const struct audio_hw_device *dev,
1699 const char *keys)
1700{
Eric Laurent688880c2012-09-07 16:46:00 -07001701 struct audio_device *adev = (struct audio_device *)dev;
1702 struct str_parms *parms = str_parms_create_str(keys);
1703 char value[32];
1704 int ret = str_parms_get_str(parms, "ec_supported", value, sizeof(value));
1705 char *str;
1706
1707 str_parms_destroy(parms);
1708 if (ret >= 0) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001709 parms = str_parms_create_str("ec_supported=yes");
Eric Laurent688880c2012-09-07 16:46:00 -07001710 str = str_parms_to_str(parms);
1711 str_parms_destroy(parms);
1712 return str;
1713 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001714 return strdup("");
1715}
1716
1717static int adev_init_check(const struct audio_hw_device *dev)
1718{
1719 return 0;
1720}
1721
1722static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1723{
1724 return -ENOSYS;
1725}
1726
1727static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1728{
1729 return -ENOSYS;
1730}
1731
1732static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1733{
1734 return 0;
1735}
1736
1737static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1738{
1739 struct audio_device *adev = (struct audio_device *)dev;
1740
1741 adev->mic_mute = state;
1742
1743 return 0;
1744}
1745
1746static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1747{
1748 struct audio_device *adev = (struct audio_device *)dev;
1749
1750 *state = adev->mic_mute;
1751
1752 return 0;
1753}
1754
1755static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1756 const struct audio_config *config)
1757{
1758
1759 return get_input_buffer_size(config->sample_rate, config->format,
Glenn Kastena83d9a12014-07-15 10:28:31 -07001760 audio_channel_count_from_in_mask(config->channel_mask),
1761 false /* is_low_latency: since we don't know, be conservative */);
Simon Wilson15f60a82012-04-24 20:56:32 -07001762}
1763
1764static int adev_open_input_stream(struct audio_hw_device *dev,
1765 audio_io_handle_t handle,
1766 audio_devices_t devices,
1767 struct audio_config *config,
Glenn Kastena83d9a12014-07-15 10:28:31 -07001768 struct audio_stream_in **stream_in,
Eric Laurent2f4b8092014-07-27 17:23:22 -07001769 audio_input_flags_t flags,
1770 const char *address __unused,
1771 audio_source_t source __unused)
Simon Wilson15f60a82012-04-24 20:56:32 -07001772{
1773 struct audio_device *adev = (struct audio_device *)dev;
1774 struct stream_in *in;
1775 int ret;
1776
1777 *stream_in = NULL;
1778
Eric Laurentd7abdd02012-07-27 14:54:41 -07001779 /* Respond with a request for mono if a different format is given. */
Eric Laurentb52afc82013-01-18 15:12:57 -08001780 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO &&
1781 config->channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK) {
Eric Laurentd7abdd02012-07-27 14:54:41 -07001782 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
Simon Wilson15f60a82012-04-24 20:56:32 -07001783 return -EINVAL;
1784 }
1785
1786 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1787 if (!in)
1788 return -ENOMEM;
1789
1790 in->stream.common.get_sample_rate = in_get_sample_rate;
1791 in->stream.common.set_sample_rate = in_set_sample_rate;
1792 in->stream.common.get_buffer_size = in_get_buffer_size;
1793 in->stream.common.get_channels = in_get_channels;
1794 in->stream.common.get_format = in_get_format;
1795 in->stream.common.set_format = in_set_format;
1796 in->stream.common.standby = in_standby;
1797 in->stream.common.dump = in_dump;
1798 in->stream.common.set_parameters = in_set_parameters;
1799 in->stream.common.get_parameters = in_get_parameters;
1800 in->stream.common.add_audio_effect = in_add_audio_effect;
1801 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1802 in->stream.set_gain = in_set_gain;
1803 in->stream.read = in_read;
1804 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1805
1806 in->dev = adev;
1807 in->standby = true;
1808 in->requested_rate = config->sample_rate;
Eric Laurent87532032012-07-16 13:53:20 -07001809 in->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001810 /* strip AUDIO_DEVICE_BIT_IN to allow bitwise comparisons */
1811 in->device = devices & ~AUDIO_DEVICE_BIT_IN;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001812 in->io_handle = handle;
Eric Laurentb52afc82013-01-18 15:12:57 -08001813 in->channel_mask = config->channel_mask;
Glenn Kastena83d9a12014-07-15 10:28:31 -07001814 in->flags = flags;
1815 struct pcm_config *pcm_config = flags & AUDIO_INPUT_FLAG_FAST ?
1816 &pcm_config_in_low_latency : &pcm_config_in;
1817 in->config = pcm_config;
Simon Wilson15f60a82012-04-24 20:56:32 -07001818
Glenn Kastena83d9a12014-07-15 10:28:31 -07001819 in->buffer = malloc(pcm_config->period_size * pcm_config->channels
Eric Laurent84c33732014-07-03 16:35:46 -07001820 * audio_stream_in_frame_size(&in->stream));
Eric Laurentd7abdd02012-07-27 14:54:41 -07001821
Simon Wilson15f60a82012-04-24 20:56:32 -07001822 if (!in->buffer) {
1823 ret = -ENOMEM;
1824 goto err_malloc;
1825 }
1826
Glenn Kastena83d9a12014-07-15 10:28:31 -07001827 if (in->requested_rate != pcm_config->rate) {
Simon Wilson15f60a82012-04-24 20:56:32 -07001828 in->buf_provider.get_next_buffer = get_next_buffer;
1829 in->buf_provider.release_buffer = release_buffer;
1830
Glenn Kastena83d9a12014-07-15 10:28:31 -07001831 ret = create_resampler(pcm_config->rate,
Simon Wilson15f60a82012-04-24 20:56:32 -07001832 in->requested_rate,
Eric Laurent1e7184b2014-07-01 20:29:10 -07001833 audio_channel_count_from_in_mask(in->channel_mask),
Simon Wilson15f60a82012-04-24 20:56:32 -07001834 RESAMPLER_QUALITY_DEFAULT,
1835 &in->buf_provider,
1836 &in->resampler);
1837 if (ret != 0) {
1838 ret = -EINVAL;
1839 goto err_resampler;
1840 }
1841 }
1842
1843 *stream_in = &in->stream;
1844 return 0;
1845
1846err_resampler:
1847 free(in->buffer);
1848err_malloc:
1849 free(in);
1850 return ret;
1851}
1852
1853static void adev_close_input_stream(struct audio_hw_device *dev,
1854 struct audio_stream_in *stream)
1855{
1856 struct stream_in *in = (struct stream_in *)stream;
1857
1858 in_standby(&stream->common);
1859 if (in->resampler) {
1860 release_resampler(in->resampler);
1861 in->resampler = NULL;
1862 }
1863 free(in->buffer);
1864 free(stream);
1865}
1866
1867static int adev_dump(const audio_hw_device_t *device, int fd)
1868{
1869 return 0;
1870}
1871
1872static int adev_close(hw_device_t *device)
1873{
1874 struct audio_device *adev = (struct audio_device *)device;
1875
1876 audio_route_free(adev->ar);
1877
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001878 eS305_Release();
1879
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001880 if (adev->hdmi_drv_fd >= 0)
1881 close(adev->hdmi_drv_fd);
Eric Laurent688880c2012-09-07 16:46:00 -07001882
Eric Laurent429f24d2012-11-02 14:37:38 -07001883 if (adev->bubble_level)
1884 bubble_level_release(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -07001885
Simon Wilson15f60a82012-04-24 20:56:32 -07001886 free(device);
1887 return 0;
1888}
1889
Simon Wilson15f60a82012-04-24 20:56:32 -07001890static int adev_open(const hw_module_t* module, const char* name,
1891 hw_device_t** device)
1892{
1893 struct audio_device *adev;
1894 int ret;
1895
1896 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1897 return -EINVAL;
1898
1899 adev = calloc(1, sizeof(struct audio_device));
1900 if (!adev)
1901 return -ENOMEM;
1902
1903 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent6a466d72012-08-28 12:13:38 -07001904 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001905 adev->hw_device.common.module = (struct hw_module_t *) module;
1906 adev->hw_device.common.close = adev_close;
1907
Simon Wilson15f60a82012-04-24 20:56:32 -07001908 adev->hw_device.init_check = adev_init_check;
1909 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1910 adev->hw_device.set_master_volume = adev_set_master_volume;
1911 adev->hw_device.set_mode = adev_set_mode;
1912 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1913 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1914 adev->hw_device.set_parameters = adev_set_parameters;
1915 adev->hw_device.get_parameters = adev_get_parameters;
1916 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1917 adev->hw_device.open_output_stream = adev_open_output_stream;
1918 adev->hw_device.close_output_stream = adev_close_output_stream;
1919 adev->hw_device.open_input_stream = adev_open_input_stream;
1920 adev->hw_device.close_input_stream = adev_close_input_stream;
1921 adev->hw_device.dump = adev_dump;
1922
Simon Wilson759c6f02013-01-15 16:38:56 -08001923 adev->ar = audio_route_init(MIXER_CARD, NULL);
Eric Laurent87532032012-07-16 13:53:20 -07001924 adev->input_source = AUDIO_SOURCE_DEFAULT;
1925 /* adev->cur_route_id initial value is 0 and such that first device
1926 * selection is always applied by select_devices() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001927
Eric Laurent688880c2012-09-07 16:46:00 -07001928 adev->es305_preset = ES305_PRESET_INIT;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001929 adev->es305_new_mode = ES305_MODE_LEVEL;
1930 adev->es305_mode = ES305_MODE_LEVEL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001931 adev->hdmi_drv_fd = -1;
Eric Laurent4f1aece2013-04-19 17:10:25 -07001932
Simon Wilson15f60a82012-04-24 20:56:32 -07001933 *device = &adev->hw_device.common;
1934
Glenn Kasten6e11d0a2014-05-12 14:41:05 -07001935 char value[PROPERTY_VALUE_MAX];
1936 if (property_get("audio_hal.period_size", value, NULL) > 0) {
1937 pcm_config.period_size = atoi(value);
1938 pcm_config_in.period_size = pcm_config.period_size;
1939 }
1940 if (property_get("audio_hal.in_period_size", value, NULL) > 0)
1941 pcm_config_in.period_size = atoi(value);
1942
Simon Wilson15f60a82012-04-24 20:56:32 -07001943 return 0;
1944}
1945
1946static struct hw_module_methods_t hal_module_methods = {
1947 .open = adev_open,
1948};
1949
1950struct audio_module HAL_MODULE_INFO_SYM = {
1951 .common = {
1952 .tag = HARDWARE_MODULE_TAG,
1953 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1954 .hal_api_version = HARDWARE_HAL_API_VERSION,
1955 .id = AUDIO_HARDWARE_MODULE_ID,
1956 .name = "Manta audio HW HAL",
1957 .author = "The Android Open Source Project",
1958 .methods = &hal_module_methods,
1959 },
1960};