blob: c5f18675c16ce30b8b20413f61aadbf72c84ac33 [file] [log] [blame]
Simon Wilson4a972582011-06-09 14:28:56 -07001/*
2 * Copyright (C) 2011 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"
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -070018/*#define LOG_NDEBUG 0*/
Simon Wilson4a972582011-06-09 14:28:56 -070019
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
23#include <sys/time.h>
24#include <stdlib.h>
25
26#include <cutils/log.h>
27#include <cutils/str_parms.h>
Simon Wilson512503b2011-08-30 16:29:05 -070028#include <cutils/properties.h>
Simon Wilson4a972582011-06-09 14:28:56 -070029
30#include <hardware/hardware.h>
31#include <system/audio.h>
32#include <hardware/audio.h>
33
34#include <tinyalsa/asoundlib.h>
Eric Laurentfa3998c2011-08-19 16:20:54 -070035#include <audio_utils/resampler.h>
Eric Laurent023d8052011-08-22 18:19:26 -070036#include <audio_utils/echo_reference.h>
37#include <hardware/audio_effect.h>
38#include <audio_effects/effect_aec.h>
Simon Wilson4a972582011-06-09 14:28:56 -070039
Simon Wilson1ff65912011-06-21 14:09:10 -070040#include "ril_interface.h"
41
Eric Laurent139959c2012-03-30 15:51:03 -070042
Simon Wilson4a972582011-06-09 14:28:56 -070043/* Mixer control names */
Simon Wilson41f2d8f2011-09-06 20:08:51 -070044#define MIXER_DL2_LEFT_EQUALIZER "DL2 Left Equalizer"
45#define MIXER_DL2_RIGHT_EQUALIZER "DL2 Right Equalizer"
Simon Wilson4a972582011-06-09 14:28:56 -070046#define MIXER_DL1_MEDIA_PLAYBACK_VOLUME "DL1 Media Playback Volume"
47#define MIXER_DL1_VOICE_PLAYBACK_VOLUME "DL1 Voice Playback Volume"
Eric Laurent4e7a5732012-04-13 16:58:17 -070048#define MIXER_DL1_TONES_PLAYBACK_VOLUME "DL1 Tones Playback Volume"
Simon Wilson4a972582011-06-09 14:28:56 -070049#define MIXER_DL2_MEDIA_PLAYBACK_VOLUME "DL2 Media Playback Volume"
Simon Wilson30f7fe22011-06-24 23:45:03 -070050#define MIXER_DL2_VOICE_PLAYBACK_VOLUME "DL2 Voice Playback Volume"
Eric Laurent4e7a5732012-04-13 16:58:17 -070051#define MIXER_DL2_TONES_PLAYBACK_VOLUME "DL2 Tones Playback Volume"
Simon Wilson4a972582011-06-09 14:28:56 -070052#define MIXER_SDT_DL_VOLUME "SDT DL Volume"
Simon Wilson512503b2011-08-30 16:29:05 -070053#define MIXER_SDT_UL_VOLUME "SDT UL Volume"
Simon Wilson4a972582011-06-09 14:28:56 -070054
55#define MIXER_HEADSET_PLAYBACK_VOLUME "Headset Playback Volume"
56#define MIXER_HANDSFREE_PLAYBACK_VOLUME "Handsfree Playback Volume"
57#define MIXER_EARPHONE_PLAYBACK_VOLUME "Earphone Playback Volume"
Chris Kelly50765d22011-07-14 14:52:55 -050058#define MIXER_BT_UL_VOLUME "BT UL Volume"
Simon Wilson4a972582011-06-09 14:28:56 -070059
Changoh.Heoc0854432011-10-18 17:47:48 -070060#define MIXER_DL1_EQUALIZER "DL1 Equalizer"
Simon Wilson4a972582011-06-09 14:28:56 -070061#define MIXER_DL1_MIXER_MULTIMEDIA "DL1 Mixer Multimedia"
62#define MIXER_DL1_MIXER_VOICE "DL1 Mixer Voice"
Eric Laurent4e7a5732012-04-13 16:58:17 -070063#define MIXER_DL1_MIXER_TONES "DL1 Mixer Tones"
Simon Wilson4a972582011-06-09 14:28:56 -070064#define MIXER_DL2_MIXER_MULTIMEDIA "DL2 Mixer Multimedia"
Simon Wilson30f7fe22011-06-24 23:45:03 -070065#define MIXER_DL2_MIXER_VOICE "DL2 Mixer Voice"
Eric Laurent4e7a5732012-04-13 16:58:17 -070066#define MIXER_DL2_MIXER_TONES "DL2 Mixer Tones"
Simon Wilson4a972582011-06-09 14:28:56 -070067#define MIXER_SIDETONE_MIXER_PLAYBACK "Sidetone Mixer Playback"
Simon Wilson512503b2011-08-30 16:29:05 -070068#define MIXER_SIDETONE_MIXER_CAPTURE "Sidetone Mixer Capture"
Simon Wilson47b361f2011-10-17 14:37:33 -070069#define MIXER_DL2_MONO_MIXER "DL2 Mono Mixer"
Simon Wilson4a972582011-06-09 14:28:56 -070070#define MIXER_DL1_PDM_SWITCH "DL1 PDM Switch"
Chris Kelly50765d22011-07-14 14:52:55 -050071#define MIXER_DL1_BT_VX_SWITCH "DL1 BT_VX Switch"
Simon Wilson1ff65912011-06-21 14:09:10 -070072#define MIXER_VOICE_CAPTURE_MIXER_CAPTURE "Voice Capture Mixer Capture"
Simon Wilson4a972582011-06-09 14:28:56 -070073
74#define MIXER_HS_LEFT_PLAYBACK "HS Left Playback"
75#define MIXER_HS_RIGHT_PLAYBACK "HS Right Playback"
76#define MIXER_HF_LEFT_PLAYBACK "HF Left Playback"
77#define MIXER_HF_RIGHT_PLAYBACK "HF Right Playback"
Simon Wilsone9ab0812011-09-19 17:22:01 -070078#define MIXER_EARPHONE_ENABLE_SWITCH "Earphone Enable Switch"
Simon Wilson4a972582011-06-09 14:28:56 -070079
80#define MIXER_ANALOG_LEFT_CAPTURE_ROUTE "Analog Left Capture Route"
Simon Wilson1ff65912011-06-21 14:09:10 -070081#define MIXER_ANALOG_RIGHT_CAPTURE_ROUTE "Analog Right Capture Route"
Simon Wilson4a972582011-06-09 14:28:56 -070082#define MIXER_CAPTURE_PREAMPLIFIER_VOLUME "Capture Preamplifier Volume"
83#define MIXER_CAPTURE_VOLUME "Capture Volume"
84#define MIXER_AMIC_UL_VOLUME "AMIC UL Volume"
85#define MIXER_AUDUL_VOICE_UL_VOLUME "AUDUL Voice UL Volume"
Simon Wilson1ff65912011-06-21 14:09:10 -070086#define MIXER_MUX_VX0 "MUX_VX0"
87#define MIXER_MUX_VX1 "MUX_VX1"
Eric Laurentdf6ed252011-07-14 15:26:25 -070088#define MIXER_MUX_UL10 "MUX_UL10"
Chris Kelly50765d22011-07-14 14:52:55 -050089#define MIXER_MUX_UL11 "MUX_UL11"
Simon Wilson4a972582011-06-09 14:28:56 -070090
91/* Mixer control gain and route values */
92#define MIXER_ABE_GAIN_0DB 120
Simon Wilson4a972582011-06-09 14:28:56 -070093#define MIXER_PLAYBACK_HS_DAC "HS DAC"
94#define MIXER_PLAYBACK_HF_DAC "HF DAC"
95#define MIXER_MAIN_MIC "Main Mic"
Simon Wilson1ff65912011-06-21 14:09:10 -070096#define MIXER_SUB_MIC "Sub Mic"
Chris Kelly9ce8ae72011-07-18 19:11:58 -050097#define MIXER_HS_MIC "Headset Mic"
Simon Wilson1ff65912011-06-21 14:09:10 -070098#define MIXER_AMIC0 "AMic0"
99#define MIXER_AMIC1 "AMic1"
Chris Kelly9ce8ae72011-07-18 19:11:58 -0500100#define MIXER_BT_LEFT "BT Left"
101#define MIXER_BT_RIGHT "BT Right"
Simon Wilson41f2d8f2011-09-06 20:08:51 -0700102#define MIXER_450HZ_HIGH_PASS "450Hz High-pass"
Changoh.Heoc0854432011-10-18 17:47:48 -0700103#define MIXER_FLAT_RESPONSE "Flat response"
104#define MIXER_4KHZ_LPF_0DB "4Khz LPF 0dB"
Simon Wilson4a972582011-06-09 14:28:56 -0700105
Eric Laurent4bf3d142012-04-30 12:30:50 -0700106/* HDMI mixer controls */
107#define MIXER_MAXIMUM_LPCM_CHANNELS "Maximum LPCM channels"
108
Eric Laurent1829c462011-09-16 16:54:45 -0700109
110/* ALSA cards for OMAP4 */
111#define CARD_OMAP4_ABE 0
112#define CARD_OMAP4_HDMI 1
113#define CARD_TUNA_DEFAULT CARD_OMAP4_ABE
114
Simon Wilson4a972582011-06-09 14:28:56 -0700115/* ALSA ports for OMAP4 */
116#define PORT_MM 0
117#define PORT_MM2_UL 1
118#define PORT_VX 2
119#define PORT_TONES 3
120#define PORT_VIBRA 4
121#define PORT_MODEM 5
Chris Kelly5b707b22011-07-19 15:33:07 -0500122#define PORT_MM_LP 6
Simon Wilsoncc4b5c92011-09-27 12:20:23 -0700123#define PORT_SPDIF 9
124#define PORT_HDMI 0
Simon Wilson4a972582011-06-09 14:28:56 -0700125
Glenn Kasten47623d42012-02-14 13:54:03 -0800126/* User serviceable */
127/* #define to use mmap no-irq mode for playback, #undef for non-mmap irq mode */
128#undef PLAYBACK_MMAP // was #define
129/* short period (aka low latency) in milliseconds */
Glenn Kasten559a9422012-08-07 15:31:20 -0700130#define SHORT_PERIOD_MS 3 // was 22
Eric Laurent359a4162012-05-11 09:17:27 -0700131/* deep buffer short period (screen on) in milliseconds */
132#define DEEP_BUFFER_SHORT_PERIOD_MS 22
133/* deep buffer long period (screen off) in milliseconds */
134#define DEEP_BUFFER_LONG_PERIOD_MS 308
Glenn Kasten47623d42012-02-14 13:54:03 -0800135
136/* Constraint imposed by ABE: for playback, all period sizes must be multiples of 24 frames
137 * = 500 us at 48 kHz. It seems to be either 48 or 96 for capture, or maybe it is because the
138 * limitation is actually a min number of bytes which translates to a different amount of frames
139 * according to the number of channels.
140 */
Eric Laurent753a1242011-10-13 08:46:22 -0700141#define ABE_BASE_FRAME_COUNT 24
Glenn Kasten47623d42012-02-14 13:54:03 -0800142
143/* Derived from MM_FULL_POWER_SAMPLING_RATE=48000 and ABE_BASE_FRAME_COUNT=24 */
144#define MULTIPLIER_FACTOR 2
145
Eric Laurent753a1242011-10-13 08:46:22 -0700146/* number of base blocks in a short period (low latency) */
Glenn Kasten47623d42012-02-14 13:54:03 -0800147#define SHORT_PERIOD_MULTIPLIER (SHORT_PERIOD_MS * MULTIPLIER_FACTOR)
Eric Laurent753a1242011-10-13 08:46:22 -0700148/* number of frames per short period (low latency) */
149#define SHORT_PERIOD_SIZE (ABE_BASE_FRAME_COUNT * SHORT_PERIOD_MULTIPLIER)
Glenn Kasten47623d42012-02-14 13:54:03 -0800150
Eric Laurent359a4162012-05-11 09:17:27 -0700151/* number of base blocks in a short deep buffer period (screen on) */
152#define DEEP_BUFFER_SHORT_PERIOD_MULTIPLIER (DEEP_BUFFER_SHORT_PERIOD_MS * MULTIPLIER_FACTOR)
153/* number of frames per short deep buffer period (screen on) */
154#define DEEP_BUFFER_SHORT_PERIOD_SIZE (ABE_BASE_FRAME_COUNT * DEEP_BUFFER_SHORT_PERIOD_MULTIPLIER)
155/* number of periods for deep buffer playback (screen on) */
156#define PLAYBACK_DEEP_BUFFER_SHORT_PERIOD_COUNT 4
157
158/* number of short deep buffer periods in a long period */
159#define DEEP_BUFFER_LONG_PERIOD_MULTIPLIER \
160 (DEEP_BUFFER_LONG_PERIOD_MS / DEEP_BUFFER_SHORT_PERIOD_MS)
161/* number of frames per long deep buffer period (screen off) */
162#define DEEP_BUFFER_LONG_PERIOD_SIZE \
163 (DEEP_BUFFER_SHORT_PERIOD_SIZE * DEEP_BUFFER_LONG_PERIOD_MULTIPLIER)
164/* number of periods for deep buffer playback (screen off) */
165#define PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT 2
166
Eric Laurent4bf3d142012-04-30 12:30:50 -0700167/* number of frames per period for HDMI multichannel output */
168#define HDMI_MULTI_PERIOD_SIZE 1024
169/* number of periods for HDMI multichannel output */
170#define HDMI_MULTI_PERIOD_COUNT 4
171/* default number of channels for HDMI multichannel output */
172#define HDMI_MULTI_DEFAULT_CHANNEL_COUNT 6
173
Glenn Kasten47623d42012-02-14 13:54:03 -0800174/* Number of pseudo periods for low latency playback.
175 * These are called "pseudo" periods in that they are not known as periods by ALSA.
176 * Formerly, ALSA was configured in MMAP mode with 2 large periods, and this
177 * number was set to 4 (2 didn't work).
178 * The short periods size and count were only known by the audio HAL.
179 * Now for low latency, we are using non-MMAP mode and can set this to 2.
180 */
181#ifdef PLAYBACK_MMAP
Eric Laurenta4a40e02011-10-19 22:09:43 -0700182#define PLAYBACK_SHORT_PERIOD_COUNT 4
Glenn Kasten8bf9bea2012-08-07 14:10:40 -0700183/* If sample rate converter is required, then use triple-buffering to
184 * help mask the variance in cycle times. Otherwise use double-buffering.
185 */
186#elif DEFAULT_OUT_SAMPLING_RATE != MM_FULL_POWER_SAMPLING_RATE
187#define PLAYBACK_SHORT_PERIOD_COUNT 3
Glenn Kasten47623d42012-02-14 13:54:03 -0800188#else
189#define PLAYBACK_SHORT_PERIOD_COUNT 2
190#endif
191
192/* write function */
193#ifdef PLAYBACK_MMAP
194#define PCM_WRITE pcm_mmap_write
195#else
196#define PCM_WRITE pcm_write
197#endif
198
199/* User serviceable */
200#define CAPTURE_PERIOD_MS 22
201
202/* Number of frames per period for capture. This cannot be reduced below 96.
203 * Possibly related to the following rule in sound/soc/omap/omap-pcm.c:
204 * ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 384);
205 * (where 96 * 4 = 384)
206 * The only constraints I can find are periods_min = 2, period_bytes_min = 32.
207 * If you define RULES_DEBUG in sound/core/pcm_native.c, you can see which rule
208 * caused capture to fail.
209 * Decoupling playback and capture period size may have impacts on echo canceler behavior:
210 * to be verified. Currently 96 = 4 x 24 but it could be changed without noticing
211 * if we use separate defines.
212 */
213#define CAPTURE_PERIOD_SIZE (ABE_BASE_FRAME_COUNT * CAPTURE_PERIOD_MS * MULTIPLIER_FACTOR)
Eric Laurent753a1242011-10-13 08:46:22 -0700214/* number of periods for capture */
215#define CAPTURE_PERIOD_COUNT 2
216/* minimum sleep time in out_write() when write threshold is not reached */
217#define MIN_WRITE_SLEEP_US 5000
218
Glenn Kasten47623d42012-02-14 13:54:03 -0800219#define DEFAULT_OUT_SAMPLING_RATE 44100 // 48000 is possible but interacts poorly with HDMI
Eric Laurent371599a2011-07-08 17:16:43 -0700220
Eric Laurent023d8052011-08-22 18:19:26 -0700221/* sampling rate when using MM low power port */
222#define MM_LOW_POWER_SAMPLING_RATE 44100
223/* sampling rate when using MM full power port */
Glenn Kasten47623d42012-02-14 13:54:03 -0800224#define MM_FULL_POWER_SAMPLING_RATE 48000 // affects MULTIPLIER_FACTOR
Eric Laurent023d8052011-08-22 18:19:26 -0700225/* sampling rate when using VX port for narrow band */
226#define VX_NB_SAMPLING_RATE 8000
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700227/* sampling rate when using VX port for wide band */
228#define VX_WB_SAMPLING_RATE 16000
Eric Laurent023d8052011-08-22 18:19:26 -0700229
Simon Wilson2b45e732011-08-22 16:49:03 -0700230/* conversions from dB to ABE and codec gains */
231#define DB_TO_ABE_GAIN(x) ((x) + MIXER_ABE_GAIN_0DB)
232#define DB_TO_CAPTURE_PREAMPLIFIER_VOLUME(x) (((x) + 6) / 6)
233#define DB_TO_CAPTURE_VOLUME(x) (((x) - 6) / 6)
Simon Wilsonaa711b02011-09-02 14:46:34 -0700234#define DB_TO_HEADSET_VOLUME(x) (((x) + 30) / 2)
235#define DB_TO_SPEAKER_VOLUME(x) (((x) + 52) / 2)
236#define DB_TO_EARPIECE_VOLUME(x) (((x) + 24) / 2)
Simon Wilson2b45e732011-08-22 16:49:03 -0700237
Simon Wilson1c2783a2011-10-18 23:25:25 -0700238/* conversions from codec and ABE gains to dB */
239#define DB_FROM_SPEAKER_VOLUME(x) ((x) * 2 - 52)
240
Simon Wilson903131d2011-09-21 15:46:02 -0700241/* use-case specific mic volumes, all in dB */
Simon Wilson1c2783a2011-10-18 23:25:25 -0700242#define CAPTURE_MAIN_MIC_VOLUME 16
Simon Wilson2b45e732011-08-22 16:49:03 -0700243#define CAPTURE_SUB_MIC_VOLUME 18
244#define CAPTURE_HEADSET_MIC_VOLUME 12
245
Jean-Michel Trivie967f722011-09-07 17:07:07 -0700246#define VOICE_RECOGNITION_MAIN_MIC_VOLUME 5
Simon Wilson2b45e732011-08-22 16:49:03 -0700247#define VOICE_RECOGNITION_SUB_MIC_VOLUME 18
Jean-Michel Trivie967f722011-09-07 17:07:07 -0700248#define VOICE_RECOGNITION_HEADSET_MIC_VOLUME 14
Simon Wilson2b45e732011-08-22 16:49:03 -0700249
250#define CAMCORDER_MAIN_MIC_VOLUME 13
Simon Wilson1c2783a2011-10-18 23:25:25 -0700251#define CAMCORDER_SUB_MIC_VOLUME 10
Simon Wilson2b45e732011-08-22 16:49:03 -0700252#define CAMCORDER_HEADSET_MIC_VOLUME 12
253
Eric Laurent023d8052011-08-22 18:19:26 -0700254#define VOIP_MAIN_MIC_VOLUME 13
255#define VOIP_SUB_MIC_VOLUME 20
Simon Wilson2b45e732011-08-22 16:49:03 -0700256#define VOIP_HEADSET_MIC_VOLUME 12
257
258#define VOICE_CALL_MAIN_MIC_VOLUME 0
Simon Wilson903131d2011-09-21 15:46:02 -0700259#define VOICE_CALL_SUB_MIC_VOLUME_MAGURO -4
260#define VOICE_CALL_SUB_MIC_VOLUME_TORO -2
Simon Wilson2b45e732011-08-22 16:49:03 -0700261#define VOICE_CALL_HEADSET_MIC_VOLUME 8
262
Simon Wilson903131d2011-09-21 15:46:02 -0700263/* use-case specific output volumes */
Simon Wilsona33a8e12012-09-18 14:32:01 -0700264#define NORMAL_SPEAKER_VOLUME_TORO 6
Simon Wilson1c2783a2011-10-18 23:25:25 -0700265#define NORMAL_SPEAKER_VOLUME_MAGURO 2
266#define NORMAL_HEADSET_VOLUME_TORO -12
267#define NORMAL_HEADSET_VOLUME_MAGURO -12
268#define NORMAL_HEADPHONE_VOLUME_TORO -6 /* allow louder output for headphones */
269#define NORMAL_HEADPHONE_VOLUME_MAGURO -6
270#define NORMAL_EARPIECE_VOLUME_TORO -2
271#define NORMAL_EARPIECE_VOLUME_MAGURO -2
Simon Wilson903131d2011-09-21 15:46:02 -0700272
Simon Wilson1c2783a2011-10-18 23:25:25 -0700273#define VOICE_CALL_SPEAKER_VOLUME_TORO 9
274#define VOICE_CALL_SPEAKER_VOLUME_MAGURO 6
275#define VOICE_CALL_HEADSET_VOLUME_TORO -6
276#define VOICE_CALL_HEADSET_VOLUME_MAGURO 0
277#define VOICE_CALL_EARPIECE_VOLUME_TORO 2
278#define VOICE_CALL_EARPIECE_VOLUME_MAGURO 6
279
280#define VOIP_SPEAKER_VOLUME_TORO 9
281#define VOIP_SPEAKER_VOLUME_MAGURO 7
282#define VOIP_HEADSET_VOLUME_TORO -6
283#define VOIP_HEADSET_VOLUME_MAGURO -6
284#define VOIP_EARPIECE_VOLUME_TORO 6
285#define VOIP_EARPIECE_VOLUME_MAGURO 6
286
Eric Laurent22eabce2011-10-06 15:46:25 -0700287#define HEADPHONE_VOLUME_TTY -2
UK KIMe6f399a2011-10-26 21:41:31 +0900288#define RINGTONE_HEADSET_VOLUME_OFFSET -14
Simon Wilson19675852011-09-30 14:31:48 -0700289
Simon Wilson512503b2011-08-30 16:29:05 -0700290/* product-specific defines */
291#define PRODUCT_DEVICE_PROPERTY "ro.product.device"
Eric Laurenta100f7d2011-09-28 19:10:01 -0700292#define PRODUCT_NAME_PROPERTY "ro.product.name"
Simon Wilson903131d2011-09-21 15:46:02 -0700293#define PRODUCT_DEVICE_TORO "toro"
Eric Laurenta100f7d2011-09-28 19:10:01 -0700294#define PRODUCT_NAME_YAKJU "yakju"
Simon Wilson512503b2011-08-30 16:29:05 -0700295
Eric Laurent4bf3d142012-04-30 12:30:50 -0700296#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
297
Eric Laurent8bbd2d22011-08-07 09:57:42 -0700298enum tty_modes {
299 TTY_MODE_OFF,
300 TTY_MODE_VCO,
301 TTY_MODE_HCO,
302 TTY_MODE_FULL
303};
304
Glenn Kasten8bf9bea2012-08-07 14:10:40 -0700305/* deep buffer */
Simon Wilson4a972582011-06-09 14:28:56 -0700306struct pcm_config pcm_config_mm = {
307 .channels = 2,
Eric Laurent023d8052011-08-22 18:19:26 -0700308 .rate = MM_FULL_POWER_SAMPLING_RATE,
Eric Laurent359a4162012-05-11 09:17:27 -0700309 .period_size = DEEP_BUFFER_LONG_PERIOD_SIZE,
310 .period_count = PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT,
Eric Laurent4e7a5732012-04-13 16:58:17 -0700311 .format = PCM_FORMAT_S16_LE,
Eric Laurent359a4162012-05-11 09:17:27 -0700312 .start_threshold = DEEP_BUFFER_SHORT_PERIOD_SIZE * 2,
313 .avail_min = DEEP_BUFFER_LONG_PERIOD_SIZE,
Eric Laurent4e7a5732012-04-13 16:58:17 -0700314};
315
Glenn Kasten8bf9bea2012-08-07 14:10:40 -0700316/* low latency */
Eric Laurent4e7a5732012-04-13 16:58:17 -0700317struct pcm_config pcm_config_tones = {
318 .channels = 2,
319 .rate = MM_FULL_POWER_SAMPLING_RATE,
Glenn Kasten47623d42012-02-14 13:54:03 -0800320 .period_size = SHORT_PERIOD_SIZE,
321 .period_count = PLAYBACK_SHORT_PERIOD_COUNT,
Simon Wilson4a972582011-06-09 14:28:56 -0700322 .format = PCM_FORMAT_S16_LE,
Glenn Kasten47623d42012-02-14 13:54:03 -0800323#ifdef PLAYBACK_MMAP
Eric Laurent4e7a5732012-04-13 16:58:17 -0700324 .start_threshold = SHORT_PERIOD_SIZE,
325 .avail_min = SHORT_PERIOD_SIZE,
Glenn Kasten47623d42012-02-14 13:54:03 -0800326#else
327 .start_threshold = 0,
328 .avail_min = 0,
329#endif
Simon Wilson4a972582011-06-09 14:28:56 -0700330};
331
Eric Laurent4bf3d142012-04-30 12:30:50 -0700332struct pcm_config pcm_config_hdmi_multi = {
333 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
334 .rate = MM_FULL_POWER_SAMPLING_RATE, /* changed when the stream is opened */
335 .period_size = HDMI_MULTI_PERIOD_SIZE,
336 .period_count = HDMI_MULTI_PERIOD_COUNT,
337 .format = PCM_FORMAT_S16_LE,
338 .start_threshold = 0,
339 .avail_min = 0,
340};
341
Simon Wilson79095f92011-09-06 14:59:51 -0700342struct pcm_config pcm_config_mm_ul = {
343 .channels = 2,
344 .rate = MM_FULL_POWER_SAMPLING_RATE,
Glenn Kasten47623d42012-02-14 13:54:03 -0800345 .period_size = CAPTURE_PERIOD_SIZE,
Eric Laurent753a1242011-10-13 08:46:22 -0700346 .period_count = CAPTURE_PERIOD_COUNT,
Simon Wilson79095f92011-09-06 14:59:51 -0700347 .format = PCM_FORMAT_S16_LE,
348};
349
Simon Wilson4a972582011-06-09 14:28:56 -0700350struct pcm_config pcm_config_vx = {
Simon Wilson3437a822011-09-09 14:46:28 -0700351 .channels = 2,
Eric Laurent023d8052011-08-22 18:19:26 -0700352 .rate = VX_NB_SAMPLING_RATE,
Simon Wilson1bf73172011-06-27 15:45:08 -0700353 .period_size = 160,
Simon Wilson4a972582011-06-09 14:28:56 -0700354 .period_count = 2,
355 .format = PCM_FORMAT_S16_LE,
356};
357
358#define MIN(x, y) ((x) > (y) ? (y) : (x))
359
360struct route_setting
361{
362 char *ctl_name;
363 int intval;
364 char *strval;
365};
366
Simon Wilson30f7fe22011-06-24 23:45:03 -0700367/* These are values that never change */
368struct route_setting defaults[] = {
369 /* general */
370 {
Simon Wilson41f2d8f2011-09-06 20:08:51 -0700371 .ctl_name = MIXER_DL2_LEFT_EQUALIZER,
372 .strval = MIXER_450HZ_HIGH_PASS,
373 },
374 {
375 .ctl_name = MIXER_DL2_RIGHT_EQUALIZER,
376 .strval = MIXER_450HZ_HIGH_PASS,
377 },
378 {
Simon Wilson30f7fe22011-06-24 23:45:03 -0700379 .ctl_name = MIXER_DL1_MEDIA_PLAYBACK_VOLUME,
Simon Wilsone522d0e2011-08-03 11:23:38 -0700380 .intval = MIXER_ABE_GAIN_0DB,
Simon Wilson30f7fe22011-06-24 23:45:03 -0700381 },
Simon Wilson4a972582011-06-09 14:28:56 -0700382 {
383 .ctl_name = MIXER_DL2_MEDIA_PLAYBACK_VOLUME,
Simon Wilsonaa711b02011-09-02 14:46:34 -0700384 .intval = MIXER_ABE_GAIN_0DB,
Simon Wilson4a972582011-06-09 14:28:56 -0700385 },
386 {
Simon Wilson30f7fe22011-06-24 23:45:03 -0700387 .ctl_name = MIXER_DL1_VOICE_PLAYBACK_VOLUME,
Simon Wilsone522d0e2011-08-03 11:23:38 -0700388 .intval = MIXER_ABE_GAIN_0DB,
Simon Wilson30f7fe22011-06-24 23:45:03 -0700389 },
390 {
391 .ctl_name = MIXER_DL2_VOICE_PLAYBACK_VOLUME,
Simon Wilsonaa711b02011-09-02 14:46:34 -0700392 .intval = MIXER_ABE_GAIN_0DB,
Simon Wilson30f7fe22011-06-24 23:45:03 -0700393 },
394 {
Eric Laurent4e7a5732012-04-13 16:58:17 -0700395 .ctl_name = MIXER_DL1_TONES_PLAYBACK_VOLUME,
396 .intval = MIXER_ABE_GAIN_0DB,
397 },
398 {
399 .ctl_name = MIXER_DL2_TONES_PLAYBACK_VOLUME,
400 .intval = MIXER_ABE_GAIN_0DB,
401 },
402 {
Simon Wilson30f7fe22011-06-24 23:45:03 -0700403 .ctl_name = MIXER_SDT_DL_VOLUME,
404 .intval = MIXER_ABE_GAIN_0DB,
405 },
406 {
Simon Wilson1ff65912011-06-21 14:09:10 -0700407 .ctl_name = MIXER_AUDUL_VOICE_UL_VOLUME,
Simon Wilson30f7fe22011-06-24 23:45:03 -0700408 .intval = MIXER_ABE_GAIN_0DB,
Simon Wilson1ff65912011-06-21 14:09:10 -0700409 },
410 {
Simon Wilson4a972582011-06-09 14:28:56 -0700411 .ctl_name = MIXER_CAPTURE_PREAMPLIFIER_VOLUME,
Simon Wilson2b45e732011-08-22 16:49:03 -0700412 .intval = DB_TO_CAPTURE_PREAMPLIFIER_VOLUME(0),
Simon Wilson4a972582011-06-09 14:28:56 -0700413 },
414 {
415 .ctl_name = MIXER_CAPTURE_VOLUME,
Simon Wilson2b45e732011-08-22 16:49:03 -0700416 .intval = DB_TO_CAPTURE_VOLUME(30),
Simon Wilson4a972582011-06-09 14:28:56 -0700417 },
Simon Wilson512503b2011-08-30 16:29:05 -0700418 {
419 .ctl_name = MIXER_SDT_UL_VOLUME,
Simon Wilson19675852011-09-30 14:31:48 -0700420 .intval = MIXER_ABE_GAIN_0DB - 17,
Simon Wilson512503b2011-08-30 16:29:05 -0700421 },
422 {
423 .ctl_name = MIXER_SIDETONE_MIXER_CAPTURE,
424 .intval = 0,
425 },
Simon Wilsonb1695f82011-07-21 14:58:26 -0700426
Simon Wilson04b38f92011-07-22 16:42:17 -0700427 /* headset */
428 {
429 .ctl_name = MIXER_SIDETONE_MIXER_PLAYBACK,
430 .intval = 1,
431 },
432 {
433 .ctl_name = MIXER_DL1_PDM_SWITCH,
434 .intval = 1,
435 },
Simon Wilson03d3caa2011-08-26 15:06:32 -0700436
437 /* bt */
438 {
439 .ctl_name = MIXER_BT_UL_VOLUME,
440 .intval = MIXER_ABE_GAIN_0DB,
441 },
442 {
443 .ctl_name = NULL,
444 },
445};
446
447struct route_setting hf_output[] = {
448 {
449 .ctl_name = MIXER_HF_LEFT_PLAYBACK,
450 .strval = MIXER_PLAYBACK_HF_DAC,
451 },
452 {
453 .ctl_name = MIXER_HF_RIGHT_PLAYBACK,
454 .strval = MIXER_PLAYBACK_HF_DAC,
455 },
456 {
457 .ctl_name = NULL,
458 },
459};
460
461struct route_setting hs_output[] = {
Simon Wilson30f7fe22011-06-24 23:45:03 -0700462 {
463 .ctl_name = MIXER_HS_LEFT_PLAYBACK,
464 .strval = MIXER_PLAYBACK_HS_DAC,
465 },
466 {
467 .ctl_name = MIXER_HS_RIGHT_PLAYBACK,
468 .strval = MIXER_PLAYBACK_HS_DAC,
469 },
Simon Wilson4a972582011-06-09 14:28:56 -0700470 {
471 .ctl_name = NULL,
472 },
473};
474
Chris Kelly50765d22011-07-14 14:52:55 -0500475/* MM UL front-end paths */
476struct route_setting mm_ul2_bt[] = {
477 {
478 .ctl_name = MIXER_MUX_UL10,
479 .strval = MIXER_BT_LEFT,
480 },
481 {
482 .ctl_name = MIXER_MUX_UL11,
Simon Wilsonfc510062011-09-15 20:21:52 -0700483 .strval = MIXER_BT_LEFT,
Chris Kelly50765d22011-07-14 14:52:55 -0500484 },
485 {
486 .ctl_name = NULL,
487 },
488};
489
Simon Wilson50dbfee2011-09-20 18:52:27 -0700490struct route_setting mm_ul2_amic_left[] = {
Chris Kelly50765d22011-07-14 14:52:55 -0500491 {
492 .ctl_name = MIXER_MUX_UL10,
493 .strval = MIXER_AMIC0,
494 },
495 {
496 .ctl_name = MIXER_MUX_UL11,
Simon Wilsonfc510062011-09-15 20:21:52 -0700497 .strval = MIXER_AMIC0,
Chris Kelly50765d22011-07-14 14:52:55 -0500498 },
499 {
500 .ctl_name = NULL,
501 },
502};
503
Simon Wilson50dbfee2011-09-20 18:52:27 -0700504struct route_setting mm_ul2_amic_right[] = {
505 {
506 .ctl_name = MIXER_MUX_UL10,
507 .strval = MIXER_AMIC1,
508 },
509 {
510 .ctl_name = MIXER_MUX_UL11,
511 .strval = MIXER_AMIC1,
512 },
513 {
514 .ctl_name = NULL,
515 },
516};
517
Eric Laurent139959c2012-03-30 15:51:03 -0700518/* dual mic configuration with main mic on main channel and sub mic on aux channel.
519 * Used for handset mode (near talk) */
520struct route_setting mm_ul2_amic_dual_main_sub[] = {
521 {
522 .ctl_name = MIXER_MUX_UL10,
523 .strval = MIXER_AMIC0,
524 },
525 {
526 .ctl_name = MIXER_MUX_UL11,
527 .strval = MIXER_AMIC1,
528 },
529 {
530 .ctl_name = NULL,
531 },
532};
533
534/* dual mic configuration with sub mic on main channel and main mic on aux channel.
535 * Used for speakerphone mode (far talk) */
536struct route_setting mm_ul2_amic_dual_sub_main[] = {
537 {
538 .ctl_name = MIXER_MUX_UL10,
539 .strval = MIXER_AMIC1,
540 },
541 {
542 .ctl_name = MIXER_MUX_UL11,
543 .strval = MIXER_AMIC0,
544 },
545 {
546 .ctl_name = NULL,
547 },
548};
549
Chris Kelly50765d22011-07-14 14:52:55 -0500550/* VX UL front-end paths */
Simon Wilson975e9152011-08-08 16:15:45 -0700551struct route_setting vx_ul_amic_left[] = {
Simon Wilson30f7fe22011-06-24 23:45:03 -0700552 {
553 .ctl_name = MIXER_MUX_VX0,
554 .strval = MIXER_AMIC0,
555 },
556 {
Chris Kelly50765d22011-07-14 14:52:55 -0500557 .ctl_name = MIXER_MUX_VX1,
Simon Wilsonfc510062011-09-15 20:21:52 -0700558 .strval = MIXER_AMIC0,
Chris Kelly50765d22011-07-14 14:52:55 -0500559 },
560 {
Simon Wilson30f7fe22011-06-24 23:45:03 -0700561 .ctl_name = MIXER_VOICE_CAPTURE_MIXER_CAPTURE,
562 .intval = 1,
563 },
564 {
Simon Wilson4a972582011-06-09 14:28:56 -0700565 .ctl_name = NULL,
566 },
567};
568
Simon Wilson975e9152011-08-08 16:15:45 -0700569struct route_setting vx_ul_amic_right[] = {
570 {
571 .ctl_name = MIXER_MUX_VX0,
572 .strval = MIXER_AMIC1,
573 },
574 {
575 .ctl_name = MIXER_MUX_VX1,
Simon Wilsonfc510062011-09-15 20:21:52 -0700576 .strval = MIXER_AMIC1,
Simon Wilson975e9152011-08-08 16:15:45 -0700577 },
578 {
579 .ctl_name = MIXER_VOICE_CAPTURE_MIXER_CAPTURE,
580 .intval = 1,
581 },
582 {
583 .ctl_name = NULL,
584 },
585};
586
Chris Kelly50765d22011-07-14 14:52:55 -0500587struct route_setting vx_ul_bt[] = {
Eric Laurentdf6ed252011-07-14 15:26:25 -0700588 {
Chris Kelly50765d22011-07-14 14:52:55 -0500589 .ctl_name = MIXER_MUX_VX0,
590 .strval = MIXER_BT_LEFT,
Eric Laurentdf6ed252011-07-14 15:26:25 -0700591 },
592 {
Chris Kelly50765d22011-07-14 14:52:55 -0500593 .ctl_name = MIXER_MUX_VX1,
Simon Wilsonfc510062011-09-15 20:21:52 -0700594 .strval = MIXER_BT_LEFT,
Chris Kelly50765d22011-07-14 14:52:55 -0500595 },
596 {
597 .ctl_name = MIXER_VOICE_CAPTURE_MIXER_CAPTURE,
598 .intval = 1,
Eric Laurentdf6ed252011-07-14 15:26:25 -0700599 },
600 {
601 .ctl_name = NULL,
602 },
603};
604
Simon Wilsone18d87d2011-07-12 15:52:45 -0700605struct mixer_ctls
606{
Changoh.Heoc0854432011-10-18 17:47:48 -0700607 struct mixer_ctl *dl1_eq;
Eric Laurentd6cc09e2012-05-08 09:31:34 -0700608 struct mixer_ctl *mm_dl1_volume;
609 struct mixer_ctl *tones_dl1_volume;
Simon Wilson1c2783a2011-10-18 23:25:25 -0700610 struct mixer_ctl *mm_dl2_volume;
611 struct mixer_ctl *vx_dl2_volume;
Eric Laurentd6cc09e2012-05-08 09:31:34 -0700612 struct mixer_ctl *tones_dl2_volume;
Chris Kelly50765d22011-07-14 14:52:55 -0500613 struct mixer_ctl *mm_dl1;
614 struct mixer_ctl *mm_dl2;
615 struct mixer_ctl *vx_dl1;
616 struct mixer_ctl *vx_dl2;
Eric Laurent4e7a5732012-04-13 16:58:17 -0700617 struct mixer_ctl *tones_dl1;
618 struct mixer_ctl *tones_dl2;
Simon Wilsone9ab0812011-09-19 17:22:01 -0700619 struct mixer_ctl *earpiece_enable;
Simon Wilson431112d2011-10-20 10:32:27 -0700620 struct mixer_ctl *dl2_mono;
Chris Kelly50765d22011-07-14 14:52:55 -0500621 struct mixer_ctl *dl1_headset;
622 struct mixer_ctl *dl1_bt;
623 struct mixer_ctl *left_capture;
624 struct mixer_ctl *right_capture;
Simon Wilson2b45e732011-08-22 16:49:03 -0700625 struct mixer_ctl *amic_ul_volume;
venkappa malaa3799ff2011-10-06 21:16:42 -0700626 struct mixer_ctl *voice_ul_volume;
Simon Wilson512503b2011-08-30 16:29:05 -0700627 struct mixer_ctl *sidetone_capture;
Simon Wilson903131d2011-09-21 15:46:02 -0700628 struct mixer_ctl *headset_volume;
629 struct mixer_ctl *speaker_volume;
Simon Wilson19675852011-09-30 14:31:48 -0700630 struct mixer_ctl *earpiece_volume;
Simon Wilsone18d87d2011-07-12 15:52:45 -0700631};
632
Eric Laurent4e7a5732012-04-13 16:58:17 -0700633enum output_type {
634 OUTPUT_DEEP_BUF, // deep PCM buffers output stream
635 OUTPUT_LOW_LATENCY, // low latency output stream
Eric Laurent4bf3d142012-04-30 12:30:50 -0700636 OUTPUT_HDMI,
Eric Laurent4e7a5732012-04-13 16:58:17 -0700637 OUTPUT_TOTAL
638};
639
640
Simon Wilson4a972582011-06-09 14:28:56 -0700641struct tuna_audio_device {
Chris Kelly9ce8ae72011-07-18 19:11:58 -0500642 struct audio_hw_device hw_device;
Simon Wilson4a972582011-06-09 14:28:56 -0700643
Eric Laurent023d8052011-08-22 18:19:26 -0700644 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson4a972582011-06-09 14:28:56 -0700645 struct mixer *mixer;
Simon Wilsone18d87d2011-07-12 15:52:45 -0700646 struct mixer_ctls mixer_ctls;
Glenn Kastend9733c42012-01-09 10:40:54 -0800647 audio_mode_t mode;
Eric Laurent7530b972012-08-28 14:24:38 -0700648 int out_device;
649 int in_device;
Simon Wilson1ff65912011-06-21 14:09:10 -0700650 struct pcm *pcm_modem_dl;
651 struct pcm *pcm_modem_ul;
652 int in_call;
UK KIM8c1bc172011-07-13 01:01:09 -0700653 float voice_volume;
Chris Kelly9ce8ae72011-07-18 19:11:58 -0500654 struct tuna_stream_in *active_input;
Eric Laurent4e7a5732012-04-13 16:58:17 -0700655 struct tuna_stream_out *outputs[OUTPUT_TOTAL];
Eric Laurent8f35a342011-08-04 10:47:36 -0700656 bool mic_mute;
Eric Laurent8bbd2d22011-08-07 09:57:42 -0700657 int tty_mode;
Eric Laurent023d8052011-08-22 18:19:26 -0700658 struct echo_reference_itfe *echo_reference;
Eric Laurent41a1ead2011-09-12 09:56:24 -0700659 bool bluetooth_nrec;
Simon Wilson1c2783a2011-10-18 23:25:25 -0700660 bool device_is_toro;
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700661 int wb_amr;
Eric Laurent359a4162012-05-11 09:17:27 -0700662 bool screen_off;
Eric Laurenta100f7d2011-09-28 19:10:01 -0700663
Simon Wilson1ff65912011-06-21 14:09:10 -0700664 /* RIL */
Kim Ukc2a69f52011-07-19 12:57:26 -0700665 struct ril_handle ril;
Simon Wilson4a972582011-06-09 14:28:56 -0700666};
667
Simon Wilson40c820f2012-01-25 10:29:55 -0800668enum pcm_type {
669 PCM_NORMAL = 0,
670 PCM_SPDIF,
671 PCM_HDMI,
672 PCM_TOTAL,
673};
674
Simon Wilson4a972582011-06-09 14:28:56 -0700675struct tuna_stream_out {
676 struct audio_stream_out stream;
677
Eric Laurent023d8052011-08-22 18:19:26 -0700678 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson40c820f2012-01-25 10:29:55 -0800679 struct pcm_config config[PCM_TOTAL];
680 struct pcm *pcm[PCM_TOTAL];
Eric Laurentfa3998c2011-08-19 16:20:54 -0700681 struct resampler_itfe *resampler;
Simon Wilson4a972582011-06-09 14:28:56 -0700682 char *buffer;
Eric Laurent4e7a5732012-04-13 16:58:17 -0700683 size_t buffer_frames;
Simon Wilson9700b232011-07-10 14:46:46 -0700684 int standby;
Eric Laurent023d8052011-08-22 18:19:26 -0700685 struct echo_reference_itfe *echo_reference;
Eric Laurent359a4162012-05-11 09:17:27 -0700686 int write_threshold;
687 bool use_long_periods;
Eric Laurent4bf3d142012-04-30 12:30:50 -0700688 audio_channel_mask_t channel_mask;
689 audio_channel_mask_t sup_channel_masks[3];
Eric Laurent359a4162012-05-11 09:17:27 -0700690
Eric Laurentd84a8f82012-06-11 12:36:38 -0700691 /* FIXME: workaround for HDMI multi channel channel swap on first playback after opening
692 * the output stream: force reopening the pcm driver after writing a few periods. */
693 int restart_periods_cnt;
694
Simon Wilson4a972582011-06-09 14:28:56 -0700695 struct tuna_audio_device *dev;
696};
697
Eric Laurent023d8052011-08-22 18:19:26 -0700698#define MAX_PREPROCESSORS 3 /* maximum one AGC + one NS + one AEC per input stream */
699
Eric Laurent139959c2012-03-30 15:51:03 -0700700struct effect_info_s {
701 effect_handle_t effect_itfe;
702 size_t num_channel_configs;
703 channel_config_t* channel_configs;
704};
705
706#define NUM_IN_AUX_CNL_CONFIGS 2
707channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
708 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
709 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
710};
711
712
Simon Wilson4a972582011-06-09 14:28:56 -0700713struct tuna_stream_in {
714 struct audio_stream_in stream;
715
Eric Laurent023d8052011-08-22 18:19:26 -0700716 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Simon Wilson1bf73172011-06-27 15:45:08 -0700717 struct pcm_config config;
Simon Wilson4a972582011-06-09 14:28:56 -0700718 struct pcm *pcm;
Chris Kelly9ce8ae72011-07-18 19:11:58 -0500719 int device;
Eric Laurentfa3998c2011-08-19 16:20:54 -0700720 struct resampler_itfe *resampler;
Eric Laurent023d8052011-08-22 18:19:26 -0700721 struct resampler_buffer_provider buf_provider;
Simon Wilson1bf73172011-06-27 15:45:08 -0700722 unsigned int requested_rate;
Simon Wilson1bf73172011-06-27 15:45:08 -0700723 int standby;
Simon Wilson2b45e732011-08-22 16:49:03 -0700724 int source;
Eric Laurent023d8052011-08-22 18:19:26 -0700725 struct echo_reference_itfe *echo_reference;
726 bool need_echo_reference;
Eric Laurent139959c2012-03-30 15:51:03 -0700727
728 int16_t *read_buf;
729 size_t read_buf_size;
730 size_t read_buf_frames;
731
732 int16_t *proc_buf_in;
733 int16_t *proc_buf_out;
Eric Laurent023d8052011-08-22 18:19:26 -0700734 size_t proc_buf_size;
Eric Laurent139959c2012-03-30 15:51:03 -0700735 size_t proc_buf_frames;
736
Eric Laurent023d8052011-08-22 18:19:26 -0700737 int16_t *ref_buf;
738 size_t ref_buf_size;
Eric Laurent139959c2012-03-30 15:51:03 -0700739 size_t ref_buf_frames;
740
Eric Laurent023d8052011-08-22 18:19:26 -0700741 int read_status;
Simon Wilson1bf73172011-06-27 15:45:08 -0700742
Eric Laurent139959c2012-03-30 15:51:03 -0700743 int num_preprocessors;
744 struct effect_info_s preprocessors[MAX_PREPROCESSORS];
745
746 bool aux_channels_changed;
747 uint32_t main_channels;
748 uint32_t aux_channels;
Simon Wilson1bf73172011-06-27 15:45:08 -0700749 struct tuna_audio_device *dev;
Simon Wilson4a972582011-06-09 14:28:56 -0700750};
751
Eric Laurent4bf3d142012-04-30 12:30:50 -0700752
753#define STRING_TO_ENUM(string) { #string, string }
754
755struct string_to_enum {
756 const char *name;
757 uint32_t value;
758};
759
760const struct string_to_enum out_channels_name_to_enum_table[] = {
761 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
762 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
763 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
764};
765
766
Eric Laurent023d8052011-08-22 18:19:26 -0700767/**
768 * NOTE: when multiple mutexes have to be acquired, always respect the following order:
769 * hw device > in stream > out stream
770 */
771
772
Simon Wilson7f380a62011-07-17 17:50:53 -0700773static void select_output_device(struct tuna_audio_device *adev);
Chris Kelly9ce8ae72011-07-18 19:11:58 -0500774static void select_input_device(struct tuna_audio_device *adev);
UK KIM8c1bc172011-07-13 01:01:09 -0700775static int adev_set_voice_volume(struct audio_hw_device *dev, float volume);
Eric Laurent023d8052011-08-22 18:19:26 -0700776static int do_input_standby(struct tuna_stream_in *in);
777static int do_output_standby(struct tuna_stream_out *out);
Eric Laurent139959c2012-03-30 15:51:03 -0700778static void in_update_aux_channels(struct tuna_stream_in *in, effect_handle_t effect);
Simon Wilson7f380a62011-07-17 17:50:53 -0700779
Simon Wilson1c2783a2011-10-18 23:25:25 -0700780/* Returns true on devices that are toro, false otherwise */
Simon Wilson903131d2011-09-21 15:46:02 -0700781static int is_device_toro(void)
Simon Wilson512503b2011-08-30 16:29:05 -0700782{
783 char property[PROPERTY_VALUE_MAX];
784
Simon Wilson903131d2011-09-21 15:46:02 -0700785 property_get(PRODUCT_DEVICE_PROPERTY, property, PRODUCT_DEVICE_TORO);
Simon Wilson512503b2011-08-30 16:29:05 -0700786
787 /* return true if the property matches the given value */
Simon Wilson903131d2011-09-21 15:46:02 -0700788 return strcmp(property, PRODUCT_DEVICE_TORO) == 0;
Simon Wilson512503b2011-08-30 16:29:05 -0700789}
790
Simon Wilson4a972582011-06-09 14:28:56 -0700791/* The enable flag when 0 makes the assumption that enums are disabled by
792 * "Off" and integers/booleans by 0 */
793static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
794 int enable)
795{
796 struct mixer_ctl *ctl;
797 unsigned int i, j;
798
799 /* Go through the route array and set each value */
800 i = 0;
801 while (route[i].ctl_name) {
802 ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
803 if (!ctl)
804 return -EINVAL;
805
806 if (route[i].strval) {
807 if (enable)
808 mixer_ctl_set_enum_by_string(ctl, route[i].strval);
809 else
810 mixer_ctl_set_enum_by_string(ctl, "Off");
811 } else {
812 /* This ensures multiple (i.e. stereo) values are set jointly */
813 for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) {
814 if (enable)
815 mixer_ctl_set_value(ctl, j, route[i].intval);
816 else
817 mixer_ctl_set_value(ctl, j, 0);
818 }
819 }
820 i++;
821 }
822
823 return 0;
824}
825
Simon Wilson30f7fe22011-06-24 23:45:03 -0700826static int start_call(struct tuna_audio_device *adev)
Simon Wilson4a972582011-06-09 14:28:56 -0700827{
Steve Block87efd3f2012-01-08 10:19:03 +0000828 ALOGE("Opening modem PCMs");
Simon Wilsonc95b4432011-09-08 11:03:32 -0700829
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700830 pcm_config_vx.rate = adev->wb_amr ? VX_WB_SAMPLING_RATE : VX_NB_SAMPLING_RATE;
831
Simon Wilson30f7fe22011-06-24 23:45:03 -0700832 /* Open modem PCM channels */
833 if (adev->pcm_modem_dl == NULL) {
834 adev->pcm_modem_dl = pcm_open(0, PORT_MODEM, PCM_OUT, &pcm_config_vx);
835 if (!pcm_is_ready(adev->pcm_modem_dl)) {
Steve Block87efd3f2012-01-08 10:19:03 +0000836 ALOGE("cannot open PCM modem DL stream: %s", pcm_get_error(adev->pcm_modem_dl));
Simon Wilson30f7fe22011-06-24 23:45:03 -0700837 goto err_open_dl;
Simon Wilson1ff65912011-06-21 14:09:10 -0700838 }
Simon Wilson4a972582011-06-09 14:28:56 -0700839 }
840
Simon Wilson30f7fe22011-06-24 23:45:03 -0700841 if (adev->pcm_modem_ul == NULL) {
842 adev->pcm_modem_ul = pcm_open(0, PORT_MODEM, PCM_IN, &pcm_config_vx);
843 if (!pcm_is_ready(adev->pcm_modem_ul)) {
Steve Block87efd3f2012-01-08 10:19:03 +0000844 ALOGE("cannot open PCM modem UL stream: %s", pcm_get_error(adev->pcm_modem_ul));
Simon Wilson30f7fe22011-06-24 23:45:03 -0700845 goto err_open_ul;
846 }
847 }
848
Simon Wilson30f7fe22011-06-24 23:45:03 -0700849 pcm_start(adev->pcm_modem_dl);
850 pcm_start(adev->pcm_modem_ul);
851
Simon Wilson4a972582011-06-09 14:28:56 -0700852 return 0;
Simon Wilson1ff65912011-06-21 14:09:10 -0700853
Simon Wilson1ff65912011-06-21 14:09:10 -0700854err_open_ul:
855 pcm_close(adev->pcm_modem_ul);
856 adev->pcm_modem_ul = NULL;
Eric Laurent0758aa12011-10-05 11:47:59 -0700857err_open_dl:
858 pcm_close(adev->pcm_modem_dl);
859 adev->pcm_modem_dl = NULL;
Simon Wilson1ff65912011-06-21 14:09:10 -0700860
861 return -ENOMEM;
Simon Wilson4a972582011-06-09 14:28:56 -0700862}
863
Simon Wilson30f7fe22011-06-24 23:45:03 -0700864static void end_call(struct tuna_audio_device *adev)
865{
Steve Block87efd3f2012-01-08 10:19:03 +0000866 ALOGE("Closing modem PCMs");
Simon Wilsonc95b4432011-09-08 11:03:32 -0700867
Simon Wilson30f7fe22011-06-24 23:45:03 -0700868 pcm_stop(adev->pcm_modem_dl);
869 pcm_stop(adev->pcm_modem_ul);
870 pcm_close(adev->pcm_modem_dl);
871 pcm_close(adev->pcm_modem_ul);
872 adev->pcm_modem_dl = NULL;
873 adev->pcm_modem_ul = NULL;
874}
875
Changoh.Heoc0854432011-10-18 17:47:48 -0700876static void set_eq_filter(struct tuna_audio_device *adev)
877{
878 /* DL1_EQ can't be used for bt */
Eric Laurent7530b972012-08-28 14:24:38 -0700879 int dl1_eq_applicable = adev->out_device & (AUDIO_DEVICE_OUT_WIRED_HEADSET |
Changoh.Heoc0854432011-10-18 17:47:48 -0700880 AUDIO_DEVICE_OUT_WIRED_HEADPHONE | AUDIO_DEVICE_OUT_EARPIECE);
881
882 /* 4Khz LPF is used only in NB-AMR voicecall */
883 if ((adev->mode == AUDIO_MODE_IN_CALL) && dl1_eq_applicable &&
884 (adev->tty_mode == TTY_MODE_OFF) && !adev->wb_amr)
885 mixer_ctl_set_enum_by_string(adev->mixer_ctls.dl1_eq, MIXER_4KHZ_LPF_0DB);
886 else
887 mixer_ctl_set_enum_by_string(adev->mixer_ctls.dl1_eq, MIXER_FLAT_RESPONSE);
888}
889
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700890void audio_set_wb_amr_callback(void *data, int enable)
891{
892 struct tuna_audio_device *adev = (struct tuna_audio_device *)data;
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700893
Simon Wilson75e07922011-10-06 15:33:55 -0700894 pthread_mutex_lock(&adev->lock);
895 if (adev->wb_amr != enable) {
896 adev->wb_amr = enable;
897
898 /* reopen the modem PCMs at the new rate */
899 if (adev->in_call) {
900 end_call(adev);
Changoh.Heoc0854432011-10-18 17:47:48 -0700901 set_eq_filter(adev);
Simon Wilson75e07922011-10-06 15:33:55 -0700902 start_call(adev);
903 }
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700904 }
Simon Wilson75e07922011-10-06 15:33:55 -0700905 pthread_mutex_unlock(&adev->lock);
Simon Wilsond2dbaf92011-09-27 13:39:53 -0700906}
907
UK KIM26038b82011-07-13 02:04:04 -0700908static void set_incall_device(struct tuna_audio_device *adev)
909{
910 int device_type;
911
Eric Laurent7530b972012-08-28 14:24:38 -0700912 switch(adev->out_device) {
UK KIM26038b82011-07-13 02:04:04 -0700913 case AUDIO_DEVICE_OUT_EARPIECE:
914 device_type = SOUND_AUDIO_PATH_HANDSET;
915 break;
916 case AUDIO_DEVICE_OUT_SPEAKER:
Eric Laurent1829c462011-09-16 16:54:45 -0700917 case AUDIO_DEVICE_OUT_AUX_DIGITAL:
Simon Wilson58fc4652011-10-31 12:57:18 -0700918 case AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
UK KIM26038b82011-07-13 02:04:04 -0700919 device_type = SOUND_AUDIO_PATH_SPEAKER;
920 break;
921 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
922 device_type = SOUND_AUDIO_PATH_HEADSET;
923 break;
924 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
925 device_type = SOUND_AUDIO_PATH_HEADPHONE;
926 break;
927 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
928 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
929 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
Eric Laurent41a1ead2011-09-12 09:56:24 -0700930 if (adev->bluetooth_nrec)
931 device_type = SOUND_AUDIO_PATH_BLUETOOTH;
932 else
933 device_type = SOUND_AUDIO_PATH_BLUETOOTH_NO_NR;
UK KIM26038b82011-07-13 02:04:04 -0700934 break;
935 default:
936 device_type = SOUND_AUDIO_PATH_HANDSET;
937 break;
938 }
939
940 /* if output device isn't supported, open modem side to handset by default */
941 ril_set_call_audio_path(&adev->ril, device_type);
942}
943
Simon Wilson2b45e732011-08-22 16:49:03 -0700944static void set_input_volumes(struct tuna_audio_device *adev, int main_mic_on,
945 int headset_mic_on, int sub_mic_on)
946{
947 unsigned int channel;
Simon Wilson0b70d022011-08-26 16:09:34 -0700948 int volume = MIXER_ABE_GAIN_0DB;
Simon Wilson2b45e732011-08-22 16:49:03 -0700949
950 if (adev->mode == AUDIO_MODE_IN_CALL) {
Simon Wilson903131d2011-09-21 15:46:02 -0700951 int sub_mic_volume = is_device_toro() ? VOICE_CALL_SUB_MIC_VOLUME_TORO :
Eric Laurent139959c2012-03-30 15:51:03 -0700952 VOICE_CALL_SUB_MIC_VOLUME_MAGURO;
Simon Wilson2b45e732011-08-22 16:49:03 -0700953 /* special case: don't look at input source for IN_CALL state */
954 volume = DB_TO_ABE_GAIN(main_mic_on ? VOICE_CALL_MAIN_MIC_VOLUME :
955 (headset_mic_on ? VOICE_CALL_HEADSET_MIC_VOLUME :
Simon Wilson903131d2011-09-21 15:46:02 -0700956 (sub_mic_on ? sub_mic_volume : 0)));
Simon Wilson0b70d022011-08-26 16:09:34 -0700957 } else if (adev->active_input) {
Simon Wilson2b45e732011-08-22 16:49:03 -0700958 /* determine input volume by use case */
959 switch (adev->active_input->source) {
960 case AUDIO_SOURCE_MIC: /* general capture */
961 volume = DB_TO_ABE_GAIN(main_mic_on ? CAPTURE_MAIN_MIC_VOLUME :
962 (headset_mic_on ? CAPTURE_HEADSET_MIC_VOLUME :
963 (sub_mic_on ? CAPTURE_SUB_MIC_VOLUME : 0)));
964 break;
965
966 case AUDIO_SOURCE_CAMCORDER:
967 volume = DB_TO_ABE_GAIN(main_mic_on ? CAMCORDER_MAIN_MIC_VOLUME :
968 (headset_mic_on ? CAMCORDER_HEADSET_MIC_VOLUME :
969 (sub_mic_on ? CAMCORDER_SUB_MIC_VOLUME : 0)));
970 break;
971
972 case AUDIO_SOURCE_VOICE_RECOGNITION:
973 volume = DB_TO_ABE_GAIN(main_mic_on ? VOICE_RECOGNITION_MAIN_MIC_VOLUME :
974 (headset_mic_on ? VOICE_RECOGNITION_HEADSET_MIC_VOLUME :
975 (sub_mic_on ? VOICE_RECOGNITION_SUB_MIC_VOLUME : 0)));
976 break;
977
978 case AUDIO_SOURCE_VOICE_COMMUNICATION: /* VoIP */
979 volume = DB_TO_ABE_GAIN(main_mic_on ? VOIP_MAIN_MIC_VOLUME :
980 (headset_mic_on ? VOIP_HEADSET_MIC_VOLUME :
981 (sub_mic_on ? VOIP_SUB_MIC_VOLUME : 0)));
982 break;
983
984 default:
Simon Wilson0b70d022011-08-26 16:09:34 -0700985 /* nothing to do */
Simon Wilson2b45e732011-08-22 16:49:03 -0700986 break;
987 }
988 }
989
990 for (channel = 0; channel < 2; channel++)
991 mixer_ctl_set_value(adev->mixer_ctls.amic_ul_volume, channel, volume);
992}
993
Eric Laurent22eabce2011-10-06 15:46:25 -0700994static void set_output_volumes(struct tuna_audio_device *adev, bool tty_volume)
Simon Wilson903131d2011-09-21 15:46:02 -0700995{
996 unsigned int channel;
997 int speaker_volume;
998 int headset_volume;
Simon Wilson19675852011-09-30 14:31:48 -0700999 int earpiece_volume;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001000 bool toro = adev->device_is_toro;
Eric Laurent7530b972012-08-28 14:24:38 -07001001 int headphone_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
1002 int speaker_on = adev->out_device & AUDIO_DEVICE_OUT_SPEAKER;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001003 int speaker_volume_overrange = MIXER_ABE_GAIN_0DB;
1004 int speaker_max_db =
1005 DB_FROM_SPEAKER_VOLUME(mixer_ctl_get_range_max(adev->mixer_ctls.speaker_volume));
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001006 int normal_speaker_volume = toro ? NORMAL_SPEAKER_VOLUME_TORO :
1007 NORMAL_SPEAKER_VOLUME_MAGURO;
1008 int normal_headphone_volume = toro ? NORMAL_HEADPHONE_VOLUME_TORO :
1009 NORMAL_HEADPHONE_VOLUME_MAGURO;
1010 int normal_headset_volume = toro ? NORMAL_HEADSET_VOLUME_TORO :
1011 NORMAL_HEADSET_VOLUME_MAGURO;
1012 int normal_earpiece_volume = toro ? NORMAL_EARPIECE_VOLUME_TORO :
1013 NORMAL_EARPIECE_VOLUME_MAGURO;
1014 int dl1_volume_correction = 0;
1015 int dl2_volume_correction = 0;
Simon Wilson903131d2011-09-21 15:46:02 -07001016
Simon Wilson1c2783a2011-10-18 23:25:25 -07001017 if (adev->mode == AUDIO_MODE_IN_CALL) {
1018 /* Voice call */
1019 speaker_volume = toro ? VOICE_CALL_SPEAKER_VOLUME_TORO :
1020 VOICE_CALL_SPEAKER_VOLUME_MAGURO;
1021 headset_volume = toro ? VOICE_CALL_HEADSET_VOLUME_TORO :
1022 VOICE_CALL_HEADSET_VOLUME_MAGURO;
1023 earpiece_volume = toro ? VOICE_CALL_EARPIECE_VOLUME_TORO :
1024 VOICE_CALL_EARPIECE_VOLUME_MAGURO;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001025 } else if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1026 /* VoIP */
1027 speaker_volume = toro ? VOIP_SPEAKER_VOLUME_TORO :
1028 VOIP_SPEAKER_VOLUME_MAGURO;
1029 headset_volume = toro ? VOIP_HEADSET_VOLUME_TORO :
1030 VOIP_HEADSET_VOLUME_MAGURO;
1031 earpiece_volume = toro ? VOIP_EARPIECE_VOLUME_TORO :
1032 VOIP_EARPIECE_VOLUME_MAGURO;
1033 } else {
1034 /* Media */
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001035 speaker_volume = normal_speaker_volume;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001036 if (headphone_on)
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001037 headset_volume = normal_headphone_volume;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001038 else
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001039 headset_volume = normal_headset_volume;
1040 earpiece_volume = normal_earpiece_volume;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001041 }
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001042
Eric Laurent22eabce2011-10-06 15:46:25 -07001043 if (tty_volume)
1044 headset_volume = HEADPHONE_VOLUME_TTY;
UK KIMe6f399a2011-10-26 21:41:31 +09001045 else if (adev->mode == AUDIO_MODE_RINGTONE)
1046 headset_volume += RINGTONE_HEADSET_VOLUME_OFFSET;
Simon Wilson1c2783a2011-10-18 23:25:25 -07001047
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001048 /* apply correction on digital volume to keep the overall volume consistent if the
1049 * analog volume is not driven by media use case
1050 */
1051 if (headphone_on)
1052 dl1_volume_correction = normal_headphone_volume - headset_volume;
Eric Laurent7530b972012-08-28 14:24:38 -07001053 else if (adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET)
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001054 dl1_volume_correction = normal_headset_volume - headset_volume;
1055 else
1056 dl1_volume_correction = normal_earpiece_volume - earpiece_volume;
1057
1058 if (speaker_on)
1059 dl2_volume_correction = normal_speaker_volume - speaker_volume;
1060
Simon Wilson1c2783a2011-10-18 23:25:25 -07001061 /* If we have run out of range in the codec (analog) speaker volume,
1062 we have to apply the remainder of the dB increase to the DL2
1063 media/voice mixer volume, which is a digital gain */
1064 if (speaker_volume > speaker_max_db) {
1065 speaker_volume_overrange += (speaker_volume - speaker_max_db);
1066 speaker_volume = speaker_max_db;
Eric Laurent22eabce2011-10-06 15:46:25 -07001067 }
Simon Wilson903131d2011-09-21 15:46:02 -07001068
1069 for (channel = 0; channel < 2; channel++) {
1070 mixer_ctl_set_value(adev->mixer_ctls.speaker_volume, channel,
1071 DB_TO_SPEAKER_VOLUME(speaker_volume));
1072 mixer_ctl_set_value(adev->mixer_ctls.headset_volume, channel,
1073 DB_TO_HEADSET_VOLUME(headset_volume));
1074 }
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001075
1076 if (!speaker_on)
1077 speaker_volume_overrange = MIXER_ABE_GAIN_0DB;
1078
1079 if (adev->mode == AUDIO_MODE_IN_CALL) {
1080 mixer_ctl_set_value(adev->mixer_ctls.tones_dl1_volume, 0,
1081 MIXER_ABE_GAIN_0DB + dl1_volume_correction);
1082 mixer_ctl_set_value(adev->mixer_ctls.vx_dl2_volume, 0,
1083 speaker_volume_overrange);
1084 mixer_ctl_set_value(adev->mixer_ctls.tones_dl2_volume, 0,
1085 speaker_volume_overrange + dl2_volume_correction);
leeminee72ef42012-09-24 10:05:34 +09001086 } else if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION) ||
1087 (adev->mode == AUDIO_MODE_RINGTONE)) {
Eric Laurentd6cc09e2012-05-08 09:31:34 -07001088 mixer_ctl_set_value(adev->mixer_ctls.tones_dl1_volume, 0,
1089 MIXER_ABE_GAIN_0DB);
1090 mixer_ctl_set_value(adev->mixer_ctls.tones_dl2_volume, 0,
1091 speaker_volume_overrange);
1092 } else {
1093 mixer_ctl_set_value(adev->mixer_ctls.tones_dl1_volume, 0,
1094 MIXER_ABE_GAIN_0DB + dl1_volume_correction);
1095 mixer_ctl_set_value(adev->mixer_ctls.tones_dl2_volume, 0,
1096 speaker_volume_overrange + dl2_volume_correction);
1097 }
1098
1099 mixer_ctl_set_value(adev->mixer_ctls.mm_dl1_volume, 0,
1100 MIXER_ABE_GAIN_0DB + dl1_volume_correction);
1101 mixer_ctl_set_value(adev->mixer_ctls.mm_dl2_volume, 0,
1102 speaker_volume_overrange + dl2_volume_correction);
1103
Simon Wilson19675852011-09-30 14:31:48 -07001104 mixer_ctl_set_value(adev->mixer_ctls.earpiece_volume, 0,
1105 DB_TO_EARPIECE_VOLUME(earpiece_volume));
Simon Wilson903131d2011-09-21 15:46:02 -07001106}
1107
Eric Laurent023d8052011-08-22 18:19:26 -07001108static void force_all_standby(struct tuna_audio_device *adev)
1109{
1110 struct tuna_stream_in *in;
Simon Wilsone8c16fe2011-09-18 12:48:52 -07001111 struct tuna_stream_out *out;
1112
Eric Laurent4e7a5732012-04-13 16:58:17 -07001113 /* only needed for low latency output streams as other streams are not used
1114 * for voice use cases */
1115 if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
1116 !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
1117 out = adev->outputs[OUTPUT_LOW_LATENCY];
Simon Wilsone8c16fe2011-09-18 12:48:52 -07001118 pthread_mutex_lock(&out->lock);
1119 do_output_standby(out);
1120 pthread_mutex_unlock(&out->lock);
1121 }
Eric Laurent023d8052011-08-22 18:19:26 -07001122
Eric Laurent023d8052011-08-22 18:19:26 -07001123 if (adev->active_input) {
1124 in = adev->active_input;
1125 pthread_mutex_lock(&in->lock);
1126 do_input_standby(in);
1127 pthread_mutex_unlock(&in->lock);
1128 }
1129}
1130
Simon Wilson30f7fe22011-06-24 23:45:03 -07001131static void select_mode(struct tuna_audio_device *adev)
1132{
1133 if (adev->mode == AUDIO_MODE_IN_CALL) {
Steve Block87efd3f2012-01-08 10:19:03 +00001134 ALOGE("Entering IN_CALL state, in_call=%d", adev->in_call);
Simon Wilson30f7fe22011-06-24 23:45:03 -07001135 if (!adev->in_call) {
Eric Laurent023d8052011-08-22 18:19:26 -07001136 force_all_standby(adev);
Simon Wilsone8c16fe2011-09-18 12:48:52 -07001137 /* force earpiece route for in call state if speaker is the
1138 only currently selected route. This prevents having to tear
1139 down the modem PCMs to change route from speaker to earpiece
1140 after the ringtone is played, but doesn't cause a route
1141 change if a headset or bt device is already connected. If
1142 speaker is not the only thing active, just remove it from
Eric Laurent7530b972012-08-28 14:24:38 -07001143 the route. We'll assume it'll never be used initially during
Simon Wilsone8c16fe2011-09-18 12:48:52 -07001144 a call. This works because we're sure that the audio policy
1145 manager will update the output device after the audio mode
1146 change, even if the device selection did not change. */
Eric Laurent7530b972012-08-28 14:24:38 -07001147 if (adev->out_device == AUDIO_DEVICE_OUT_SPEAKER) {
1148 adev->out_device = AUDIO_DEVICE_OUT_EARPIECE;
1149 adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
1150 } else
1151 adev->out_device &= ~AUDIO_DEVICE_OUT_SPEAKER;
Simon Wilson7f380a62011-07-17 17:50:53 -07001152 select_output_device(adev);
Simon Wilson30f7fe22011-06-24 23:45:03 -07001153 start_call(adev);
Eric Laurent996da012012-06-15 14:49:21 -07001154 ril_set_call_volume(&adev->ril, SOUND_TYPE_VOICE, adev->voice_volume);
Simon Wilson30f7fe22011-06-24 23:45:03 -07001155 adev->in_call = 1;
1156 }
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001157 } else {
Steve Block87efd3f2012-01-08 10:19:03 +00001158 ALOGE("Leaving IN_CALL state, in_call=%d, mode=%d",
Simon Wilsonc95b4432011-09-08 11:03:32 -07001159 adev->in_call, adev->mode);
Simon Wilson30f7fe22011-06-24 23:45:03 -07001160 if (adev->in_call) {
1161 adev->in_call = 0;
1162 end_call(adev);
Eric Laurent023d8052011-08-22 18:19:26 -07001163 force_all_standby(adev);
Simon Wilson7f380a62011-07-17 17:50:53 -07001164 select_output_device(adev);
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001165 select_input_device(adev);
Simon Wilson30f7fe22011-06-24 23:45:03 -07001166 }
1167 }
1168}
1169
1170static void select_output_device(struct tuna_audio_device *adev)
1171{
Simon Wilsone18d87d2011-07-12 15:52:45 -07001172 int headset_on;
Simon Wilsona25c2e62011-08-08 19:57:43 -07001173 int headphone_on;
Simon Wilsone18d87d2011-07-12 15:52:45 -07001174 int speaker_on;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001175 int earpiece_on;
Chris Kelly50765d22011-07-14 14:52:55 -05001176 int bt_on;
1177 int dl1_on;
Simon Wilson512503b2011-08-30 16:29:05 -07001178 int sidetone_capture_on = 0;
Eric Laurent22eabce2011-10-06 15:46:25 -07001179 bool tty_volume = false;
venkappa malaa3799ff2011-10-06 21:16:42 -07001180 unsigned int channel;
1181
1182 /* Mute VX_UL to avoid pop noises in the tx path
1183 * during call before switch changes.
1184 */
1185 if (adev->mode == AUDIO_MODE_IN_CALL) {
1186 for (channel = 0; channel < 2; channel++)
1187 mixer_ctl_set_value(adev->mixer_ctls.voice_ul_volume,
1188 channel, 0);
1189 }
Simon Wilson30f7fe22011-06-24 23:45:03 -07001190
Eric Laurent7530b972012-08-28 14:24:38 -07001191 headset_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET;
1192 headphone_on = adev->out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
1193 speaker_on = adev->out_device & AUDIO_DEVICE_OUT_SPEAKER;
1194 earpiece_on = adev->out_device & AUDIO_DEVICE_OUT_EARPIECE;
1195 bt_on = adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO;
Eric Laurent8bbd2d22011-08-07 09:57:42 -07001196
1197 /* force rx path according to TTY mode when in call */
1198 if (adev->mode == AUDIO_MODE_IN_CALL && !bt_on) {
1199 switch(adev->tty_mode) {
1200 case TTY_MODE_FULL:
1201 case TTY_MODE_VCO:
1202 /* rx path to headphones */
1203 headphone_on = 1;
1204 headset_on = 0;
1205 speaker_on = 0;
1206 earpiece_on = 0;
Eric Laurent22eabce2011-10-06 15:46:25 -07001207 tty_volume = true;
Eric Laurent8bbd2d22011-08-07 09:57:42 -07001208 break;
1209 case TTY_MODE_HCO:
1210 /* rx path to device speaker */
1211 headphone_on = 0;
1212 headset_on = 0;
1213 speaker_on = 1;
1214 earpiece_on = 0;
1215 break;
1216 case TTY_MODE_OFF:
1217 default:
Simon Wilson58fc4652011-10-31 12:57:18 -07001218 /* force speaker on when in call and HDMI or S/PDIF is selected
1219 * as voice DL audio cannot be routed there by ABE */
Eric Laurent7530b972012-08-28 14:24:38 -07001220 if (adev->out_device &
Simon Wilson58fc4652011-10-31 12:57:18 -07001221 (AUDIO_DEVICE_OUT_AUX_DIGITAL |
1222 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET))
Eric Laurent1829c462011-09-16 16:54:45 -07001223 speaker_on = 1;
Eric Laurent8bbd2d22011-08-07 09:57:42 -07001224 break;
1225 }
1226 }
1227
Simon Wilsona25c2e62011-08-08 19:57:43 -07001228 dl1_on = headset_on | headphone_on | earpiece_on | bt_on;
Simon Wilsone18d87d2011-07-12 15:52:45 -07001229
Chris Kelly50765d22011-07-14 14:52:55 -05001230 /* Select front end */
1231 mixer_ctl_set_value(adev->mixer_ctls.mm_dl2, 0, speaker_on);
Eric Laurent4e7a5732012-04-13 16:58:17 -07001232 mixer_ctl_set_value(adev->mixer_ctls.tones_dl2, 0, speaker_on);
Chris Kelly50765d22011-07-14 14:52:55 -05001233 mixer_ctl_set_value(adev->mixer_ctls.vx_dl2, 0,
Simon Wilson7f380a62011-07-17 17:50:53 -07001234 speaker_on && (adev->mode == AUDIO_MODE_IN_CALL));
Chris Kelly50765d22011-07-14 14:52:55 -05001235 mixer_ctl_set_value(adev->mixer_ctls.mm_dl1, 0, dl1_on);
Eric Laurent4e7a5732012-04-13 16:58:17 -07001236 mixer_ctl_set_value(adev->mixer_ctls.tones_dl1, 0, dl1_on);
Chris Kelly50765d22011-07-14 14:52:55 -05001237 mixer_ctl_set_value(adev->mixer_ctls.vx_dl1, 0,
1238 dl1_on && (adev->mode == AUDIO_MODE_IN_CALL));
1239 /* Select back end */
Simon Wilsona25c2e62011-08-08 19:57:43 -07001240 mixer_ctl_set_value(adev->mixer_ctls.dl1_headset, 0,
1241 headset_on | headphone_on | earpiece_on);
Chris Kelly50765d22011-07-14 14:52:55 -05001242 mixer_ctl_set_value(adev->mixer_ctls.dl1_bt, 0, bt_on);
Simon Wilson431112d2011-10-20 10:32:27 -07001243 mixer_ctl_set_value(adev->mixer_ctls.dl2_mono, 0,
1244 (adev->mode != AUDIO_MODE_IN_CALL) && speaker_on);
Simon Wilsone9ab0812011-09-19 17:22:01 -07001245 mixer_ctl_set_value(adev->mixer_ctls.earpiece_enable, 0, earpiece_on);
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001246
Simon Wilson03d3caa2011-08-26 15:06:32 -07001247 /* select output stage */
Simon Wilson903131d2011-09-21 15:46:02 -07001248 set_route_by_array(adev->mixer, hs_output, headset_on | headphone_on);
Simon Wilson03d3caa2011-08-26 15:06:32 -07001249 set_route_by_array(adev->mixer, hf_output, speaker_on);
1250
Changoh.Heoc0854432011-10-18 17:47:48 -07001251 set_eq_filter(adev);
Eric Laurent22eabce2011-10-06 15:46:25 -07001252 set_output_volumes(adev, tty_volume);
Simon Wilson903131d2011-09-21 15:46:02 -07001253
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001254 /* Special case: select input path if in a call, otherwise
1255 in_set_parameters is used to update the input route
1256 todo: use sub mic for handsfree case */
1257 if (adev->mode == AUDIO_MODE_IN_CALL) {
1258 if (bt_on)
1259 set_route_by_array(adev->mixer, vx_ul_bt, bt_on);
1260 else {
Eric Laurent8bbd2d22011-08-07 09:57:42 -07001261 /* force tx path according to TTY mode when in call */
1262 switch(adev->tty_mode) {
1263 case TTY_MODE_FULL:
1264 case TTY_MODE_HCO:
1265 /* tx path from headset mic */
1266 headphone_on = 0;
1267 headset_on = 1;
1268 speaker_on = 0;
1269 earpiece_on = 0;
1270 break;
1271 case TTY_MODE_VCO:
1272 /* tx path from device sub mic */
1273 headphone_on = 0;
1274 headset_on = 0;
1275 speaker_on = 1;
1276 earpiece_on = 0;
1277 break;
1278 case TTY_MODE_OFF:
1279 default:
1280 break;
1281 }
1282
Simon Wilsona25c2e62011-08-08 19:57:43 -07001283 if (headset_on || headphone_on || earpiece_on)
Simon Wilson975e9152011-08-08 16:15:45 -07001284 set_route_by_array(adev->mixer, vx_ul_amic_left, 1);
1285 else if (speaker_on)
1286 set_route_by_array(adev->mixer, vx_ul_amic_right, 1);
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001287 else
Simon Wilson975e9152011-08-08 16:15:45 -07001288 set_route_by_array(adev->mixer, vx_ul_amic_left, 0);
1289
1290 mixer_ctl_set_enum_by_string(adev->mixer_ctls.left_capture,
Simon Wilsona25c2e62011-08-08 19:57:43 -07001291 (earpiece_on || headphone_on) ? MIXER_MAIN_MIC :
Simon Wilson975e9152011-08-08 16:15:45 -07001292 (headset_on ? MIXER_HS_MIC : "Off"));
1293 mixer_ctl_set_enum_by_string(adev->mixer_ctls.right_capture,
1294 speaker_on ? MIXER_SUB_MIC : "Off");
Simon Wilson2b45e732011-08-22 16:49:03 -07001295
1296 set_input_volumes(adev, earpiece_on || headphone_on,
1297 headset_on, speaker_on);
Simon Wilson512503b2011-08-30 16:29:05 -07001298
1299 /* enable sidetone mixer capture if needed */
Simon Wilson1c2783a2011-10-18 23:25:25 -07001300 sidetone_capture_on = earpiece_on && adev->device_is_toro;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001301 }
Simon Wilson5173fd22011-09-28 14:52:15 -07001302
1303 set_incall_device(adev);
venkappa malaa3799ff2011-10-06 21:16:42 -07001304
1305 /* Unmute VX_UL after the switch */
1306 for (channel = 0; channel < 2; channel++) {
1307 mixer_ctl_set_value(adev->mixer_ctls.voice_ul_volume,
1308 channel, MIXER_ABE_GAIN_0DB);
1309 }
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001310 }
Simon Wilson512503b2011-08-30 16:29:05 -07001311
1312 mixer_ctl_set_value(adev->mixer_ctls.sidetone_capture, 0, sidetone_capture_on);
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001313}
1314
1315static void select_input_device(struct tuna_audio_device *adev)
1316{
Eric Laurent023d8052011-08-22 18:19:26 -07001317 int headset_on = 0;
1318 int main_mic_on = 0;
Simon Wilson2b45e732011-08-22 16:49:03 -07001319 int sub_mic_on = 0;
Eric Laurent7530b972012-08-28 14:24:38 -07001320 int bt_on = adev->in_device & AUDIO_DEVICE_IN_ALL_SCO;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001321
Eric Laurent023d8052011-08-22 18:19:26 -07001322 if (!bt_on) {
1323 if ((adev->mode != AUDIO_MODE_IN_CALL) && (adev->active_input != 0)) {
Eric Laurent023d8052011-08-22 18:19:26 -07001324 /* sub mic is used for camcorder or VoIP on speaker phone */
1325 sub_mic_on = (adev->active_input->source == AUDIO_SOURCE_CAMCORDER) ||
Eric Laurent7530b972012-08-28 14:24:38 -07001326 ((adev->out_device & AUDIO_DEVICE_OUT_SPEAKER) &&
Eric Laurent023d8052011-08-22 18:19:26 -07001327 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION));
1328 }
1329 if (!sub_mic_on) {
Eric Laurent7530b972012-08-28 14:24:38 -07001330 headset_on = adev->in_device & AUDIO_DEVICE_IN_WIRED_HEADSET;
1331 main_mic_on = adev->in_device & AUDIO_DEVICE_IN_BUILTIN_MIC;
Eric Laurent023d8052011-08-22 18:19:26 -07001332 }
Simon Wilson2b45e732011-08-22 16:49:03 -07001333 }
1334
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001335 /* TODO: check how capture is possible during voice calls or if
1336 * both use cases are mutually exclusive.
1337 */
Simon Wilson4283faf2011-09-08 20:27:33 -07001338 if (bt_on)
1339 set_route_by_array(adev->mixer, mm_ul2_bt, 1);
1340 else {
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001341 /* Select front end */
Eric Laurent139959c2012-03-30 15:51:03 -07001342
1343
Eric Laurentb6603122013-01-18 18:05:45 -08001344 if ((adev->active_input != 0) && (adev->active_input->aux_channels ||
1345 adev->active_input->main_channels == AUDIO_CHANNEL_IN_FRONT_BACK)) {
Eric Laurent139959c2012-03-30 15:51:03 -07001346 ALOGV("select input device(): multi-mic configuration main mic %s sub mic %s",
1347 main_mic_on ? "ON" : "OFF", sub_mic_on ? "ON" : "OFF");
1348 if (main_mic_on) {
1349 set_route_by_array(adev->mixer, mm_ul2_amic_dual_main_sub, 1);
1350 sub_mic_on = 1;
1351 }
1352 else if (sub_mic_on) {
1353 set_route_by_array(adev->mixer, mm_ul2_amic_dual_sub_main, 1);
1354 main_mic_on = 1;
1355 }
1356 else {
1357 set_route_by_array(adev->mixer, mm_ul2_amic_dual_main_sub, 0);
1358 }
1359 } else {
1360 ALOGV("select input device(): single mic configuration");
1361 if (main_mic_on || headset_on)
1362 set_route_by_array(adev->mixer, mm_ul2_amic_left, 1);
1363 else if (sub_mic_on)
1364 set_route_by_array(adev->mixer, mm_ul2_amic_right, 1);
1365 else
1366 set_route_by_array(adev->mixer, mm_ul2_amic_left, 0);
1367 }
1368
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001369
1370 /* Select back end */
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -07001371 mixer_ctl_set_enum_by_string(adev->mixer_ctls.right_capture,
Simon Wilson2b45e732011-08-22 16:49:03 -07001372 sub_mic_on ? MIXER_SUB_MIC : "Off");
1373 mixer_ctl_set_enum_by_string(adev->mixer_ctls.left_capture,
1374 main_mic_on ? MIXER_MAIN_MIC :
1375 (headset_on ? MIXER_HS_MIC : "Off"));
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001376 }
Simon Wilsone18d87d2011-07-12 15:52:45 -07001377
Simon Wilson2b45e732011-08-22 16:49:03 -07001378 set_input_volumes(adev, main_mic_on, headset_on, sub_mic_on);
Simon Wilson30f7fe22011-06-24 23:45:03 -07001379}
1380
Eric Laurent023d8052011-08-22 18:19:26 -07001381/* must be called with hw device and output stream mutexes locked */
Eric Laurent4e7a5732012-04-13 16:58:17 -07001382static int start_output_stream_low_latency(struct tuna_stream_out *out)
Simon Wilson9700b232011-07-10 14:46:46 -07001383{
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001384 struct tuna_audio_device *adev = out->dev;
Glenn Kasten47623d42012-02-14 13:54:03 -08001385#ifdef PLAYBACK_MMAP
Simon Wilson40c820f2012-01-25 10:29:55 -08001386 unsigned int flags = PCM_OUT | PCM_MMAP | PCM_NOIRQ;
Glenn Kasten47623d42012-02-14 13:54:03 -08001387#else
1388 unsigned int flags = PCM_OUT;
1389#endif
Simon Wilson40c820f2012-01-25 10:29:55 -08001390 int i;
1391 bool success = true;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001392
Eric Laurent023d8052011-08-22 18:19:26 -07001393 if (adev->mode != AUDIO_MODE_IN_CALL) {
Eric Laurent023d8052011-08-22 18:19:26 -07001394 select_output_device(adev);
1395 }
Simon Wilson40c820f2012-01-25 10:29:55 -08001396
Eric Laurent753a1242011-10-13 08:46:22 -07001397 /* default to low power: will be corrected in out_write if necessary before first write to
1398 * tinyalsa.
1399 */
Eric Laurent753a1242011-10-13 08:46:22 -07001400
Eric Laurent7530b972012-08-28 14:24:38 -07001401 if (adev->out_device & ~(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET | AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Simon Wilson40c820f2012-01-25 10:29:55 -08001402 /* Something not a dock in use */
Eric Laurent4e7a5732012-04-13 16:58:17 -07001403 out->config[PCM_NORMAL] = pcm_config_tones;
Simon Wilson40c820f2012-01-25 10:29:55 -08001404 out->config[PCM_NORMAL].rate = MM_FULL_POWER_SAMPLING_RATE;
Eric Laurent4e7a5732012-04-13 16:58:17 -07001405 out->pcm[PCM_NORMAL] = pcm_open(CARD_TUNA_DEFAULT, PORT_TONES,
1406 flags, &out->config[PCM_NORMAL]);
Simon Wilson9700b232011-07-10 14:46:46 -07001407 }
1408
Eric Laurent7530b972012-08-28 14:24:38 -07001409 if (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) {
Simon Wilson40c820f2012-01-25 10:29:55 -08001410 /* SPDIF output in use */
Eric Laurent4e7a5732012-04-13 16:58:17 -07001411 out->config[PCM_SPDIF] = pcm_config_tones;
Simon Wilson40c820f2012-01-25 10:29:55 -08001412 out->config[PCM_SPDIF].rate = MM_FULL_POWER_SAMPLING_RATE;
Eric Laurent4e7a5732012-04-13 16:58:17 -07001413 out->pcm[PCM_SPDIF] = pcm_open(CARD_TUNA_DEFAULT, PORT_SPDIF,
1414 flags, &out->config[PCM_SPDIF]);
Simon Wilson40c820f2012-01-25 10:29:55 -08001415 }
Eric Laurent023d8052011-08-22 18:19:26 -07001416
Eric Laurent4bf3d142012-04-30 12:30:50 -07001417 /* priority is given to multichannel HDMI output */
Eric Laurent7530b972012-08-28 14:24:38 -07001418 if ((adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Eric Laurent4bf3d142012-04-30 12:30:50 -07001419 (adev->outputs[OUTPUT_HDMI] == NULL || adev->outputs[OUTPUT_HDMI]->standby)) {
Simon Wilson40c820f2012-01-25 10:29:55 -08001420 /* HDMI output in use */
Eric Laurent4e7a5732012-04-13 16:58:17 -07001421 out->config[PCM_HDMI] = pcm_config_tones;
Simon Wilson40c820f2012-01-25 10:29:55 -08001422 out->config[PCM_HDMI].rate = MM_LOW_POWER_SAMPLING_RATE;
Eric Laurent4e7a5732012-04-13 16:58:17 -07001423 out->pcm[PCM_HDMI] = pcm_open(CARD_OMAP4_HDMI, PORT_HDMI,
1424 flags, &out->config[PCM_HDMI]);
Simon Wilson40c820f2012-01-25 10:29:55 -08001425 }
Eric Laurentfa3998c2011-08-19 16:20:54 -07001426
Simon Wilson40c820f2012-01-25 10:29:55 -08001427 /* Close any PCMs that could not be opened properly and return an error */
1428 for (i = 0; i < PCM_TOTAL; i++) {
1429 if (out->pcm[i] && !pcm_is_ready(out->pcm[i])) {
Eric Laurent4bf3d142012-04-30 12:30:50 -07001430 ALOGE("cannot open pcm_out driver %d: %s", i, pcm_get_error(out->pcm[i]));
Simon Wilson40c820f2012-01-25 10:29:55 -08001431 pcm_close(out->pcm[i]);
1432 out->pcm[i] = NULL;
1433 success = false;
1434 }
1435 }
1436
1437 if (success) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07001438 out->buffer_frames = pcm_config_tones.period_size * 2;
1439 if (out->buffer == NULL)
1440 out->buffer = malloc(out->buffer_frames * audio_stream_frame_size(&out->stream.common));
1441
Simon Wilson40c820f2012-01-25 10:29:55 -08001442 if (adev->echo_reference != NULL)
1443 out->echo_reference = adev->echo_reference;
1444 out->resampler->reset(out->resampler);
1445
1446 return 0;
1447 }
1448
Simon Wilson40c820f2012-01-25 10:29:55 -08001449 return -ENOMEM;
Simon Wilson9700b232011-07-10 14:46:46 -07001450}
1451
Eric Laurent4e7a5732012-04-13 16:58:17 -07001452/* must be called with hw device and output stream mutexes locked */
1453static int start_output_stream_deep_buffer(struct tuna_stream_out *out)
1454{
1455 struct tuna_audio_device *adev = out->dev;
1456
1457 if (adev->mode != AUDIO_MODE_IN_CALL) {
1458 select_output_device(adev);
1459 }
1460
Eric Laurent359a4162012-05-11 09:17:27 -07001461 out->write_threshold = PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT * DEEP_BUFFER_LONG_PERIOD_SIZE;
1462 out->use_long_periods = true;
1463
Eric Laurent4e7a5732012-04-13 16:58:17 -07001464 out->config[PCM_NORMAL] = pcm_config_mm;
1465 out->config[PCM_NORMAL].rate = MM_FULL_POWER_SAMPLING_RATE;
1466 out->pcm[PCM_NORMAL] = pcm_open(CARD_TUNA_DEFAULT, PORT_MM,
1467 PCM_OUT | PCM_MMAP | PCM_NOIRQ, &out->config[PCM_NORMAL]);
1468 if (out->pcm[PCM_NORMAL] && !pcm_is_ready(out->pcm[PCM_NORMAL])) {
1469 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm[PCM_NORMAL]));
1470 pcm_close(out->pcm[PCM_NORMAL]);
1471 out->pcm[PCM_NORMAL] = NULL;
1472 return -ENOMEM;
1473 }
Eric Laurent359a4162012-05-11 09:17:27 -07001474 out->buffer_frames = DEEP_BUFFER_SHORT_PERIOD_SIZE * 2;
Eric Laurent4e7a5732012-04-13 16:58:17 -07001475 if (out->buffer == NULL)
1476 out->buffer = malloc(out->buffer_frames * audio_stream_frame_size(&out->stream.common));
1477
1478 return 0;
1479}
1480
Eric Laurent4bf3d142012-04-30 12:30:50 -07001481static int start_output_stream_hdmi(struct tuna_stream_out *out)
1482{
1483 struct tuna_audio_device *adev = out->dev;
1484
1485 /* force standby on low latency output stream to close HDMI driver in case it was in use */
1486 if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
1487 !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
1488 struct tuna_stream_out *ll_out = adev->outputs[OUTPUT_LOW_LATENCY];
1489 pthread_mutex_lock(&ll_out->lock);
1490 do_output_standby(ll_out);
1491 pthread_mutex_unlock(&ll_out->lock);
1492 }
1493
1494 out->pcm[PCM_HDMI] = pcm_open(CARD_OMAP4_HDMI, PORT_HDMI, PCM_OUT, &out->config[PCM_HDMI]);
1495
1496 if (out->pcm[PCM_HDMI] && !pcm_is_ready(out->pcm[PCM_HDMI])) {
1497 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm[PCM_HDMI]));
1498 pcm_close(out->pcm[PCM_HDMI]);
1499 out->pcm[PCM_HDMI] = NULL;
1500 return -ENOMEM;
1501 }
1502 return 0;
1503}
1504
Glenn Kastenb9637562012-01-12 11:46:47 -08001505static int check_input_parameters(uint32_t sample_rate, audio_format_t format, int channel_count)
Eric Laurentdf6ed252011-07-14 15:26:25 -07001506{
1507 if (format != AUDIO_FORMAT_PCM_16_BIT)
1508 return -EINVAL;
1509
1510 if ((channel_count < 1) || (channel_count > 2))
1511 return -EINVAL;
1512
1513 switch(sample_rate) {
1514 case 8000:
Eric Laurent3c930972011-07-14 18:49:47 -07001515 case 11025:
Eric Laurentdf6ed252011-07-14 15:26:25 -07001516 case 16000:
Eric Laurent3c930972011-07-14 18:49:47 -07001517 case 22050:
1518 case 24000:
1519 case 32000:
1520 case 44100:
Eric Laurentdf6ed252011-07-14 15:26:25 -07001521 case 48000:
1522 break;
1523 default:
1524 return -EINVAL;
1525 }
1526
1527 return 0;
1528}
1529
Glenn Kastenb9637562012-01-12 11:46:47 -08001530static size_t get_input_buffer_size(uint32_t sample_rate, audio_format_t format, int channel_count)
Eric Laurent3c930972011-07-14 18:49:47 -07001531{
1532 size_t size;
1533 size_t device_rate;
1534
1535 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1536 return 0;
1537
Simon Wilson79095f92011-09-06 14:59:51 -07001538 /* take resampling into account and return the closest majoring
1539 multiple of 16 frames, as audioflinger expects audio buffers to
1540 be a multiple of 16 frames */
1541 size = (pcm_config_mm_ul.period_size * sample_rate) / pcm_config_mm_ul.rate;
1542 size = ((size + 15) / 16) * 16;
Eric Laurent3c930972011-07-14 18:49:47 -07001543
1544 return size * channel_count * sizeof(short);
1545}
Eric Laurentdf6ed252011-07-14 15:26:25 -07001546
Eric Laurent023d8052011-08-22 18:19:26 -07001547static void add_echo_reference(struct tuna_stream_out *out,
1548 struct echo_reference_itfe *reference)
1549{
1550 pthread_mutex_lock(&out->lock);
1551 out->echo_reference = reference;
1552 pthread_mutex_unlock(&out->lock);
1553}
1554
1555static void remove_echo_reference(struct tuna_stream_out *out,
1556 struct echo_reference_itfe *reference)
1557{
1558 pthread_mutex_lock(&out->lock);
1559 if (out->echo_reference == reference) {
1560 /* stop writing to echo reference */
1561 reference->write(reference, NULL);
1562 out->echo_reference = NULL;
1563 }
1564 pthread_mutex_unlock(&out->lock);
1565}
1566
1567static void put_echo_reference(struct tuna_audio_device *adev,
1568 struct echo_reference_itfe *reference)
1569{
1570 if (adev->echo_reference != NULL &&
1571 reference == adev->echo_reference) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07001572 /* echo reference is taken from the low latency output stream used
1573 * for voice use cases */
1574 if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
1575 !adev->outputs[OUTPUT_LOW_LATENCY]->standby)
1576 remove_echo_reference(adev->outputs[OUTPUT_LOW_LATENCY], reference);
Eric Laurent023d8052011-08-22 18:19:26 -07001577 release_echo_reference(reference);
1578 adev->echo_reference = NULL;
1579 }
1580}
1581
1582static struct echo_reference_itfe *get_echo_reference(struct tuna_audio_device *adev,
1583 audio_format_t format,
1584 uint32_t channel_count,
1585 uint32_t sampling_rate)
1586{
1587 put_echo_reference(adev, adev->echo_reference);
Eric Laurent4e7a5732012-04-13 16:58:17 -07001588 /* echo reference is taken from the low latency output stream used
1589 * for voice use cases */
1590 if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
1591 !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
1592 struct audio_stream *stream =
1593 &adev->outputs[OUTPUT_LOW_LATENCY]->stream.common;
Eric Laurent023d8052011-08-22 18:19:26 -07001594 uint32_t wr_channel_count = popcount(stream->get_channels(stream));
1595 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1596
1597 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1598 channel_count,
1599 sampling_rate,
1600 AUDIO_FORMAT_PCM_16_BIT,
1601 wr_channel_count,
1602 wr_sampling_rate,
1603 &adev->echo_reference);
1604 if (status == 0)
Eric Laurent4e7a5732012-04-13 16:58:17 -07001605 add_echo_reference(adev->outputs[OUTPUT_LOW_LATENCY],
1606 adev->echo_reference);
Eric Laurent023d8052011-08-22 18:19:26 -07001607 }
1608 return adev->echo_reference;
1609}
1610
1611static int get_playback_delay(struct tuna_stream_out *out,
1612 size_t frames,
1613 struct echo_reference_buffer *buffer)
1614{
1615 size_t kernel_frames;
1616 int status;
Simon Wilson40c820f2012-01-25 10:29:55 -08001617 int primary_pcm = 0;
Eric Laurent023d8052011-08-22 18:19:26 -07001618
Simon Wilson40c820f2012-01-25 10:29:55 -08001619 /* Find the first active PCM to act as primary */
1620 while ((primary_pcm < PCM_TOTAL) && !out->pcm[primary_pcm])
1621 primary_pcm++;
1622
1623 status = pcm_get_htimestamp(out->pcm[primary_pcm], &kernel_frames, &buffer->time_stamp);
Eric Laurent023d8052011-08-22 18:19:26 -07001624 if (status < 0) {
1625 buffer->time_stamp.tv_sec = 0;
1626 buffer->time_stamp.tv_nsec = 0;
1627 buffer->delay_ns = 0;
Steve Block6bf50092011-10-20 11:56:21 +01001628 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
Eric Laurent023d8052011-08-22 18:19:26 -07001629 "setting playbackTimestamp to 0");
1630 return status;
1631 }
1632
Simon Wilson40c820f2012-01-25 10:29:55 -08001633 kernel_frames = pcm_get_buffer_size(out->pcm[primary_pcm]) - kernel_frames;
Eric Laurent023d8052011-08-22 18:19:26 -07001634
1635 /* adjust render time stamp with delay added by current driver buffer.
1636 * Add the duration of current frame as we want the render time of the last
1637 * sample being written. */
1638 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1639 MM_FULL_POWER_SAMPLING_RATE);
1640
1641 return 0;
1642}
1643
Simon Wilson4a972582011-06-09 14:28:56 -07001644static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1645{
Eric Laurent371599a2011-07-08 17:16:43 -07001646 return DEFAULT_OUT_SAMPLING_RATE;
Simon Wilson4a972582011-06-09 14:28:56 -07001647}
1648
Eric Laurent4bf3d142012-04-30 12:30:50 -07001649static uint32_t out_get_sample_rate_hdmi(const struct audio_stream *stream)
1650{
1651 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1652
1653 return out->config[PCM_HDMI].rate;
1654}
1655
Simon Wilson4a972582011-06-09 14:28:56 -07001656static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1657{
1658 return 0;
1659}
1660
Eric Laurent4e7a5732012-04-13 16:58:17 -07001661static size_t out_get_buffer_size_low_latency(const struct audio_stream *stream)
1662{
1663 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1664
1665 /* take resampling into account and return the closest majoring
1666 multiple of 16 frames, as audioflinger expects audio buffers to
1667 be a multiple of 16 frames. Note: we use the default rate here
1668 from pcm_config_tones.rate. */
1669 size_t size = (SHORT_PERIOD_SIZE * DEFAULT_OUT_SAMPLING_RATE) / pcm_config_tones.rate;
1670 size = ((size + 15) / 16) * 16;
1671 return size * audio_stream_frame_size((struct audio_stream *)stream);
1672}
1673
1674static size_t out_get_buffer_size_deep_buffer(const struct audio_stream *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07001675{
1676 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1677
Eric Laurent371599a2011-07-08 17:16:43 -07001678 /* take resampling into account and return the closest majoring
1679 multiple of 16 frames, as audioflinger expects audio buffers to
Simon Wilson40c820f2012-01-25 10:29:55 -08001680 be a multiple of 16 frames. Note: we use the default rate here
1681 from pcm_config_mm.rate. */
Eric Laurent359a4162012-05-11 09:17:27 -07001682 size_t size = (DEEP_BUFFER_SHORT_PERIOD_SIZE * DEFAULT_OUT_SAMPLING_RATE) /
1683 pcm_config_mm.rate;
Eric Laurent371599a2011-07-08 17:16:43 -07001684 size = ((size + 15) / 16) * 16;
1685 return size * audio_stream_frame_size((struct audio_stream *)stream);
Simon Wilson4a972582011-06-09 14:28:56 -07001686}
1687
Eric Laurent4bf3d142012-04-30 12:30:50 -07001688static size_t out_get_buffer_size_hdmi(const struct audio_stream *stream)
1689{
1690 return HDMI_MULTI_PERIOD_SIZE * audio_stream_frame_size((struct audio_stream *)stream);
1691}
1692
Glenn Kasten8eb734e2012-03-14 12:50:51 -07001693static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07001694{
Eric Laurent4bf3d142012-04-30 12:30:50 -07001695 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1696
1697 return out->channel_mask;
Simon Wilson4a972582011-06-09 14:28:56 -07001698}
1699
Glenn Kastenb9637562012-01-12 11:46:47 -08001700static audio_format_t out_get_format(const struct audio_stream *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07001701{
1702 return AUDIO_FORMAT_PCM_16_BIT;
1703}
1704
Glenn Kastenb9637562012-01-12 11:46:47 -08001705static int out_set_format(struct audio_stream *stream, audio_format_t format)
Simon Wilson4a972582011-06-09 14:28:56 -07001706{
1707 return 0;
1708}
1709
Eric Laurent023d8052011-08-22 18:19:26 -07001710/* must be called with hw device and output stream mutexes locked */
1711static int do_output_standby(struct tuna_stream_out *out)
Simon Wilson4a972582011-06-09 14:28:56 -07001712{
Simon Wilson03d3caa2011-08-26 15:06:32 -07001713 struct tuna_audio_device *adev = out->dev;
Simon Wilson40c820f2012-01-25 10:29:55 -08001714 int i;
Eric Laurent4e7a5732012-04-13 16:58:17 -07001715 bool all_outputs_in_standby = true;
Simon Wilson9700b232011-07-10 14:46:46 -07001716
Simon Wilson9700b232011-07-10 14:46:46 -07001717 if (!out->standby) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07001718 out->standby = 1;
1719
Simon Wilson40c820f2012-01-25 10:29:55 -08001720 for (i = 0; i < PCM_TOTAL; i++) {
1721 if (out->pcm[i]) {
1722 pcm_close(out->pcm[i]);
1723 out->pcm[i] = NULL;
1724 }
1725 }
Eric Laurent023d8052011-08-22 18:19:26 -07001726
Eric Laurent4e7a5732012-04-13 16:58:17 -07001727 for (i = 0; i < OUTPUT_TOTAL; i++) {
1728 if (adev->outputs[i] != NULL && !adev->outputs[i]->standby) {
1729 all_outputs_in_standby = false;
1730 break;
1731 }
1732 }
Simon Wilson03d3caa2011-08-26 15:06:32 -07001733 /* if in call, don't turn off the output stage. This will
1734 be done when the call is ended */
Eric Laurent4e7a5732012-04-13 16:58:17 -07001735 if (all_outputs_in_standby && adev->mode != AUDIO_MODE_IN_CALL) {
Simon Wilson03d3caa2011-08-26 15:06:32 -07001736 set_route_by_array(adev->mixer, hs_output, 0);
1737 set_route_by_array(adev->mixer, hf_output, 0);
1738 }
Eric Laurent023d8052011-08-22 18:19:26 -07001739
Eric Laurent4bf3d142012-04-30 12:30:50 -07001740 /* force standby on low latency output stream so that it can reuse HDMI driver if
1741 * necessary when restarted */
1742 if (out == adev->outputs[OUTPUT_HDMI]) {
1743 if (adev->outputs[OUTPUT_LOW_LATENCY] != NULL &&
1744 !adev->outputs[OUTPUT_LOW_LATENCY]->standby) {
1745 struct tuna_stream_out *ll_out = adev->outputs[OUTPUT_LOW_LATENCY];
1746 pthread_mutex_lock(&ll_out->lock);
1747 do_output_standby(ll_out);
1748 pthread_mutex_unlock(&ll_out->lock);
1749 }
1750 }
1751
Eric Laurent023d8052011-08-22 18:19:26 -07001752 /* stop writing to echo reference */
1753 if (out->echo_reference != NULL) {
1754 out->echo_reference->write(out->echo_reference, NULL);
1755 out->echo_reference = NULL;
1756 }
Simon Wilson9700b232011-07-10 14:46:46 -07001757 }
Simon Wilson4a972582011-06-09 14:28:56 -07001758 return 0;
1759}
1760
Eric Laurent023d8052011-08-22 18:19:26 -07001761static int out_standby(struct audio_stream *stream)
1762{
1763 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1764 int status;
1765
1766 pthread_mutex_lock(&out->dev->lock);
1767 pthread_mutex_lock(&out->lock);
1768 status = do_output_standby(out);
1769 pthread_mutex_unlock(&out->lock);
1770 pthread_mutex_unlock(&out->dev->lock);
1771 return status;
1772}
1773
Simon Wilson4a972582011-06-09 14:28:56 -07001774static int out_dump(const struct audio_stream *stream, int fd)
1775{
1776 return 0;
1777}
1778
1779static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1780{
1781 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1782 struct tuna_audio_device *adev = out->dev;
Eric Laurent023d8052011-08-22 18:19:26 -07001783 struct tuna_stream_in *in;
Simon Wilson4a972582011-06-09 14:28:56 -07001784 struct str_parms *parms;
1785 char *str;
1786 char value[32];
Chris Kelly067d7522011-07-29 22:37:00 -05001787 int ret, val = 0;
Eric Laurent023d8052011-08-22 18:19:26 -07001788 bool force_input_standby = false;
Simon Wilson4a972582011-06-09 14:28:56 -07001789
1790 parms = str_parms_create_str(kvpairs);
Simon Wilson4a972582011-06-09 14:28:56 -07001791
1792 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1793 if (ret >= 0) {
Chris Kelly067d7522011-07-29 22:37:00 -05001794 val = atoi(value);
Eric Laurent023d8052011-08-22 18:19:26 -07001795 pthread_mutex_lock(&adev->lock);
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001796 pthread_mutex_lock(&out->lock);
Eric Laurent7530b972012-08-28 14:24:38 -07001797 if ((adev->out_device != val) && (val != 0)) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07001798 /* this is needed only when changing device on low latency output
1799 * as other output streams are not used for voice use cases nor
1800 * handle duplication to HDMI or SPDIF */
1801 if (out == adev->outputs[OUTPUT_LOW_LATENCY] && !out->standby) {
Eric Laurent023d8052011-08-22 18:19:26 -07001802 /* a change in output device may change the microphone selection */
1803 if (adev->active_input &&
1804 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1805 force_input_standby = true;
1806 }
Simon Wilson40c820f2012-01-25 10:29:55 -08001807 /* force standby if moving to/from HDMI/SPDIF or if the output
1808 * device changes when in HDMI/SPDIF mode */
Eric Laurent2cbfd062012-06-18 11:46:41 -07001809 /* FIXME also force standby when in call as some audio path switches do not work
1810 * while in call and an output stream is active (e.g BT SCO => earpiece) */
Eric Laurent78a76092012-03-16 18:59:28 -07001811
1812 /* FIXME workaround for audio being dropped when switching path without forcing standby
1813 * (several hundred ms of audio can be lost: e.g beginning of a ringtone. We must understand
1814 * the root cause in audio HAL, driver or ABE.
Simon Wilsoncc4b5c92011-09-27 12:20:23 -07001815 if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^
Eric Laurent7530b972012-08-28 14:24:38 -07001816 (adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
Simon Wilsoncc4b5c92011-09-27 12:20:23 -07001817 ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent7530b972012-08-28 14:24:38 -07001818 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1819 (adev->out_device & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
Simon Wilson40c820f2012-01-25 10:29:55 -08001820 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)))
Eric Laurent78a76092012-03-16 18:59:28 -07001821 */
1822 if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^
Eric Laurent7530b972012-08-28 14:24:38 -07001823 (adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
Eric Laurent78a76092012-03-16 18:59:28 -07001824 ((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
Eric Laurent7530b972012-08-28 14:24:38 -07001825 (adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
1826 (adev->out_device & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
Eric Laurent78a76092012-03-16 18:59:28 -07001827 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
Eric Laurent915f5d02012-03-26 19:02:43 -07001828 ((val & AUDIO_DEVICE_OUT_SPEAKER) ^
Eric Laurent7530b972012-08-28 14:24:38 -07001829 (adev->out_device & AUDIO_DEVICE_OUT_SPEAKER)) ||
Eric Laurent2cbfd062012-06-18 11:46:41 -07001830 (adev->mode == AUDIO_MODE_IN_CALL))
Simon Wilsoncc4b5c92011-09-27 12:20:23 -07001831 do_output_standby(out);
Chris Kelly9ce8ae72011-07-18 19:11:58 -05001832 }
Eric Laurent4bf3d142012-04-30 12:30:50 -07001833 if (out != adev->outputs[OUTPUT_HDMI]) {
Eric Laurent7530b972012-08-28 14:24:38 -07001834 adev->out_device = val;
Eric Laurent4bf3d142012-04-30 12:30:50 -07001835 select_output_device(adev);
1836 }
Eric Laurent023d8052011-08-22 18:19:26 -07001837 }
1838 pthread_mutex_unlock(&out->lock);
1839 if (force_input_standby) {
1840 in = adev->active_input;
1841 pthread_mutex_lock(&in->lock);
1842 do_input_standby(in);
1843 pthread_mutex_unlock(&in->lock);
1844 }
1845 pthread_mutex_unlock(&adev->lock);
Simon Wilson4a972582011-06-09 14:28:56 -07001846 }
1847
Simon Wilson4a972582011-06-09 14:28:56 -07001848 str_parms_destroy(parms);
1849 return ret;
1850}
1851
1852static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
1853{
Eric Laurent4bf3d142012-04-30 12:30:50 -07001854 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1855
1856 struct str_parms *query = str_parms_create_str(keys);
1857 char *str;
1858 char value[256];
1859 struct str_parms *reply = str_parms_create();
1860 size_t i, j;
1861 int ret;
1862 bool first = true;
1863
1864 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1865 if (ret >= 0) {
1866 value[0] = '\0';
1867 i = 0;
1868 while (out->sup_channel_masks[i] != 0) {
1869 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1870 if (out_channels_name_to_enum_table[j].value == out->sup_channel_masks[i]) {
1871 if (!first) {
1872 strcat(value, "|");
1873 }
1874 strcat(value, out_channels_name_to_enum_table[j].name);
1875 first = false;
1876 break;
1877 }
1878 }
1879 i++;
1880 }
1881 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Eric Laurente71d5702012-09-07 11:56:12 -07001882 str = str_parms_to_str(reply);
Eric Laurent4bf3d142012-04-30 12:30:50 -07001883 } else {
1884 str = strdup(keys);
1885 }
1886 str_parms_destroy(query);
1887 str_parms_destroy(reply);
1888 return str;
Simon Wilson4a972582011-06-09 14:28:56 -07001889}
1890
Eric Laurent4e7a5732012-04-13 16:58:17 -07001891static uint32_t out_get_latency_low_latency(const struct audio_stream_out *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07001892{
Eric Laurent371599a2011-07-08 17:16:43 -07001893 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
Simon Wilson4a972582011-06-09 14:28:56 -07001894
Simon Wilson40c820f2012-01-25 10:29:55 -08001895 /* Note: we use the default rate here from pcm_config_mm.rate */
Eric Laurent4e7a5732012-04-13 16:58:17 -07001896 return (SHORT_PERIOD_SIZE * PLAYBACK_SHORT_PERIOD_COUNT * 1000) / pcm_config_tones.rate;
1897}
1898
1899static uint32_t out_get_latency_deep_buffer(const struct audio_stream_out *stream)
1900{
1901 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1902
1903 /* Note: we use the default rate here from pcm_config_mm.rate */
Eric Laurent359a4162012-05-11 09:17:27 -07001904 return (DEEP_BUFFER_LONG_PERIOD_SIZE * PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT * 1000) /
1905 pcm_config_mm.rate;
Simon Wilson4a972582011-06-09 14:28:56 -07001906}
1907
Eric Laurent4bf3d142012-04-30 12:30:50 -07001908static uint32_t out_get_latency_hdmi(const struct audio_stream_out *stream)
1909{
1910 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1911
1912 return (HDMI_MULTI_PERIOD_SIZE * HDMI_MULTI_PERIOD_COUNT * 1000) / out->config[PCM_HDMI].rate;
1913}
1914
Simon Wilson4a972582011-06-09 14:28:56 -07001915static int out_set_volume(struct audio_stream_out *stream, float left,
1916 float right)
1917{
1918 return -ENOSYS;
1919}
1920
Eric Laurent4e7a5732012-04-13 16:58:17 -07001921static ssize_t out_write_low_latency(struct audio_stream_out *stream, const void* buffer,
Simon Wilson4a972582011-06-09 14:28:56 -07001922 size_t bytes)
1923{
1924 int ret;
1925 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
1926 struct tuna_audio_device *adev = out->dev;
Eric Laurent023d8052011-08-22 18:19:26 -07001927 size_t frame_size = audio_stream_frame_size(&out->stream.common);
1928 size_t in_frames = bytes / frame_size;
Eric Laurent4e7a5732012-04-13 16:58:17 -07001929 size_t out_frames = in_frames;
Eric Laurent023d8052011-08-22 18:19:26 -07001930 bool force_input_standby = false;
1931 struct tuna_stream_in *in;
Simon Wilson40c820f2012-01-25 10:29:55 -08001932 int i;
Simon Wilson4a972582011-06-09 14:28:56 -07001933
Eric Laurent023d8052011-08-22 18:19:26 -07001934 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
1935 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
1936 * mutex
1937 */
1938 pthread_mutex_lock(&adev->lock);
Simon Wilson4a972582011-06-09 14:28:56 -07001939 pthread_mutex_lock(&out->lock);
Simon Wilson9700b232011-07-10 14:46:46 -07001940 if (out->standby) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07001941 ret = start_output_stream_low_latency(out);
Eric Laurent753a1242011-10-13 08:46:22 -07001942 if (ret != 0) {
1943 pthread_mutex_unlock(&adev->lock);
1944 goto exit;
Eric Laurent023d8052011-08-22 18:19:26 -07001945 }
Eric Laurent753a1242011-10-13 08:46:22 -07001946 out->standby = 0;
1947 /* a change in output device may change the microphone selection */
1948 if (adev->active_input &&
1949 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
1950 force_input_standby = true;
Simon Wilson9700b232011-07-10 14:46:46 -07001951 }
Eric Laurent023d8052011-08-22 18:19:26 -07001952 pthread_mutex_unlock(&adev->lock);
Eric Laurentfa3998c2011-08-19 16:20:54 -07001953
Simon Wilson40c820f2012-01-25 10:29:55 -08001954 for (i = 0; i < PCM_TOTAL; i++) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07001955 /* only use resampler if required */
1956 if (out->pcm[i] && (out->config[i].rate != DEFAULT_OUT_SAMPLING_RATE)) {
1957 out_frames = out->buffer_frames;
1958 out->resampler->resample_from_input(out->resampler,
1959 (int16_t *)buffer,
1960 &in_frames,
1961 (int16_t *)out->buffer,
1962 &out_frames);
1963 break;
Simon Wilson40c820f2012-01-25 10:29:55 -08001964 }
1965 }
1966
Eric Laurent023d8052011-08-22 18:19:26 -07001967 if (out->echo_reference != NULL) {
1968 struct echo_reference_buffer b;
1969 b.raw = (void *)buffer;
Eric Laurent209789d2011-10-05 11:52:08 -07001970 b.frame_count = in_frames;
Eric Laurent023d8052011-08-22 18:19:26 -07001971
1972 get_playback_delay(out, out_frames, &b);
1973 out->echo_reference->write(out->echo_reference, &b);
1974 }
1975
Simon Wilson40c820f2012-01-25 10:29:55 -08001976 /* Write to all active PCMs */
1977 for (i = 0; i < PCM_TOTAL; i++) {
1978 if (out->pcm[i]) {
1979 if (out->config[i].rate == DEFAULT_OUT_SAMPLING_RATE) {
1980 /* PCM uses native sample rate */
Glenn Kasten47623d42012-02-14 13:54:03 -08001981 ret = PCM_WRITE(out->pcm[i], (void *)buffer, bytes);
Simon Wilson40c820f2012-01-25 10:29:55 -08001982 } else {
1983 /* PCM needs resampler */
Glenn Kasten47623d42012-02-14 13:54:03 -08001984 ret = PCM_WRITE(out->pcm[i], (void *)out->buffer, out_frames * frame_size);
Simon Wilson40c820f2012-01-25 10:29:55 -08001985 }
1986 if (ret)
1987 break;
1988 }
1989 }
Eric Laurent753a1242011-10-13 08:46:22 -07001990
1991exit:
Simon Wilson4a972582011-06-09 14:28:56 -07001992 pthread_mutex_unlock(&out->lock);
Eric Laurent023d8052011-08-22 18:19:26 -07001993
Eric Laurent753a1242011-10-13 08:46:22 -07001994 if (ret != 0) {
1995 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
1996 out_get_sample_rate(&stream->common));
1997 }
1998
Eric Laurent023d8052011-08-22 18:19:26 -07001999 if (force_input_standby) {
2000 pthread_mutex_lock(&adev->lock);
2001 if (adev->active_input) {
2002 in = adev->active_input;
2003 pthread_mutex_lock(&in->lock);
2004 do_input_standby(in);
2005 pthread_mutex_unlock(&in->lock);
2006 }
2007 pthread_mutex_unlock(&adev->lock);
2008 }
2009
Simon Wilson4a972582011-06-09 14:28:56 -07002010 return bytes;
2011}
2012
Eric Laurent4e7a5732012-04-13 16:58:17 -07002013static ssize_t out_write_deep_buffer(struct audio_stream_out *stream, const void* buffer,
2014 size_t bytes)
2015{
2016 int ret;
2017 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
2018 struct tuna_audio_device *adev = out->dev;
2019 size_t frame_size = audio_stream_frame_size(&out->stream.common);
2020 size_t in_frames = bytes / frame_size;
Eric Laurent359a4162012-05-11 09:17:27 -07002021 size_t out_frames;
2022 bool use_long_periods;
2023 int kernel_frames;
2024 void *buf;
Eric Laurent4e7a5732012-04-13 16:58:17 -07002025
2026 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
2027 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
2028 * mutex
2029 */
2030 pthread_mutex_lock(&adev->lock);
2031 pthread_mutex_lock(&out->lock);
2032 if (out->standby) {
2033 ret = start_output_stream_deep_buffer(out);
2034 if (ret != 0) {
2035 pthread_mutex_unlock(&adev->lock);
2036 goto exit;
2037 }
2038 out->standby = 0;
2039 }
Eric Laurent359a4162012-05-11 09:17:27 -07002040 use_long_periods = adev->screen_off && !adev->active_input;
Eric Laurent4e7a5732012-04-13 16:58:17 -07002041 pthread_mutex_unlock(&adev->lock);
2042
Eric Laurent359a4162012-05-11 09:17:27 -07002043 if (use_long_periods != out->use_long_periods) {
2044 size_t period_size;
2045 size_t period_count;
2046
2047 if (use_long_periods) {
2048 period_size = DEEP_BUFFER_LONG_PERIOD_SIZE;
2049 period_count = PLAYBACK_DEEP_BUFFER_LONG_PERIOD_COUNT;
2050 } else {
2051 period_size = DEEP_BUFFER_SHORT_PERIOD_SIZE;
2052 period_count = PLAYBACK_DEEP_BUFFER_SHORT_PERIOD_COUNT;
2053 }
2054 out->write_threshold = period_size * period_count;
2055 pcm_set_avail_min(out->pcm[PCM_NORMAL], period_size);
2056 out->use_long_periods = use_long_periods;
2057 }
2058
Eric Laurent4e7a5732012-04-13 16:58:17 -07002059 /* only use resampler if required */
2060 if (out->config[PCM_NORMAL].rate != DEFAULT_OUT_SAMPLING_RATE) {
Eric Laurent359a4162012-05-11 09:17:27 -07002061 out_frames = out->buffer_frames;
Eric Laurent4e7a5732012-04-13 16:58:17 -07002062 out->resampler->resample_from_input(out->resampler,
2063 (int16_t *)buffer,
2064 &in_frames,
2065 (int16_t *)out->buffer,
2066 &out_frames);
Eric Laurent359a4162012-05-11 09:17:27 -07002067 buf = (void *)out->buffer;
2068 } else {
2069 out_frames = in_frames;
2070 buf = (void *)buffer;
2071 }
2072
2073 /* do not allow more than out->write_threshold frames in kernel pcm driver buffer */
2074 do {
2075 struct timespec time_stamp;
2076
2077 if (pcm_get_htimestamp(out->pcm[PCM_NORMAL],
2078 (unsigned int *)&kernel_frames, &time_stamp) < 0)
2079 break;
2080 kernel_frames = pcm_get_buffer_size(out->pcm[PCM_NORMAL]) - kernel_frames;
2081
2082 if (kernel_frames > out->write_threshold) {
2083 unsigned long time = (unsigned long)
2084 (((int64_t)(kernel_frames - out->write_threshold) * 1000000) /
2085 MM_FULL_POWER_SAMPLING_RATE);
2086 if (time < MIN_WRITE_SLEEP_US)
2087 time = MIN_WRITE_SLEEP_US;
2088 usleep(time);
2089 }
2090 } while (kernel_frames > out->write_threshold);
2091
2092 ret = pcm_mmap_write(out->pcm[PCM_NORMAL], buf, out_frames * frame_size);
Eric Laurent4e7a5732012-04-13 16:58:17 -07002093
2094exit:
2095 pthread_mutex_unlock(&out->lock);
2096
2097 if (ret != 0) {
2098 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
2099 out_get_sample_rate(&stream->common));
2100 }
2101
2102 return bytes;
2103}
2104
Eric Laurent4bf3d142012-04-30 12:30:50 -07002105static ssize_t out_write_hdmi(struct audio_stream_out *stream, const void* buffer,
2106 size_t bytes)
2107{
2108 int ret;
2109 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
2110 struct tuna_audio_device *adev = out->dev;
2111 size_t frame_size = audio_stream_frame_size(&out->stream.common);
2112 size_t in_frames = bytes / frame_size;
2113
2114 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
2115 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
2116 * mutex
2117 */
2118 pthread_mutex_lock(&adev->lock);
2119 pthread_mutex_lock(&out->lock);
2120 if (out->standby) {
2121 ret = start_output_stream_hdmi(out);
2122 if (ret != 0) {
2123 pthread_mutex_unlock(&adev->lock);
2124 goto exit;
2125 }
2126 out->standby = 0;
2127 }
2128 pthread_mutex_unlock(&adev->lock);
2129
2130 ret = pcm_write(out->pcm[PCM_HDMI],
2131 buffer,
2132 pcm_frames_to_bytes(out->pcm[PCM_HDMI], in_frames));
2133
2134exit:
2135 pthread_mutex_unlock(&out->lock);
2136
2137 if (ret != 0) {
2138 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
2139 out_get_sample_rate_hdmi(&stream->common));
2140 }
Eric Laurentd84a8f82012-06-11 12:36:38 -07002141 /* FIXME: workaround for HDMI multi channel channel swap on first playback after opening
2142 * the output stream: force reopening the pcm driver after writing a few periods. */
2143 if ((out->restart_periods_cnt > 0) &&
2144 (--out->restart_periods_cnt == 0))
2145 out_standby(&stream->common);
Eric Laurent4bf3d142012-04-30 12:30:50 -07002146
2147 return bytes;
2148}
2149
Simon Wilson4a972582011-06-09 14:28:56 -07002150static int out_get_render_position(const struct audio_stream_out *stream,
2151 uint32_t *dsp_frames)
2152{
2153 return -EINVAL;
2154}
2155
Eric Laurent27fda172011-07-11 12:21:56 -07002156static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
2157{
2158 return 0;
2159}
2160
2161static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
2162{
2163 return 0;
2164}
2165
Simon Wilson4a972582011-06-09 14:28:56 -07002166/** audio_stream_in implementation **/
Eric Laurent023d8052011-08-22 18:19:26 -07002167
2168/* must be called with hw device and input stream mutexes locked */
Simon Wilson1bf73172011-06-27 15:45:08 -07002169static int start_input_stream(struct tuna_stream_in *in)
2170{
2171 int ret = 0;
2172 struct tuna_audio_device *adev = in->dev;
2173
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002174 adev->active_input = in;
Eric Laurent023d8052011-08-22 18:19:26 -07002175
2176 if (adev->mode != AUDIO_MODE_IN_CALL) {
Eric Laurent7530b972012-08-28 14:24:38 -07002177 adev->in_device = in->device;
Eric Laurent023d8052011-08-22 18:19:26 -07002178 select_input_device(adev);
2179 }
2180
Eric Laurent139959c2012-03-30 15:51:03 -07002181 if (in->aux_channels_changed)
2182 {
2183 in->aux_channels_changed = false;
2184 in->config.channels = popcount(in->main_channels | in->aux_channels);
2185
2186 if (in->resampler) {
2187 /* release and recreate the resampler with the new number of channel of the input */
2188 release_resampler(in->resampler);
2189 in->resampler = NULL;
2190 ret = create_resampler(in->config.rate,
2191 in->requested_rate,
2192 in->config.channels,
2193 RESAMPLER_QUALITY_DEFAULT,
2194 &in->buf_provider,
2195 &in->resampler);
2196 }
2197 ALOGV("start_input_stream(): New channel configuration, "
2198 "main_channels = [%04x], aux_channels = [%04x], config.channels = %d",
2199 in->main_channels, in->aux_channels, in->config.channels);
2200 }
2201
Eric Laurent023d8052011-08-22 18:19:26 -07002202 if (in->need_echo_reference && in->echo_reference == NULL)
2203 in->echo_reference = get_echo_reference(adev,
2204 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent69645ac2012-08-30 11:20:32 -07002205 popcount(in->main_channels),
Eric Laurent023d8052011-08-22 18:19:26 -07002206 in->requested_rate);
Simon Wilson1bf73172011-06-27 15:45:08 -07002207
2208 /* this assumes routing is done previously */
Simon Wilson4283faf2011-09-08 20:27:33 -07002209 in->pcm = pcm_open(0, PORT_MM2_UL, PCM_IN, &in->config);
Simon Wilson1bf73172011-06-27 15:45:08 -07002210 if (!pcm_is_ready(in->pcm)) {
Steve Block87efd3f2012-01-08 10:19:03 +00002211 ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
Simon Wilson1bf73172011-06-27 15:45:08 -07002212 pcm_close(in->pcm);
Eric Laurent023d8052011-08-22 18:19:26 -07002213 adev->active_input = NULL;
Simon Wilson1bf73172011-06-27 15:45:08 -07002214 return -ENOMEM;
2215 }
Eric Laurent023d8052011-08-22 18:19:26 -07002216
Eric Laurent139959c2012-03-30 15:51:03 -07002217 /* force read and proc buf reallocation case of frame size or channel count change */
2218 in->read_buf_frames = 0;
2219 in->read_buf_size = 0;
2220 in->proc_buf_frames = 0;
2221 in->proc_buf_size = 0;
Simon Wilson1bf73172011-06-27 15:45:08 -07002222 /* if no supported sample rate is available, use the resampler */
Eric Laurentfa3998c2011-08-19 16:20:54 -07002223 if (in->resampler) {
2224 in->resampler->reset(in->resampler);
Simon Wilson1bf73172011-06-27 15:45:08 -07002225 }
2226 return 0;
2227}
2228
Simon Wilson4a972582011-06-09 14:28:56 -07002229static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2230{
Simon Wilson1bf73172011-06-27 15:45:08 -07002231 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
2232
2233 return in->requested_rate;
Simon Wilson4a972582011-06-09 14:28:56 -07002234}
2235
2236static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2237{
2238 return 0;
2239}
2240
2241static size_t in_get_buffer_size(const struct audio_stream *stream)
2242{
Simon Wilson1bf73172011-06-27 15:45:08 -07002243 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
Simon Wilson1bf73172011-06-27 15:45:08 -07002244
Eric Laurent3c930972011-07-14 18:49:47 -07002245 return get_input_buffer_size(in->requested_rate,
2246 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent139959c2012-03-30 15:51:03 -07002247 popcount(in->main_channels));
Simon Wilson4a972582011-06-09 14:28:56 -07002248}
2249
Glenn Kasten8eb734e2012-03-14 12:50:51 -07002250static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07002251{
Eric Laurent3c930972011-07-14 18:49:47 -07002252 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
2253
Eric Laurent139959c2012-03-30 15:51:03 -07002254 return in->main_channels;
Simon Wilson4a972582011-06-09 14:28:56 -07002255}
2256
Glenn Kastenb9637562012-01-12 11:46:47 -08002257static audio_format_t in_get_format(const struct audio_stream *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07002258{
2259 return AUDIO_FORMAT_PCM_16_BIT;
2260}
2261
Glenn Kastenb9637562012-01-12 11:46:47 -08002262static int in_set_format(struct audio_stream *stream, audio_format_t format)
Simon Wilson4a972582011-06-09 14:28:56 -07002263{
2264 return 0;
2265}
2266
Eric Laurent023d8052011-08-22 18:19:26 -07002267/* must be called with hw device and input stream mutexes locked */
2268static int do_input_standby(struct tuna_stream_in *in)
Simon Wilson4a972582011-06-09 14:28:56 -07002269{
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002270 struct tuna_audio_device *adev = in->dev;
Simon Wilson1bf73172011-06-27 15:45:08 -07002271
Simon Wilson1bf73172011-06-27 15:45:08 -07002272 if (!in->standby) {
2273 pcm_close(in->pcm);
2274 in->pcm = NULL;
Eric Laurent023d8052011-08-22 18:19:26 -07002275
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002276 adev->active_input = 0;
Eric Laurent023d8052011-08-22 18:19:26 -07002277 if (adev->mode != AUDIO_MODE_IN_CALL) {
Eric Laurent7530b972012-08-28 14:24:38 -07002278 adev->in_device = AUDIO_DEVICE_NONE;
Eric Laurent023d8052011-08-22 18:19:26 -07002279 select_input_device(adev);
2280 }
2281
2282 if (in->echo_reference != NULL) {
2283 /* stop reading from echo reference */
2284 in->echo_reference->read(in->echo_reference, NULL);
2285 put_echo_reference(adev, in->echo_reference);
2286 in->echo_reference = NULL;
2287 }
2288
Simon Wilson1bf73172011-06-27 15:45:08 -07002289 in->standby = 1;
2290 }
Simon Wilson4a972582011-06-09 14:28:56 -07002291 return 0;
2292}
2293
Eric Laurent023d8052011-08-22 18:19:26 -07002294static int in_standby(struct audio_stream *stream)
2295{
2296 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
2297 int status;
2298
2299 pthread_mutex_lock(&in->dev->lock);
2300 pthread_mutex_lock(&in->lock);
2301 status = do_input_standby(in);
2302 pthread_mutex_unlock(&in->lock);
2303 pthread_mutex_unlock(&in->dev->lock);
2304 return status;
2305}
2306
Simon Wilson4a972582011-06-09 14:28:56 -07002307static int in_dump(const struct audio_stream *stream, int fd)
2308{
2309 return 0;
2310}
2311
2312static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2313{
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002314 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
2315 struct tuna_audio_device *adev = in->dev;
2316 struct str_parms *parms;
2317 char *str;
2318 char value[32];
2319 int ret, val = 0;
Simon Wilson2b45e732011-08-22 16:49:03 -07002320 bool do_standby = false;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002321
2322 parms = str_parms_create_str(kvpairs);
2323
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -07002324 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
Eric Laurent023d8052011-08-22 18:19:26 -07002325
2326 pthread_mutex_lock(&adev->lock);
2327 pthread_mutex_lock(&in->lock);
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -07002328 if (ret >= 0) {
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -07002329 val = atoi(value);
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -07002330 /* no audio source uses val == 0 */
Simon Wilson2b45e732011-08-22 16:49:03 -07002331 if ((in->source != val) && (val != 0)) {
2332 in->source = val;
2333 do_standby = true;
Simon Wilsonf2f0dcc2011-08-08 21:19:07 -07002334 }
2335 }
2336
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002337 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2338 if (ret >= 0) {
Eric Laurent7530b972012-08-28 14:24:38 -07002339 val = atoi(value) & ~AUDIO_DEVICE_BIT_IN;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002340 if ((in->device != val) && (val != 0)) {
2341 in->device = val;
Simon Wilson2b45e732011-08-22 16:49:03 -07002342 do_standby = true;
Eric Laurent139959c2012-03-30 15:51:03 -07002343 /* make sure new device selection is incompatible with multi-mic pre processing
2344 * configuration */
2345 in_update_aux_channels(in, NULL);
Simon Wilson2b45e732011-08-22 16:49:03 -07002346 }
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002347 }
2348
Simon Wilson2b45e732011-08-22 16:49:03 -07002349 if (do_standby)
Eric Laurent023d8052011-08-22 18:19:26 -07002350 do_input_standby(in);
2351 pthread_mutex_unlock(&in->lock);
2352 pthread_mutex_unlock(&adev->lock);
Simon Wilson2b45e732011-08-22 16:49:03 -07002353
Chris Kelly9ce8ae72011-07-18 19:11:58 -05002354 str_parms_destroy(parms);
2355 return ret;
Simon Wilson4a972582011-06-09 14:28:56 -07002356}
2357
2358static char * in_get_parameters(const struct audio_stream *stream,
2359 const char *keys)
2360{
2361 return strdup("");
2362}
2363
2364static int in_set_gain(struct audio_stream_in *stream, float gain)
2365{
2366 return 0;
2367}
2368
Eric Laurent023d8052011-08-22 18:19:26 -07002369static void get_capture_delay(struct tuna_stream_in *in,
2370 size_t frames,
2371 struct echo_reference_buffer *buffer)
2372{
2373
2374 /* read frames available in kernel driver buffer */
2375 size_t kernel_frames;
2376 struct timespec tstamp;
2377 long buf_delay;
2378 long rsmp_delay;
2379 long kernel_delay;
2380 long delay_ns;
2381
2382 if (pcm_get_htimestamp(in->pcm, &kernel_frames, &tstamp) < 0) {
2383 buffer->time_stamp.tv_sec = 0;
2384 buffer->time_stamp.tv_nsec = 0;
2385 buffer->delay_ns = 0;
Steve Blockc0212a22012-01-05 23:28:09 +00002386 ALOGW("read get_capture_delay(): pcm_htimestamp error");
Eric Laurent023d8052011-08-22 18:19:26 -07002387 return;
2388 }
2389
2390 /* read frames available in audio HAL input buffer
2391 * add number of frames being read as we want the capture time of first sample
2392 * in current buffer */
Eric Laurent22ab5222012-03-30 09:43:23 -07002393 /* frames in in->buffer are at driver sampling rate while frames in in->proc_buf are
2394 * at requested sampling rate */
Eric Laurent139959c2012-03-30 15:51:03 -07002395 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
2396 ((int64_t)(in->proc_buf_frames) * 1000000000) /
2397 in->requested_rate);
Eric Laurent22ab5222012-03-30 09:43:23 -07002398
Eric Laurent023d8052011-08-22 18:19:26 -07002399 /* add delay introduced by resampler */
2400 rsmp_delay = 0;
2401 if (in->resampler) {
2402 rsmp_delay = in->resampler->delay_ns(in->resampler);
2403 }
2404
2405 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
2406
2407 delay_ns = kernel_delay + buf_delay + rsmp_delay;
2408
2409 buffer->time_stamp = tstamp;
2410 buffer->delay_ns = delay_ns;
Steve Block6bf50092011-10-20 11:56:21 +01002411 ALOGV("get_capture_delay time_stamp = [%ld].[%ld], delay_ns: [%d],"
Eric Laurent023d8052011-08-22 18:19:26 -07002412 " kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], kernel_frames:[%d], "
Eric Laurent139959c2012-03-30 15:51:03 -07002413 "in->read_buf_frames:[%d], in->proc_buf_frames:[%d], frames:[%d]",
Eric Laurent023d8052011-08-22 18:19:26 -07002414 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, buffer->delay_ns,
2415 kernel_delay, buf_delay, rsmp_delay, kernel_frames,
Eric Laurent139959c2012-03-30 15:51:03 -07002416 in->read_buf_frames, in->proc_buf_frames, frames);
Eric Laurent023d8052011-08-22 18:19:26 -07002417
2418}
2419
2420static int32_t update_echo_reference(struct tuna_stream_in *in, size_t frames)
2421{
2422 struct echo_reference_buffer b;
2423 b.delay_ns = 0;
2424
Eric Laurent139959c2012-03-30 15:51:03 -07002425 ALOGV("update_echo_reference, frames = [%d], in->ref_buf_frames = [%d], "
Eric Laurent023d8052011-08-22 18:19:26 -07002426 "b.frame_count = [%d]",
Eric Laurent139959c2012-03-30 15:51:03 -07002427 frames, in->ref_buf_frames, frames - in->ref_buf_frames);
2428 if (in->ref_buf_frames < frames) {
Eric Laurent023d8052011-08-22 18:19:26 -07002429 if (in->ref_buf_size < frames) {
2430 in->ref_buf_size = frames;
Eric Laurent139959c2012-03-30 15:51:03 -07002431 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(in->pcm, frames));
2432 ALOG_ASSERT((in->ref_buf != NULL),
2433 "update_echo_reference() failed to reallocate ref_buf");
2434 ALOGV("update_echo_reference(): ref_buf %p extended to %d bytes",
2435 in->ref_buf, pcm_frames_to_bytes(in->pcm, frames));
Eric Laurent023d8052011-08-22 18:19:26 -07002436 }
Eric Laurent139959c2012-03-30 15:51:03 -07002437 b.frame_count = frames - in->ref_buf_frames;
2438 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
Eric Laurent023d8052011-08-22 18:19:26 -07002439
2440 get_capture_delay(in, frames, &b);
2441
2442 if (in->echo_reference->read(in->echo_reference, &b) == 0)
2443 {
Eric Laurent139959c2012-03-30 15:51:03 -07002444 in->ref_buf_frames += b.frame_count;
2445 ALOGV("update_echo_reference(): in->ref_buf_frames:[%d], "
Eric Laurent023d8052011-08-22 18:19:26 -07002446 "in->ref_buf_size:[%d], frames:[%d], b.frame_count:[%d]",
Eric Laurent139959c2012-03-30 15:51:03 -07002447 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
Eric Laurent023d8052011-08-22 18:19:26 -07002448 }
2449 } else
Eric Laurent139959c2012-03-30 15:51:03 -07002450 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
Eric Laurent023d8052011-08-22 18:19:26 -07002451 return b.delay_ns;
2452}
2453
2454static int set_preprocessor_param(effect_handle_t handle,
2455 effect_param_t *param)
2456{
2457 uint32_t size = sizeof(int);
2458 uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
2459 param->vsize;
2460
2461 int status = (*handle)->command(handle,
2462 EFFECT_CMD_SET_PARAM,
2463 sizeof (effect_param_t) + psize,
2464 param,
2465 &size,
2466 &param->status);
2467 if (status == 0)
2468 status = param->status;
2469
2470 return status;
2471}
2472
2473static int set_preprocessor_echo_delay(effect_handle_t handle,
2474 int32_t delay_us)
2475{
2476 uint32_t buf[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
2477 effect_param_t *param = (effect_param_t *)buf;
2478
2479 param->psize = sizeof(uint32_t);
2480 param->vsize = sizeof(uint32_t);
2481 *(uint32_t *)param->data = AEC_PARAM_ECHO_DELAY;
2482 *((int32_t *)param->data + 1) = delay_us;
2483
2484 return set_preprocessor_param(handle, param);
2485}
2486
2487static void push_echo_reference(struct tuna_stream_in *in, size_t frames)
2488{
2489 /* read frames from echo reference buffer and update echo delay
Eric Laurent139959c2012-03-30 15:51:03 -07002490 * in->ref_buf_frames is updated with frames available in in->ref_buf */
Eric Laurent023d8052011-08-22 18:19:26 -07002491 int32_t delay_us = update_echo_reference(in, frames)/1000;
2492 int i;
2493 audio_buffer_t buf;
2494
Eric Laurent139959c2012-03-30 15:51:03 -07002495 if (in->ref_buf_frames < frames)
2496 frames = in->ref_buf_frames;
Eric Laurent023d8052011-08-22 18:19:26 -07002497
2498 buf.frameCount = frames;
2499 buf.raw = in->ref_buf;
2500
2501 for (i = 0; i < in->num_preprocessors; i++) {
Eric Laurent139959c2012-03-30 15:51:03 -07002502 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
Eric Laurent023d8052011-08-22 18:19:26 -07002503 continue;
2504
Eric Laurent139959c2012-03-30 15:51:03 -07002505 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
Eric Laurent023d8052011-08-22 18:19:26 -07002506 &buf,
2507 NULL);
Eric Laurent139959c2012-03-30 15:51:03 -07002508 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
Eric Laurent023d8052011-08-22 18:19:26 -07002509 }
2510
Eric Laurent139959c2012-03-30 15:51:03 -07002511 in->ref_buf_frames -= buf.frameCount;
2512 if (in->ref_buf_frames) {
Eric Laurent023d8052011-08-22 18:19:26 -07002513 memcpy(in->ref_buf,
2514 in->ref_buf + buf.frameCount * in->config.channels,
Eric Laurent139959c2012-03-30 15:51:03 -07002515 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
Eric Laurent023d8052011-08-22 18:19:26 -07002516 }
2517}
2518
2519static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
2520 struct resampler_buffer* buffer)
2521{
2522 struct tuna_stream_in *in;
2523
2524 if (buffer_provider == NULL || buffer == NULL)
2525 return -EINVAL;
2526
2527 in = (struct tuna_stream_in *)((char *)buffer_provider -
2528 offsetof(struct tuna_stream_in, buf_provider));
2529
2530 if (in->pcm == NULL) {
2531 buffer->raw = NULL;
2532 buffer->frame_count = 0;
2533 in->read_status = -ENODEV;
2534 return -ENODEV;
2535 }
2536
Eric Laurent139959c2012-03-30 15:51:03 -07002537 if (in->read_buf_frames == 0) {
2538 size_t size_in_bytes = pcm_frames_to_bytes(in->pcm, in->config.period_size);
2539 if (in->read_buf_size < in->config.period_size) {
2540 in->read_buf_size = in->config.period_size;
2541 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
2542 ALOG_ASSERT((in->read_buf != NULL),
2543 "get_next_buffer() failed to reallocate read_buf");
2544 ALOGV("get_next_buffer(): read_buf %p extended to %d bytes",
2545 in->read_buf, size_in_bytes);
2546 }
2547
2548 in->read_status = pcm_read(in->pcm, (void*)in->read_buf, size_in_bytes);
2549
Eric Laurent023d8052011-08-22 18:19:26 -07002550 if (in->read_status != 0) {
Steve Block87efd3f2012-01-08 10:19:03 +00002551 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
Eric Laurent023d8052011-08-22 18:19:26 -07002552 buffer->raw = NULL;
2553 buffer->frame_count = 0;
2554 return in->read_status;
2555 }
Eric Laurent139959c2012-03-30 15:51:03 -07002556 in->read_buf_frames = in->config.period_size;
Eric Laurent023d8052011-08-22 18:19:26 -07002557 }
2558
Eric Laurent139959c2012-03-30 15:51:03 -07002559 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
2560 in->read_buf_frames : buffer->frame_count;
2561 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
Eric Laurent023d8052011-08-22 18:19:26 -07002562 in->config.channels;
2563
2564 return in->read_status;
2565
2566}
2567
2568static void release_buffer(struct resampler_buffer_provider *buffer_provider,
2569 struct resampler_buffer* buffer)
2570{
2571 struct tuna_stream_in *in;
2572
2573 if (buffer_provider == NULL || buffer == NULL)
2574 return;
2575
2576 in = (struct tuna_stream_in *)((char *)buffer_provider -
2577 offsetof(struct tuna_stream_in, buf_provider));
2578
Eric Laurent139959c2012-03-30 15:51:03 -07002579 in->read_buf_frames -= buffer->frame_count;
Eric Laurent023d8052011-08-22 18:19:26 -07002580}
2581
2582/* read_frames() reads frames from kernel driver, down samples to capture rate
2583 * if necessary and output the number of frames requested to the buffer specified */
2584static ssize_t read_frames(struct tuna_stream_in *in, void *buffer, ssize_t frames)
2585{
2586 ssize_t frames_wr = 0;
2587
2588 while (frames_wr < frames) {
2589 size_t frames_rd = frames - frames_wr;
2590 if (in->resampler != NULL) {
2591 in->resampler->resample_from_provider(in->resampler,
Eric Laurent139959c2012-03-30 15:51:03 -07002592 (int16_t *)((char *)buffer +
2593 pcm_frames_to_bytes(in->pcm ,frames_wr)),
2594 &frames_rd);
2595
Eric Laurent023d8052011-08-22 18:19:26 -07002596 } else {
2597 struct resampler_buffer buf = {
2598 { raw : NULL, },
2599 frame_count : frames_rd,
2600 };
2601 get_next_buffer(&in->buf_provider, &buf);
2602 if (buf.raw != NULL) {
2603 memcpy((char *)buffer +
Eric Laurent139959c2012-03-30 15:51:03 -07002604 pcm_frames_to_bytes(in->pcm, frames_wr),
Eric Laurent023d8052011-08-22 18:19:26 -07002605 buf.raw,
Eric Laurent139959c2012-03-30 15:51:03 -07002606 pcm_frames_to_bytes(in->pcm, buf.frame_count));
Eric Laurent023d8052011-08-22 18:19:26 -07002607 frames_rd = buf.frame_count;
2608 }
2609 release_buffer(&in->buf_provider, &buf);
2610 }
2611 /* in->read_status is updated by getNextBuffer() also called by
2612 * in->resampler->resample_from_provider() */
2613 if (in->read_status != 0)
2614 return in->read_status;
2615
2616 frames_wr += frames_rd;
2617 }
2618 return frames_wr;
2619}
2620
2621/* process_frames() reads frames from kernel driver (via read_frames()),
2622 * calls the active audio pre processings and output the number of frames requested
2623 * to the buffer specified */
2624static ssize_t process_frames(struct tuna_stream_in *in, void* buffer, ssize_t frames)
2625{
2626 ssize_t frames_wr = 0;
2627 audio_buffer_t in_buf;
2628 audio_buffer_t out_buf;
2629 int i;
Eric Laurent139959c2012-03-30 15:51:03 -07002630 bool has_aux_channels = (~in->main_channels & in->aux_channels);
2631 void *proc_buf_out;
Eric Laurent023d8052011-08-22 18:19:26 -07002632
Eric Laurent139959c2012-03-30 15:51:03 -07002633 if (has_aux_channels)
2634 proc_buf_out = in->proc_buf_out;
2635 else
2636 proc_buf_out = buffer;
2637
2638 /* since all the processing below is done in frames and using the config.channels
2639 * as the number of channels, no changes is required in case aux_channels are present */
Eric Laurent023d8052011-08-22 18:19:26 -07002640 while (frames_wr < frames) {
2641 /* first reload enough frames at the end of process input buffer */
Eric Laurent139959c2012-03-30 15:51:03 -07002642 if (in->proc_buf_frames < (size_t)frames) {
Eric Laurent023d8052011-08-22 18:19:26 -07002643 ssize_t frames_rd;
2644
2645 if (in->proc_buf_size < (size_t)frames) {
Eric Laurent139959c2012-03-30 15:51:03 -07002646 size_t size_in_bytes = pcm_frames_to_bytes(in->pcm, frames);
2647
Eric Laurent023d8052011-08-22 18:19:26 -07002648 in->proc_buf_size = (size_t)frames;
Eric Laurent139959c2012-03-30 15:51:03 -07002649 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
2650 ALOG_ASSERT((in->proc_buf_in != NULL),
2651 "process_frames() failed to reallocate proc_buf_in");
2652 if (has_aux_channels) {
2653 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
2654 ALOG_ASSERT((in->proc_buf_out != NULL),
2655 "process_frames() failed to reallocate proc_buf_out");
2656 proc_buf_out = in->proc_buf_out;
2657 }
2658 ALOGV("process_frames(): proc_buf_in %p extended to %d bytes",
2659 in->proc_buf_in, size_in_bytes);
Eric Laurent023d8052011-08-22 18:19:26 -07002660 }
2661 frames_rd = read_frames(in,
Eric Laurent139959c2012-03-30 15:51:03 -07002662 in->proc_buf_in +
2663 in->proc_buf_frames * in->config.channels,
2664 frames - in->proc_buf_frames);
Eric Laurent023d8052011-08-22 18:19:26 -07002665 if (frames_rd < 0) {
2666 frames_wr = frames_rd;
2667 break;
2668 }
Eric Laurent139959c2012-03-30 15:51:03 -07002669 in->proc_buf_frames += frames_rd;
Eric Laurent023d8052011-08-22 18:19:26 -07002670 }
2671
2672 if (in->echo_reference != NULL)
Eric Laurent139959c2012-03-30 15:51:03 -07002673 push_echo_reference(in, in->proc_buf_frames);
Eric Laurent023d8052011-08-22 18:19:26 -07002674
2675 /* in_buf.frameCount and out_buf.frameCount indicate respectively
2676 * the maximum number of frames to be consumed and produced by process() */
Eric Laurent139959c2012-03-30 15:51:03 -07002677 in_buf.frameCount = in->proc_buf_frames;
2678 in_buf.s16 = in->proc_buf_in;
Eric Laurent023d8052011-08-22 18:19:26 -07002679 out_buf.frameCount = frames - frames_wr;
Eric Laurent139959c2012-03-30 15:51:03 -07002680 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
Eric Laurent023d8052011-08-22 18:19:26 -07002681
Eric Laurent139959c2012-03-30 15:51:03 -07002682 /* FIXME: this works because of current pre processing library implementation that
2683 * does the actual process only when the last enabled effect process is called.
2684 * The generic solution is to have an output buffer for each effect and pass it as
2685 * input to the next.
2686 */
2687 for (i = 0; i < in->num_preprocessors; i++) {
2688 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
Eric Laurent023d8052011-08-22 18:19:26 -07002689 &in_buf,
2690 &out_buf);
Eric Laurent139959c2012-03-30 15:51:03 -07002691 }
Eric Laurent023d8052011-08-22 18:19:26 -07002692
2693 /* process() has updated the number of frames consumed and produced in
2694 * in_buf.frameCount and out_buf.frameCount respectively
Eric Laurent139959c2012-03-30 15:51:03 -07002695 * move remaining frames to the beginning of in->proc_buf_in */
2696 in->proc_buf_frames -= in_buf.frameCount;
2697
2698 if (in->proc_buf_frames) {
2699 memcpy(in->proc_buf_in,
2700 in->proc_buf_in + in_buf.frameCount * in->config.channels,
2701 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
Eric Laurent023d8052011-08-22 18:19:26 -07002702 }
2703
2704 /* if not enough frames were passed to process(), read more and retry. */
Eric Laurent139959c2012-03-30 15:51:03 -07002705 if (out_buf.frameCount == 0) {
2706 ALOGW("No frames produced by preproc");
Eric Laurent023d8052011-08-22 18:19:26 -07002707 continue;
Eric Laurent139959c2012-03-30 15:51:03 -07002708 }
Eric Laurent023d8052011-08-22 18:19:26 -07002709
Eric Laurent139959c2012-03-30 15:51:03 -07002710 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
2711 frames_wr += out_buf.frameCount;
2712 } else {
2713 /* The effect does not comply to the API. In theory, we should never end up here! */
2714 ALOGE("preprocessing produced too many frames: %d + %d > %d !",
2715 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
2716 frames_wr = frames;
2717 }
Eric Laurent023d8052011-08-22 18:19:26 -07002718 }
Eric Laurent139959c2012-03-30 15:51:03 -07002719
2720 /* Remove aux_channels that have been added on top of main_channels
2721 * Assumption is made that the channels are interleaved and that the main
2722 * channels are first. */
2723 if (has_aux_channels)
2724 {
2725 size_t src_channels = in->config.channels;
2726 size_t dst_channels = popcount(in->main_channels);
2727 int16_t* src_buffer = (int16_t *)proc_buf_out;
2728 int16_t* dst_buffer = (int16_t *)buffer;
2729
2730 if (dst_channels == 1) {
2731 for (i = frames_wr; i > 0; i--)
2732 {
2733 *dst_buffer++ = *src_buffer;
2734 src_buffer += src_channels;
2735 }
2736 } else {
2737 for (i = frames_wr; i > 0; i--)
2738 {
2739 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
2740 dst_buffer += dst_channels;
2741 src_buffer += src_channels;
2742 }
2743 }
2744 }
2745
Eric Laurent023d8052011-08-22 18:19:26 -07002746 return frames_wr;
2747}
2748
Simon Wilson4a972582011-06-09 14:28:56 -07002749static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
Eric Laurent139959c2012-03-30 15:51:03 -07002750
Simon Wilson4a972582011-06-09 14:28:56 -07002751 size_t bytes)
2752{
Simon Wilson1bf73172011-06-27 15:45:08 -07002753 int ret = 0;
2754 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
2755 struct tuna_audio_device *adev = in->dev;
Eric Laurent023d8052011-08-22 18:19:26 -07002756 size_t frames_rq = bytes / audio_stream_frame_size(&stream->common);
Simon Wilson1bf73172011-06-27 15:45:08 -07002757
Eric Laurent023d8052011-08-22 18:19:26 -07002758 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
2759 * on the input stream mutex - e.g. executing select_mode() while holding the hw device
2760 * mutex
2761 */
2762 pthread_mutex_lock(&adev->lock);
Simon Wilson1bf73172011-06-27 15:45:08 -07002763 pthread_mutex_lock(&in->lock);
2764 if (in->standby) {
2765 ret = start_input_stream(in);
2766 if (ret == 0)
2767 in->standby = 0;
2768 }
Eric Laurent023d8052011-08-22 18:19:26 -07002769 pthread_mutex_unlock(&adev->lock);
Simon Wilson1bf73172011-06-27 15:45:08 -07002770
Eric Laurent3c930972011-07-14 18:49:47 -07002771 if (ret < 0)
2772 goto exit;
2773
Eric Laurent023d8052011-08-22 18:19:26 -07002774 if (in->num_preprocessors != 0)
2775 ret = process_frames(in, buffer, frames_rq);
2776 else if (in->resampler != NULL)
2777 ret = read_frames(in, buffer, frames_rq);
2778 else
Simon Wilson1bf73172011-06-27 15:45:08 -07002779 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurent023d8052011-08-22 18:19:26 -07002780
2781 if (ret > 0)
2782 ret = 0;
Simon Wilson1bf73172011-06-27 15:45:08 -07002783
Eric Laurent8f35a342011-08-04 10:47:36 -07002784 if (ret == 0 && adev->mic_mute)
2785 memset(buffer, 0, bytes);
2786
Eric Laurent3c930972011-07-14 18:49:47 -07002787exit:
Simon Wilson1bf73172011-06-27 15:45:08 -07002788 if (ret < 0)
2789 usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) /
2790 in_get_sample_rate(&stream->common));
2791
2792 pthread_mutex_unlock(&in->lock);
Simon Wilson4a972582011-06-09 14:28:56 -07002793 return bytes;
2794}
2795
2796static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
2797{
2798 return 0;
2799}
2800
Eric Laurent139959c2012-03-30 15:51:03 -07002801#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
2802 do { \
2803 if (fct_status != 0) \
2804 status = fct_status; \
2805 else if (cmd_status != 0) \
2806 status = cmd_status; \
2807 } while(0)
2808
2809static int in_configure_reverse(struct tuna_stream_in *in)
2810{
2811 int32_t cmd_status;
2812 uint32_t size = sizeof(int);
2813 effect_config_t config;
2814 int32_t status = 0;
2815 int32_t fct_status = 0;
2816 int i;
2817
2818 if (in->num_preprocessors > 0) {
2819 config.inputCfg.channels = in->main_channels;
2820 config.outputCfg.channels = in->main_channels;
2821 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
2822 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
2823 config.inputCfg.samplingRate = in->requested_rate;
2824 config.outputCfg.samplingRate = in->requested_rate;
2825 config.inputCfg.mask =
2826 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
2827 config.outputCfg.mask =
2828 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
2829
2830 for (i = 0; i < in->num_preprocessors; i++)
2831 {
2832 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
2833 continue;
2834 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
2835 in->preprocessors[i].effect_itfe,
2836 EFFECT_CMD_SET_CONFIG_REVERSE,
2837 sizeof(effect_config_t),
2838 &config,
2839 &size,
2840 &cmd_status);
2841 GET_COMMAND_STATUS(status, fct_status, cmd_status);
2842 }
2843 }
2844 return status;
2845}
2846
2847#define MAX_NUM_CHANNEL_CONFIGS 10
2848
2849static void in_read_audio_effect_channel_configs(struct tuna_stream_in *in,
2850 struct effect_info_s *effect_info)
2851{
2852 /* size and format of the cmd are defined in hardware/audio_effect.h */
2853 effect_handle_t effect = effect_info->effect_itfe;
2854 uint32_t cmd_size = 2 * sizeof(uint32_t);
2855 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
2856 /* reply = status + number of configs (n) + n x channel_config_t */
2857 uint32_t reply_size =
2858 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
2859 int32_t reply[reply_size];
2860 int32_t cmd_status;
2861
2862 ALOG_ASSERT((effect_info->num_channel_configs == 0),
2863 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
2864 ALOG_ASSERT((effect_info->channel_configs == NULL),
2865 "in_read_audio_effect_channel_configs() channel_configs not cleared");
2866
2867 /* if this command is not supported, then the effect is supposed to return -EINVAL.
2868 * This error will be interpreted as if the effect supports the main_channels but does not
2869 * support any aux_channels */
2870 cmd_status = (*effect)->command(effect,
2871 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
2872 cmd_size,
2873 (void*)&cmd,
2874 &reply_size,
2875 (void*)&reply);
2876
2877 if (cmd_status != 0) {
2878 ALOGV("in_read_audio_effect_channel_configs(): "
2879 "fx->command returned %d", cmd_status);
2880 return;
2881 }
2882
2883 if (reply[0] != 0) {
2884 ALOGW("in_read_audio_effect_channel_configs(): "
2885 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
2886 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
2887 return;
2888 }
2889
2890 /* the feature is not supported */
2891 ALOGV("in_read_audio_effect_channel_configs()(): "
2892 "Feature supported and adding %d channel configs to the list", reply[1]);
2893 effect_info->num_channel_configs = reply[1];
2894 effect_info->channel_configs =
2895 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
2896 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
2897}
2898
2899
2900static uint32_t in_get_aux_channels(struct tuna_stream_in *in)
2901{
2902 int i;
2903 channel_config_t new_chcfg = {0, 0};
2904
2905 if (in->num_preprocessors == 0)
2906 return 0;
2907
2908 /* do not enable dual mic configurations when capturing from other microphones than
2909 * main or sub */
2910 if (!(in->device & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
2911 return 0;
2912
2913 /* retain most complex aux channels configuration compatible with requested main channels and
2914 * supported by audio driver and all pre processors */
2915 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
2916 channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
2917 if (cur_chcfg->main_channels == in->main_channels) {
2918 size_t match_cnt;
2919 size_t idx_preproc;
2920 for (idx_preproc = 0, match_cnt = 0;
2921 /* no need to continue if at least one preprocessor doesn't match */
2922 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
2923 idx_preproc++) {
2924 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
2925 size_t idx_chcfg;
2926
2927 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
2928 if (memcmp(effect_info->channel_configs + idx_chcfg,
2929 cur_chcfg,
2930 sizeof(channel_config_t)) == 0) {
2931 match_cnt++;
2932 break;
2933 }
2934 }
2935 }
2936 /* if all preprocessors match, we have a candidate */
2937 if (match_cnt == (size_t)in->num_preprocessors) {
2938 /* retain most complex aux channels configuration */
2939 if (popcount(cur_chcfg->aux_channels) > popcount(new_chcfg.aux_channels)) {
2940 new_chcfg = *cur_chcfg;
2941 }
2942 }
2943 }
2944 }
2945
2946 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
2947
2948 return new_chcfg.aux_channels;
2949}
2950
2951static int in_configure_effect_channels(effect_handle_t effect,
2952 channel_config_t *channel_config)
2953{
2954 int status = 0;
2955 int fct_status;
2956 int32_t cmd_status;
2957 uint32_t reply_size;
2958 effect_config_t config;
2959 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
2960
2961 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
2962 channel_config->main_channels,
2963 channel_config->aux_channels);
2964
2965 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
2966 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
2967 reply_size = sizeof(effect_config_t);
2968 fct_status = (*effect)->command(effect,
2969 EFFECT_CMD_GET_CONFIG,
2970 0,
2971 NULL,
2972 &reply_size,
2973 &config);
2974 if (fct_status != 0) {
2975 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
2976 return fct_status;
2977 }
2978
2979 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
2980 config.outputCfg.channels = config.inputCfg.channels;
2981 reply_size = sizeof(uint32_t);
2982 fct_status = (*effect)->command(effect,
2983 EFFECT_CMD_SET_CONFIG,
2984 sizeof(effect_config_t),
2985 &config,
2986 &reply_size,
2987 &cmd_status);
2988 GET_COMMAND_STATUS(status, fct_status, cmd_status);
2989
2990 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
2991 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
2992 reply_size = sizeof(uint32_t);
2993 fct_status = (*effect)->command(effect,
2994 EFFECT_CMD_SET_FEATURE_CONFIG,
2995 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
2996 cmd,
2997 &reply_size,
2998 &cmd_status);
2999 GET_COMMAND_STATUS(status, fct_status, cmd_status);
3000
3001 /* some implementations need to be re-enabled after a config change */
3002 reply_size = sizeof(uint32_t);
3003 fct_status = (*effect)->command(effect,
3004 EFFECT_CMD_ENABLE,
3005 0,
3006 NULL,
3007 &reply_size,
3008 &cmd_status);
3009 GET_COMMAND_STATUS(status, fct_status, cmd_status);
3010
3011 return status;
3012}
3013
3014static int in_reconfigure_channels(struct tuna_stream_in *in,
3015 effect_handle_t effect,
3016 channel_config_t *channel_config,
3017 bool config_changed) {
3018
3019 int status = 0;
3020
3021 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
3022 config_changed, effect);
3023
3024 /* if config changed, reconfigure all previously added effects */
3025 if (config_changed) {
3026 int i;
3027 for (i = 0; i < in->num_preprocessors; i++)
3028 {
3029 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
3030 channel_config);
3031 if (cur_status != 0) {
3032 ALOGV("in_reconfigure_channels(): error %d configuring effect "
3033 "%d with channels: [%04x][%04x]",
3034 cur_status,
3035 i,
3036 channel_config->main_channels,
3037 channel_config->aux_channels);
3038 status = cur_status;
3039 }
3040 }
3041 } else if (effect != NULL && channel_config->aux_channels) {
3042 /* if aux channels config did not change but aux channels are present,
3043 * we still need to configure the effect being added */
3044 status = in_configure_effect_channels(effect, channel_config);
3045 }
3046 return status;
3047}
3048
3049static void in_update_aux_channels(struct tuna_stream_in *in,
3050 effect_handle_t effect)
3051{
3052 uint32_t aux_channels;
3053 channel_config_t channel_config;
3054 int status;
3055
3056 aux_channels = in_get_aux_channels(in);
3057
3058 channel_config.main_channels = in->main_channels;
3059 channel_config.aux_channels = aux_channels;
3060 status = in_reconfigure_channels(in,
3061 effect,
3062 &channel_config,
3063 (aux_channels != in->aux_channels));
3064
3065 if (status != 0) {
3066 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
3067 /* resetting aux channels configuration */
3068 aux_channels = 0;
3069 channel_config.aux_channels = 0;
3070 in_reconfigure_channels(in, effect, &channel_config, true);
3071 }
3072 if (in->aux_channels != aux_channels) {
3073 in->aux_channels_changed = true;
3074 in->aux_channels = aux_channels;
3075 do_input_standby(in);
3076 }
3077}
3078
Eric Laurent023d8052011-08-22 18:19:26 -07003079static int in_add_audio_effect(const struct audio_stream *stream,
3080 effect_handle_t effect)
Eric Laurent27fda172011-07-11 12:21:56 -07003081{
Eric Laurent023d8052011-08-22 18:19:26 -07003082 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
3083 int status;
3084 effect_descriptor_t desc;
3085
3086 pthread_mutex_lock(&in->dev->lock);
3087 pthread_mutex_lock(&in->lock);
3088 if (in->num_preprocessors >= MAX_PREPROCESSORS) {
3089 status = -ENOSYS;
3090 goto exit;
3091 }
3092
3093 status = (*effect)->get_descriptor(effect, &desc);
3094 if (status != 0)
3095 goto exit;
3096
Eric Laurent139959c2012-03-30 15:51:03 -07003097 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3098 /* add the supported channel of the effect in the channel_configs */
3099 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3100
3101 in->num_preprocessors++;
3102
3103 /* check compatibility between main channel supported and possible auxiliary channels */
3104 in_update_aux_channels(in, effect);
3105
3106 ALOGV("in_add_audio_effect(), effect type: %08x", desc.type.timeLow);
Eric Laurent023d8052011-08-22 18:19:26 -07003107
3108 if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3109 in->need_echo_reference = true;
3110 do_input_standby(in);
Eric Laurent139959c2012-03-30 15:51:03 -07003111 in_configure_reverse(in);
Eric Laurent023d8052011-08-22 18:19:26 -07003112 }
3113
3114exit:
3115
Eric Laurent139959c2012-03-30 15:51:03 -07003116 ALOGW_IF(status != 0, "in_add_audio_effect() error %d", status);
Eric Laurent023d8052011-08-22 18:19:26 -07003117 pthread_mutex_unlock(&in->lock);
3118 pthread_mutex_unlock(&in->dev->lock);
3119 return status;
Eric Laurent27fda172011-07-11 12:21:56 -07003120}
3121
Eric Laurent023d8052011-08-22 18:19:26 -07003122static int in_remove_audio_effect(const struct audio_stream *stream,
3123 effect_handle_t effect)
Eric Laurent27fda172011-07-11 12:21:56 -07003124{
Eric Laurent023d8052011-08-22 18:19:26 -07003125 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
3126 int i;
3127 int status = -EINVAL;
Eric Laurent023d8052011-08-22 18:19:26 -07003128 effect_descriptor_t desc;
3129
3130 pthread_mutex_lock(&in->dev->lock);
3131 pthread_mutex_lock(&in->lock);
3132 if (in->num_preprocessors <= 0) {
3133 status = -ENOSYS;
3134 goto exit;
3135 }
3136
3137 for (i = 0; i < in->num_preprocessors; i++) {
Eric Laurent139959c2012-03-30 15:51:03 -07003138 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3139 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3140 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3141 in->preprocessors[i - 1].num_channel_configs = in->preprocessors[i].num_channel_configs;
3142 ALOGV("in_remove_audio_effect moving fx from %d to %d", i, i - 1);
Eric Laurent023d8052011-08-22 18:19:26 -07003143 continue;
3144 }
Eric Laurent139959c2012-03-30 15:51:03 -07003145 if (in->preprocessors[i].effect_itfe == effect) {
3146 ALOGV("in_remove_audio_effect found fx at index %d", i);
3147 free(in->preprocessors[i].channel_configs);
Eric Laurent023d8052011-08-22 18:19:26 -07003148 status = 0;
Eric Laurent023d8052011-08-22 18:19:26 -07003149 }
3150 }
3151
3152 if (status != 0)
3153 goto exit;
3154
3155 in->num_preprocessors--;
Eric Laurent139959c2012-03-30 15:51:03 -07003156 /* if we remove one effect, at least the last preproc should be reset */
3157 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3158 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3159 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3160
3161
3162 /* check compatibility between main channel supported and possible auxiliary channels */
3163 in_update_aux_channels(in, NULL);
Eric Laurent023d8052011-08-22 18:19:26 -07003164
3165 status = (*effect)->get_descriptor(effect, &desc);
3166 if (status != 0)
3167 goto exit;
Eric Laurent139959c2012-03-30 15:51:03 -07003168
3169 ALOGV("in_remove_audio_effect(), effect type: %08x", desc.type.timeLow);
3170
Eric Laurent023d8052011-08-22 18:19:26 -07003171 if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3172 in->need_echo_reference = false;
3173 do_input_standby(in);
3174 }
3175
3176exit:
3177
Eric Laurent139959c2012-03-30 15:51:03 -07003178 ALOGW_IF(status != 0, "in_remove_audio_effect() error %d", status);
Eric Laurent023d8052011-08-22 18:19:26 -07003179 pthread_mutex_unlock(&in->lock);
3180 pthread_mutex_unlock(&in->dev->lock);
3181 return status;
Eric Laurent27fda172011-07-11 12:21:56 -07003182}
3183
Eric Laurent4bf3d142012-04-30 12:30:50 -07003184static int out_read_hdmi_channel_masks(struct tuna_stream_out *out) {
3185 int max_channels = 0;
3186 struct mixer *mixer_hdmi;
3187
3188 mixer_hdmi = mixer_open(CARD_OMAP4_HDMI);
3189 if (mixer_hdmi) {
3190 struct mixer_ctl *ctl;
3191
3192 ctl = mixer_get_ctl_by_name(mixer_hdmi, MIXER_MAXIMUM_LPCM_CHANNELS);
3193 if (ctl)
3194 max_channels = mixer_ctl_get_value(ctl, 0);
3195 mixer_close(mixer_hdmi);
3196 }
3197
3198 ALOGV("out_read_hdmi_channel_masks() got %d max channels", max_channels);
3199
3200 if (max_channels != 6 && max_channels != 8)
3201 return -ENOSYS;
3202
3203 out->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
3204 if (max_channels == 8)
3205 out->sup_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
3206
3207 return 0;
3208}
Simon Wilson4a972582011-06-09 14:28:56 -07003209
3210static int adev_open_output_stream(struct audio_hw_device *dev,
Eric Laurent72337872012-04-13 17:08:13 -07003211 audio_io_handle_t handle,
3212 audio_devices_t devices,
3213 audio_output_flags_t flags,
3214 struct audio_config *config,
Simon Wilson4a972582011-06-09 14:28:56 -07003215 struct audio_stream_out **stream_out)
3216{
3217 struct tuna_audio_device *ladev = (struct tuna_audio_device *)dev;
3218 struct tuna_stream_out *out;
3219 int ret;
Eric Laurent4e7a5732012-04-13 16:58:17 -07003220 int output_type;
Simon Wilson4a972582011-06-09 14:28:56 -07003221
Eric Laurent72337872012-04-13 17:08:13 -07003222 *stream_out = NULL;
3223
Simon Wilson4a972582011-06-09 14:28:56 -07003224 out = (struct tuna_stream_out *)calloc(1, sizeof(struct tuna_stream_out));
3225 if (!out)
3226 return -ENOMEM;
3227
Eric Laurent4bf3d142012-04-30 12:30:50 -07003228 out->sup_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3229 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3230
3231 if (flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3232 devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3233 ALOGV("adev_open_output_stream() HDMI multichannel");
3234 if (ladev->outputs[OUTPUT_HDMI] != NULL) {
3235 ret = -ENOSYS;
3236 goto err_open;
3237 }
3238 ret = out_read_hdmi_channel_masks(out);
3239 if (ret != 0)
3240 goto err_open;
3241 output_type = OUTPUT_HDMI;
3242 if (config->sample_rate == 0)
3243 config->sample_rate = MM_FULL_POWER_SAMPLING_RATE;
3244 if (config->channel_mask == 0)
3245 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3246 out->channel_mask = config->channel_mask;
3247 out->stream.common.get_buffer_size = out_get_buffer_size_hdmi;
3248 out->stream.common.get_sample_rate = out_get_sample_rate_hdmi;
3249 out->stream.get_latency = out_get_latency_hdmi;
3250 out->stream.write = out_write_hdmi;
3251 out->config[PCM_HDMI] = pcm_config_hdmi_multi;
3252 out->config[PCM_HDMI].rate = config->sample_rate;
3253 out->config[PCM_HDMI].channels = popcount(config->channel_mask);
Eric Laurentd84a8f82012-06-11 12:36:38 -07003254 /* FIXME: workaround for channel swap on first playback after opening the output */
3255 out->restart_periods_cnt = out->config[PCM_HDMI].period_count * 2;
Eric Laurent4bf3d142012-04-30 12:30:50 -07003256 } else if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Eric Laurent4e7a5732012-04-13 16:58:17 -07003257 ALOGV("adev_open_output_stream() deep buffer");
Eric Laurent079bd662012-05-02 11:24:19 -07003258 if (ladev->outputs[OUTPUT_DEEP_BUF] != NULL) {
3259 ret = -ENOSYS;
3260 goto err_open;
3261 }
Eric Laurent4e7a5732012-04-13 16:58:17 -07003262 output_type = OUTPUT_DEEP_BUF;
Eric Laurent4bf3d142012-04-30 12:30:50 -07003263 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurent4e7a5732012-04-13 16:58:17 -07003264 out->stream.common.get_buffer_size = out_get_buffer_size_deep_buffer;
Eric Laurent4bf3d142012-04-30 12:30:50 -07003265 out->stream.common.get_sample_rate = out_get_sample_rate;
Eric Laurent4e7a5732012-04-13 16:58:17 -07003266 out->stream.get_latency = out_get_latency_deep_buffer;
3267 out->stream.write = out_write_deep_buffer;
3268 } else {
3269 ALOGV("adev_open_output_stream() normal buffer");
Eric Laurent079bd662012-05-02 11:24:19 -07003270 if (ladev->outputs[OUTPUT_LOW_LATENCY] != NULL) {
3271 ret = -ENOSYS;
3272 goto err_open;
3273 }
Eric Laurent4e7a5732012-04-13 16:58:17 -07003274 output_type = OUTPUT_LOW_LATENCY;
3275 out->stream.common.get_buffer_size = out_get_buffer_size_low_latency;
Eric Laurent4bf3d142012-04-30 12:30:50 -07003276 out->stream.common.get_sample_rate = out_get_sample_rate;
Eric Laurent4e7a5732012-04-13 16:58:17 -07003277 out->stream.get_latency = out_get_latency_low_latency;
3278 out->stream.write = out_write_low_latency;
3279 }
3280
Eric Laurentfa3998c2011-08-19 16:20:54 -07003281 ret = create_resampler(DEFAULT_OUT_SAMPLING_RATE,
Eric Laurent023d8052011-08-22 18:19:26 -07003282 MM_FULL_POWER_SAMPLING_RATE,
3283 2,
3284 RESAMPLER_QUALITY_DEFAULT,
3285 NULL,
3286 &out->resampler);
Eric Laurentfa3998c2011-08-19 16:20:54 -07003287 if (ret != 0)
3288 goto err_open;
Eric Laurentfa3998c2011-08-19 16:20:54 -07003289
Simon Wilson4a972582011-06-09 14:28:56 -07003290 out->stream.common.set_sample_rate = out_set_sample_rate;
Simon Wilson4a972582011-06-09 14:28:56 -07003291 out->stream.common.get_channels = out_get_channels;
3292 out->stream.common.get_format = out_get_format;
3293 out->stream.common.set_format = out_set_format;
3294 out->stream.common.standby = out_standby;
3295 out->stream.common.dump = out_dump;
3296 out->stream.common.set_parameters = out_set_parameters;
3297 out->stream.common.get_parameters = out_get_parameters;
Eric Laurent27fda172011-07-11 12:21:56 -07003298 out->stream.common.add_audio_effect = out_add_audio_effect;
3299 out->stream.common.remove_audio_effect = out_remove_audio_effect;
Simon Wilson4a972582011-06-09 14:28:56 -07003300 out->stream.set_volume = out_set_volume;
Simon Wilson4a972582011-06-09 14:28:56 -07003301 out->stream.get_render_position = out_get_render_position;
3302
Simon Wilson4a972582011-06-09 14:28:56 -07003303 out->dev = ladev;
Eric Laurent023d8052011-08-22 18:19:26 -07003304 out->standby = 1;
Simon Wilson4a972582011-06-09 14:28:56 -07003305
Simon Wilsondf84bfd2011-09-07 17:56:21 -07003306 /* FIXME: when we support multiple output devices, we will want to
3307 * do the following:
Eric Laurent7530b972012-08-28 14:24:38 -07003308 * adev->out_device = out->device;
Simon Wilsondf84bfd2011-09-07 17:56:21 -07003309 * select_output_device(adev);
3310 * This is because out_set_parameters() with a route is not
3311 * guaranteed to be called after an output stream is opened. */
3312
Eric Laurent4bf3d142012-04-30 12:30:50 -07003313 config->format = out->stream.common.get_format(&out->stream.common);
3314 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3315 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Jean-Michel Trivi15335ee2011-06-28 16:21:22 -07003316
Simon Wilson4a972582011-06-09 14:28:56 -07003317 *stream_out = &out->stream;
Eric Laurent4e7a5732012-04-13 16:58:17 -07003318 ladev->outputs[output_type] = out;
3319
Simon Wilson4a972582011-06-09 14:28:56 -07003320 return 0;
3321
3322err_open:
3323 free(out);
Simon Wilson4a972582011-06-09 14:28:56 -07003324 return ret;
3325}
3326
3327static void adev_close_output_stream(struct audio_hw_device *dev,
3328 struct audio_stream_out *stream)
3329{
Eric Laurent4e7a5732012-04-13 16:58:17 -07003330 struct tuna_audio_device *ladev = (struct tuna_audio_device *)dev;
Simon Wilson4a972582011-06-09 14:28:56 -07003331 struct tuna_stream_out *out = (struct tuna_stream_out *)stream;
Eric Laurent4e7a5732012-04-13 16:58:17 -07003332 int i;
Simon Wilson4a972582011-06-09 14:28:56 -07003333
Chris Kelly9ce8ae72011-07-18 19:11:58 -05003334 out_standby(&stream->common);
Eric Laurent4e7a5732012-04-13 16:58:17 -07003335 for (i = 0; i < OUTPUT_TOTAL; i++) {
3336 if (ladev->outputs[i] == out) {
3337 ladev->outputs[i] = NULL;
3338 break;
3339 }
3340 }
3341
Simon Wilson9700b232011-07-10 14:46:46 -07003342 if (out->buffer)
3343 free(out->buffer);
Eric Laurentfa3998c2011-08-19 16:20:54 -07003344 if (out->resampler)
3345 release_resampler(out->resampler);
Simon Wilson4a972582011-06-09 14:28:56 -07003346 free(stream);
3347}
3348
3349static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3350{
Eric Laurent8bbd2d22011-08-07 09:57:42 -07003351 struct tuna_audio_device *adev = (struct tuna_audio_device *)dev;
3352 struct str_parms *parms;
3353 char *str;
3354 char value[32];
3355 int ret;
3356
3357 parms = str_parms_create_str(kvpairs);
3358 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
3359 if (ret >= 0) {
3360 int tty_mode;
3361
3362 if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
3363 tty_mode = TTY_MODE_OFF;
3364 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
3365 tty_mode = TTY_MODE_VCO;
3366 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
3367 tty_mode = TTY_MODE_HCO;
3368 else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
3369 tty_mode = TTY_MODE_FULL;
3370 else
3371 return -EINVAL;
3372
3373 pthread_mutex_lock(&adev->lock);
3374 if (tty_mode != adev->tty_mode) {
3375 adev->tty_mode = tty_mode;
3376 if (adev->mode == AUDIO_MODE_IN_CALL)
3377 select_output_device(adev);
3378 }
3379 pthread_mutex_unlock(&adev->lock);
3380 }
3381
Eric Laurent41a1ead2011-09-12 09:56:24 -07003382 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3383 if (ret >= 0) {
3384 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3385 adev->bluetooth_nrec = true;
3386 else
3387 adev->bluetooth_nrec = false;
3388 }
3389
Eric Laurent359a4162012-05-11 09:17:27 -07003390 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3391 if (ret >= 0) {
3392 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3393 adev->screen_off = false;
3394 else
3395 adev->screen_off = true;
3396 }
3397
Eric Laurent8bbd2d22011-08-07 09:57:42 -07003398 str_parms_destroy(parms);
3399 return ret;
Simon Wilson4a972582011-06-09 14:28:56 -07003400}
3401
3402static char * adev_get_parameters(const struct audio_hw_device *dev,
3403 const char *keys)
3404{
Eric Laurent2006f1c2011-07-19 11:51:08 -07003405 return strdup("");
Simon Wilson4a972582011-06-09 14:28:56 -07003406}
3407
3408static int adev_init_check(const struct audio_hw_device *dev)
3409{
3410 return 0;
3411}
3412
3413static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3414{
Simon Wilson1ff65912011-06-21 14:09:10 -07003415 struct tuna_audio_device *adev = (struct tuna_audio_device *)dev;
3416
Eric Laurent996da012012-06-15 14:49:21 -07003417 pthread_mutex_lock(&adev->lock);
UK KIM8c1bc172011-07-13 01:01:09 -07003418 adev->voice_volume = volume;
3419
Simon Wilson046e31e2011-07-26 20:12:51 -07003420 if (adev->mode == AUDIO_MODE_IN_CALL)
3421 ril_set_call_volume(&adev->ril, SOUND_TYPE_VOICE, volume);
Simon Wilson1ff65912011-06-21 14:09:10 -07003422
Eric Laurent996da012012-06-15 14:49:21 -07003423 pthread_mutex_unlock(&adev->lock);
Simon Wilson1ff65912011-06-21 14:09:10 -07003424 return 0;
Simon Wilson4a972582011-06-09 14:28:56 -07003425}
3426
3427static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
3428{
3429 return -ENOSYS;
3430}
3431
Glenn Kastend9733c42012-01-09 10:40:54 -08003432static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
Simon Wilson4a972582011-06-09 14:28:56 -07003433{
3434 struct tuna_audio_device *adev = (struct tuna_audio_device *)dev;
3435
3436 pthread_mutex_lock(&adev->lock);
3437 if (adev->mode != mode) {
3438 adev->mode = mode;
Simon Wilson30f7fe22011-06-24 23:45:03 -07003439 select_mode(adev);
Simon Wilson4a972582011-06-09 14:28:56 -07003440 }
3441 pthread_mutex_unlock(&adev->lock);
3442
3443 return 0;
3444}
3445
3446static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3447{
Eric Laurent8f35a342011-08-04 10:47:36 -07003448 struct tuna_audio_device *adev = (struct tuna_audio_device *)dev;
3449
3450 adev->mic_mute = state;
3451
3452 return 0;
Simon Wilson4a972582011-06-09 14:28:56 -07003453}
3454
3455static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3456{
Eric Laurent8f35a342011-08-04 10:47:36 -07003457 struct tuna_audio_device *adev = (struct tuna_audio_device *)dev;
3458
3459 *state = adev->mic_mute;
3460
3461 return 0;
Simon Wilson4a972582011-06-09 14:28:56 -07003462}
3463
3464static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Eric Laurent72337872012-04-13 17:08:13 -07003465 const struct audio_config *config)
Simon Wilson4a972582011-06-09 14:28:56 -07003466{
Eric Laurentdf6ed252011-07-14 15:26:25 -07003467 size_t size;
Eric Laurent72337872012-04-13 17:08:13 -07003468 int channel_count = popcount(config->channel_mask);
3469 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
Eric Laurentdf6ed252011-07-14 15:26:25 -07003470 return 0;
3471
Eric Laurent72337872012-04-13 17:08:13 -07003472 return get_input_buffer_size(config->sample_rate, config->format, channel_count);
Simon Wilson4a972582011-06-09 14:28:56 -07003473}
3474
Eric Laurent72337872012-04-13 17:08:13 -07003475static int adev_open_input_stream(struct audio_hw_device *dev,
3476 audio_io_handle_t handle,
3477 audio_devices_t devices,
3478 struct audio_config *config,
Simon Wilson4a972582011-06-09 14:28:56 -07003479 struct audio_stream_in **stream_in)
3480{
3481 struct tuna_audio_device *ladev = (struct tuna_audio_device *)dev;
3482 struct tuna_stream_in *in;
3483 int ret;
Eric Laurent72337872012-04-13 17:08:13 -07003484 int channel_count = popcount(config->channel_mask);
Eric Laurentdf6ed252011-07-14 15:26:25 -07003485
Eric Laurent72337872012-04-13 17:08:13 -07003486 *stream_in = NULL;
3487
3488 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
Eric Laurentdf6ed252011-07-14 15:26:25 -07003489 return -EINVAL;
Simon Wilson4a972582011-06-09 14:28:56 -07003490
3491 in = (struct tuna_stream_in *)calloc(1, sizeof(struct tuna_stream_in));
3492 if (!in)
3493 return -ENOMEM;
3494
3495 in->stream.common.get_sample_rate = in_get_sample_rate;
3496 in->stream.common.set_sample_rate = in_set_sample_rate;
3497 in->stream.common.get_buffer_size = in_get_buffer_size;
3498 in->stream.common.get_channels = in_get_channels;
3499 in->stream.common.get_format = in_get_format;
3500 in->stream.common.set_format = in_set_format;
3501 in->stream.common.standby = in_standby;
3502 in->stream.common.dump = in_dump;
3503 in->stream.common.set_parameters = in_set_parameters;
3504 in->stream.common.get_parameters = in_get_parameters;
Eric Laurent27fda172011-07-11 12:21:56 -07003505 in->stream.common.add_audio_effect = in_add_audio_effect;
3506 in->stream.common.remove_audio_effect = in_remove_audio_effect;
Simon Wilson4a972582011-06-09 14:28:56 -07003507 in->stream.set_gain = in_set_gain;
3508 in->stream.read = in_read;
3509 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3510
Eric Laurent72337872012-04-13 17:08:13 -07003511 in->requested_rate = config->sample_rate;
Simon Wilson1bf73172011-06-27 15:45:08 -07003512
Simon Wilson79095f92011-09-06 14:59:51 -07003513 memcpy(&in->config, &pcm_config_mm_ul, sizeof(pcm_config_mm_ul));
Eric Laurentdf6ed252011-07-14 15:26:25 -07003514 in->config.channels = channel_count;
Simon Wilson1bf73172011-06-27 15:45:08 -07003515
Eric Laurent72337872012-04-13 17:08:13 -07003516 in->main_channels = config->channel_mask;
Eric Laurent139959c2012-03-30 15:51:03 -07003517
3518 /* initialisation of preprocessor structure array is implicit with the calloc.
3519 * same for in->aux_channels and in->aux_channels_changed */
Eric Laurent023d8052011-08-22 18:19:26 -07003520
Eric Laurent3c930972011-07-14 18:49:47 -07003521 if (in->requested_rate != in->config.rate) {
Eric Laurent023d8052011-08-22 18:19:26 -07003522 in->buf_provider.get_next_buffer = get_next_buffer;
3523 in->buf_provider.release_buffer = release_buffer;
3524
Eric Laurentfa3998c2011-08-19 16:20:54 -07003525 ret = create_resampler(in->config.rate,
3526 in->requested_rate,
3527 in->config.channels,
3528 RESAMPLER_QUALITY_DEFAULT,
Eric Laurent023d8052011-08-22 18:19:26 -07003529 &in->buf_provider,
Eric Laurentfa3998c2011-08-19 16:20:54 -07003530 &in->resampler);
3531 if (ret != 0) {
Eric Laurent3c930972011-07-14 18:49:47 -07003532 ret = -EINVAL;
3533 goto err;
3534 }
Eric Laurent3c930972011-07-14 18:49:47 -07003535 }
3536
Simon Wilson1bf73172011-06-27 15:45:08 -07003537 in->dev = ladev;
Eric Laurent3c930972011-07-14 18:49:47 -07003538 in->standby = 1;
Eric Laurent7530b972012-08-28 14:24:38 -07003539 in->device = devices & ~AUDIO_DEVICE_BIT_IN;
Simon Wilson1bf73172011-06-27 15:45:08 -07003540
Simon Wilson4a972582011-06-09 14:28:56 -07003541 *stream_in = &in->stream;
3542 return 0;
3543
Simon Wilson1bf73172011-06-27 15:45:08 -07003544err:
Eric Laurentfa3998c2011-08-19 16:20:54 -07003545 if (in->resampler)
3546 release_resampler(in->resampler);
Eric Laurent3c930972011-07-14 18:49:47 -07003547
Simon Wilson4a972582011-06-09 14:28:56 -07003548 free(in);
Simon Wilson4a972582011-06-09 14:28:56 -07003549 return ret;
3550}
3551
3552static void adev_close_input_stream(struct audio_hw_device *dev,
Simon Wilson1bf73172011-06-27 15:45:08 -07003553 struct audio_stream_in *stream)
Simon Wilson4a972582011-06-09 14:28:56 -07003554{
Simon Wilson1bf73172011-06-27 15:45:08 -07003555 struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
Eric Laurent139959c2012-03-30 15:51:03 -07003556 int i;
Simon Wilson1bf73172011-06-27 15:45:08 -07003557
3558 in_standby(&stream->common);
Eric Laurent3c930972011-07-14 18:49:47 -07003559
Eric Laurent139959c2012-03-30 15:51:03 -07003560 for (i = 0; i < in->num_preprocessors; i++) {
3561 free(in->preprocessors[i].channel_configs);
3562 }
3563
3564 free(in->read_buf);
Eric Laurentfa3998c2011-08-19 16:20:54 -07003565 if (in->resampler) {
Eric Laurentfa3998c2011-08-19 16:20:54 -07003566 release_resampler(in->resampler);
Eric Laurent3c930972011-07-14 18:49:47 -07003567 }
Eric Laurent139959c2012-03-30 15:51:03 -07003568 if (in->proc_buf_in)
3569 free(in->proc_buf_in);
3570 if (in->proc_buf_out)
3571 free(in->proc_buf_out);
Eric Laurent7a170e12011-12-13 10:13:59 -08003572 if (in->ref_buf)
3573 free(in->ref_buf);
Eric Laurent3c930972011-07-14 18:49:47 -07003574
Simon Wilson1bf73172011-06-27 15:45:08 -07003575 free(stream);
Simon Wilson4a972582011-06-09 14:28:56 -07003576 return;
3577}
3578
3579static int adev_dump(const audio_hw_device_t *device, int fd)
3580{
3581 return 0;
3582}
3583
3584static int adev_close(hw_device_t *device)
3585{
3586 struct tuna_audio_device *adev = (struct tuna_audio_device *)device;
3587
Simon Wilson1ff65912011-06-21 14:09:10 -07003588 /* RIL */
Kim Ukc2a69f52011-07-19 12:57:26 -07003589 ril_close(&adev->ril);
Simon Wilson1ff65912011-06-21 14:09:10 -07003590
Simon Wilson4a972582011-06-09 14:28:56 -07003591 mixer_close(adev->mixer);
3592 free(device);
3593 return 0;
3594}
3595
Simon Wilson4a972582011-06-09 14:28:56 -07003596static int adev_open(const hw_module_t* module, const char* name,
3597 hw_device_t** device)
3598{
3599 struct tuna_audio_device *adev;
3600 int ret;
3601
3602 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
3603 return -EINVAL;
3604
3605 adev = calloc(1, sizeof(struct tuna_audio_device));
3606 if (!adev)
3607 return -ENOMEM;
3608
Chris Kelly9ce8ae72011-07-18 19:11:58 -05003609 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent7530b972012-08-28 14:24:38 -07003610 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Chris Kelly9ce8ae72011-07-18 19:11:58 -05003611 adev->hw_device.common.module = (struct hw_module_t *) module;
3612 adev->hw_device.common.close = adev_close;
Simon Wilson4a972582011-06-09 14:28:56 -07003613
Chris Kelly9ce8ae72011-07-18 19:11:58 -05003614 adev->hw_device.init_check = adev_init_check;
3615 adev->hw_device.set_voice_volume = adev_set_voice_volume;
3616 adev->hw_device.set_master_volume = adev_set_master_volume;
3617 adev->hw_device.set_mode = adev_set_mode;
3618 adev->hw_device.set_mic_mute = adev_set_mic_mute;
3619 adev->hw_device.get_mic_mute = adev_get_mic_mute;
3620 adev->hw_device.set_parameters = adev_set_parameters;
3621 adev->hw_device.get_parameters = adev_get_parameters;
3622 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
3623 adev->hw_device.open_output_stream = adev_open_output_stream;
3624 adev->hw_device.close_output_stream = adev_close_output_stream;
3625 adev->hw_device.open_input_stream = adev_open_input_stream;
3626 adev->hw_device.close_input_stream = adev_close_input_stream;
3627 adev->hw_device.dump = adev_dump;
Simon Wilson4a972582011-06-09 14:28:56 -07003628
Eric Laurent4bf3d142012-04-30 12:30:50 -07003629 adev->mixer = mixer_open(CARD_OMAP4_ABE);
Simon Wilson4a972582011-06-09 14:28:56 -07003630 if (!adev->mixer) {
3631 free(adev);
Steve Block87efd3f2012-01-08 10:19:03 +00003632 ALOGE("Unable to open the mixer, aborting.");
Simon Wilson4274dd42011-08-02 11:07:55 -07003633 return -EINVAL;
Simon Wilson4a972582011-06-09 14:28:56 -07003634 }
3635
Changoh.Heoc0854432011-10-18 17:47:48 -07003636 adev->mixer_ctls.dl1_eq = mixer_get_ctl_by_name(adev->mixer,
3637 MIXER_DL1_EQUALIZER);
Eric Laurentd6cc09e2012-05-08 09:31:34 -07003638 adev->mixer_ctls.mm_dl1_volume = mixer_get_ctl_by_name(adev->mixer,
3639 MIXER_DL1_MEDIA_PLAYBACK_VOLUME);
3640 adev->mixer_ctls.tones_dl1_volume = mixer_get_ctl_by_name(adev->mixer,
3641 MIXER_DL1_TONES_PLAYBACK_VOLUME);
Simon Wilson1c2783a2011-10-18 23:25:25 -07003642 adev->mixer_ctls.mm_dl2_volume = mixer_get_ctl_by_name(adev->mixer,
3643 MIXER_DL2_MEDIA_PLAYBACK_VOLUME);
3644 adev->mixer_ctls.vx_dl2_volume = mixer_get_ctl_by_name(adev->mixer,
3645 MIXER_DL2_VOICE_PLAYBACK_VOLUME);
Eric Laurentd6cc09e2012-05-08 09:31:34 -07003646 adev->mixer_ctls.tones_dl2_volume = mixer_get_ctl_by_name(adev->mixer,
3647 MIXER_DL2_TONES_PLAYBACK_VOLUME);
Chris Kelly50765d22011-07-14 14:52:55 -05003648 adev->mixer_ctls.mm_dl1 = mixer_get_ctl_by_name(adev->mixer,
Simon Wilsone18d87d2011-07-12 15:52:45 -07003649 MIXER_DL1_MIXER_MULTIMEDIA);
Chris Kelly50765d22011-07-14 14:52:55 -05003650 adev->mixer_ctls.vx_dl1 = mixer_get_ctl_by_name(adev->mixer,
Simon Wilsone18d87d2011-07-12 15:52:45 -07003651 MIXER_DL1_MIXER_VOICE);
Eric Laurent4e7a5732012-04-13 16:58:17 -07003652 adev->mixer_ctls.tones_dl1 = mixer_get_ctl_by_name(adev->mixer,
3653 MIXER_DL1_MIXER_TONES);
Chris Kelly50765d22011-07-14 14:52:55 -05003654 adev->mixer_ctls.mm_dl2 = mixer_get_ctl_by_name(adev->mixer,
Simon Wilsone18d87d2011-07-12 15:52:45 -07003655 MIXER_DL2_MIXER_MULTIMEDIA);
Chris Kelly50765d22011-07-14 14:52:55 -05003656 adev->mixer_ctls.vx_dl2 = mixer_get_ctl_by_name(adev->mixer,
Simon Wilsone18d87d2011-07-12 15:52:45 -07003657 MIXER_DL2_MIXER_VOICE);
Eric Laurent4e7a5732012-04-13 16:58:17 -07003658 adev->mixer_ctls.tones_dl2 = mixer_get_ctl_by_name(adev->mixer,
3659 MIXER_DL2_MIXER_TONES);
Simon Wilson431112d2011-10-20 10:32:27 -07003660 adev->mixer_ctls.dl2_mono = mixer_get_ctl_by_name(adev->mixer,
3661 MIXER_DL2_MONO_MIXER);
Chris Kelly50765d22011-07-14 14:52:55 -05003662 adev->mixer_ctls.dl1_headset = mixer_get_ctl_by_name(adev->mixer,
3663 MIXER_DL1_PDM_SWITCH);
3664 adev->mixer_ctls.dl1_bt = mixer_get_ctl_by_name(adev->mixer,
3665 MIXER_DL1_BT_VX_SWITCH);
Simon Wilsone9ab0812011-09-19 17:22:01 -07003666 adev->mixer_ctls.earpiece_enable = mixer_get_ctl_by_name(adev->mixer,
3667 MIXER_EARPHONE_ENABLE_SWITCH);
Chris Kelly50765d22011-07-14 14:52:55 -05003668 adev->mixer_ctls.left_capture = mixer_get_ctl_by_name(adev->mixer,
3669 MIXER_ANALOG_LEFT_CAPTURE_ROUTE);
3670 adev->mixer_ctls.right_capture = mixer_get_ctl_by_name(adev->mixer,
3671 MIXER_ANALOG_RIGHT_CAPTURE_ROUTE);
Simon Wilson2b45e732011-08-22 16:49:03 -07003672 adev->mixer_ctls.amic_ul_volume = mixer_get_ctl_by_name(adev->mixer,
3673 MIXER_AMIC_UL_VOLUME);
venkappa malaa3799ff2011-10-06 21:16:42 -07003674 adev->mixer_ctls.voice_ul_volume = mixer_get_ctl_by_name(adev->mixer,
3675 MIXER_AUDUL_VOICE_UL_VOLUME);
Simon Wilson512503b2011-08-30 16:29:05 -07003676 adev->mixer_ctls.sidetone_capture = mixer_get_ctl_by_name(adev->mixer,
3677 MIXER_SIDETONE_MIXER_CAPTURE);
Simon Wilson903131d2011-09-21 15:46:02 -07003678 adev->mixer_ctls.headset_volume = mixer_get_ctl_by_name(adev->mixer,
3679 MIXER_HEADSET_PLAYBACK_VOLUME);
3680 adev->mixer_ctls.speaker_volume = mixer_get_ctl_by_name(adev->mixer,
3681 MIXER_HANDSFREE_PLAYBACK_VOLUME);
Simon Wilson19675852011-09-30 14:31:48 -07003682 adev->mixer_ctls.earpiece_volume = mixer_get_ctl_by_name(adev->mixer,
3683 MIXER_EARPHONE_PLAYBACK_VOLUME);
Chris Kelly50765d22011-07-14 14:52:55 -05003684
Eric Laurentd6cc09e2012-05-08 09:31:34 -07003685 if (!adev->mixer_ctls.dl1_eq ||
3686 !adev->mixer_ctls.mm_dl1_volume ||
3687 !adev->mixer_ctls.tones_dl1_volume ||
3688 !adev->mixer_ctls.mm_dl2_volume ||
3689 !adev->mixer_ctls.vx_dl2_volume ||
3690 !adev->mixer_ctls.tones_dl2_volume ||
3691 !adev->mixer_ctls.mm_dl1 ||
3692 !adev->mixer_ctls.vx_dl1 ||
3693 !adev->mixer_ctls.tones_dl1 ||
3694 !adev->mixer_ctls.mm_dl2 ||
3695 !adev->mixer_ctls.vx_dl2 ||
3696 !adev->mixer_ctls.tones_dl2 ||
3697 !adev->mixer_ctls.dl2_mono ||
3698 !adev->mixer_ctls.dl1_headset ||
3699 !adev->mixer_ctls.dl1_bt ||
3700 !adev->mixer_ctls.earpiece_enable ||
3701 !adev->mixer_ctls.left_capture ||
3702 !adev->mixer_ctls.right_capture ||
3703 !adev->mixer_ctls.amic_ul_volume ||
3704 !adev->mixer_ctls.voice_ul_volume ||
3705 !adev->mixer_ctls.sidetone_capture ||
3706 !adev->mixer_ctls.headset_volume ||
3707 !adev->mixer_ctls.speaker_volume ||
venkappa malaa3799ff2011-10-06 21:16:42 -07003708 !adev->mixer_ctls.earpiece_volume) {
Simon Wilsone18d87d2011-07-12 15:52:45 -07003709 mixer_close(adev->mixer);
3710 free(adev);
Steve Block87efd3f2012-01-08 10:19:03 +00003711 ALOGE("Unable to locate all mixer controls, aborting.");
Simon Wilson4274dd42011-08-02 11:07:55 -07003712 return -EINVAL;
Simon Wilsone18d87d2011-07-12 15:52:45 -07003713 }
3714
Simon Wilson1ff65912011-06-21 14:09:10 -07003715 /* Set the default route before the PCM stream is opened */
Simon Wilsond974bd32011-07-25 16:56:43 -07003716 pthread_mutex_lock(&adev->lock);
Simon Wilson30f7fe22011-06-24 23:45:03 -07003717 set_route_by_array(adev->mixer, defaults, 1);
Simon Wilson1ff65912011-06-21 14:09:10 -07003718 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurent7530b972012-08-28 14:24:38 -07003719 adev->out_device = AUDIO_DEVICE_OUT_SPEAKER;
3720 adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
Simon Wilson30f7fe22011-06-24 23:45:03 -07003721 select_output_device(adev);
Simon Wilson1ff65912011-06-21 14:09:10 -07003722
3723 adev->pcm_modem_dl = NULL;
3724 adev->pcm_modem_ul = NULL;
UK KIM8c1bc172011-07-13 01:01:09 -07003725 adev->voice_volume = 1.0f;
Eric Laurent8bbd2d22011-08-07 09:57:42 -07003726 adev->tty_mode = TTY_MODE_OFF;
Simon Wilson1c2783a2011-10-18 23:25:25 -07003727 adev->device_is_toro = is_device_toro();
Eric Laurent41a1ead2011-09-12 09:56:24 -07003728 adev->bluetooth_nrec = true;
Simon Wilsond2dbaf92011-09-27 13:39:53 -07003729 adev->wb_amr = 0;
Simon Wilson1ff65912011-06-21 14:09:10 -07003730
3731 /* RIL */
Kim Ukc2a69f52011-07-19 12:57:26 -07003732 ril_open(&adev->ril);
Simon Wilsond974bd32011-07-25 16:56:43 -07003733 pthread_mutex_unlock(&adev->lock);
Simon Wilsond2dbaf92011-09-27 13:39:53 -07003734 /* register callback for wideband AMR setting */
3735 ril_register_set_wb_amr_callback(audio_set_wb_amr_callback, (void *)adev);
Simon Wilson4a972582011-06-09 14:28:56 -07003736
Chris Kelly9ce8ae72011-07-18 19:11:58 -05003737 *device = &adev->hw_device.common;
Simon Wilson4a972582011-06-09 14:28:56 -07003738
3739 return 0;
3740}
3741
3742static struct hw_module_methods_t hal_module_methods = {
3743 .open = adev_open,
3744};
3745
3746struct audio_module HAL_MODULE_INFO_SYM = {
3747 .common = {
3748 .tag = HARDWARE_MODULE_TAG,
Eric Laurent72337872012-04-13 17:08:13 -07003749 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3750 .hal_api_version = HARDWARE_HAL_API_VERSION,
Simon Wilson4a972582011-06-09 14:28:56 -07003751 .id = AUDIO_HARDWARE_MODULE_ID,
3752 .name = "Tuna audio HW HAL",
3753 .author = "The Android Open Source Project",
3754 .methods = &hal_module_methods,
3755 },
3756};