blob: 75d3ff0af0cfc513e074a1e553f83536442bdc23 [file] [log] [blame]
Amit Pundir4e375822019-04-18 16:46:10 +05301/*
Amit Pundire6732bb2020-09-28 12:43:59 +05302 * Copyright (C) 2016 The Android Open Source Project
Amit Pundir4e375822019-04-18 16:46:10 +05303 *
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.
Amit Pundir456949d2020-02-18 22:44:16 +053015 *
Amit Pundire6732bb2020-09-28 12:43:59 +053016 * Copied as it is from device/amlogic/generic/hal/audio/
Amit Pundir4e375822019-04-18 16:46:10 +053017 */
18
Amit Pundire6732bb2020-09-28 12:43:59 +053019#define LOG_TAG "audio_hw_yukawa"
20//#define LOG_NDEBUG 0
Amit Pundir4e375822019-04-18 16:46:10 +053021
22#include <errno.h>
Amit Pundir456949d2020-02-18 22:44:16 +053023#include <inttypes.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053024#include <malloc.h>
Amit Pundir4e375822019-04-18 16:46:10 +053025#include <pthread.h>
26#include <stdint.h>
Amit Pundir4e375822019-04-18 16:46:10 +053027#include <stdlib.h>
Amit Pundir456949d2020-02-18 22:44:16 +053028#include <sys/time.h>
Amit Pundir4e375822019-04-18 16:46:10 +053029#include <unistd.h>
Amit Pundirc0ad8942021-12-14 19:45:56 +053030#include <string.h>
Amit Pundir4e375822019-04-18 16:46:10 +053031
32#include <log/log.h>
33#include <cutils/str_parms.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053034#include <cutils/properties.h>
Amit Pundir4e375822019-04-18 16:46:10 +053035
36#include <hardware/hardware.h>
37#include <system/audio.h>
38#include <hardware/audio.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053039
40#include <audio_effects/effect_aec.h>
41#include <audio_route/audio_route.h>
42#include <audio_utils/clock.h>
43#include <audio_utils/echo_reference.h>
44#include <audio_utils/resampler.h>
Amit Pundirc0ad8942021-12-14 19:45:56 +053045#include <cutils/properties.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053046#include <hardware/audio_alsaops.h>
47#include <hardware/audio_effect.h>
48#include <sound/asound.h>
Amit Pundir4e375822019-04-18 16:46:10 +053049#include <tinyalsa/asoundlib.h>
Amit Pundir456949d2020-02-18 22:44:16 +053050
Amit Pundire6732bb2020-09-28 12:43:59 +053051#include <sys/ioctl.h>
Amit Pundir4e375822019-04-18 16:46:10 +053052
Amit Pundire6732bb2020-09-28 12:43:59 +053053#include "audio_aec.h"
54#include "audio_hw.h"
Amit Pundir4e375822019-04-18 16:46:10 +053055
Amit Pundire6732bb2020-09-28 12:43:59 +053056static int adev_get_mic_mute(const struct audio_hw_device* dev, bool* state);
57static int adev_get_microphones(const struct audio_hw_device* dev,
58 struct audio_microphone_characteristic_t* mic_array,
59 size_t* mic_count);
60static size_t out_get_buffer_size(const struct audio_stream* stream);
Amit Pundir4e375822019-04-18 16:46:10 +053061
Alden DSouzae44e0672021-02-11 17:07:01 -080062static bool is_aec_input(const struct alsa_stream_in* in) {
63 /* If AEC is in the app, only configure based on ECHO_REFERENCE spec.
64 * If AEC is in the HAL, configure using the given mic stream. */
65 bool aec_input = true;
66#if !defined(AEC_HAL)
67 aec_input = (in->source == AUDIO_SOURCE_ECHO_REFERENCE);
68#endif
69 return aec_input;
70}
71
Amit Pundire6732bb2020-09-28 12:43:59 +053072static int get_audio_output_port(audio_devices_t devices) {
73 /* Only HDMI out for now #FIXME */
74 return PORT_HDMI;
Amit Pundir4e375822019-04-18 16:46:10 +053075}
76
John Stultz57a02362021-09-02 03:26:56 +000077static int get_audio_card(int direction, int port) {
78 struct pcm_params* params = NULL;
79 int card = 0;
80
81 while (!params && card < 8) {
82 /* Find the first input/output device that works */
83 params = pcm_params_get(card, port, direction);
84 card++;
85 }
86 pcm_params_free(params);
87
88 return card - 1;
89}
90
Amit Pundire6732bb2020-09-28 12:43:59 +053091static void timestamp_adjust(struct timespec* ts, ssize_t frames, uint32_t sampling_rate) {
92 /* This function assumes the adjustment (in nsec) is less than the max value of long,
93 * which for 32-bit long this is 2^31 * 1e-9 seconds, slightly over 2 seconds.
94 * For 64-bit long it is 9e+9 seconds. */
95 long adj_nsec = (frames / (float) sampling_rate) * 1E9L;
96 ts->tv_nsec += adj_nsec;
97 while (ts->tv_nsec > 1E9L) {
98 ts->tv_sec++;
99 ts->tv_nsec -= 1E9L;
Amit Pundir456949d2020-02-18 22:44:16 +0530100 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530101 if (ts->tv_nsec < 0) {
102 ts->tv_sec--;
103 ts->tv_nsec += 1E9L;
104 }
Amit Pundir456949d2020-02-18 22:44:16 +0530105}
106
Amit Pundire6732bb2020-09-28 12:43:59 +0530107/* Helper function to get PCM hardware timestamp.
108 * Only the field 'timestamp' of argument 'ts' is updated. */
109static int get_pcm_timestamp(struct pcm* pcm, uint32_t sample_rate, struct aec_info* info,
110 bool isOutput) {
111 int ret = 0;
112 if (pcm_get_htimestamp(pcm, &info->available, &info->timestamp) < 0) {
113 ALOGE("Error getting PCM timestamp!");
114 info->timestamp.tv_sec = 0;
115 info->timestamp.tv_nsec = 0;
Amit Pundir456949d2020-02-18 22:44:16 +0530116 return -EINVAL;
117 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530118 ssize_t frames;
119 if (isOutput) {
120 frames = pcm_get_buffer_size(pcm) - info->available;
121 } else {
122 frames = -info->available; /* rewind timestamp */
123 }
124 timestamp_adjust(&info->timestamp, frames, sample_rate);
125 return ret;
Amit Pundir456949d2020-02-18 22:44:16 +0530126}
127
Amit Pundire6732bb2020-09-28 12:43:59 +0530128static int read_filter_from_file(const char* filename, int16_t* filter, int max_length) {
129 FILE* fp = fopen(filename, "r");
130 if (fp == NULL) {
131 ALOGI("%s: File %s not found.", __func__, filename);
132 return 0;
133 }
134 int num_taps = 0;
135 char* line = NULL;
136 size_t len = 0;
137 while (!feof(fp)) {
138 size_t size = getline(&line, &len, fp);
139 if ((line[0] == '#') || (size < 2)) {
140 continue;
141 }
142 int n = sscanf(line, "%" SCNd16 "\n", &filter[num_taps++]);
143 if (n < 1) {
144 ALOGE("Could not find coefficient %d! Exiting...", num_taps - 1);
145 return 0;
146 }
147 ALOGV("Coeff %d : %" PRId16, num_taps, filter[num_taps - 1]);
148 if (num_taps == max_length) {
149 ALOGI("%s: max tap length %d reached.", __func__, max_length);
Amit Pundir456949d2020-02-18 22:44:16 +0530150 break;
151 }
Amit Pundir456949d2020-02-18 22:44:16 +0530152 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530153 free(line);
154 fclose(fp);
155 return num_taps;
Amit Pundir456949d2020-02-18 22:44:16 +0530156}
157
Amit Pundire6732bb2020-09-28 12:43:59 +0530158static void out_set_eq(struct alsa_stream_out* out) {
159 out->speaker_eq = NULL;
160 int16_t* speaker_eq_coeffs = (int16_t*)calloc(SPEAKER_MAX_EQ_LENGTH, sizeof(int16_t));
161 if (speaker_eq_coeffs == NULL) {
162 ALOGE("%s: Failed to allocate speaker EQ", __func__);
163 return;
164 }
165 int num_taps = read_filter_from_file(SPEAKER_EQ_FILE, speaker_eq_coeffs, SPEAKER_MAX_EQ_LENGTH);
166 if (num_taps == 0) {
167 ALOGI("%s: Empty filter file or 0 taps set.", __func__);
168 free(speaker_eq_coeffs);
169 return;
170 }
171 out->speaker_eq = fir_init(
172 out->config.channels, FIR_SINGLE_FILTER, num_taps,
173 out_get_buffer_size(&out->stream.common) / out->config.channels / sizeof(int16_t),
174 speaker_eq_coeffs);
175 free(speaker_eq_coeffs);
176}
Amit Pundir456949d2020-02-18 22:44:16 +0530177
Amit Pundire6732bb2020-09-28 12:43:59 +0530178/* must be called with hw device and output stream mutexes locked */
179static int start_output_stream(struct alsa_stream_out *out)
180{
181 struct alsa_audio_device *adev = out->dev;
182
183 /* default to low power: will be corrected in out_write if necessary before first write to
184 * tinyalsa.
185 */
186 out->write_threshold = PLAYBACK_PERIOD_COUNT * PLAYBACK_PERIOD_SIZE;
187 out->config.start_threshold = PLAYBACK_PERIOD_START_THRESHOLD * PLAYBACK_PERIOD_SIZE;
188 out->config.avail_min = PLAYBACK_PERIOD_SIZE;
189 out->unavailable = true;
190 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
191 int out_port = get_audio_output_port(out->devices);
John Stultz57a02362021-09-02 03:26:56 +0000192 int out_card = get_audio_card(PCM_OUT, out_port);
Amit Pundire6732bb2020-09-28 12:43:59 +0530193
194 while (1) {
John Stultz57a02362021-09-02 03:26:56 +0000195 out->pcm = pcm_open(out_card, out_port, PCM_OUT | PCM_MONOTONIC, &out->config);
Amit Pundire6732bb2020-09-28 12:43:59 +0530196 if ((out->pcm != NULL) && pcm_is_ready(out->pcm)) {
Amit Pundir456949d2020-02-18 22:44:16 +0530197 break;
Amit Pundire6732bb2020-09-28 12:43:59 +0530198 } else {
199 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm));
200 if (out->pcm != NULL) {
201 pcm_close(out->pcm);
202 out->pcm = NULL;
203 }
204 if (--pcm_retry_count == 0) {
205 ALOGE("Failed to open pcm_out after %d tries", PCM_OPEN_RETRIES);
206 return -ENODEV;
207 }
208 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
Amit Pundir456949d2020-02-18 22:44:16 +0530209 }
Amit Pundir456949d2020-02-18 22:44:16 +0530210 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530211 out->unavailable = false;
212 adev->active_output = out;
213 return 0;
Amit Pundir456949d2020-02-18 22:44:16 +0530214}
215
Amit Pundir4e375822019-04-18 16:46:10 +0530216static uint32_t out_get_sample_rate(const struct audio_stream *stream)
217{
Amit Pundire6732bb2020-09-28 12:43:59 +0530218 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
219 return out->config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530220}
221
222static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
223{
Amit Pundire6732bb2020-09-28 12:43:59 +0530224 ALOGV("out_set_sample_rate: %d", 0);
Amit Pundir4e375822019-04-18 16:46:10 +0530225 return -ENOSYS;
226}
227
228static size_t out_get_buffer_size(const struct audio_stream *stream)
229{
Amit Pundire6732bb2020-09-28 12:43:59 +0530230 ALOGV("out_get_buffer_size: %d", 4096);
Amit Pundir4e375822019-04-18 16:46:10 +0530231
Amit Pundire6732bb2020-09-28 12:43:59 +0530232 /* return the closest majoring multiple of 16 frames, as
233 * audioflinger expects audio buffers to be a multiple of 16 frames */
234 size_t size = PLAYBACK_PERIOD_SIZE;
235 size = ((size + 15) / 16) * 16;
236 return size * audio_stream_out_frame_size((struct audio_stream_out *)stream);
Amit Pundir4e375822019-04-18 16:46:10 +0530237}
238
239static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
240{
Amit Pundire6732bb2020-09-28 12:43:59 +0530241 ALOGV("out_get_channels");
242 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
243 return audio_channel_out_mask_from_count(out->config.channels);
Amit Pundir4e375822019-04-18 16:46:10 +0530244}
245
246static audio_format_t out_get_format(const struct audio_stream *stream)
247{
Amit Pundire6732bb2020-09-28 12:43:59 +0530248 ALOGV("out_get_format");
249 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
250 return audio_format_from_pcm_format(out->config.format);
Amit Pundir4e375822019-04-18 16:46:10 +0530251}
252
253static int out_set_format(struct audio_stream *stream, audio_format_t format)
254{
Amit Pundire6732bb2020-09-28 12:43:59 +0530255 ALOGV("out_set_format: %d",format);
Amit Pundir4e375822019-04-18 16:46:10 +0530256 return -ENOSYS;
257}
258
Amit Pundire6732bb2020-09-28 12:43:59 +0530259static int do_output_standby(struct alsa_stream_out *out)
260{
261 struct alsa_audio_device *adev = out->dev;
262
263 fir_reset(out->speaker_eq);
264
265 if (!out->standby) {
266 pcm_close(out->pcm);
267 out->pcm = NULL;
268 adev->active_output = NULL;
269 out->standby = 1;
270 }
271 aec_set_spk_running(adev->aec, false);
272 return 0;
273}
274
275static int out_standby(struct audio_stream *stream)
276{
277 ALOGV("out_standby");
278 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
279 int status;
280
281 pthread_mutex_lock(&out->dev->lock);
282 pthread_mutex_lock(&out->lock);
283 status = do_output_standby(out);
284 pthread_mutex_unlock(&out->lock);
285 pthread_mutex_unlock(&out->dev->lock);
286 return status;
287}
288
Amit Pundir4e375822019-04-18 16:46:10 +0530289static int out_dump(const struct audio_stream *stream, int fd)
290{
Amit Pundire6732bb2020-09-28 12:43:59 +0530291 ALOGV("out_dump");
Amit Pundir4e375822019-04-18 16:46:10 +0530292 return 0;
293}
294
295static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
296{
Amit Pundire6732bb2020-09-28 12:43:59 +0530297 ALOGV("out_set_parameters");
298 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
299 struct alsa_audio_device *adev = out->dev;
Amit Pundir4e375822019-04-18 16:46:10 +0530300 struct str_parms *parms;
301 char value[32];
Amit Pundire6732bb2020-09-28 12:43:59 +0530302 int ret, val = 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530303
304 parms = str_parms_create_str(kvpairs);
305
Amit Pundire6732bb2020-09-28 12:43:59 +0530306 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
307 if (ret >= 0) {
308 val = atoi(value);
309 pthread_mutex_lock(&adev->lock);
310 pthread_mutex_lock(&out->lock);
311 if (((out->devices & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) {
312 out->devices &= ~AUDIO_DEVICE_OUT_ALL;
313 out->devices |= val;
314 }
315 pthread_mutex_unlock(&out->lock);
316 pthread_mutex_unlock(&adev->lock);
Amit Pundir4e375822019-04-18 16:46:10 +0530317 }
318
319 str_parms_destroy(parms);
Amit Pundire6732bb2020-09-28 12:43:59 +0530320 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530321}
322
323static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
324{
Amit Pundire6732bb2020-09-28 12:43:59 +0530325 ALOGV("out_get_parameters");
326 return strdup("");
Amit Pundir4e375822019-04-18 16:46:10 +0530327}
328
329static uint32_t out_get_latency(const struct audio_stream_out *stream)
330{
Amit Pundire6732bb2020-09-28 12:43:59 +0530331 ALOGV("out_get_latency");
332 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
333 return (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT * 1000) / out->config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530334}
335
336static int out_set_volume(struct audio_stream_out *stream, float left,
Amit Pundire6732bb2020-09-28 12:43:59 +0530337 float right)
Amit Pundir4e375822019-04-18 16:46:10 +0530338{
Amit Pundire6732bb2020-09-28 12:43:59 +0530339 ALOGV("out_set_volume: Left:%f Right:%f", left, right);
Amit Pundir456949d2020-02-18 22:44:16 +0530340 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530341}
342
Amit Pundire6732bb2020-09-28 12:43:59 +0530343static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
344 size_t bytes)
Amit Pundir4e375822019-04-18 16:46:10 +0530345{
Amit Pundire6732bb2020-09-28 12:43:59 +0530346 int ret;
347 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
348 struct alsa_audio_device *adev = out->dev;
349 size_t frame_size = audio_stream_out_frame_size(stream);
350 size_t out_frames = bytes / frame_size;
Amit Pundir456949d2020-02-18 22:44:16 +0530351
Amit Pundire6732bb2020-09-28 12:43:59 +0530352 ALOGV("%s: devices: %d, bytes %zu", __func__, out->devices, bytes);
Amit Pundir456949d2020-02-18 22:44:16 +0530353
Amit Pundire6732bb2020-09-28 12:43:59 +0530354 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
355 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
356 * mutex
357 */
358 pthread_mutex_lock(&adev->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530359 pthread_mutex_lock(&out->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530360 if (out->standby) {
Amit Pundire6732bb2020-09-28 12:43:59 +0530361 ret = start_output_stream(out);
362 if (ret != 0) {
363 pthread_mutex_unlock(&adev->lock);
364 goto exit;
365 }
366 out->standby = 0;
367 aec_set_spk_running(adev->aec, true);
Amit Pundir456949d2020-02-18 22:44:16 +0530368 }
369
Amit Pundire6732bb2020-09-28 12:43:59 +0530370 pthread_mutex_unlock(&adev->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530371
Amit Pundire6732bb2020-09-28 12:43:59 +0530372 if (out->speaker_eq != NULL) {
373 fir_process_interleaved(out->speaker_eq, (int16_t*)buffer, (int16_t*)buffer, out_frames);
Amit Pundir456949d2020-02-18 22:44:16 +0530374 }
Amit Pundir456949d2020-02-18 22:44:16 +0530375
Amit Pundire6732bb2020-09-28 12:43:59 +0530376 ret = pcm_write(out->pcm, buffer, out_frames * frame_size);
377 if (ret == 0) {
378 out->frames_written += out_frames;
379
380 struct aec_info info;
381 get_pcm_timestamp(out->pcm, out->config.rate, &info, true /*isOutput*/);
382 out->timestamp = info.timestamp;
383 info.bytes = out_frames * frame_size;
384 int aec_ret = write_to_reference_fifo(adev->aec, (void *)buffer, &info);
385 if (aec_ret) {
386 ALOGE("AEC: Write to speaker loopback FIFO failed!");
387 }
388 }
389
390exit:
Amit Pundir4e375822019-04-18 16:46:10 +0530391 pthread_mutex_unlock(&out->lock);
392
Amit Pundire6732bb2020-09-28 12:43:59 +0530393 if (ret != 0) {
394 usleep((int64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
395 out_get_sample_rate(&stream->common));
Amit Pundir4e375822019-04-18 16:46:10 +0530396 }
397
Amit Pundir456949d2020-02-18 22:44:16 +0530398 return bytes;
Amit Pundir4e375822019-04-18 16:46:10 +0530399}
400
Amit Pundire6732bb2020-09-28 12:43:59 +0530401static int out_get_render_position(const struct audio_stream_out *stream,
402 uint32_t *dsp_frames)
403{
404 ALOGV("out_get_render_position: dsp_frames: %p", dsp_frames);
405 return -ENOSYS;
406}
407
Amit Pundir4e375822019-04-18 16:46:10 +0530408static int out_get_presentation_position(const struct audio_stream_out *stream,
409 uint64_t *frames, struct timespec *timestamp)
410{
Amit Pundir456949d2020-02-18 22:44:16 +0530411 if (stream == NULL || frames == NULL || timestamp == NULL) {
412 return -EINVAL;
413 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530414 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
Amit Pundir4e375822019-04-18 16:46:10 +0530415
Amit Pundire6732bb2020-09-28 12:43:59 +0530416 *frames = out->frames_written;
417 *timestamp = out->timestamp;
418 ALOGV("%s: frames: %" PRIu64 ", timestamp (nsec): %" PRIu64, __func__, *frames,
419 audio_utils_ns_from_timespec(timestamp));
Amit Pundir4e375822019-04-18 16:46:10 +0530420
Amit Pundir456949d2020-02-18 22:44:16 +0530421 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530422}
423
424
425static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
426{
Amit Pundire6732bb2020-09-28 12:43:59 +0530427 ALOGV("out_add_audio_effect: %p", effect);
Amit Pundir4e375822019-04-18 16:46:10 +0530428 return 0;
429}
430
431static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
432{
Amit Pundire6732bb2020-09-28 12:43:59 +0530433 ALOGV("out_remove_audio_effect: %p", effect);
Amit Pundir4e375822019-04-18 16:46:10 +0530434 return 0;
435}
436
437static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
Amit Pundire6732bb2020-09-28 12:43:59 +0530438 int64_t *timestamp)
Amit Pundir4e375822019-04-18 16:46:10 +0530439{
Amit Pundire6732bb2020-09-28 12:43:59 +0530440 *timestamp = 0;
441 ALOGV("out_get_next_write_timestamp: %ld", (long int)(*timestamp));
Amit Pundir456949d2020-02-18 22:44:16 +0530442 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530443}
444
Amit Pundire6732bb2020-09-28 12:43:59 +0530445/** audio_stream_in implementation **/
446
447/* must be called with hw device and input stream mutexes locked */
448static int start_input_stream(struct alsa_stream_in *in)
449{
450 struct alsa_audio_device *adev = in->dev;
451 in->unavailable = true;
452 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
John Stultz57a02362021-09-02 03:26:56 +0000453 int in_card = get_audio_card(PCM_IN, PORT_BUILTIN_MIC);
Amit Pundire6732bb2020-09-28 12:43:59 +0530454
455 while (1) {
John Stultz57a02362021-09-02 03:26:56 +0000456 in->pcm = pcm_open(in_card, PORT_BUILTIN_MIC, PCM_IN | PCM_MONOTONIC, &in->config);
Amit Pundire6732bb2020-09-28 12:43:59 +0530457 if ((in->pcm != NULL) && pcm_is_ready(in->pcm)) {
458 break;
459 } else {
460 ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
461 if (in->pcm != NULL) {
462 pcm_close(in->pcm);
463 in->pcm = NULL;
464 }
465 if (--pcm_retry_count == 0) {
466 ALOGE("Failed to open pcm_in after %d tries", PCM_OPEN_RETRIES);
467 return -ENODEV;
468 }
469 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
470 }
471 }
472 in->unavailable = false;
473 adev->active_input = in;
474 return 0;
475}
476
477static void get_mic_characteristics(struct audio_microphone_characteristic_t* mic_data,
478 size_t* mic_count) {
479 *mic_count = 1;
480 memset(mic_data, 0, sizeof(struct audio_microphone_characteristic_t));
481 strlcpy(mic_data->device_id, "builtin_mic", AUDIO_MICROPHONE_ID_MAX_LEN - 1);
482 strlcpy(mic_data->address, "top", AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
483 memset(mic_data->channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
484 sizeof(mic_data->channel_mapping));
485 mic_data->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
486 mic_data->sensitivity = -37.0;
487 mic_data->max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
488 mic_data->min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
489 mic_data->orientation.x = 0.0f;
490 mic_data->orientation.y = 0.0f;
491 mic_data->orientation.z = 0.0f;
492 mic_data->geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
493 mic_data->geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
494 mic_data->geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
495}
496
Amit Pundir4e375822019-04-18 16:46:10 +0530497static uint32_t in_get_sample_rate(const struct audio_stream *stream)
498{
Amit Pundire6732bb2020-09-28 12:43:59 +0530499 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
500 return in->config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530501}
502
503static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
504{
Amit Pundire6732bb2020-09-28 12:43:59 +0530505 ALOGV("in_set_sample_rate: %d", rate);
Amit Pundir4e375822019-04-18 16:46:10 +0530506 return -ENOSYS;
507}
508
Amit Pundire6732bb2020-09-28 12:43:59 +0530509static size_t get_input_buffer_size(size_t frames, audio_format_t format,
510 audio_channel_mask_t channel_mask) {
511 /* return the closest majoring multiple of 16 frames, as
512 * audioflinger expects audio buffers to be a multiple of 16 frames */
513 frames = ((frames + 15) / 16) * 16;
514 size_t bytes_per_frame = audio_channel_count_from_in_mask(channel_mask) *
515 audio_bytes_per_sample(format);
516 size_t buffer_size = frames * bytes_per_frame;
517 return buffer_size;
Amit Pundir4e375822019-04-18 16:46:10 +0530518}
519
520static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
521{
Amit Pundire6732bb2020-09-28 12:43:59 +0530522 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
523 ALOGV("in_get_channels: %d", in->config.channels);
524 return audio_channel_in_mask_from_count(in->config.channels);
Amit Pundir4e375822019-04-18 16:46:10 +0530525}
526
527static audio_format_t in_get_format(const struct audio_stream *stream)
528{
Amit Pundire6732bb2020-09-28 12:43:59 +0530529 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
530 ALOGV("in_get_format: %d", in->config.format);
531 return audio_format_from_pcm_format(in->config.format);
Amit Pundir4e375822019-04-18 16:46:10 +0530532}
533
534static int in_set_format(struct audio_stream *stream, audio_format_t format)
535{
536 return -ENOSYS;
537}
538
Amit Pundire6732bb2020-09-28 12:43:59 +0530539static size_t in_get_buffer_size(const struct audio_stream *stream)
Amit Pundir4e375822019-04-18 16:46:10 +0530540{
Amit Pundire6732bb2020-09-28 12:43:59 +0530541 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
542 size_t frames = CAPTURE_PERIOD_SIZE;
543 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
544 frames = CAPTURE_PERIOD_SIZE * PLAYBACK_CODEC_SAMPLING_RATE / CAPTURE_CODEC_SAMPLING_RATE;
545 }
546
547 size_t buffer_size =
548 get_input_buffer_size(frames, stream->get_format(stream), stream->get_channels(stream));
549 ALOGV("in_get_buffer_size: %zu", buffer_size);
550 return buffer_size;
551}
552
553static int in_get_active_microphones(const struct audio_stream_in* stream,
554 struct audio_microphone_characteristic_t* mic_array,
555 size_t* mic_count) {
556 ALOGV("in_get_active_microphones");
557 if ((mic_array == NULL) || (mic_count == NULL)) {
558 return -EINVAL;
559 }
560 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
561 struct audio_hw_device* dev = (struct audio_hw_device*)in->dev;
562 bool mic_muted = false;
563 adev_get_mic_mute(dev, &mic_muted);
564 if ((in->source == AUDIO_SOURCE_ECHO_REFERENCE) || mic_muted) {
565 *mic_count = 0;
566 return 0;
567 }
568 adev_get_microphones(dev, mic_array, mic_count);
569 return 0;
570}
571
572static int do_input_standby(struct alsa_stream_in *in)
573{
574 struct alsa_audio_device *adev = in->dev;
575
576 if (!in->standby) {
577 pcm_close(in->pcm);
578 in->pcm = NULL;
579 adev->active_input = NULL;
580 in->standby = true;
581 }
582 return 0;
583}
584
585static int in_standby(struct audio_stream *stream)
586{
587 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
588 int status;
Amit Pundir456949d2020-02-18 22:44:16 +0530589
590 pthread_mutex_lock(&in->lock);
Amit Pundire6732bb2020-09-28 12:43:59 +0530591 pthread_mutex_lock(&in->dev->lock);
592 status = do_input_standby(in);
593 pthread_mutex_unlock(&in->dev->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530594 pthread_mutex_unlock(&in->lock);
Amit Pundire6732bb2020-09-28 12:43:59 +0530595 return status;
596}
597
598static int in_dump(const struct audio_stream *stream, int fd)
599{
600 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
601 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
602 return 0;
603 }
604
605 struct audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
606 size_t mic_count;
607
608 get_mic_characteristics(mic_array, &mic_count);
609
610 dprintf(fd, " Microphone count: %zd\n", mic_count);
611 size_t idx;
612 for (idx = 0; idx < mic_count; idx++) {
613 dprintf(fd, " Microphone: %zd\n", idx);
614 dprintf(fd, " Address: %s\n", mic_array[idx].address);
615 dprintf(fd, " Device: %d\n", mic_array[idx].device);
616 dprintf(fd, " Sensitivity (dB): %.2f\n", mic_array[idx].sensitivity);
617 }
618
Amit Pundir4e375822019-04-18 16:46:10 +0530619 return 0;
620}
621
622static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
623{
Amit Pundire6732bb2020-09-28 12:43:59 +0530624 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530625}
626
627static char * in_get_parameters(const struct audio_stream *stream,
Amit Pundire6732bb2020-09-28 12:43:59 +0530628 const char *keys)
Amit Pundir4e375822019-04-18 16:46:10 +0530629{
Amit Pundire6732bb2020-09-28 12:43:59 +0530630 return strdup("");
Amit Pundir4e375822019-04-18 16:46:10 +0530631}
632
633static int in_set_gain(struct audio_stream_in *stream, float gain)
634{
635 return 0;
636}
637
Amit Pundir456949d2020-02-18 22:44:16 +0530638static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
Amit Pundire6732bb2020-09-28 12:43:59 +0530639 size_t bytes)
Amit Pundir456949d2020-02-18 22:44:16 +0530640{
Amit Pundire6732bb2020-09-28 12:43:59 +0530641 int ret;
642 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
643 struct alsa_audio_device *adev = in->dev;
644 size_t frame_size = audio_stream_in_frame_size(stream);
645 size_t in_frames = bytes / frame_size;
Amit Pundir456949d2020-02-18 22:44:16 +0530646
Amit Pundire6732bb2020-09-28 12:43:59 +0530647 ALOGV("in_read: stream: %d, bytes %zu", in->source, bytes);
Amit Pundir456949d2020-02-18 22:44:16 +0530648
Amit Pundire6732bb2020-09-28 12:43:59 +0530649 /* Special handling for Echo Reference: simply get the reference from FIFO.
650 * The format and sample rate should be specified by arguments to adev_open_input_stream. */
651 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
652 struct aec_info info;
653 info.bytes = bytes;
Amit Pundir456949d2020-02-18 22:44:16 +0530654
Amit Pundire6732bb2020-09-28 12:43:59 +0530655 const uint64_t time_increment_nsec = (uint64_t)bytes * NANOS_PER_SECOND /
656 audio_stream_in_frame_size(stream) /
657 in_get_sample_rate(&stream->common);
658 if (!aec_get_spk_running(adev->aec)) {
659 if (in->timestamp_nsec == 0) {
660 struct timespec now;
661 clock_gettime(CLOCK_MONOTONIC, &now);
662 const uint64_t timestamp_nsec = audio_utils_ns_from_timespec(&now);
663 in->timestamp_nsec = timestamp_nsec;
664 } else {
665 in->timestamp_nsec += time_increment_nsec;
666 }
667 memset(buffer, 0, bytes);
668 const uint64_t time_increment_usec = time_increment_nsec / 1000;
669 usleep(time_increment_usec);
670 } else {
671 int ref_ret = get_reference_samples(adev->aec, buffer, &info);
672 if ((ref_ret) || (info.timestamp_usec == 0)) {
673 memset(buffer, 0, bytes);
674 in->timestamp_nsec += time_increment_nsec;
675 } else {
676 in->timestamp_nsec = 1000 * info.timestamp_usec;
Amit Pundir456949d2020-02-18 22:44:16 +0530677 }
678 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530679 in->frames_read += in_frames;
Amit Pundir456949d2020-02-18 22:44:16 +0530680
Amit Pundire6732bb2020-09-28 12:43:59 +0530681#if DEBUG_AEC
682 FILE* fp_ref = fopen("/data/local/traces/aec_ref.pcm", "a+");
683 if (fp_ref) {
684 fwrite((char*)buffer, 1, bytes, fp_ref);
685 fclose(fp_ref);
686 } else {
687 ALOGE("AEC debug: Could not open file aec_ref.pcm!");
Amit Pundir456949d2020-02-18 22:44:16 +0530688 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530689 FILE* fp_ref_ts = fopen("/data/local/traces/aec_ref_timestamps.txt", "a+");
690 if (fp_ref_ts) {
691 fprintf(fp_ref_ts, "%" PRIu64 "\n", in->timestamp_nsec);
692 fclose(fp_ref_ts);
693 } else {
694 ALOGE("AEC debug: Could not open file aec_ref_timestamps.txt!");
695 }
696#endif
697 return info.bytes;
698 }
699
700 /* Microphone input stream read */
701
702 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
703 * on the input stream mutex - e.g. executing select_mode() while holding the hw device
704 * mutex
705 */
706 pthread_mutex_lock(&in->lock);
707 pthread_mutex_lock(&adev->lock);
708 if (in->standby) {
709 ret = start_input_stream(in);
710 if (ret != 0) {
711 pthread_mutex_unlock(&adev->lock);
712 ALOGE("start_input_stream failed with code %d", ret);
713 goto exit;
714 }
715 in->standby = false;
716 }
717
718 pthread_mutex_unlock(&adev->lock);
719
720 ret = pcm_read(in->pcm, buffer, in_frames * frame_size);
721 struct aec_info info;
722 get_pcm_timestamp(in->pcm, in->config.rate, &info, false /*isOutput*/);
723 if (ret == 0) {
724 in->frames_read += in_frames;
725 in->timestamp_nsec = audio_utils_ns_from_timespec(&info.timestamp);
726 }
727 else {
728 ALOGE("pcm_read failed with code %d", ret);
Amit Pundir456949d2020-02-18 22:44:16 +0530729 }
730
731exit:
Amit Pundir456949d2020-02-18 22:44:16 +0530732 pthread_mutex_unlock(&in->lock);
733
Amit Pundire6732bb2020-09-28 12:43:59 +0530734 bool mic_muted = false;
735 adev_get_mic_mute((struct audio_hw_device*)adev, &mic_muted);
736 if (mic_muted) {
737 memset(buffer, 0, bytes);
738 }
739
740 if (ret != 0) {
741 usleep((int64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
742 in_get_sample_rate(&stream->common));
743 } else {
744 /* Process AEC if available */
745 /* TODO move to a separate thread */
746 if (!mic_muted) {
747 info.bytes = bytes;
748 int aec_ret = process_aec(adev->aec, buffer, &info);
749 if (aec_ret) {
750 ALOGE("process_aec returned error code %d", aec_ret);
751 }
752 }
753 }
754
755#if DEBUG_AEC && !defined(AEC_HAL)
756 FILE* fp_in = fopen("/data/local/traces/aec_in.pcm", "a+");
757 if (fp_in) {
758 fwrite((char*)buffer, 1, bytes, fp_in);
759 fclose(fp_in);
760 } else {
761 ALOGE("AEC debug: Could not open file aec_in.pcm!");
762 }
763 FILE* fp_mic_ts = fopen("/data/local/traces/aec_in_timestamps.txt", "a+");
764 if (fp_mic_ts) {
765 fprintf(fp_mic_ts, "%" PRIu64 "\n", in->timestamp_nsec);
766 fclose(fp_mic_ts);
767 } else {
768 ALOGE("AEC debug: Could not open file aec_in_timestamps.txt!");
769 }
770#endif
771
Amit Pundir4e375822019-04-18 16:46:10 +0530772 return bytes;
773}
774
Amit Pundire6732bb2020-09-28 12:43:59 +0530775static int in_get_capture_position(const struct audio_stream_in* stream, int64_t* frames,
776 int64_t* time) {
777 if (stream == NULL || frames == NULL || time == NULL) {
778 return -EINVAL;
779 }
780 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
781
782 *frames = in->frames_read;
783 *time = in->timestamp_nsec;
784 ALOGV("%s: source: %d, timestamp (nsec): %" PRIu64, __func__, in->source, *time);
785
786 return 0;
787}
788
Amit Pundir4e375822019-04-18 16:46:10 +0530789static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
790{
791 return 0;
792}
793
794static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
795{
796 return 0;
797}
798
799static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
800{
801 return 0;
802}
803
804static int adev_open_output_stream(struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530805 audio_io_handle_t handle,
806 audio_devices_t devices,
807 audio_output_flags_t flags,
808 struct audio_config *config,
809 struct audio_stream_out **stream_out,
810 const char *address __unused)
Amit Pundir4e375822019-04-18 16:46:10 +0530811{
Amit Pundire6732bb2020-09-28 12:43:59 +0530812 ALOGV("adev_open_output_stream...");
813
814 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundire6732bb2020-09-28 12:43:59 +0530815 int out_port = get_audio_output_port(devices);
John Stultz57a02362021-09-02 03:26:56 +0000816 int out_card = get_audio_card(PCM_OUT, out_port);
817 struct pcm_params* params = pcm_params_get(out_card, out_port, PCM_OUT);
Alden DSouzae44e0672021-02-11 17:07:01 -0800818 if (!params) {
Amit Pundire6732bb2020-09-28 12:43:59 +0530819 return -ENOSYS;
Alden DSouzae44e0672021-02-11 17:07:01 -0800820 }
Amit Pundir456949d2020-02-18 22:44:16 +0530821
Alden DSouzae44e0672021-02-11 17:07:01 -0800822 struct alsa_stream_out* out =
823 (struct alsa_stream_out*)calloc(1, sizeof(struct alsa_stream_out));
824 if (!out) {
Amit Pundir4e375822019-04-18 16:46:10 +0530825 return -ENOMEM;
Alden DSouzae44e0672021-02-11 17:07:01 -0800826 }
Amit Pundir4e375822019-04-18 16:46:10 +0530827
828 out->stream.common.get_sample_rate = out_get_sample_rate;
829 out->stream.common.set_sample_rate = out_set_sample_rate;
830 out->stream.common.get_buffer_size = out_get_buffer_size;
831 out->stream.common.get_channels = out_get_channels;
832 out->stream.common.get_format = out_get_format;
833 out->stream.common.set_format = out_set_format;
834 out->stream.common.standby = out_standby;
835 out->stream.common.dump = out_dump;
836 out->stream.common.set_parameters = out_set_parameters;
837 out->stream.common.get_parameters = out_get_parameters;
838 out->stream.common.add_audio_effect = out_add_audio_effect;
839 out->stream.common.remove_audio_effect = out_remove_audio_effect;
840 out->stream.get_latency = out_get_latency;
841 out->stream.set_volume = out_set_volume;
842 out->stream.write = out_write;
843 out->stream.get_render_position = out_get_render_position;
Amit Pundir456949d2020-02-18 22:44:16 +0530844 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Amit Pundire6732bb2020-09-28 12:43:59 +0530845 out->stream.get_presentation_position = out_get_presentation_position;
Amit Pundir4e375822019-04-18 16:46:10 +0530846
Amit Pundire6732bb2020-09-28 12:43:59 +0530847 out->config.channels = CHANNEL_STEREO;
848 out->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
849 out->config.format = PCM_FORMAT_S16_LE;
850 out->config.period_size = PLAYBACK_PERIOD_SIZE;
851 out->config.period_count = PLAYBACK_PERIOD_COUNT;
Amit Pundir4e375822019-04-18 16:46:10 +0530852
Amit Pundire6732bb2020-09-28 12:43:59 +0530853 if (out->config.rate != config->sample_rate ||
854 audio_channel_count_from_out_mask(config->channel_mask) != CHANNEL_STEREO ||
855 out->config.format != pcm_format_from_audio_format(config->format) ) {
856 config->sample_rate = out->config.rate;
857 config->format = audio_format_from_pcm_format(out->config.format);
858 config->channel_mask = audio_channel_out_mask_from_count(CHANNEL_STEREO);
Alden DSouzae44e0672021-02-11 17:07:01 -0800859 goto error_1;
Amit Pundir4e375822019-04-18 16:46:10 +0530860 }
861
Amit Pundire6732bb2020-09-28 12:43:59 +0530862 ALOGI("adev_open_output_stream selects channels=%d rate=%d format=%d, devices=%d",
863 out->config.channels, out->config.rate, out->config.format, devices);
864
865 out->dev = ladev;
866 out->standby = 1;
867 out->unavailable = false;
868 out->devices = devices;
869
870 config->format = out_get_format(&out->stream.common);
871 config->channel_mask = out_get_channels(&out->stream.common);
872 config->sample_rate = out_get_sample_rate(&out->stream.common);
Amit Pundir4e375822019-04-18 16:46:10 +0530873
Amit Pundire6732bb2020-09-28 12:43:59 +0530874 out->speaker_eq = NULL;
875 if (out_port == PORT_INTERNAL_SPEAKER) {
876 out_set_eq(out);
877 if (out->speaker_eq == NULL) {
878 ALOGE("%s: Failed to initialize speaker EQ", __func__);
879 }
880 }
881
Alden DSouzae44e0672021-02-11 17:07:01 -0800882 int aec_ret = init_aec_reference_config(ladev->aec, out);
883 if (aec_ret) {
884 ALOGE("AEC: Speaker config init failed!");
885 goto error_2;
Amit Pundire6732bb2020-09-28 12:43:59 +0530886 }
Amit Pundir4e375822019-04-18 16:46:10 +0530887
Alden DSouzae44e0672021-02-11 17:07:01 -0800888 *stream_out = &out->stream;
889 return 0;
890
891error_2:
892 fir_release(out->speaker_eq);
893error_1:
894 free(out);
895 return -EINVAL;
Amit Pundir4e375822019-04-18 16:46:10 +0530896}
897
898static void adev_close_output_stream(struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530899 struct audio_stream_out *stream)
Amit Pundir4e375822019-04-18 16:46:10 +0530900{
Amit Pundire6732bb2020-09-28 12:43:59 +0530901 ALOGV("adev_close_output_stream...");
902 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
903 destroy_aec_reference_config(adev->aec);
904 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
905 fir_release(out->speaker_eq);
Amit Pundir4e375822019-04-18 16:46:10 +0530906 free(stream);
907}
908
909static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
910{
Amit Pundire6732bb2020-09-28 12:43:59 +0530911 ALOGV("adev_set_parameters");
912 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530913}
914
915static char * adev_get_parameters(const struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530916 const char *keys)
Amit Pundir4e375822019-04-18 16:46:10 +0530917{
Amit Pundire6732bb2020-09-28 12:43:59 +0530918 ALOGV("adev_get_parameters");
Amit Pundir4e375822019-04-18 16:46:10 +0530919 return strdup("");
920}
921
Amit Pundire6732bb2020-09-28 12:43:59 +0530922static int adev_get_microphones(const struct audio_hw_device* dev,
923 struct audio_microphone_characteristic_t* mic_array,
924 size_t* mic_count) {
925 ALOGV("adev_get_microphones");
926 if ((mic_array == NULL) || (mic_count == NULL)) {
927 return -EINVAL;
928 }
929 get_mic_characteristics(mic_array, mic_count);
930 return 0;
931}
932
Amit Pundir4e375822019-04-18 16:46:10 +0530933static int adev_init_check(const struct audio_hw_device *dev)
934{
Amit Pundire6732bb2020-09-28 12:43:59 +0530935 ALOGV("adev_init_check");
Amit Pundir4e375822019-04-18 16:46:10 +0530936 return 0;
937}
938
939static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
940{
Amit Pundire6732bb2020-09-28 12:43:59 +0530941 ALOGV("adev_set_voice_volume: %f", volume);
942 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530943}
944
945static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
946{
Amit Pundire6732bb2020-09-28 12:43:59 +0530947 ALOGV("adev_set_master_volume: %f", volume);
Amit Pundir4e375822019-04-18 16:46:10 +0530948 return -ENOSYS;
949}
950
951static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
952{
Amit Pundire6732bb2020-09-28 12:43:59 +0530953 ALOGV("adev_get_master_volume: %f", *volume);
Amit Pundir4e375822019-04-18 16:46:10 +0530954 return -ENOSYS;
955}
956
957static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
958{
Amit Pundire6732bb2020-09-28 12:43:59 +0530959 ALOGV("adev_set_master_mute: %d", muted);
Amit Pundir4e375822019-04-18 16:46:10 +0530960 return -ENOSYS;
961}
962
963static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
964{
Amit Pundire6732bb2020-09-28 12:43:59 +0530965 ALOGV("adev_get_master_mute: %d", *muted);
Amit Pundir4e375822019-04-18 16:46:10 +0530966 return -ENOSYS;
967}
968
969static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
970{
Amit Pundire6732bb2020-09-28 12:43:59 +0530971 ALOGV("adev_set_mode: %d", mode);
Amit Pundir4e375822019-04-18 16:46:10 +0530972 return 0;
973}
974
975static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
976{
Amit Pundire6732bb2020-09-28 12:43:59 +0530977 ALOGV("adev_set_mic_mute: %d",state);
978 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir456949d2020-02-18 22:44:16 +0530979 pthread_mutex_lock(&adev->lock);
980 adev->mic_mute = state;
981 pthread_mutex_unlock(&adev->lock);
982 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530983}
984
985static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
986{
Amit Pundire6732bb2020-09-28 12:43:59 +0530987 ALOGV("adev_get_mic_mute");
988 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir456949d2020-02-18 22:44:16 +0530989 pthread_mutex_lock(&adev->lock);
990 *state = adev->mic_mute;
991 pthread_mutex_unlock(&adev->lock);
992 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530993}
994
995static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530996 const struct audio_config *config)
Amit Pundir4e375822019-04-18 16:46:10 +0530997{
Amit Pundire6732bb2020-09-28 12:43:59 +0530998 size_t buffer_size =
999 get_input_buffer_size(CAPTURE_PERIOD_SIZE, config->format, config->channel_mask);
1000 ALOGV("adev_get_input_buffer_size: %zu", buffer_size);
1001 return buffer_size;
Amit Pundir4e375822019-04-18 16:46:10 +05301002}
1003
Amit Pundire6732bb2020-09-28 12:43:59 +05301004static int adev_open_input_stream(struct audio_hw_device* dev, audio_io_handle_t handle,
1005 audio_devices_t devices, struct audio_config* config,
1006 struct audio_stream_in** stream_in,
1007 audio_input_flags_t flags __unused, const char* address __unused,
1008 audio_source_t source) {
1009 ALOGV("adev_open_input_stream...");
Amit Pundir456949d2020-02-18 22:44:16 +05301010
Amit Pundire6732bb2020-09-28 12:43:59 +05301011 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundir456949d2020-02-18 22:44:16 +05301012
John Stultz57a02362021-09-02 03:26:56 +00001013 int in_card = get_audio_card(PCM_IN, PORT_BUILTIN_MIC);
1014 struct pcm_params* params = pcm_params_get(in_card, PORT_BUILTIN_MIC, PCM_IN);
Alden DSouzae44e0672021-02-11 17:07:01 -08001015 if (!params) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301016 return -ENOSYS;
Alden DSouzae44e0672021-02-11 17:07:01 -08001017 }
Amit Pundire6732bb2020-09-28 12:43:59 +05301018
Alden DSouzae44e0672021-02-11 17:07:01 -08001019 struct alsa_stream_in* in = (struct alsa_stream_in*)calloc(1, sizeof(struct alsa_stream_in));
1020 if (!in) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301021 return -ENOMEM;
Alden DSouzae44e0672021-02-11 17:07:01 -08001022 }
Amit Pundir4e375822019-04-18 16:46:10 +05301023
1024 in->stream.common.get_sample_rate = in_get_sample_rate;
Amit Pundire6732bb2020-09-28 12:43:59 +05301025 in->stream.common.set_sample_rate = in_set_sample_rate;
Amit Pundir4e375822019-04-18 16:46:10 +05301026 in->stream.common.get_buffer_size = in_get_buffer_size;
1027 in->stream.common.get_channels = in_get_channels;
1028 in->stream.common.get_format = in_get_format;
Amit Pundire6732bb2020-09-28 12:43:59 +05301029 in->stream.common.set_format = in_set_format;
Amit Pundir4e375822019-04-18 16:46:10 +05301030 in->stream.common.standby = in_standby;
1031 in->stream.common.dump = in_dump;
1032 in->stream.common.set_parameters = in_set_parameters;
1033 in->stream.common.get_parameters = in_get_parameters;
Amit Pundire6732bb2020-09-28 12:43:59 +05301034 in->stream.common.add_audio_effect = in_add_audio_effect;
1035 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1036 in->stream.set_gain = in_set_gain;
Amit Pundir4e375822019-04-18 16:46:10 +05301037 in->stream.read = in_read;
Amit Pundire6732bb2020-09-28 12:43:59 +05301038 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Amit Pundir456949d2020-02-18 22:44:16 +05301039 in->stream.get_capture_position = in_get_capture_position;
1040 in->stream.get_active_microphones = in_get_active_microphones;
1041
Amit Pundire6732bb2020-09-28 12:43:59 +05301042 in->config.channels = CHANNEL_STEREO;
1043 if (source == AUDIO_SOURCE_ECHO_REFERENCE) {
1044 in->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
1045 } else {
1046 in->config.rate = CAPTURE_CODEC_SAMPLING_RATE;
1047 }
1048 in->config.format = PCM_FORMAT_S32_LE;
1049 in->config.period_size = CAPTURE_PERIOD_SIZE;
1050 in->config.period_count = CAPTURE_PERIOD_COUNT;
Amit Pundir456949d2020-02-18 22:44:16 +05301051
Amit Pundire6732bb2020-09-28 12:43:59 +05301052 if (in->config.rate != config->sample_rate ||
1053 audio_channel_count_from_in_mask(config->channel_mask) != CHANNEL_STEREO ||
1054 in->config.format != pcm_format_from_audio_format(config->format) ) {
Alden DSouzae44e0672021-02-11 17:07:01 -08001055 config->format = in_get_format(&in->stream.common);
1056 config->channel_mask = in_get_channels(&in->stream.common);
1057 config->sample_rate = in_get_sample_rate(&in->stream.common);
1058 goto error_1;
Amit Pundire6732bb2020-09-28 12:43:59 +05301059 }
Amit Pundir456949d2020-02-18 22:44:16 +05301060
Amit Pundire6732bb2020-09-28 12:43:59 +05301061 ALOGI("adev_open_input_stream selects channels=%d rate=%d format=%d source=%d",
1062 in->config.channels, in->config.rate, in->config.format, source);
1063
1064 in->dev = ladev;
Amit Pundir456949d2020-02-18 22:44:16 +05301065 in->standby = true;
Amit Pundire6732bb2020-09-28 12:43:59 +05301066 in->unavailable = false;
1067 in->source = source;
1068 in->devices = devices;
Amit Pundir456949d2020-02-18 22:44:16 +05301069
Alden DSouzae44e0672021-02-11 17:07:01 -08001070 if (is_aec_input(in)) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301071 int aec_ret = init_aec_mic_config(ladev->aec, in);
1072 if (aec_ret) {
1073 ALOGE("AEC: Mic config init failed!");
Alden DSouzae44e0672021-02-11 17:07:01 -08001074 goto error_1;
Amit Pundir456949d2020-02-18 22:44:16 +05301075 }
Amit Pundire6732bb2020-09-28 12:43:59 +05301076 }
1077
Amit Pundire6732bb2020-09-28 12:43:59 +05301078#if DEBUG_AEC
1079 remove("/data/local/traces/aec_ref.pcm");
1080 remove("/data/local/traces/aec_in.pcm");
1081 remove("/data/local/traces/aec_ref_timestamps.txt");
1082 remove("/data/local/traces/aec_in_timestamps.txt");
1083#endif
Alden DSouzae44e0672021-02-11 17:07:01 -08001084
1085 *stream_in = &in->stream;
1086 return 0;
1087
1088error_1:
1089 free(in);
1090 return -EINVAL;
Amit Pundire6732bb2020-09-28 12:43:59 +05301091}
Amit Pundir456949d2020-02-18 22:44:16 +05301092
Amit Pundire6732bb2020-09-28 12:43:59 +05301093static void adev_close_input_stream(struct audio_hw_device *dev,
1094 struct audio_stream_in *stream)
1095{
1096 ALOGV("adev_close_input_stream...");
Alden DSouzae44e0672021-02-11 17:07:01 -08001097 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
1098 if (is_aec_input(in)) {
1099 destroy_aec_mic_config(in->dev->aec);
1100 }
Amit Pundire6732bb2020-09-28 12:43:59 +05301101 free(stream);
1102 return;
1103}
Amit Pundir456949d2020-02-18 22:44:16 +05301104
Amit Pundire6732bb2020-09-28 12:43:59 +05301105static int adev_dump(const audio_hw_device_t *device, int fd)
1106{
1107 ALOGV("adev_dump");
Amit Pundir4e375822019-04-18 16:46:10 +05301108 return 0;
1109}
1110
Amit Pundire6732bb2020-09-28 12:43:59 +05301111static int adev_close(hw_device_t *device)
Amit Pundir456949d2020-02-18 22:44:16 +05301112{
Amit Pundire6732bb2020-09-28 12:43:59 +05301113 ALOGV("adev_close");
Amit Pundir456949d2020-02-18 22:44:16 +05301114
Amit Pundire6732bb2020-09-28 12:43:59 +05301115 struct alsa_audio_device *adev = (struct alsa_audio_device *)device;
1116 release_aec(adev->aec);
Alden DSouzae44e0672021-02-11 17:07:01 -08001117 audio_route_free(adev->audio_route);
1118 mixer_close(adev->mixer);
Amit Pundire6732bb2020-09-28 12:43:59 +05301119 free(device);
1120 return 0;
Amit Pundir456949d2020-02-18 22:44:16 +05301121}
1122
Amit Pundir4e375822019-04-18 16:46:10 +05301123static int adev_open(const hw_module_t* module, const char* name,
Amit Pundire6732bb2020-09-28 12:43:59 +05301124 hw_device_t** device)
Amit Pundir4e375822019-04-18 16:46:10 +05301125{
Amit Pundirc0ad8942021-12-14 19:45:56 +05301126 char vendor_hw[PROPERTY_VALUE_MAX] = {0};
1127 // Prefix for the hdmi path, the board name is the suffix
1128 char path_name[256] = "hdmi_";
Amit Pundire6732bb2020-09-28 12:43:59 +05301129 ALOGV("adev_open: %s", name);
Amit Pundir4e375822019-04-18 16:46:10 +05301130
Alden DSouzae44e0672021-02-11 17:07:01 -08001131 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
Amit Pundir4e375822019-04-18 16:46:10 +05301132 return -EINVAL;
Alden DSouzae44e0672021-02-11 17:07:01 -08001133 }
Amit Pundir4e375822019-04-18 16:46:10 +05301134
Alden DSouzae44e0672021-02-11 17:07:01 -08001135 struct alsa_audio_device* adev = calloc(1, sizeof(struct alsa_audio_device));
1136 if (!adev) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301137 return -ENOMEM;
Alden DSouzae44e0672021-02-11 17:07:01 -08001138 }
Amit Pundir4e375822019-04-18 16:46:10 +05301139
Amit Pundire6732bb2020-09-28 12:43:59 +05301140 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
1141 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1142 adev->hw_device.common.module = (struct hw_module_t *) module;
1143 adev->hw_device.common.close = adev_close;
1144 adev->hw_device.init_check = adev_init_check;
1145 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1146 adev->hw_device.set_master_volume = adev_set_master_volume;
1147 adev->hw_device.get_master_volume = adev_get_master_volume;
1148 adev->hw_device.set_master_mute = adev_set_master_mute;
1149 adev->hw_device.get_master_mute = adev_get_master_mute;
1150 adev->hw_device.set_mode = adev_set_mode;
1151 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1152 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1153 adev->hw_device.set_parameters = adev_set_parameters;
1154 adev->hw_device.get_parameters = adev_get_parameters;
1155 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1156 adev->hw_device.open_output_stream = adev_open_output_stream;
1157 adev->hw_device.close_output_stream = adev_close_output_stream;
1158 adev->hw_device.open_input_stream = adev_open_input_stream;
1159 adev->hw_device.close_input_stream = adev_close_input_stream;
1160 adev->hw_device.dump = adev_dump;
1161 adev->hw_device.get_microphones = adev_get_microphones;
Amit Pundir4e375822019-04-18 16:46:10 +05301162
Amit Pundire6732bb2020-09-28 12:43:59 +05301163 *device = &adev->hw_device.common;
Amit Pundir4e375822019-04-18 16:46:10 +05301164
John Stultz57a02362021-09-02 03:26:56 +00001165 int out_card = get_audio_card(PCM_OUT, 0);
1166 adev->mixer = mixer_open(out_card);
Amit Pundire6732bb2020-09-28 12:43:59 +05301167 if (!adev->mixer) {
1168 ALOGE("Unable to open the mixer, aborting.");
Alden DSouzae44e0672021-02-11 17:07:01 -08001169 goto error_1;
Amit Pundir456949d2020-02-18 22:44:16 +05301170 }
1171
John Stultz57a02362021-09-02 03:26:56 +00001172 adev->audio_route = audio_route_init(out_card, MIXER_XML_PATH);
Amit Pundire6732bb2020-09-28 12:43:59 +05301173 if (!adev->audio_route) {
1174 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
Alden DSouzae44e0672021-02-11 17:07:01 -08001175 goto error_2;
Amit Pundire6732bb2020-09-28 12:43:59 +05301176 }
Amit Pundir456949d2020-02-18 22:44:16 +05301177
Amit Pundirc0ad8942021-12-14 19:45:56 +05301178 /*
1179 * To support both the db845c and rb5 we need to used the right mixer path
1180 * we do this by checking the hardware name. Which is set at boot time.
1181 */
1182 property_get("vendor.hw", vendor_hw, "db845c");
1183 strlcat(path_name, vendor_hw, 256);
1184 ALOGV("%s: Using mixer path: %s", __func__, path_name);
1185 audio_route_apply_and_update_path(adev->audio_route, path_name);
1186
Amit Pundire6732bb2020-09-28 12:43:59 +05301187 pthread_mutex_lock(&adev->lock);
1188 if (init_aec(CAPTURE_CODEC_SAMPLING_RATE, NUM_AEC_REFERENCE_CHANNELS,
1189 CHANNEL_STEREO, &adev->aec)) {
1190 pthread_mutex_unlock(&adev->lock);
Alden DSouzae44e0672021-02-11 17:07:01 -08001191 goto error_3;
Amit Pundire6732bb2020-09-28 12:43:59 +05301192 }
1193 pthread_mutex_unlock(&adev->lock);
1194
Amit Pundir4e375822019-04-18 16:46:10 +05301195 return 0;
Alden DSouzae44e0672021-02-11 17:07:01 -08001196
1197error_3:
1198 audio_route_free(adev->audio_route);
1199error_2:
1200 mixer_close(adev->mixer);
1201error_1:
1202 free(adev);
1203 return -EINVAL;
Amit Pundir4e375822019-04-18 16:46:10 +05301204}
1205
1206static struct hw_module_methods_t hal_module_methods = {
1207 .open = adev_open,
1208};
1209
1210struct audio_module HAL_MODULE_INFO_SYM = {
1211 .common = {
1212 .tag = HARDWARE_MODULE_TAG,
1213 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1214 .hal_api_version = HARDWARE_HAL_API_VERSION,
1215 .id = AUDIO_HARDWARE_MODULE_ID,
Amit Pundire6732bb2020-09-28 12:43:59 +05301216 .name = "Yukawa audio HW HAL",
Amit Pundir4e375822019-04-18 16:46:10 +05301217 .author = "The Android Open Source Project",
1218 .methods = &hal_module_methods,
1219 },
1220};