blob: e316e82a5c69af52ff50266a6ca4540302a54d0d [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
Simon Wilsonf051bcf2012-09-26 14:10:07 -070034#include <linux/videodev2.h>
35#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,
81 .period_size = 1024,
82 .period_count = 2,
83 .format = PCM_FORMAT_S16_LE,
84};
85
Simon Wilsona282d2f2012-09-12 16:14:24 -070086struct pcm_config pcm_config_sco = {
87 .channels = 1,
88 .rate = 8000,
89 .period_size = 128,
90 .period_count = 2,
91 .format = PCM_FORMAT_S16_LE,
92};
93
Glenn Kastene0aa8f32012-08-17 09:26:58 -070094struct pcm_config pcm_config_deep = {
95 .channels = 2,
96 .rate = 44100,
97 /* FIXME This is an arbitrary number, may change.
98 * Dynamic configuration based on screen on/off is not implemented;
99 * let's see what power consumption is first to see if necessary.
100 */
101 .period_size = 8192,
102 .period_count = 2,
103 .format = PCM_FORMAT_S16_LE,
104};
105
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700106struct pcm_config pcm_config_hdmi_multi = {
107 .channels = 6, /* changed when the stream is opened */
108 .rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE,
109 .period_size = 1024,
110 .period_count = 4,
111 .format = PCM_FORMAT_S16_LE,
112};
113
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700114enum output_type {
115 OUTPUT_DEEP_BUF, // deep PCM buffers output stream
116 OUTPUT_LOW_LATENCY, // low latency output stream
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700117 OUTPUT_HDMI, // HDMI multi channel
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700118 OUTPUT_TOTAL
119};
120
Simon Wilson15f60a82012-04-24 20:56:32 -0700121struct audio_device {
122 struct audio_hw_device hw_device;
123
124 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700125 audio_devices_t out_device; /* "or" of stream_out.device for all active output streams */
Eric Laurent42531fa2012-10-03 09:06:14 -0700126 audio_devices_t in_device;
Simon Wilson15f60a82012-04-24 20:56:32 -0700127 bool mic_mute;
128 struct audio_route *ar;
Eric Laurent87532032012-07-16 13:53:20 -0700129 audio_source_t input_source;
130 int cur_route_id; /* current route ID: combination of input source
131 * and output device IDs */
Simon Wilsona282d2f2012-09-12 16:14:24 -0700132 struct pcm *pcm_voice_out;
133 struct pcm *pcm_sco_out;
134 struct pcm *pcm_voice_in;
135 struct pcm *pcm_sco_in;
Eric Laurent688880c2012-09-07 16:46:00 -0700136 int es305_preset;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700137 int es305_new_mode;
Eric Laurent688880c2012-09-07 16:46:00 -0700138 int es305_mode;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700139 int hdmi_drv_fd;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700140 struct bubble_level *bubble_level;
Eric Laurentb52afc82013-01-18 15:12:57 -0800141 audio_channel_mask_t in_channel_mask;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700142
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700143 struct stream_out *outputs[OUTPUT_TOTAL];
Simon Wilson15f60a82012-04-24 20:56:32 -0700144};
145
146struct stream_out {
147 struct audio_stream_out stream;
148
149 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson56d84e22012-08-17 13:55:27 -0700150 struct pcm *pcm[PCM_TOTAL];
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700151 struct pcm_config config;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700152 unsigned int pcm_device;
Simon Wilson56d84e22012-08-17 13:55:27 -0700153 bool standby; /* true if all PCMs are inactive */
Eric Laurent42531fa2012-10-03 09:06:14 -0700154 audio_devices_t device;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700155 /* FIXME: when HDMI multichannel output is active, other outputs must be disabled as
156 * HDMI and WM1811 share the same I2S. This means that notifications and other sounds are
157 * silent when watching a 5.1 movie. */
158 bool disabled;
159 audio_channel_mask_t channel_mask;
160 /* Array of supported channel mask configurations. +1 so that the last entry is always 0 */
161 audio_channel_mask_t supported_channel_masks[MAX_SUPPORTED_CHANNEL_MASKS + 1];
Simon Wilson15f60a82012-04-24 20:56:32 -0700162
163 struct audio_device *dev;
164};
165
166struct stream_in {
167 struct audio_stream_in stream;
168
169 pthread_mutex_t lock; /* see note below on mutex acquisition order */
170 struct pcm *pcm;
171 bool standby;
172
173 unsigned int requested_rate;
174 struct resampler_itfe *resampler;
175 struct resampler_buffer_provider buf_provider;
176 int16_t *buffer;
177 size_t frames_in;
178 int read_status;
Eric Laurent87532032012-07-16 13:53:20 -0700179 audio_source_t input_source;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700180 audio_io_handle_t io_handle;
Eric Laurent42531fa2012-10-03 09:06:14 -0700181 audio_devices_t device;
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700182 uint16_t ramp_vol;
183 uint16_t ramp_step;
184 size_t ramp_frames;
Eric Laurentb52afc82013-01-18 15:12:57 -0800185 audio_channel_mask_t channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700186
187 struct audio_device *dev;
188};
189
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700190#define STRING_TO_ENUM(string) { #string, string }
191
192struct string_to_enum {
193 const char *name;
194 uint32_t value;
195};
196
197const struct string_to_enum out_channels_name_to_enum_table[] = {
198 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
199 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
200 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
201};
202
Eric Laurent87532032012-07-16 13:53:20 -0700203enum {
204 OUT_DEVICE_SPEAKER,
205 OUT_DEVICE_HEADSET,
206 OUT_DEVICE_HEADPHONES,
207 OUT_DEVICE_BT_SCO,
208 OUT_DEVICE_SPEAKER_AND_HEADSET,
209 OUT_DEVICE_TAB_SIZE, /* number of rows in route_configs[][] */
210 OUT_DEVICE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700211 OUT_DEVICE_CNT
212};
213
214enum {
215 IN_SOURCE_MIC,
216 IN_SOURCE_CAMCORDER,
217 IN_SOURCE_VOICE_RECOGNITION,
218 IN_SOURCE_VOICE_COMMUNICATION,
219 IN_SOURCE_TAB_SIZE, /* number of lines in route_configs[][] */
220 IN_SOURCE_NONE,
Eric Laurent87532032012-07-16 13:53:20 -0700221 IN_SOURCE_CNT
222};
223
Eric Laurent688880c2012-09-07 16:46:00 -0700224enum {
Eric Laurent688880c2012-09-07 16:46:00 -0700225 ES305_MODE_DEFAULT,
Eric Laurenta989ebf2012-10-15 15:14:44 -0700226 ES305_MODE_LEVEL,
Eric Laurent688880c2012-09-07 16:46:00 -0700227 ES305_NUM_MODES,
228};
229
Eric Laurent42531fa2012-10-03 09:06:14 -0700230int get_output_device_id(audio_devices_t device)
Eric Laurent87532032012-07-16 13:53:20 -0700231{
Eric Laurent6a466d72012-08-28 12:13:38 -0700232 if (device == AUDIO_DEVICE_NONE)
Eric Laurent87532032012-07-16 13:53:20 -0700233 return OUT_DEVICE_NONE;
234
235 if (popcount(device) == 2) {
236 if ((device == (AUDIO_DEVICE_OUT_SPEAKER |
237 AUDIO_DEVICE_OUT_WIRED_HEADSET)) ||
238 (device == (AUDIO_DEVICE_OUT_SPEAKER |
239 AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
240 return OUT_DEVICE_SPEAKER_AND_HEADSET;
241 else
Simon Wilsona6b94122012-09-12 12:52:24 -0700242 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700243 }
244
245 if (popcount(device) != 1)
Simon Wilsona6b94122012-09-12 12:52:24 -0700246 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700247
248 switch (device) {
249 case AUDIO_DEVICE_OUT_SPEAKER:
250 return OUT_DEVICE_SPEAKER;
251 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
252 return OUT_DEVICE_HEADSET;
253 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
254 return OUT_DEVICE_HEADPHONES;
255 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
256 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
257 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
258 return OUT_DEVICE_BT_SCO;
259 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700260 return OUT_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700261 }
262}
263
264int get_input_source_id(audio_source_t source)
265{
266 switch (source) {
267 case AUDIO_SOURCE_DEFAULT:
268 return IN_SOURCE_NONE;
269 case AUDIO_SOURCE_MIC:
270 return IN_SOURCE_MIC;
271 case AUDIO_SOURCE_CAMCORDER:
272 return IN_SOURCE_CAMCORDER;
273 case AUDIO_SOURCE_VOICE_RECOGNITION:
274 return IN_SOURCE_VOICE_RECOGNITION;
275 case AUDIO_SOURCE_VOICE_COMMUNICATION:
276 return IN_SOURCE_VOICE_COMMUNICATION;
277 default:
Simon Wilsona6b94122012-09-12 12:52:24 -0700278 return IN_SOURCE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -0700279 }
280}
281
282struct route_config {
283 const char * const output_route;
284 const char * const input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700285 int es305_preset[ES305_NUM_MODES]; // es305 preset for this route.
286 // -1 means es305 bypass
Eric Laurent87532032012-07-16 13:53:20 -0700287};
288
289const struct route_config media_speaker = {
290 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700291 "media-main-mic",
292 { ES305_PRESET_OFF,
293 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700294};
295
296const struct route_config media_headphones = {
297 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700298 "media-main-mic",
299 { ES305_PRESET_OFF,
300 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700301};
302
303const struct route_config media_headset = {
304 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700305 "media-headset-mic",
306 { ES305_PRESET_OFF,
307 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700308};
309
310const struct route_config camcorder_speaker = {
311 "media-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700312 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700313 { ES305_PRESET_CAMCORDER,
314 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700315};
316
317const struct route_config camcorder_headphones = {
318 "media-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700319 "media-second-mic",
Jean-Michel Trivi48277c52012-10-08 10:22:59 -0700320 { ES305_PRESET_CAMCORDER,
321 ES305_PRESET_CAMCORDER }
Eric Laurent87532032012-07-16 13:53:20 -0700322};
323
324const struct route_config voice_rec_speaker = {
325 "voice-rec-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700326 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700327 { ES305_PRESET_ASRA_HANDHELD,
328 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700329};
330
331const struct route_config voice_rec_headphones = {
332 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700333 "voice-rec-main-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700334 { ES305_PRESET_ASRA_HANDHELD,
335 ES305_PRESET_ASRA_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700336};
337
338const struct route_config voice_rec_headset = {
339 "voice-rec-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700340 "voice-rec-headset-mic",
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700341 { ES305_PRESET_ASRA_HEADSET,
342 ES305_PRESET_ASRA_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700343};
344
345const struct route_config communication_speaker = {
346 "communication-speaker",
Eric Laurent688880c2012-09-07 16:46:00 -0700347 "communication-main-mic",
348 { ES305_PRESET_VOIP_HANDHELD,
349 ES305_PRESET_VOIP_DESKTOP }
Eric Laurent87532032012-07-16 13:53:20 -0700350};
351
352const struct route_config communication_headphones = {
353 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700354 "communication-main-mic",
355 { ES305_PRESET_VOIP_HEADPHONES,
356 ES305_PRESET_VOIP_HP_DESKTOP}
Eric Laurent87532032012-07-16 13:53:20 -0700357};
358
359const struct route_config communication_headset = {
360 "communication-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700361 "communication-headset-mic",
362 { ES305_PRESET_VOIP_HEADSET,
363 ES305_PRESET_VOIP_HEADSET }
Eric Laurent87532032012-07-16 13:53:20 -0700364};
365
366const struct route_config speaker_and_headphones = {
367 "speaker-and-headphones",
Eric Laurent688880c2012-09-07 16:46:00 -0700368 "main-mic",
369 { ES305_PRESET_CURRENT,
370 ES305_PRESET_CURRENT }
Eric Laurent87532032012-07-16 13:53:20 -0700371};
372
373const struct route_config bluetooth_sco = {
374 "bt-sco-headset",
Eric Laurent688880c2012-09-07 16:46:00 -0700375 "bt-sco-mic",
376 { ES305_PRESET_OFF,
377 ES305_PRESET_OFF }
Eric Laurent87532032012-07-16 13:53:20 -0700378};
379
380const struct route_config * const route_configs[IN_SOURCE_TAB_SIZE]
381 [OUT_DEVICE_TAB_SIZE] = {
382 { /* IN_SOURCE_MIC */
383 &media_speaker, /* OUT_DEVICE_SPEAKER */
384 &media_headset, /* OUT_DEVICE_HEADSET */
385 &media_headphones, /* OUT_DEVICE_HEADPHONES */
386 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
387 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
388 },
389 { /* IN_SOURCE_CAMCORDER */
390 &camcorder_speaker, /* OUT_DEVICE_SPEAKER */
391 &camcorder_headphones, /* OUT_DEVICE_HEADSET */
392 &camcorder_headphones, /* OUT_DEVICE_HEADPHONES */
393 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
394 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
395 },
396 { /* IN_SOURCE_VOICE_RECOGNITION */
397 &voice_rec_speaker, /* OUT_DEVICE_SPEAKER */
398 &voice_rec_headset, /* OUT_DEVICE_HEADSET */
399 &voice_rec_headphones, /* OUT_DEVICE_HEADPHONES */
400 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
401 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
402 },
403 { /* IN_SOURCE_VOICE_COMMUNICATION */
404 &communication_speaker, /* OUT_DEVICE_SPEAKER */
405 &communication_headset, /* OUT_DEVICE_HEADSET */
406 &communication_headphones, /* OUT_DEVICE_HEADPHONES */
407 &bluetooth_sco, /* OUT_DEVICE_BT_SCO */
408 &speaker_and_headphones /* OUT_DEVICE_SPEAKER_AND_HEADSET */
409 }
410};
411
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700412static int do_out_standby(struct stream_out *out);
413
Simon Wilson15f60a82012-04-24 20:56:32 -0700414/**
415 * NOTE: when multiple mutexes have to be acquired, always respect the
416 * following order: hw device > in stream > out stream
417 */
418
419/* Helper functions */
420
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700421static int open_hdmi_driver(struct audio_device *adev)
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700422{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700423 if (adev->hdmi_drv_fd < 0) {
424 adev->hdmi_drv_fd = open("/dev/video16", O_RDWR);
425 if (adev->hdmi_drv_fd < 0)
426 ALOGE("%s cannot open video16 (%d)", __func__, adev->hdmi_drv_fd);
427 }
428 return adev->hdmi_drv_fd;
429}
430
431/* must be called with hw device mutex locked */
432static int enable_hdmi_audio(struct audio_device *adev, int enable)
433{
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700434 int ret;
435 struct v4l2_control ctrl;
436
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700437 ret = open_hdmi_driver(adev);
438 if (ret < 0)
439 return ret;
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700440
441 ctrl.id = V4L2_CID_TV_ENABLE_HDMI_AUDIO;
442 ctrl.value = !!enable;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700443 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700444
445 if (ret < 0)
446 ALOGE("V4L2_CID_TV_ENABLE_HDMI_AUDIO ioctl error (%d)", errno);
447
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700448 return ret;
449}
450
451/* must be called with hw device mutex locked */
452static int read_hdmi_channel_masks(struct audio_device *adev, struct stream_out *out) {
453 int ret;
454 struct v4l2_control ctrl;
455
456 ret = open_hdmi_driver(adev);
457 if (ret < 0)
458 return ret;
459
460 ctrl.id = V4L2_CID_TV_MAX_AUDIO_CHANNELS;
461 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_G_CTRL, &ctrl);
462 if (ret < 0) {
463 ALOGE("V4L2_CID_TV_MAX_AUDIO_CHANNELS ioctl error (%d)", errno);
464 return ret;
465 }
466
467 ALOGV("%s ioctl %d got %d max channels", __func__, ret, ctrl.value);
468
469 if (ctrl.value != 6 && ctrl.value != 8)
470 return -ENOSYS;
471
472 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
473 if (ctrl.value == 8)
474 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
475
476 return ret;
477}
478
479/* must be called with hw device mutex locked */
480static int set_hdmi_channels(struct audio_device *adev, int channels) {
481 int ret;
482 struct v4l2_control ctrl;
483
484 ret = open_hdmi_driver(adev);
485 if (ret < 0)
486 return ret;
487
488 ctrl.id = V4L2_CID_TV_SET_NUM_CHANNELS;
489 ctrl.value = channels;
490 ret = ioctl(adev->hdmi_drv_fd, VIDIOC_S_CTRL, &ctrl);
491 if (ret < 0)
492 ALOGE("V4L2_CID_TV_SET_NUM_CHANNELS ioctl error (%d)", errno);
Simon Wilsonf051bcf2012-09-26 14:10:07 -0700493
494 return ret;
495}
496
Simon Wilson15f60a82012-04-24 20:56:32 -0700497static void select_devices(struct audio_device *adev)
498{
Eric Laurent6a466d72012-08-28 12:13:38 -0700499 int output_device_id = get_output_device_id(adev->out_device);
Eric Laurent87532032012-07-16 13:53:20 -0700500 int input_source_id = get_input_source_id(adev->input_source);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700501 const char *output_route = NULL;
502 const char *input_route = NULL;
Eric Laurent87532032012-07-16 13:53:20 -0700503 int new_route_id;
Eric Laurent688880c2012-09-07 16:46:00 -0700504 int new_es305_preset = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -0700505
Simon Wilson759c6f02013-01-15 16:38:56 -0800506 audio_route_reset(adev->ar);
Simon Wilsonc4006be2012-08-17 11:23:38 -0700507
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700508 enable_hdmi_audio(adev, adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL);
Simon Wilsonab5dda62012-10-01 17:44:38 -0700509
Eric Laurent87532032012-07-16 13:53:20 -0700510 new_route_id = (1 << (input_source_id + OUT_DEVICE_CNT)) + (1 << output_device_id);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700511 if ((new_route_id == adev->cur_route_id) && (adev->es305_mode == adev->es305_new_mode))
Eric Laurent87532032012-07-16 13:53:20 -0700512 return;
513 adev->cur_route_id = new_route_id;
Eric Laurenta989ebf2012-10-15 15:14:44 -0700514 adev->es305_mode = adev->es305_new_mode;
Simon Wilson15f60a82012-04-24 20:56:32 -0700515
Eric Laurent87532032012-07-16 13:53:20 -0700516 if (input_source_id != IN_SOURCE_NONE) {
517 if (output_device_id != OUT_DEVICE_NONE) {
518 input_route =
519 route_configs[input_source_id][output_device_id]->input_route;
520 output_route =
521 route_configs[input_source_id][output_device_id]->output_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700522 new_es305_preset =
523 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700524 } else {
Eric Laurent42531fa2012-10-03 09:06:14 -0700525 switch (adev->in_device) {
526 case AUDIO_DEVICE_IN_WIRED_HEADSET:
527 output_device_id = OUT_DEVICE_HEADSET;
528 break;
529 case AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
530 output_device_id = OUT_DEVICE_BT_SCO;
531 break;
532 default:
533 output_device_id = OUT_DEVICE_SPEAKER;
534 break;
535 }
Eric Laurent87532032012-07-16 13:53:20 -0700536 input_route =
Eric Laurent42531fa2012-10-03 09:06:14 -0700537 route_configs[input_source_id][output_device_id]->input_route;
Eric Laurent688880c2012-09-07 16:46:00 -0700538 new_es305_preset =
Eric Laurent42531fa2012-10-03 09:06:14 -0700539 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
Eric Laurent87532032012-07-16 13:53:20 -0700540 }
Eric Laurentb52afc82013-01-18 15:12:57 -0800541 // disable noise suppression when capturing front and back mic for voice recognition
542 if ((adev->input_source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
543 (adev->in_channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK))
544 new_es305_preset = -1;
Eric Laurent87532032012-07-16 13:53:20 -0700545 } else {
546 if (output_device_id != OUT_DEVICE_NONE) {
547 output_route =
548 route_configs[IN_SOURCE_MIC][output_device_id]->output_route;
549 }
550 }
551
552 ALOGV("select_devices() devices %#x input src %d output route %s input route %s",
Eric Laurent6a466d72012-08-28 12:13:38 -0700553 adev->out_device, adev->input_source,
Simon Wilsonc4006be2012-08-17 11:23:38 -0700554 output_route ? output_route : "none",
555 input_route ? input_route : "none");
Eric Laurent87532032012-07-16 13:53:20 -0700556
Simon Wilsonc4006be2012-08-17 11:23:38 -0700557 if (output_route)
558 audio_route_apply_path(adev->ar, output_route);
559 if (input_route)
560 audio_route_apply_path(adev->ar, input_route);
Simon Wilson15f60a82012-04-24 20:56:32 -0700561
Eric Laurent688880c2012-09-07 16:46:00 -0700562 if ((new_es305_preset != ES305_PRESET_CURRENT) &&
563 (new_es305_preset != adev->es305_preset)) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700564 ALOGV(" select_devices() changing es305 preset from %d to %d",
565 adev->es305_preset, new_es305_preset);
566 if (eS305_UsePreset(new_es305_preset) == 0) {
Eric Laurent688880c2012-09-07 16:46:00 -0700567 adev->es305_preset = new_es305_preset;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700568 }
Eric Laurent688880c2012-09-07 16:46:00 -0700569 }
570
Simon Wilson759c6f02013-01-15 16:38:56 -0800571 audio_route_update_mixer(adev->ar);
Simon Wilson15f60a82012-04-24 20:56:32 -0700572}
573
Eric Laurenta989ebf2012-10-15 15:14:44 -0700574void bubblelevel_callback(bool is_level, void *user_data)
575{
576 struct audio_device *adev = (struct audio_device *)user_data;
577 int es305_mode;
578
579 if (is_level)
580 es305_mode = ES305_MODE_LEVEL;
581 else
582 es305_mode = ES305_MODE_DEFAULT;
583
584 pthread_mutex_lock(&adev->lock);
585 if (es305_mode != adev->es305_mode) {
586 adev->es305_new_mode = es305_mode;
587 select_devices(adev);
588 ALOGV("bubblelevel_callback is_level %d es305_mode %d", is_level, es305_mode);
589 }
590 pthread_mutex_unlock(&adev->lock);
591}
592
Eric Laurent429f24d2012-11-02 14:37:38 -0700593/* must be called with hw device mutex locked */
594bool get_bubblelevel(struct audio_device *adev)
595{
596 if (!adev->bubble_level) {
597 adev->bubble_level = bubble_level_create();
598 if (adev->bubble_level)
599 adev->bubble_level->set_callback(adev->bubble_level, bubblelevel_callback, adev);
600 }
601 return (adev->bubble_level != NULL);
602}
603
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700604static void force_non_hdmi_out_standby(struct audio_device *adev)
605{
606 enum output_type type;
607 struct stream_out *out;
608
609 for (type = 0; type < OUTPUT_TOTAL; ++type) {
610 out = adev->outputs[type];
611 if (type == OUTPUT_HDMI || !out)
612 continue;
613 pthread_mutex_lock(&out->lock);
614 do_out_standby(out);
615 pthread_mutex_unlock(&out->lock);
616 }
617}
618
Simon Wilson15f60a82012-04-24 20:56:32 -0700619/* must be called with hw device and output stream mutexes locked */
620static int start_output_stream(struct stream_out *out)
621{
622 struct audio_device *adev = out->dev;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700623 int type;
624
625 if (out == adev->outputs[OUTPUT_HDMI]) {
626 force_non_hdmi_out_standby(adev);
627 } else if (adev->outputs[OUTPUT_HDMI] && !adev->outputs[OUTPUT_HDMI]->standby) {
628 out->disabled = true;
629 return 0;
630 }
631
632 out->disabled = false;
Simon Wilson15f60a82012-04-24 20:56:32 -0700633
Simon Wilson56d84e22012-08-17 13:55:27 -0700634 if (out->device & (AUDIO_DEVICE_OUT_SPEAKER |
635 AUDIO_DEVICE_OUT_WIRED_HEADSET |
636 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
Simon Wilsona282d2f2012-09-12 16:14:24 -0700637 AUDIO_DEVICE_OUT_AUX_DIGITAL |
638 AUDIO_DEVICE_OUT_ALL_SCO)) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700639
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700640 out->pcm[PCM_CARD] = pcm_open(PCM_CARD, out->pcm_device,
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700641 PCM_OUT, &out->config);
Simon Wilson15f60a82012-04-24 20:56:32 -0700642
Simon Wilson56d84e22012-08-17 13:55:27 -0700643 if (out->pcm[PCM_CARD] && !pcm_is_ready(out->pcm[PCM_CARD])) {
644 ALOGE("pcm_open(PCM_CARD) failed: %s",
645 pcm_get_error(out->pcm[PCM_CARD]));
646 pcm_close(out->pcm[PCM_CARD]);
647 return -ENOMEM;
648 }
649 }
650
651 if (out->device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700652 out->pcm[PCM_CARD_SPDIF] = pcm_open(PCM_CARD_SPDIF, out->pcm_device,
653 PCM_OUT, &out->config);
Simon Wilson56d84e22012-08-17 13:55:27 -0700654
655 if (out->pcm[PCM_CARD_SPDIF] &&
656 !pcm_is_ready(out->pcm[PCM_CARD_SPDIF])) {
657 ALOGE("pcm_open(PCM_CARD_SPDIF) failed: %s",
658 pcm_get_error(out->pcm[PCM_CARD_SPDIF]));
659 pcm_close(out->pcm[PCM_CARD_SPDIF]);
660 return -ENOMEM;
661 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700662 }
663
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700664 adev->out_device |= out->device;
Eric Laurent87532032012-07-16 13:53:20 -0700665 select_devices(adev);
666
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700667 if (out->device & AUDIO_DEVICE_OUT_AUX_DIGITAL)
668 set_hdmi_channels(adev, out->config.channels);
669
Eric Laurenta989ebf2012-10-15 15:14:44 -0700670 /* anticipate level measurement in case we start capture later */
Eric Laurent429f24d2012-11-02 14:37:38 -0700671 if (get_bubblelevel(adev))
672 adev->bubble_level->poll_once(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -0700673
Simon Wilson15f60a82012-04-24 20:56:32 -0700674 return 0;
675}
676
677/* must be called with hw device and input stream mutexes locked */
678static int start_input_stream(struct stream_in *in)
679{
680 struct audio_device *adev = in->dev;
681
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700682 in->pcm = pcm_open(PCM_CARD, PCM_DEVICE, PCM_IN, &pcm_config_in);
Simon Wilson15f60a82012-04-24 20:56:32 -0700683
684 if (in->pcm && !pcm_is_ready(in->pcm)) {
685 ALOGE("pcm_open() failed: %s", pcm_get_error(in->pcm));
686 pcm_close(in->pcm);
687 return -ENOMEM;
688 }
689
690 /* if no supported sample rate is available, use the resampler */
691 if (in->resampler)
692 in->resampler->reset(in->resampler);
693
Eric Laurentf4231822012-08-22 16:06:38 -0700694 in->frames_in = 0;
Eric Laurent87532032012-07-16 13:53:20 -0700695 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -0700696 adev->in_device = in->device;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -0700697
698 eS305_SetActiveIoHandle(in->io_handle);
Eric Laurent87532032012-07-16 13:53:20 -0700699 select_devices(adev);
700
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700701 /* initialize volume ramp */
702 in->ramp_frames = (CAPTURE_START_RAMP_MS * in->requested_rate) / 1000;
703 in->ramp_step = (uint16_t)(USHRT_MAX / in->ramp_frames);
704 in->ramp_vol = 0;;
705
Eric Laurent429f24d2012-11-02 14:37:38 -0700706 if (get_bubblelevel(adev)) {
707 adev->bubble_level->set_poll_interval(adev->bubble_level, BL_POLL_INTERVAL_MIN_SEC);
708 adev->bubble_level->start_polling(adev->bubble_level);
709 }
Eric Laurenta989ebf2012-10-15 15:14:44 -0700710
Simon Wilson15f60a82012-04-24 20:56:32 -0700711 return 0;
712}
713
Simon Wilsona282d2f2012-09-12 16:14:24 -0700714/* must be called with the hw device mutex locked, OK to hold other mutexes */
715static void start_bt_sco(struct audio_device *adev) {
716 adev->pcm_voice_out = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_OUT,
717 &pcm_config_sco);
718 if (adev->pcm_voice_out && !pcm_is_ready(adev->pcm_voice_out)) {
719 ALOGE("pcm_open(VOICE_OUT) failed: %s", pcm_get_error(adev->pcm_voice_out));
720 goto err_voice_out;
721 }
722 adev->pcm_sco_out = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_OUT,
723 &pcm_config_sco);
724 if (adev->pcm_sco_out && !pcm_is_ready(adev->pcm_sco_out)) {
725 ALOGE("pcm_open(SCO_OUT) failed: %s", pcm_get_error(adev->pcm_sco_out));
726 goto err_sco_out;
727 }
728 adev->pcm_voice_in = pcm_open(PCM_CARD, PCM_DEVICE_VOICE, PCM_IN,
729 &pcm_config_sco);
730 if (adev->pcm_voice_in && !pcm_is_ready(adev->pcm_voice_in)) {
731 ALOGE("pcm_open(VOICE_IN) failed: %s", pcm_get_error(adev->pcm_voice_in));
732 goto err_voice_in;
733 }
734 adev->pcm_sco_in = pcm_open(PCM_CARD, PCM_DEVICE_SCO, PCM_IN,
735 &pcm_config_sco);
736 if (adev->pcm_sco_in && !pcm_is_ready(adev->pcm_sco_in)) {
737 ALOGE("pcm_open(SCO_IN) failed: %s", pcm_get_error(adev->pcm_sco_in));
738 goto err_sco_in;
739 }
740
741 pcm_start(adev->pcm_voice_out);
742 pcm_start(adev->pcm_sco_out);
743 pcm_start(adev->pcm_voice_in);
744 pcm_start(adev->pcm_sco_in);
745
746 return;
747
748err_sco_in:
749 pcm_close(adev->pcm_sco_in);
750err_voice_in:
751 pcm_close(adev->pcm_voice_in);
752err_sco_out:
753 pcm_close(adev->pcm_sco_out);
754err_voice_out:
755 pcm_close(adev->pcm_voice_out);
756}
757
758/* must be called with the hw device mutex locked, OK to hold other mutexes */
759static void stop_bt_sco(struct audio_device *adev) {
760 pcm_stop(adev->pcm_voice_out);
761 pcm_stop(adev->pcm_sco_out);
762 pcm_stop(adev->pcm_voice_in);
763 pcm_stop(adev->pcm_sco_in);
764
765 pcm_close(adev->pcm_voice_out);
766 pcm_close(adev->pcm_sco_out);
767 pcm_close(adev->pcm_voice_in);
768 pcm_close(adev->pcm_sco_in);
769}
Eric Laurent1a0c0a72012-08-24 11:29:04 -0700770
Simon Wilson15f60a82012-04-24 20:56:32 -0700771static size_t get_input_buffer_size(unsigned int sample_rate,
772 audio_format_t format,
773 unsigned int channel_count)
774{
775 size_t size;
776
777 /*
778 * take resampling into account and return the closest majoring
779 * multiple of 16 frames, as audioflinger expects audio buffers to
780 * be a multiple of 16 frames
781 */
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700782 size = (pcm_config_in.period_size * sample_rate) / pcm_config_in.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700783 size = ((size + 15) / 16) * 16;
784
785 return size * channel_count * audio_bytes_per_sample(format);
786}
787
788static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
789 struct resampler_buffer* buffer)
790{
791 struct stream_in *in;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700792 size_t i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700793
794 if (buffer_provider == NULL || buffer == NULL)
795 return -EINVAL;
796
797 in = (struct stream_in *)((char *)buffer_provider -
798 offsetof(struct stream_in, buf_provider));
799
800 if (in->pcm == NULL) {
801 buffer->raw = NULL;
802 buffer->frame_count = 0;
803 in->read_status = -ENODEV;
804 return -ENODEV;
805 }
806
807 if (in->frames_in == 0) {
808 in->read_status = pcm_read(in->pcm,
809 (void*)in->buffer,
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700810 pcm_frames_to_bytes(in->pcm, pcm_config_in.period_size));
Simon Wilson15f60a82012-04-24 20:56:32 -0700811 if (in->read_status != 0) {
812 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
813 buffer->raw = NULL;
814 buffer->frame_count = 0;
815 return in->read_status;
816 }
Eric Laurentd7abdd02012-07-27 14:54:41 -0700817
Glenn Kasten7ecf6232012-09-28 12:01:31 -0700818 in->frames_in = pcm_config_in.period_size;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700819
820 /* Do stereo to mono conversion in place by discarding right channel */
Eric Laurentb52afc82013-01-18 15:12:57 -0800821 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
822 for (i = 1; i < in->frames_in; i++)
823 in->buffer[i] = in->buffer[i * 2];
Simon Wilson15f60a82012-04-24 20:56:32 -0700824 }
825
826 buffer->frame_count = (buffer->frame_count > in->frames_in) ?
827 in->frames_in : buffer->frame_count;
Eric Laurentb52afc82013-01-18 15:12:57 -0800828 buffer->i16 = in->buffer +
829 (pcm_config_in.period_size - in->frames_in) * popcount(in->channel_mask);
Simon Wilson15f60a82012-04-24 20:56:32 -0700830
831 return in->read_status;
832
833}
834
835static void release_buffer(struct resampler_buffer_provider *buffer_provider,
836 struct resampler_buffer* buffer)
837{
838 struct stream_in *in;
839
840 if (buffer_provider == NULL || buffer == NULL)
841 return;
842
843 in = (struct stream_in *)((char *)buffer_provider -
844 offsetof(struct stream_in, buf_provider));
845
846 in->frames_in -= buffer->frame_count;
847}
848
849/* read_frames() reads frames from kernel driver, down samples to capture rate
850 * if necessary and output the number of frames requested to the buffer specified */
851static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
852{
853 ssize_t frames_wr = 0;
Eric Laurentd7abdd02012-07-27 14:54:41 -0700854 size_t frame_size = audio_stream_frame_size(&in->stream.common);
Simon Wilson15f60a82012-04-24 20:56:32 -0700855
856 while (frames_wr < frames) {
857 size_t frames_rd = frames - frames_wr;
858 if (in->resampler != NULL) {
859 in->resampler->resample_from_provider(in->resampler,
860 (int16_t *)((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700861 frames_wr * frame_size),
Simon Wilson15f60a82012-04-24 20:56:32 -0700862 &frames_rd);
863 } else {
864 struct resampler_buffer buf = {
865 { raw : NULL, },
866 frame_count : frames_rd,
867 };
868 get_next_buffer(&in->buf_provider, &buf);
869 if (buf.raw != NULL) {
870 memcpy((char *)buffer +
Eric Laurentd7abdd02012-07-27 14:54:41 -0700871 frames_wr * frame_size,
Simon Wilson15f60a82012-04-24 20:56:32 -0700872 buf.raw,
Eric Laurentd7abdd02012-07-27 14:54:41 -0700873 buf.frame_count * frame_size);
Simon Wilson15f60a82012-04-24 20:56:32 -0700874 frames_rd = buf.frame_count;
875 }
876 release_buffer(&in->buf_provider, &buf);
877 }
878 /* in->read_status is updated by getNextBuffer() also called by
879 * in->resampler->resample_from_provider() */
880 if (in->read_status != 0)
881 return in->read_status;
882
883 frames_wr += frames_rd;
884 }
885 return frames_wr;
886}
887
888/* API functions */
889
890static uint32_t out_get_sample_rate(const struct audio_stream *stream)
891{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700892 struct stream_out *out = (struct stream_out *)stream;
893
894 return out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -0700895}
896
897static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
898{
899 return -ENOSYS;
900}
901
902static size_t out_get_buffer_size(const struct audio_stream *stream)
903{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700904 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700905
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700906 return out->config.period_size *
907 audio_stream_frame_size((struct audio_stream *)stream);
Simon Wilson15f60a82012-04-24 20:56:32 -0700908}
909
Glenn Kastenca1414b2012-06-25 10:38:47 -0700910static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
Simon Wilson15f60a82012-04-24 20:56:32 -0700911{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700912 struct stream_out *out = (struct stream_out *)stream;
913
914 return out->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -0700915}
916
917static audio_format_t out_get_format(const struct audio_stream *stream)
918{
919 return AUDIO_FORMAT_PCM_16_BIT;
920}
921
922static int out_set_format(struct audio_stream *stream, audio_format_t format)
923{
924 return -ENOSYS;
925}
926
Glenn Kasten068b84e2012-09-26 12:34:51 -0700927/* Return the set of output devices associated with active streams
928 * other than out. Assumes out is non-NULL and out->dev is locked.
929 */
930static audio_devices_t output_devices(struct stream_out *out)
931{
932 struct audio_device *dev = out->dev;
933 enum output_type type;
934 audio_devices_t devices = AUDIO_DEVICE_NONE;
935
936 for (type = 0; type < OUTPUT_TOTAL; ++type) {
937 struct stream_out *other = dev->outputs[type];
938 if (other && (other != out) && !other->standby) {
939 /* safe to access other stream without a mutex,
940 * because we hold the dev lock,
941 * which prevents the other stream from being closed
942 */
943 devices |= other->device;
944 }
945 }
946
947 return devices;
948}
949
Simon Wilson459d5bd2012-08-21 12:18:07 -0700950static int do_out_standby(struct stream_out *out)
Simon Wilson15f60a82012-04-24 20:56:32 -0700951{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700952 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -0700953 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -0700954
Simon Wilson15f60a82012-04-24 20:56:32 -0700955 if (!out->standby) {
Simon Wilson56d84e22012-08-17 13:55:27 -0700956 for (i = 0; i < PCM_TOTAL; i++) {
957 if (out->pcm[i]) {
958 pcm_close(out->pcm[i]);
959 out->pcm[i] = NULL;
960 }
961 }
Simon Wilson15f60a82012-04-24 20:56:32 -0700962 out->standby = true;
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700963
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700964 if (out == adev->outputs[OUTPUT_HDMI]) {
965 /* force standby on low latency output stream so that it can reuse HDMI driver if
966 * necessary when restarted */
967 force_non_hdmi_out_standby(adev);
968 }
Glenn Kastene0aa8f32012-08-17 09:26:58 -0700969
Eric Laurentb2c0b4f2012-09-21 11:42:48 -0700970 /* re-calculate the set of active devices from other streams */
971 adev->out_device = output_devices(out);
Simon Wilson79a2e012012-10-19 14:20:33 -0700972
973 /* Skip resetting the mixer if no output device is active */
974 if (adev->out_device)
975 select_devices(adev);
Simon Wilson15f60a82012-04-24 20:56:32 -0700976 }
977
Simon Wilson459d5bd2012-08-21 12:18:07 -0700978 return 0;
979}
980
981static int out_standby(struct audio_stream *stream)
982{
983 struct stream_out *out = (struct stream_out *)stream;
984 int ret;
985
986 pthread_mutex_lock(&out->dev->lock);
987 pthread_mutex_lock(&out->lock);
988
989 ret = do_out_standby(out);
990
Simon Wilson15f60a82012-04-24 20:56:32 -0700991 pthread_mutex_unlock(&out->lock);
992 pthread_mutex_unlock(&out->dev->lock);
993
Simon Wilson459d5bd2012-08-21 12:18:07 -0700994 return ret;
Simon Wilson15f60a82012-04-24 20:56:32 -0700995}
996
997static int out_dump(const struct audio_stream *stream, int fd)
998{
999 return 0;
1000}
1001
1002static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1003{
1004 struct stream_out *out = (struct stream_out *)stream;
1005 struct audio_device *adev = out->dev;
1006 struct str_parms *parms;
1007 char value[32];
1008 int ret;
1009 unsigned int val;
1010
1011 parms = str_parms_create_str(kvpairs);
1012
1013 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1014 value, sizeof(value));
1015 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001016 pthread_mutex_lock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001017 if (ret >= 0) {
1018 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001019 if ((out->device != val) && (val != 0)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001020 /* Force standby if moving to/from SPDIF or if the output
1021 * device changes when in SPDIF mode */
1022 if (((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent6a466d72012-08-28 12:13:38 -07001023 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1024 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) {
Simon Wilson459d5bd2012-08-21 12:18:07 -07001025 do_out_standby(out);
1026 }
1027
Simon Wilsona282d2f2012-09-12 16:14:24 -07001028 /* Start/stop the BT SCO stream */
1029 if ((val & AUDIO_DEVICE_OUT_ALL_SCO) ^
1030 (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO)) {
1031 if (val & AUDIO_DEVICE_OUT_ALL_SCO)
1032 start_bt_sco(adev);
1033 else
1034 stop_bt_sco(adev);
1035 }
1036
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001037 if (!out->standby && (out == adev->outputs[OUTPUT_HDMI] ||
1038 !adev->outputs[OUTPUT_HDMI] ||
1039 adev->outputs[OUTPUT_HDMI]->standby)) {
1040 adev->out_device = output_devices(out) | val;
Eric Laurent87532032012-07-16 13:53:20 -07001041 select_devices(adev);
1042 }
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001043 out->device = val;
Simon Wilson15f60a82012-04-24 20:56:32 -07001044 }
1045 }
Eric Laurent87532032012-07-16 13:53:20 -07001046 pthread_mutex_unlock(&out->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001047 pthread_mutex_unlock(&adev->lock);
1048
1049 str_parms_destroy(parms);
1050 return ret;
1051}
1052
1053static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1054{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001055 struct stream_out *out = (struct stream_out *)stream;
1056 struct str_parms *query = str_parms_create_str(keys);
1057 char *str;
1058 char value[256];
1059 struct str_parms *reply = str_parms_create();
1060 size_t i, j;
1061 int ret;
1062 bool first = true;
1063
1064 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1065 if (ret >= 0) {
1066 value[0] = '\0';
1067 i = 0;
1068 /* the last entry in supported_channel_masks[] is always 0 */
1069 while (out->supported_channel_masks[i] != 0) {
1070 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1071 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1072 if (!first) {
1073 strcat(value, "|");
1074 }
1075 strcat(value, out_channels_name_to_enum_table[j].name);
1076 first = false;
1077 break;
1078 }
1079 }
1080 i++;
1081 }
1082 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1083 str = str_parms_to_str(reply);
1084 } else {
1085 str = strdup(keys);
1086 }
1087
1088 str_parms_destroy(query);
1089 str_parms_destroy(reply);
1090 return str;
Simon Wilson15f60a82012-04-24 20:56:32 -07001091}
1092
1093static uint32_t out_get_latency(const struct audio_stream_out *stream)
1094{
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001095 struct stream_out *out = (struct stream_out *)stream;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001096
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001097 return (out->config.period_size * out->config.period_count * 1000) /
1098 out->config.rate;
Simon Wilson15f60a82012-04-24 20:56:32 -07001099}
1100
1101static int out_set_volume(struct audio_stream_out *stream, float left,
1102 float right)
1103{
1104 return -ENOSYS;
1105}
1106
1107static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
1108 size_t bytes)
1109{
1110 int ret;
1111 struct stream_out *out = (struct stream_out *)stream;
1112 struct audio_device *adev = out->dev;
Simon Wilson56d84e22012-08-17 13:55:27 -07001113 int i;
Simon Wilson15f60a82012-04-24 20:56:32 -07001114
1115 /*
1116 * acquiring hw device mutex systematically is useful if a low
1117 * priority thread is waiting on the output stream mutex - e.g.
1118 * executing out_set_parameters() while holding the hw device
1119 * mutex
1120 */
1121 pthread_mutex_lock(&adev->lock);
1122 pthread_mutex_lock(&out->lock);
1123 if (out->standby) {
1124 ret = start_output_stream(out);
1125 if (ret != 0) {
1126 pthread_mutex_unlock(&adev->lock);
1127 goto exit;
1128 }
1129 out->standby = false;
1130 }
1131 pthread_mutex_unlock(&adev->lock);
1132
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001133 if (out->disabled) {
1134 ret = -EPIPE;
1135 goto exit;
1136 }
1137
Simon Wilson56d84e22012-08-17 13:55:27 -07001138 /* Write to all active PCMs */
1139 for (i = 0; i < PCM_TOTAL; i++)
1140 if (out->pcm[i])
1141 pcm_write(out->pcm[i], (void *)buffer, bytes);
Simon Wilson15f60a82012-04-24 20:56:32 -07001142
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001143
Simon Wilson15f60a82012-04-24 20:56:32 -07001144exit:
1145 pthread_mutex_unlock(&out->lock);
1146
1147 if (ret != 0) {
1148 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1149 out_get_sample_rate(&stream->common));
1150 }
1151
1152 return bytes;
1153}
1154
1155static int out_get_render_position(const struct audio_stream_out *stream,
1156 uint32_t *dsp_frames)
1157{
1158 return -EINVAL;
1159}
1160
1161static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1162{
1163 return 0;
1164}
1165
1166static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1167{
1168 return 0;
1169}
1170
1171static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
1172 int64_t *timestamp)
1173{
1174 return -EINVAL;
1175}
1176
1177/** audio_stream_in implementation **/
1178static uint32_t in_get_sample_rate(const struct audio_stream *stream)
1179{
1180 struct stream_in *in = (struct stream_in *)stream;
1181
1182 return in->requested_rate;
1183}
1184
1185static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1186{
1187 return 0;
1188}
1189
Eric Laurentd7abdd02012-07-27 14:54:41 -07001190static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
1191{
Eric Laurentb52afc82013-01-18 15:12:57 -08001192 struct stream_in *in = (struct stream_in *)stream;
1193
1194 return in->channel_mask;
Eric Laurentd7abdd02012-07-27 14:54:41 -07001195}
1196
1197
Simon Wilson15f60a82012-04-24 20:56:32 -07001198static size_t in_get_buffer_size(const struct audio_stream *stream)
1199{
1200 struct stream_in *in = (struct stream_in *)stream;
1201
1202 return get_input_buffer_size(in->requested_rate,
1203 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurentd7abdd02012-07-27 14:54:41 -07001204 popcount(in_get_channels(stream)));
Simon Wilson15f60a82012-04-24 20:56:32 -07001205}
1206
1207static audio_format_t in_get_format(const struct audio_stream *stream)
1208{
1209 return AUDIO_FORMAT_PCM_16_BIT;
1210}
1211
1212static int in_set_format(struct audio_stream *stream, audio_format_t format)
1213{
1214 return -ENOSYS;
1215}
1216
1217static int in_standby(struct audio_stream *stream)
1218{
1219 struct stream_in *in = (struct stream_in *)stream;
1220
1221 pthread_mutex_lock(&in->dev->lock);
1222 pthread_mutex_lock(&in->lock);
1223
1224 if (!in->standby) {
1225 pcm_close(in->pcm);
1226 in->pcm = NULL;
Eric Laurent87532032012-07-16 13:53:20 -07001227 in->dev->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001228 in->dev->in_device = AUDIO_DEVICE_NONE;
Eric Laurent87532032012-07-16 13:53:20 -07001229 select_devices(in->dev);
Simon Wilson15f60a82012-04-24 20:56:32 -07001230 in->standby = true;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001231
Eric Laurent429f24d2012-11-02 14:37:38 -07001232 if (get_bubblelevel(in->dev))
1233 in->dev->bubble_level->stop_polling(in->dev->bubble_level);
Simon Wilson15f60a82012-04-24 20:56:32 -07001234 }
1235
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001236 eS305_SetActiveIoHandle(ES305_IO_HANDLE_NONE);
1237
Simon Wilson15f60a82012-04-24 20:56:32 -07001238 pthread_mutex_unlock(&in->lock);
1239 pthread_mutex_unlock(&in->dev->lock);
1240
1241 return 0;
1242}
1243
1244static int in_dump(const struct audio_stream *stream, int fd)
1245{
1246 return 0;
1247}
1248
1249static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1250{
1251 struct stream_in *in = (struct stream_in *)stream;
1252 struct audio_device *adev = in->dev;
1253 struct str_parms *parms;
1254 char value[32];
1255 int ret;
1256 unsigned int val;
Eric Laurent87532032012-07-16 13:53:20 -07001257 bool apply_now = false;
Simon Wilson15f60a82012-04-24 20:56:32 -07001258
1259 parms = str_parms_create_str(kvpairs);
1260
Simon Wilson15f60a82012-04-24 20:56:32 -07001261 pthread_mutex_lock(&adev->lock);
Eric Laurent87532032012-07-16 13:53:20 -07001262 pthread_mutex_lock(&in->lock);
Eric Laurent42531fa2012-10-03 09:06:14 -07001263 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE,
1264 value, sizeof(value));
Simon Wilson15f60a82012-04-24 20:56:32 -07001265 if (ret >= 0) {
1266 val = atoi(value);
Eric Laurent87532032012-07-16 13:53:20 -07001267 /* no audio source uses val == 0 */
1268 if ((in->input_source != val) && (val != 0)) {
1269 in->input_source = val;
1270 apply_now = !in->standby;
Simon Wilson15f60a82012-04-24 20:56:32 -07001271 }
1272 }
Eric Laurent87532032012-07-16 13:53:20 -07001273
Eric Laurent42531fa2012-10-03 09:06:14 -07001274 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
1275 value, sizeof(value));
1276 if (ret >= 0) {
1277 val = atoi(value);
1278 /* no audio device uses val == 0 */
1279 if ((in->device != val) && (val != 0)) {
1280 in->device = val;
1281 apply_now = !in->standby;
1282 }
1283 }
1284
Eric Laurent87532032012-07-16 13:53:20 -07001285 if (apply_now) {
Eric Laurent87532032012-07-16 13:53:20 -07001286 adev->input_source = in->input_source;
Eric Laurent42531fa2012-10-03 09:06:14 -07001287 adev->in_device = in->device;
Eric Laurent87532032012-07-16 13:53:20 -07001288 select_devices(adev);
1289 }
1290
1291 pthread_mutex_unlock(&in->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001292 pthread_mutex_unlock(&adev->lock);
1293
1294 str_parms_destroy(parms);
1295 return ret;
1296}
1297
1298static char * in_get_parameters(const struct audio_stream *stream,
1299 const char *keys)
1300{
1301 return strdup("");
1302}
1303
1304static int in_set_gain(struct audio_stream_in *stream, float gain)
1305{
1306 return 0;
1307}
1308
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001309static void in_apply_ramp(struct stream_in *in, int16_t *buffer, size_t frames)
1310{
1311 size_t i;
1312 uint16_t vol = in->ramp_vol;
1313 uint16_t step = in->ramp_step;
1314
1315 frames = (frames < in->ramp_frames) ? frames : in->ramp_frames;
1316
Eric Laurentb52afc82013-01-18 15:12:57 -08001317 if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
1318 for (i = 0; i < frames; i++)
1319 {
1320 buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
1321 vol += step;
1322 }
1323 else
1324 for (i = 0; i < frames; i++)
1325 {
1326 buffer[2*i] = (int16_t)((buffer[2*i] * vol) >> 16);
1327 buffer[2*i + 1] = (int16_t)((buffer[2*i + 1] * vol) >> 16);
1328 vol += step;
1329 }
1330
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001331
1332 in->ramp_vol = vol;
1333 in->ramp_frames -= frames;
1334}
1335
Simon Wilson15f60a82012-04-24 20:56:32 -07001336static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1337 size_t bytes)
1338{
1339 int ret = 0;
1340 struct stream_in *in = (struct stream_in *)stream;
1341 struct audio_device *adev = in->dev;
1342 size_t frames_rq = bytes / audio_stream_frame_size(&stream->common);
1343
1344 /*
1345 * acquiring hw device mutex systematically is useful if a low
1346 * priority thread is waiting on the input stream mutex - e.g.
1347 * executing in_set_parameters() while holding the hw device
1348 * mutex
1349 */
1350 pthread_mutex_lock(&adev->lock);
1351 pthread_mutex_lock(&in->lock);
1352 if (in->standby) {
1353 ret = start_input_stream(in);
1354 if (ret == 0)
1355 in->standby = 0;
1356 }
1357 pthread_mutex_unlock(&adev->lock);
1358
1359 if (ret < 0)
1360 goto exit;
1361
1362 /*if (in->num_preprocessors != 0)
1363 ret = process_frames(in, buffer, frames_rq);
Eric Laurentd7abdd02012-07-27 14:54:41 -07001364 else */
1365 ret = read_frames(in, buffer, frames_rq);
Simon Wilson15f60a82012-04-24 20:56:32 -07001366
1367 if (ret > 0)
1368 ret = 0;
1369
Eric Laurent1a0c0a72012-08-24 11:29:04 -07001370 if (in->ramp_frames > 0)
1371 in_apply_ramp(in, buffer, frames_rq);
1372
Simon Wilson15f60a82012-04-24 20:56:32 -07001373 /*
1374 * Instead of writing zeroes here, we could trust the hardware
1375 * to always provide zeroes when muted.
1376 */
1377 if (ret == 0 && adev->mic_mute)
1378 memset(buffer, 0, bytes);
1379
1380exit:
1381 if (ret < 0)
1382 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1383 in_get_sample_rate(&stream->common));
1384
1385 pthread_mutex_unlock(&in->lock);
1386 return bytes;
1387}
1388
1389static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1390{
1391 return 0;
1392}
1393
1394static int in_add_audio_effect(const struct audio_stream *stream,
1395 effect_handle_t effect)
1396{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001397 struct stream_in *in = (struct stream_in *)stream;
1398 effect_descriptor_t descr;
1399 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1400
1401 pthread_mutex_lock(&in->dev->lock);
1402 pthread_mutex_lock(&in->lock);
1403
1404 eS305_AddEffect(&descr, in->io_handle);
1405
1406 pthread_mutex_unlock(&in->lock);
1407 pthread_mutex_unlock(&in->dev->lock);
1408 }
1409
Simon Wilson15f60a82012-04-24 20:56:32 -07001410 return 0;
1411}
1412
1413static int in_remove_audio_effect(const struct audio_stream *stream,
1414 effect_handle_t effect)
1415{
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001416 struct stream_in *in = (struct stream_in *)stream;
1417 effect_descriptor_t descr;
1418 if ((*effect)->get_descriptor(effect, &descr) == 0) {
1419
1420 pthread_mutex_lock(&in->dev->lock);
1421 pthread_mutex_lock(&in->lock);
1422
1423 eS305_RemoveEffect(&descr, in->io_handle);
1424
1425 pthread_mutex_unlock(&in->lock);
1426 pthread_mutex_unlock(&in->dev->lock);
1427 }
1428
Simon Wilson15f60a82012-04-24 20:56:32 -07001429 return 0;
1430}
1431
Simon Wilson15f60a82012-04-24 20:56:32 -07001432static int adev_open_output_stream(struct audio_hw_device *dev,
1433 audio_io_handle_t handle,
1434 audio_devices_t devices,
1435 audio_output_flags_t flags,
1436 struct audio_config *config,
1437 struct audio_stream_out **stream_out)
1438{
1439 struct audio_device *adev = (struct audio_device *)dev;
1440 struct stream_out *out;
1441 int ret;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001442 enum output_type type;
Simon Wilson15f60a82012-04-24 20:56:32 -07001443
1444 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
1445 if (!out)
1446 return -ENOMEM;
1447
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001448 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
1449 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
1450 if (devices == AUDIO_DEVICE_NONE)
1451 devices = AUDIO_DEVICE_OUT_SPEAKER;
1452 out->device = devices;
1453
1454 if (flags & AUDIO_OUTPUT_FLAG_DIRECT &&
1455 devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1456 pthread_mutex_lock(&adev->lock);
1457 ret = read_hdmi_channel_masks(adev, out);
1458 pthread_mutex_unlock(&adev->lock);
1459 if (ret != 0)
1460 goto err_open;
1461 if (config->sample_rate == 0)
1462 config->sample_rate = HDMI_MULTI_DEFAULT_SAMPLING_RATE;
1463 if (config->channel_mask == 0)
1464 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
1465 out->channel_mask = config->channel_mask;
1466 out->config = pcm_config_hdmi_multi;
1467 out->config.rate = config->sample_rate;
1468 out->config.channels = popcount(config->channel_mask);
1469 out->pcm_device = PCM_DEVICE;
1470 type = OUTPUT_HDMI;
1471 } else if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
1472 out->config = pcm_config_deep;
1473 out->pcm_device = PCM_DEVICE_DEEP;
1474 type = OUTPUT_DEEP_BUF;
1475 } else {
1476 out->config = pcm_config;
1477 out->pcm_device = PCM_DEVICE;
1478 type = OUTPUT_LOW_LATENCY;
1479 }
1480
Simon Wilson15f60a82012-04-24 20:56:32 -07001481 out->stream.common.get_sample_rate = out_get_sample_rate;
1482 out->stream.common.set_sample_rate = out_set_sample_rate;
1483 out->stream.common.get_buffer_size = out_get_buffer_size;
1484 out->stream.common.get_channels = out_get_channels;
1485 out->stream.common.get_format = out_get_format;
1486 out->stream.common.set_format = out_set_format;
1487 out->stream.common.standby = out_standby;
1488 out->stream.common.dump = out_dump;
1489 out->stream.common.set_parameters = out_set_parameters;
1490 out->stream.common.get_parameters = out_get_parameters;
1491 out->stream.common.add_audio_effect = out_add_audio_effect;
1492 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1493 out->stream.get_latency = out_get_latency;
1494 out->stream.set_volume = out_set_volume;
1495 out->stream.write = out_write;
1496 out->stream.get_render_position = out_get_render_position;
1497 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
1498
1499 out->dev = adev;
1500
1501 config->format = out_get_format(&out->stream.common);
1502 config->channel_mask = out_get_channels(&out->stream.common);
1503 config->sample_rate = out_get_sample_rate(&out->stream.common);
1504
1505 out->standby = true;
1506
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001507 pthread_mutex_lock(&adev->lock);
1508 if (adev->outputs[type]) {
1509 pthread_mutex_unlock(&adev->lock);
1510 ret = -EBUSY;
1511 goto err_open;
1512 }
1513 adev->outputs[type] = out;
1514 pthread_mutex_unlock(&adev->lock);
1515
Simon Wilson15f60a82012-04-24 20:56:32 -07001516 *stream_out = &out->stream;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001517
Simon Wilson15f60a82012-04-24 20:56:32 -07001518 return 0;
1519
1520err_open:
1521 free(out);
1522 *stream_out = NULL;
1523 return ret;
1524}
1525
1526static void adev_close_output_stream(struct audio_hw_device *dev,
1527 struct audio_stream_out *stream)
1528{
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001529 struct audio_device *adev;
1530 enum output_type type;
1531
Simon Wilson15f60a82012-04-24 20:56:32 -07001532 out_standby(&stream->common);
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001533 adev = (struct audio_device *)dev;
1534 pthread_mutex_lock(&adev->lock);
1535 for (type = 0; type < OUTPUT_TOTAL; ++type) {
1536 if (adev->outputs[type] == (struct stream_out *) stream) {
1537 adev->outputs[type] = NULL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001538 break;
Glenn Kastene0aa8f32012-08-17 09:26:58 -07001539 }
1540 }
1541 pthread_mutex_unlock(&adev->lock);
Simon Wilson15f60a82012-04-24 20:56:32 -07001542 free(stream);
1543}
1544
1545static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1546{
Eric Laurenta989ebf2012-10-15 15:14:44 -07001547 return 0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001548}
1549
1550static char * adev_get_parameters(const struct audio_hw_device *dev,
1551 const char *keys)
1552{
Eric Laurent688880c2012-09-07 16:46:00 -07001553 struct audio_device *adev = (struct audio_device *)dev;
1554 struct str_parms *parms = str_parms_create_str(keys);
1555 char value[32];
1556 int ret = str_parms_get_str(parms, "ec_supported", value, sizeof(value));
1557 char *str;
1558
1559 str_parms_destroy(parms);
1560 if (ret >= 0) {
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001561 parms = str_parms_create_str("ec_supported=yes");
Eric Laurent688880c2012-09-07 16:46:00 -07001562 str = str_parms_to_str(parms);
1563 str_parms_destroy(parms);
1564 return str;
1565 }
Simon Wilson15f60a82012-04-24 20:56:32 -07001566 return strdup("");
1567}
1568
1569static int adev_init_check(const struct audio_hw_device *dev)
1570{
1571 return 0;
1572}
1573
1574static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1575{
1576 return -ENOSYS;
1577}
1578
1579static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1580{
1581 return -ENOSYS;
1582}
1583
1584static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1585{
1586 return 0;
1587}
1588
1589static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1590{
1591 struct audio_device *adev = (struct audio_device *)dev;
1592
1593 adev->mic_mute = state;
1594
1595 return 0;
1596}
1597
1598static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1599{
1600 struct audio_device *adev = (struct audio_device *)dev;
1601
1602 *state = adev->mic_mute;
1603
1604 return 0;
1605}
1606
1607static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1608 const struct audio_config *config)
1609{
1610
1611 return get_input_buffer_size(config->sample_rate, config->format,
1612 popcount(config->channel_mask));
1613}
1614
1615static int adev_open_input_stream(struct audio_hw_device *dev,
1616 audio_io_handle_t handle,
1617 audio_devices_t devices,
1618 struct audio_config *config,
1619 struct audio_stream_in **stream_in)
1620{
1621 struct audio_device *adev = (struct audio_device *)dev;
1622 struct stream_in *in;
1623 int ret;
1624
1625 *stream_in = NULL;
1626
Eric Laurentd7abdd02012-07-27 14:54:41 -07001627 /* Respond with a request for mono if a different format is given. */
Eric Laurentb52afc82013-01-18 15:12:57 -08001628 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO &&
1629 config->channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK) {
Eric Laurentd7abdd02012-07-27 14:54:41 -07001630 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
Simon Wilson15f60a82012-04-24 20:56:32 -07001631 return -EINVAL;
1632 }
1633
1634 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
1635 if (!in)
1636 return -ENOMEM;
1637
1638 in->stream.common.get_sample_rate = in_get_sample_rate;
1639 in->stream.common.set_sample_rate = in_set_sample_rate;
1640 in->stream.common.get_buffer_size = in_get_buffer_size;
1641 in->stream.common.get_channels = in_get_channels;
1642 in->stream.common.get_format = in_get_format;
1643 in->stream.common.set_format = in_set_format;
1644 in->stream.common.standby = in_standby;
1645 in->stream.common.dump = in_dump;
1646 in->stream.common.set_parameters = in_set_parameters;
1647 in->stream.common.get_parameters = in_get_parameters;
1648 in->stream.common.add_audio_effect = in_add_audio_effect;
1649 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1650 in->stream.set_gain = in_set_gain;
1651 in->stream.read = in_read;
1652 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1653
1654 in->dev = adev;
1655 in->standby = true;
1656 in->requested_rate = config->sample_rate;
Eric Laurent87532032012-07-16 13:53:20 -07001657 in->input_source = AUDIO_SOURCE_DEFAULT;
Eric Laurent42531fa2012-10-03 09:06:14 -07001658 in->device = devices;
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001659 in->io_handle = handle;
Eric Laurentb52afc82013-01-18 15:12:57 -08001660 in->channel_mask = config->channel_mask;
Simon Wilson15f60a82012-04-24 20:56:32 -07001661
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001662 in->buffer = malloc(pcm_config_in.period_size * pcm_config_in.channels
Eric Laurentd7abdd02012-07-27 14:54:41 -07001663 * audio_stream_frame_size(&in->stream.common));
1664
Simon Wilson15f60a82012-04-24 20:56:32 -07001665 if (!in->buffer) {
1666 ret = -ENOMEM;
1667 goto err_malloc;
1668 }
1669
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001670 if (in->requested_rate != pcm_config_in.rate) {
Simon Wilson15f60a82012-04-24 20:56:32 -07001671 in->buf_provider.get_next_buffer = get_next_buffer;
1672 in->buf_provider.release_buffer = release_buffer;
1673
Glenn Kasten7ecf6232012-09-28 12:01:31 -07001674 ret = create_resampler(pcm_config_in.rate,
Simon Wilson15f60a82012-04-24 20:56:32 -07001675 in->requested_rate,
Eric Laurentb52afc82013-01-18 15:12:57 -08001676 popcount(in->channel_mask),
Simon Wilson15f60a82012-04-24 20:56:32 -07001677 RESAMPLER_QUALITY_DEFAULT,
1678 &in->buf_provider,
1679 &in->resampler);
1680 if (ret != 0) {
1681 ret = -EINVAL;
1682 goto err_resampler;
1683 }
1684 }
1685
1686 *stream_in = &in->stream;
1687 return 0;
1688
1689err_resampler:
1690 free(in->buffer);
1691err_malloc:
1692 free(in);
1693 return ret;
1694}
1695
1696static void adev_close_input_stream(struct audio_hw_device *dev,
1697 struct audio_stream_in *stream)
1698{
1699 struct stream_in *in = (struct stream_in *)stream;
1700
1701 in_standby(&stream->common);
1702 if (in->resampler) {
1703 release_resampler(in->resampler);
1704 in->resampler = NULL;
1705 }
1706 free(in->buffer);
1707 free(stream);
1708}
1709
1710static int adev_dump(const audio_hw_device_t *device, int fd)
1711{
1712 return 0;
1713}
1714
1715static int adev_close(hw_device_t *device)
1716{
1717 struct audio_device *adev = (struct audio_device *)device;
1718
1719 audio_route_free(adev->ar);
1720
Jean-Michel Trivie04f7c92012-09-30 16:01:41 -07001721 eS305_Release();
1722
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001723 if (adev->hdmi_drv_fd >= 0)
1724 close(adev->hdmi_drv_fd);
Eric Laurent688880c2012-09-07 16:46:00 -07001725
Eric Laurent429f24d2012-11-02 14:37:38 -07001726 if (adev->bubble_level)
1727 bubble_level_release(adev->bubble_level);
Eric Laurenta989ebf2012-10-15 15:14:44 -07001728
Simon Wilson15f60a82012-04-24 20:56:32 -07001729 free(device);
1730 return 0;
1731}
1732
Simon Wilson15f60a82012-04-24 20:56:32 -07001733static int adev_open(const hw_module_t* module, const char* name,
1734 hw_device_t** device)
1735{
1736 struct audio_device *adev;
1737 int ret;
1738
1739 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1740 return -EINVAL;
1741
1742 adev = calloc(1, sizeof(struct audio_device));
1743 if (!adev)
1744 return -ENOMEM;
1745
1746 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent6a466d72012-08-28 12:13:38 -07001747 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Simon Wilson15f60a82012-04-24 20:56:32 -07001748 adev->hw_device.common.module = (struct hw_module_t *) module;
1749 adev->hw_device.common.close = adev_close;
1750
Simon Wilson15f60a82012-04-24 20:56:32 -07001751 adev->hw_device.init_check = adev_init_check;
1752 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1753 adev->hw_device.set_master_volume = adev_set_master_volume;
1754 adev->hw_device.set_mode = adev_set_mode;
1755 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1756 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1757 adev->hw_device.set_parameters = adev_set_parameters;
1758 adev->hw_device.get_parameters = adev_get_parameters;
1759 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1760 adev->hw_device.open_output_stream = adev_open_output_stream;
1761 adev->hw_device.close_output_stream = adev_close_output_stream;
1762 adev->hw_device.open_input_stream = adev_open_input_stream;
1763 adev->hw_device.close_input_stream = adev_close_input_stream;
1764 adev->hw_device.dump = adev_dump;
1765
Simon Wilson759c6f02013-01-15 16:38:56 -08001766 adev->ar = audio_route_init(MIXER_CARD, NULL);
Eric Laurent87532032012-07-16 13:53:20 -07001767 adev->input_source = AUDIO_SOURCE_DEFAULT;
1768 /* adev->cur_route_id initial value is 0 and such that first device
1769 * selection is always applied by select_devices() */
Simon Wilson15f60a82012-04-24 20:56:32 -07001770
Eric Laurent688880c2012-09-07 16:46:00 -07001771 adev->es305_preset = ES305_PRESET_INIT;
Eric Laurenta989ebf2012-10-15 15:14:44 -07001772 adev->es305_new_mode = ES305_MODE_LEVEL;
1773 adev->es305_mode = ES305_MODE_LEVEL;
Eric Laurentb2c0b4f2012-09-21 11:42:48 -07001774 adev->hdmi_drv_fd = -1;
Simon Wilson15f60a82012-04-24 20:56:32 -07001775 *device = &adev->hw_device.common;
1776
Simon Wilson15f60a82012-04-24 20:56:32 -07001777 return 0;
1778}
1779
1780static struct hw_module_methods_t hal_module_methods = {
1781 .open = adev_open,
1782};
1783
1784struct audio_module HAL_MODULE_INFO_SYM = {
1785 .common = {
1786 .tag = HARDWARE_MODULE_TAG,
1787 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1788 .hal_api_version = HARDWARE_HAL_API_VERSION,
1789 .id = AUDIO_HARDWARE_MODULE_ID,
1790 .name = "Manta audio HW HAL",
1791 .author = "The Android Open Source Project",
1792 .methods = &hal_module_methods,
1793 },
1794};